Files
portfoliowai/admin/dashboard.php
T

812 lines
41 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
require_once __DIR__ . '/auth.php';
require_once __DIR__ . '/../config/db.php';
require_once __DIR__ . '/../models/settings.php';
require_once __DIR__ . '/../models/projects.php';
require_once __DIR__ . '/../models/certifications.php';
require_once __DIR__ . '/../models/articles.php';
require_once __DIR__ . '/../models/techstack.php';
// Generate CSRF token if not exists
if (empty($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}
$success_msg = '';
$error_msg = '';
if (isset($_SESSION['success'])) {
$success_msg = $_SESSION['success'];
unset($_SESSION['success']);
}
if (isset($_SESSION['error'])) {
$error_msg = $_SESSION['error'];
unset($_SESSION['error']);
}
// Determine current active tab
$active_tab = isset($_GET['tab']) ? trim($_GET['tab']) : 'profile';
if (isset($_GET['edit_project_id'])) $active_tab = 'projects';
if (isset($_GET['edit_cert_id'])) $active_tab = 'certifications';
if (isset($_GET['edit_article_id'])) $active_tab = 'articles';
// Handle Form Submissions
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// CSRF check
$post_token = $_POST['csrf_token'] ?? '';
if (!hash_equals($_SESSION['csrf_token'], $post_token)) {
$_SESSION['error'] = 'Security check failed. CSRF token invalid.';
header("Location: dashboard.php?tab=" . urlencode($active_tab));
exit();
}
$action = $_POST['action'] ?? '';
if ($action === 'update_settings') {
$about_text_1 = trim($_POST['about_text_1'] ?? '');
$about_text_2 = trim($_POST['about_text_2'] ?? '');
$years_coding = trim($_POST['years_coding'] ?? '');
$projects_count = trim($_POST['projects_count'] ?? '');
$certifications_count = trim($_POST['certifications_count'] ?? '');
$tiktok_url = trim($_POST['tiktok_url'] ?? '');
$facebook_url = trim($_POST['facebook_url'] ?? '');
$instagram_url = trim($_POST['instagram_url'] ?? '');
$linkedin_url = trim($_POST['linkedin_url'] ?? '');
$github_url = trim($_POST['github_url'] ?? '');
if (updateSettings($mysqli, $about_text_1, $about_text_2, $years_coding, $projects_count, $certifications_count, $tiktok_url, $facebook_url, $instagram_url, $linkedin_url, $github_url)) {
$_SESSION['success'] = 'Profile settings updated successfully.';
} else {
$_SESSION['error'] = 'Failed to update profile settings.';
}
header("Location: dashboard.php?tab=profile");
exit();
}
// Projects CRUD Handlers
if ($action === 'add_project') {
$title = trim($_POST['title'] ?? '');
$des = trim($_POST['des'] ?? '');
$techstack = trim($_POST['techstack'] ?? '');
$url = trim($_POST['url'] ?? '');
$img_url = trim($_POST['img_url'] ?? '');
if (!empty($title) && !empty($des)) {
if (addProject($mysqli, $title, $des, $techstack, $url, $img_url)) {
$_SESSION['success'] = 'Project added successfully.';
} else {
$_SESSION['error'] = 'Failed to add project.';
}
} else {
$_SESSION['error'] = 'Title and description are required.';
}
header("Location: dashboard.php?tab=projects");
exit();
}
if ($action === 'edit_project') {
$id = intval($_POST['id'] ?? 0);
$title = trim($_POST['title'] ?? '');
$des = trim($_POST['des'] ?? '');
$techstack = trim($_POST['techstack'] ?? '');
$url = trim($_POST['url'] ?? '');
$img_url = trim($_POST['img_url'] ?? '');
if ($id > 0 && !empty($title) && !empty($des)) {
if (editProject($mysqli, $id, $title, $des, $techstack, $url, $img_url)) {
$_SESSION['success'] = 'Project updated successfully.';
} else {
$_SESSION['error'] = 'Failed to update project.';
}
} else {
$_SESSION['error'] = 'Invalid project data.';
}
header("Location: dashboard.php?tab=projects");
exit();
}
if ($action === 'delete_project') {
$id = intval($_POST['id'] ?? 0);
if ($id > 0) {
if (deleteProject($mysqli, $id)) {
$_SESSION['success'] = 'Project deleted successfully.';
} else {
$_SESSION['error'] = 'Failed to delete project.';
}
}
header("Location: dashboard.php?tab=projects");
exit();
}
// Certifications CRUD Handlers
if ($action === 'add_certification') {
$title = trim($_POST['title'] ?? '');
$issuer = trim($_POST['issuer'] ?? '');
$date_issued = trim($_POST['date_issued'] ?? '');
$icon = trim($_POST['icon'] ?? '');
if (!empty($title) && !empty($issuer)) {
if (addCertification($mysqli, $title, $issuer, $date_issued, $icon)) {
$_SESSION['success'] = 'Certification added successfully.';
} else {
$_SESSION['error'] = 'Failed to add certification.';
}
} else {
$_SESSION['error'] = 'Title and issuer are required.';
}
header("Location: dashboard.php?tab=certifications");
exit();
}
if ($action === 'edit_certification') {
$id = intval($_POST['id'] ?? 0);
$title = trim($_POST['title'] ?? '');
$issuer = trim($_POST['issuer'] ?? '');
$date_issued = trim($_POST['date_issued'] ?? '');
$icon = trim($_POST['icon'] ?? '');
if ($id > 0 && !empty($title) && !empty($issuer)) {
if (editCertification($mysqli, $id, $title, $issuer, $date_issued, $icon)) {
$_SESSION['success'] = 'Certification updated successfully.';
} else {
$_SESSION['error'] = 'Failed to update certification.';
}
} else {
$_SESSION['error'] = 'Invalid certification data.';
}
header("Location: dashboard.php?tab=certifications");
exit();
}
if ($action === 'delete_certification') {
$id = intval($_POST['id'] ?? 0);
if ($id > 0) {
if (deleteCertification($mysqli, $id)) {
$_SESSION['success'] = 'Certification deleted successfully.';
} else {
$_SESSION['error'] = 'Failed to delete certification.';
}
}
header("Location: dashboard.php?tab=certifications");
exit();
}
// Articles CRUD Handlers
if ($action === 'add_article') {
$title = trim($_POST['title'] ?? '');
$excerpt = trim($_POST['excerpt'] ?? '');
$date_published = trim($_POST['date_published'] ?? '');
$tag = trim($_POST['tag'] ?? '');
$url = trim($_POST['url'] ?? '#');
if (!empty($title) && !empty($excerpt)) {
if (addArticle($mysqli, $title, $excerpt, $date_published, $tag, $url)) {
$_SESSION['success'] = 'Article added successfully.';
} else {
$_SESSION['error'] = 'Failed to add article.';
}
} else {
$_SESSION['error'] = 'Title and excerpt are required.';
}
header("Location: dashboard.php?tab=articles");
exit();
}
if ($action === 'edit_article') {
$id = intval($_POST['id'] ?? 0);
$title = trim($_POST['title'] ?? '');
$excerpt = trim($_POST['excerpt'] ?? '');
$date_published = trim($_POST['date_published'] ?? '');
$tag = trim($_POST['tag'] ?? '');
$url = trim($_POST['url'] ?? '#');
if ($id > 0 && !empty($title) && !empty($excerpt)) {
if (editArticle($mysqli, $id, $title, $excerpt, $date_published, $tag, $url)) {
$_SESSION['success'] = 'Article updated successfully.';
} else {
$_SESSION['error'] = 'Failed to update article.';
}
} else {
$_SESSION['error'] = 'Invalid article data.';
}
header("Location: dashboard.php?tab=articles");
exit();
}
if ($action === 'delete_article') {
$id = intval($_POST['id'] ?? 0);
if ($id > 0) {
if (deleteArticle($mysqli, $id)) {
$_SESSION['success'] = 'Article deleted successfully.';
} else {
$_SESSION['error'] = 'Failed to delete article.';
}
}
header("Location: dashboard.php?tab=articles");
exit();
}
// Tech Stack Handlers
if ($action === 'add_techstack') {
$tech_name = trim($_POST['tech_name'] ?? '');
if (!empty($tech_name)) {
if (addTechStackItem($mysqli, $tech_name)) {
$_SESSION['success'] = 'Tech stack item added successfully.';
} else {
$_SESSION['error'] = 'Failed to add tech stack item.';
}
} else {
$_SESSION['error'] = 'Tech name cannot be empty.';
}
header("Location: dashboard.php?tab=techstack");
exit();
}
if ($action === 'delete_techstack') {
$id = intval($_POST['id'] ?? 0);
if ($id > 0) {
if (deleteTechStackItem($mysqli, $id)) {
$_SESSION['success'] = 'Tech stack item deleted successfully.';
} else {
$_SESSION['error'] = 'Failed to delete tech stack item.';
}
}
header("Location: dashboard.php?tab=techstack");
exit();
}
}
// Load Data for Display
$settings = getSettings($mysqli);
$projects = getProjects($mysqli);
$certifications = getCertifications($mysqli);
$articles = getArticles($mysqli);
$techstack = getTechStackRaw($mysqli);
// Retrieve individual edit records if requested
$edit_project = null;
if (isset($_GET['edit_project_id'])) {
$edit_project = getProjectById($mysqli, intval($_GET['edit_project_id']));
}
$edit_cert = null;
if (isset($_GET['edit_cert_id'])) {
$edit_cert = getCertificationById($mysqli, intval($_GET['edit_cert_id']));
}
$edit_article = null;
if (isset($_GET['edit_article_id'])) {
$edit_article = getArticleById($mysqli, intval($_GET['edit_article_id']));
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Admin Dashboard | Portfolio</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<!-- Mobile Header -->
<header class="mobile-top-bar">
<div class="logo-text" style="font-size: 1.25rem;">
<span>Admin Panel</span>
<span class="logo-dot"></span>
</div>
<button class="mobile-nav-toggle" id="mobile-toggle-btn">☰</button>
</header>
<!-- Sidebar Navigation -->
<div class="sidebar" id="sidebar">
<div class="logo-container">
<div class="logo-text">
<span>Admin Panel</span>
<span class="logo-dot"></span>
</div>
</div>
<div class="sidebar-nav">
<button class="nav-link <?php echo $active_tab === 'profile' ? 'active' : ''; ?>" onclick="switchTab('profile')">👤 Profile & Stats</button>
<button class="nav-link <?php echo $active_tab === 'projects' ? 'active' : ''; ?>" onclick="switchTab('projects')">💻 Projects</button>
<button class="nav-link <?php echo $active_tab === 'certifications' ? 'active' : ''; ?>" onclick="switchTab('certifications')">🏆 Certifications</button>
<button class="nav-link <?php echo $active_tab === 'articles' ? 'active' : ''; ?>" onclick="switchTab('articles')">📰 Blog Articles</button>
<button class="nav-link <?php echo $active_tab === 'techstack' ? 'active' : ''; ?>" onclick="switchTab('techstack')">⚡ Tech Stack</button>
</div>
<div class="sidebar-footer">
<a href="logout.php" class="logout-btn">Logout ➔</a>
</div>
</div>
<!-- Main Content -->
<main class="main-content" id="main-content">
<div class="top-bar">
<div class="page-title">
<h1 id="tab-title-text">Profile & Stats Management</h1>
<p>Welcome back, <?php echo htmlspecialchars($_SESSION['admin_username']); ?>.</p>
</div>
<div class="user-badge">
<span class="status-dot"></span>
<span>Active Session</span>
</div>
</div>
<!-- System Alerts -->
<?php if (!empty($success_msg)): ?>
<div class="alert alert-success">
<span>✓</span>
<div><?php echo htmlspecialchars($success_msg); ?></div>
</div>
<?php endif; ?>
<?php if (!empty($error_msg)): ?>
<div class="alert alert-danger">
<span>⚠️</span>
<div><?php echo htmlspecialchars($error_msg); ?></div>
</div>
<?php endif; ?>
<!-- ================= TAB: PROFILE ================= -->
<div id="tab-profile" class="tab-pane <?php echo $active_tab === 'profile' ? 'active' : ''; ?>">
<form action="dashboard.php?tab=profile" method="POST">
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token']; ?>">
<input type="hidden" name="action" value="update_settings">
<div class="card">
<div class="card-title">📝 About Me Bio Copy</div>
<div class="form-group">
<label for="about_text_1">About Paragraph 1</label>
<textarea name="about_text_1" id="about_text_1" required><?php echo htmlspecialchars($settings['about_text_1'] ?? ''); ?></textarea>
</div>
<div class="form-group">
<label for="about_text_2">About Paragraph 2</label>
<textarea name="about_text_2" id="about_text_2" required><?php echo htmlspecialchars($settings['about_text_2'] ?? ''); ?></textarea>
</div>
</div>
<div class="card">
<div class="card-title">📈 Statistics Counters</div>
<div class="form-grid">
<div class="form-group">
<label for="years_coding">Years Coding Count (e.g. 3+)</label>
<input type="text" name="years_coding" id="years_coding" value="<?php echo htmlspecialchars($settings['years_coding'] ?? ''); ?>" required>
</div>
<div class="form-group">
<label for="projects_count">Projects Built Count (e.g. 10+)</label>
<input type="text" name="projects_count" id="projects_count" value="<?php echo htmlspecialchars($settings['projects_count'] ?? ''); ?>" required>
</div>
<div class="form-group">
<label for="certifications_count">Certifications Count (e.g. 6+)</label>
<input type="text" name="certifications_count" id="certifications_count" value="<?php echo htmlspecialchars($settings['certifications_count'] ?? ''); ?>" required>
</div>
</div>
</div>
<div class="card">
<div class="card-title">🔗 Social Links</div>
<div class="form-grid">
<div class="form-group">
<label for="tiktok_url">TikTok URL</label>
<input type="url" name="tiktok_url" id="tiktok_url" value="<?php echo htmlspecialchars($settings['tiktok_url'] ?? ''); ?>">
</div>
<div class="form-group">
<label for="github_url">GitHub URL</label>
<input type="url" name="github_url" id="github_url" value="<?php echo htmlspecialchars($settings['github_url'] ?? ''); ?>">
</div>
<div class="form-group">
<label for="linkedin_url">LinkedIn URL</label>
<input type="url" name="linkedin_url" id="linkedin_url" value="<?php echo htmlspecialchars($settings['linkedin_url'] ?? ''); ?>">
</div>
<div class="form-group">
<label for="facebook_url">Facebook URL</label>
<input type="url" name="facebook_url" id="facebook_url" value="<?php echo htmlspecialchars($settings['facebook_url'] ?? ''); ?>">
</div>
<div class="form-group">
<label for="instagram_url">Instagram URL</label>
<input type="url" name="instagram_url" id="instagram_url" value="<?php echo htmlspecialchars($settings['instagram_url'] ?? ''); ?>">
</div>
</div>
</div>
<button type="submit" class="btn primary">Save Changes</button>
</form>
</div>
<!-- ================= TAB: PROJECTS ================= -->
<div id="tab-projects" class="tab-pane <?php echo $active_tab === 'projects' ? 'active' : ''; ?>">
<!-- Add or Edit Project Form -->
<div class="card <?php echo $edit_project ? 'form-overlay-card' : ''; ?>">
<div class="card-title">
<?php echo $edit_project ? '✏️ Edit Project' : '➕ Add New Project'; ?>
</div>
<form action="dashboard.php?tab=projects" method="POST">
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token']; ?>">
<input type="hidden" name="action" value="<?php echo $edit_project ? 'edit_project' : 'add_project'; ?>">
<?php if ($edit_project): ?>
<input type="hidden" name="id" value="<?php echo $edit_project['id']; ?>">
<?php endif; ?>
<div class="form-grid">
<div class="form-group">
<label for="proj_title">Project Title</label>
<input type="text" name="title" id="proj_title" value="<?php echo htmlspecialchars($edit_project['title'] ?? ''); ?>" required placeholder="e.g. UniMarket E-Commerce">
</div>
<div class="form-group">
<label for="proj_tech">Tech Stack (comma-separated list)</label>
<input type="text" name="techstack" id="proj_tech" value="<?php echo htmlspecialchars($edit_project['techstack'] ?? ''); ?>" placeholder="e.g. React, Node.js, Firebase">
</div>
<div class="form-group">
<label for="proj_url">Project Link / URL</label>
<input type="text" name="url" id="proj_url" value="<?php echo htmlspecialchars($edit_project['url'] ?? ''); ?>" placeholder="e.g. https://github.com/...">
</div>
<div class="form-group">
<label for="proj_img">Preview Image URL</label>
<input type="text" name="img_url" id="proj_img" value="<?php echo htmlspecialchars($edit_project['img_url'] ?? ''); ?>" placeholder="e.g. https://images.unsplash.com/...">
</div>
<div class="form-group form-group-full">
<label for="proj_des">Project Description</label>
<textarea name="des" id="proj_des" required placeholder="Describe the application features, challenges and stacks used..."><?php echo htmlspecialchars($edit_project['des'] ?? ''); ?></textarea>
</div>
</div>
<div style="display:flex; gap: 12px; margin-top: 10px;">
<button type="submit" class="btn primary"><?php echo $edit_project ? 'Update Project' : 'Add Project'; ?></button>
<?php if ($edit_project): ?>
<a href="dashboard.php?tab=projects" class="btn secondary">Cancel</a>
<?php endif; ?>
</div>
</form>
</div>
<!-- Projects List -->
<div class="card">
<div class="card-title">📁 Current Projects</div>
<div class="table-container">
<table>
<thead>
<tr>
<th>Image</th>
<th>Title</th>
<th>Tech Stack</th>
<th>Description</th>
<th class="text-center">Actions</th>
</tr>
</thead>
<tbody>
<?php if (empty($projects)): ?>
<tr>
<td colspan="5" class="text-center" style="color: var(--text-muted);">No projects found. Add one above.</td>
</tr>
<?php else: ?>
<?php foreach ($projects as $proj): ?>
<tr>
<td>
<?php if (!empty($proj['img_url'])): ?>
<img src="<?php echo htmlspecialchars($proj['img_url']); ?>" alt="" style="width: 50px; height: 35px; object-fit: cover; border-radius: 4px; border: 1px solid var(--border-color);">
<?php else: ?>
<span style="font-size: 1.2rem;">🖼️</span>
<?php endif; ?>
</td>
<td style="font-weight: 600; color: #fff;"><?php echo htmlspecialchars($proj['title']); ?></td>
<td style="font-size: 0.85rem; color: var(--accent);"><?php echo htmlspecialchars($proj['techstack']); ?></td>
<td style="font-size: 0.85rem; color: var(--text-muted); max-width: 250px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;"><?php echo htmlspecialchars($proj['des']); ?></td>
<td>
<div class="btn-actions">
<a href="dashboard.php?edit_project_id=<?php echo $proj['id']; ?>" class="btn secondary btn-sm">Edit</a>
<form action="dashboard.php?tab=projects" method="POST" onsubmit="return confirm('Are you sure you want to delete this project?');" style="display:inline;">
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token']; ?>">
<input type="hidden" name="action" value="delete_project">
<input type="hidden" name="id" value="<?php echo $proj['id']; ?>">
<button type="submit" class="btn danger btn-sm">Delete</button>
</form>
</div>
</td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
</div>
</div>
</div>
<!-- ================= TAB: CERTIFICATIONS ================= -->
<div id="tab-certifications" class="tab-pane <?php echo $active_tab === 'certifications' ? 'active' : ''; ?>">
<!-- Add or Edit Cert Form -->
<div class="card <?php echo $edit_cert ? 'form-overlay-card' : ''; ?>">
<div class="card-title">
<?php echo $edit_cert ? '✏️ Edit Certification' : '➕ Add New Certification'; ?>
</div>
<form action="dashboard.php?tab=certifications" method="POST">
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token']; ?>">
<input type="hidden" name="action" value="<?php echo $edit_cert ? 'edit_certification' : 'add_certification'; ?>">
<?php if ($edit_cert): ?>
<input type="hidden" name="id" value="<?php echo $edit_cert['id']; ?>">
<?php endif; ?>
<div class="form-grid">
<div class="form-group">
<label for="cert_title">Certification Title</label>
<input type="text" name="title" id="cert_title" value="<?php echo htmlspecialchars($edit_cert['title'] ?? ''); ?>" required placeholder="e.g. Responsive Web Design">
</div>
<div class="form-group">
<label for="cert_issuer">Issuer / Provider</label>
<input type="text" name="issuer" id="cert_issuer" value="<?php echo htmlspecialchars($edit_cert['issuer'] ?? ''); ?>" required placeholder="e.g. FreeCodeCamp">
</div>
<div class="form-group">
<label for="cert_date">Date Issued</label>
<input type="text" name="date_issued" id="cert_date" value="<?php echo htmlspecialchars($edit_cert['date_issued'] ?? ''); ?>" placeholder="e.g. Dec 2024">
</div>
<div class="form-group">
<label for="cert_icon">Icon (Single Emoji)</label>
<input type="text" name="icon" id="cert_icon" value="<?php echo htmlspecialchars($edit_cert['icon'] ?? '🏆'); ?>" placeholder="e.g. 🏆">
</div>
</div>
<div style="display:flex; gap: 12px; margin-top: 10px;">
<button type="submit" class="btn primary"><?php echo $edit_cert ? 'Update Certification' : 'Add Certification'; ?></button>
<?php if ($edit_cert): ?>
<a href="dashboard.php?tab=certifications" class="btn secondary">Cancel</a>
<?php endif; ?>
</div>
</form>
</div>
<!-- Certs List -->
<div class="card">
<div class="card-title">🏆 Current Certifications</div>
<div class="table-container">
<table>
<thead>
<tr>
<th style="width: 60px;" class="text-center">Icon</th>
<th>Title</th>
<th>Issuer</th>
<th>Date</th>
<th class="text-center">Actions</th>
</tr>
</thead>
<tbody>
<?php if (empty($certifications)): ?>
<tr>
<td colspan="5" class="text-center" style="color: var(--text-muted);">No certifications found. Add one above.</td>
</tr>
<?php else: ?>
<?php foreach ($certifications as $cert): ?>
<tr>
<td class="text-center" style="font-size: 1.5rem;"><?php echo htmlspecialchars($cert['icon']); ?></td>
<td style="font-weight: 600; color: #fff;"><?php echo htmlspecialchars($cert['title']); ?></td>
<td style="color: var(--text-muted);"><?php echo htmlspecialchars($cert['issuer']); ?></td>
<td><?php echo htmlspecialchars($cert['date_issued']); ?></td>
<td>
<div class="btn-actions">
<a href="dashboard.php?edit_cert_id=<?php echo $cert['id']; ?>" class="btn secondary btn-sm">Edit</a>
<form action="dashboard.php?tab=certifications" method="POST" onsubmit="return confirm('Are you sure you want to delete this certification?');" style="display:inline;">
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token']; ?>">
<input type="hidden" name="action" value="delete_certification">
<input type="hidden" name="id" value="<?php echo $cert['id']; ?>">
<button type="submit" class="btn danger btn-sm">Delete</button>
</form>
</div>
</td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
</div>
</div>
</div>
<!-- ================= TAB: ARTICLES ================= -->
<div id="tab-articles" class="tab-pane <?php echo $active_tab === 'articles' ? 'active' : ''; ?>">
<!-- Add or Edit Article Form -->
<div class="card <?php echo $edit_article ? 'form-overlay-card' : ''; ?>">
<div class="card-title">
<?php echo $edit_article ? '✏️ Edit Article' : '➕ Add New Blog Article'; ?>
</div>
<form action="dashboard.php?tab=articles" method="POST">
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token']; ?>">
<input type="hidden" name="action" value="<?php echo $edit_article ? 'edit_article' : 'add_article'; ?>">
<?php if ($edit_article): ?>
<input type="hidden" name="id" value="<?php echo $edit_article['id']; ?>">
<?php endif; ?>
<div class="form-grid">
<div class="form-group">
<label for="art_title">Article Title</label>
<input type="text" name="title" id="art_title" value="<?php echo htmlspecialchars($edit_article['title'] ?? ''); ?>" required placeholder="e.g. Guide to React Custom Hooks">
</div>
<div class="form-group">
<label for="art_date">Publish Date</label>
<input type="text" name="date_published" id="art_date" value="<?php echo htmlspecialchars($edit_article['date_published'] ?? ''); ?>" placeholder="e.g. Feb 10, 2026">
</div>
<div class="form-group">
<label for="art_tag">Tag / Category</label>
<input type="text" name="tag" id="art_tag" value="<?php echo htmlspecialchars($edit_article['tag'] ?? ''); ?>" placeholder="e.g. React">
</div>
<div class="form-group">
<label for="art_url">Article Link / URL (external or '#')</label>
<input type="text" name="url" id="art_url" value="<?php echo htmlspecialchars($edit_article['url'] ?? '#'); ?>" placeholder="e.g. # or external blog URL">
</div>
<div class="form-group form-group-full">
<label for="art_excerpt">Short Excerpt</label>
<textarea name="excerpt" id="art_excerpt" required placeholder="A brief description of what this article is about..."><?php echo htmlspecialchars($edit_article['excerpt'] ?? ''); ?></textarea>
</div>
</div>
<div style="display:flex; gap: 12px; margin-top: 10px;">
<button type="submit" class="btn primary"><?php echo $edit_article ? 'Update Article' : 'Add Article'; ?></button>
<?php if ($edit_article): ?>
<a href="dashboard.php?tab=articles" class="btn secondary">Cancel</a>
<?php endif; ?>
</div>
</form>
</div>
<!-- Articles List -->
<div class="card">
<div class="card-title">📰 Current Blog Articles</div>
<div class="table-container">
<table>
<thead>
<tr>
<th>Title</th>
<th>Tag</th>
<th>Published Date</th>
<th>Excerpt</th>
<th class="text-center">Actions</th>
</tr>
</thead>
<tbody>
<?php if (empty($articles)): ?>
<tr>
<td colspan="5" class="text-center" style="color: var(--text-muted);">No articles found. Add one above.</td>
</tr>
<?php else: ?>
<?php foreach ($articles as $art): ?>
<tr>
<td style="font-weight: 600; color: #fff;"><?php echo htmlspecialchars($art['title']); ?></td>
<td><span style="font-size: 0.85rem; padding: 4px 8px; background-color: rgba(59, 130, 246, 0.1); border: 1px solid rgba(59, 130, 246, 0.15); border-radius: 4px; color: var(--accent);"><?php echo htmlspecialchars($art['tag']); ?></span></td>
<td><?php echo htmlspecialchars($art['date_published']); ?></td>
<td style="font-size: 0.85rem; color: var(--text-muted); max-width: 250px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;"><?php echo htmlspecialchars($art['excerpt']); ?></td>
<td>
<div class="btn-actions">
<a href="dashboard.php?edit_article_id=<?php echo $art['id']; ?>" class="btn secondary btn-sm">Edit</a>
<form action="dashboard.php?tab=articles" method="POST" onsubmit="return confirm('Are you sure you want to delete this article?');" style="display:inline;">
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token']; ?>">
<input type="hidden" name="action" value="delete_article">
<input type="hidden" name="id" value="<?php echo $art['id']; ?>">
<button type="submit" class="btn danger btn-sm">Delete</button>
</form>
</div>
</td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
</div>
</div>
</div>
<!-- ================= TAB: TECH STACK ================= -->
<div id="tab-techstack" class="tab-pane <?php echo $active_tab === 'techstack' ? 'active' : ''; ?>">
<!-- Add Tech Item -->
<div class="card">
<div class="card-title">➕ Add Technology</div>
<form action="dashboard.php?tab=techstack" method="POST" style="display: flex; gap: 12px; align-items: flex-end;">
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token']; ?>">
<input type="hidden" name="action" value="add_techstack">
<div class="form-group" style="flex-grow: 1; margin-bottom: 0;">
<label for="tech_name">Technology Name</label>
<input type="text" name="tech_name" id="tech_name" required placeholder="e.g. Next.js, GraphQL, PostgreSQL">
</div>
<button type="submit" class="btn primary">Add Tech</button>
</form>
</div>
<!-- Badges List -->
<div class="card">
<div class="card-title">⚡ Current Technologies</div>
<?php if (empty($techstack)): ?>
<p style="color: var(--text-muted);">No technologies configured. Add one above.</p>
<?php else: ?>
<div class="tech-badges-grid">
<?php foreach ($techstack as $tech): ?>
<div class="tech-badge-item">
<span><?php echo htmlspecialchars($tech['tech_name']); ?></span>
<form action="dashboard.php?tab=techstack" method="POST" style="display: inline;" onsubmit="return confirm('Delete this technology?');">
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token']; ?>">
<input type="hidden" name="action" value="delete_techstack">
<input type="hidden" name="id" value="<?php echo $tech['id']; ?>">
<button type="submit" class="tech-badge-delete" title="Delete tag">×</button>
</form>
</div>
<?php endforeach; ?>
</div>
<?php endif; ?>
</div>
</div>
</main>
<script>
// Simple JS tab switching logic
const tabs = {
'profile': 'Profile & Stats Management',
'projects': 'Projects Management',
'certifications': 'Certifications Management',
'articles': 'Blog Articles Management',
'techstack': 'Tech Stack Management'
};
function switchTab(tabId) {
// Hide all tab panes
document.querySelectorAll('.tab-pane').forEach(el => {
el.classList.remove('active');
});
// Show selected tab pane
const activePane = document.getElementById('tab-' + tabId);
if (activePane) {
activePane.classList.add('active');
}
// Remove active class from nav links
document.querySelectorAll('.nav-link').forEach(el => {
el.classList.remove('active');
});
// Add active class to corresponding link (both desktop and mobile sidebar click)
const activeLinks = document.querySelectorAll('.sidebar-nav button');
activeLinks.forEach(link => {
if (link.getAttribute('onclick') === `switchTab('${tabId}')`) {
link.classList.add('active');
}
});
// Update title text
const titleEl = document.getElementById('tab-title-text');
if (titleEl && tabs[tabId]) {
titleEl.textContent = tabs[tabId];
}
// Set URL parameter without reloading page for consistency on refresh
const url = new URL(window.location);
url.searchParams.set('tab', tabId);
// Clear edit params on tab switch
url.searchParams.delete('edit_project_id');
url.searchParams.delete('edit_cert_id');
url.searchParams.delete('edit_article_id');
window.history.pushState({}, '', url);
// Close sidebar on mobile
closeSidebar();
}
// Mobile Sidebar Toggling logic
const sidebar = document.getElementById('sidebar');
const mobileToggleBtn = document.getElementById('mobile-toggle-btn');
if (mobileToggleBtn) {
mobileToggleBtn.addEventListener('click', toggleSidebar);
}
function toggleSidebar(e) {
if (e) e.stopPropagation();
sidebar.classList.toggle('open');
}
function closeSidebar() {
sidebar.classList.remove('open');
}
// Close sidebar if user clicks outside of it on mobile
document.addEventListener('click', function(event) {
const isClickInsideSidebar = sidebar.contains(event.target);
const isClickOnToggle = mobileToggleBtn && mobileToggleBtn.contains(event.target);
if (!isClickInsideSidebar && !isClickOnToggle && window.innerWidth <= 1024) {
closeSidebar();
}
});
</script>
</body>
</html>