812 lines
41 KiB
PHP
812 lines
41 KiB
PHP
<?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>
|