37254-vm/index.php
Flatlogic Bot 6908213cbc init
2026-02-15 21:17:22 +00:00

342 lines
18 KiB
PHP

<?php
declare(strict_types=1);
session_start();
require_once __DIR__ . '/cls/class.pef.php';
if (!isset($_SESSION['user'])) {
header('Location: login.php');
exit;
}
$user = $_SESSION['user'];
$pef = new Pef();
$stats = $pef->getStats();
$projects = $pef->getProjects();
$selectedProjectId = isset($_GET['project_id']) ? (int)$_GET['project_id'] : null;
$selectedProject = $selectedProjectId ? $pef->getProject($selectedProjectId) : null;
$logs = $selectedProjectId ? $pef->getProjectLogs($selectedProjectId) : [];
$view = $_GET['view'] ?? 'dashboard';
?>
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>CMS Dashboard - Construction & Education</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
<style>
:root {
--sidebar-bg: #1e293b;
--sidebar-hover: #334155;
--primary: #3b82f6;
--bg: #f8fafc;
--card: #ffffff;
--text: #1e293b;
--text-muted: #64748b;
--border: #e2e8f0;
}
body { margin: 0; font-family: 'Inter', sans-serif; background: var(--bg); color: var(--text); display: flex; min-height: 100vh; }
/* Sidebar */
nav { width: 260px; background: var(--sidebar-bg); color: white; display: flex; flex-direction: column; }
.nav-header { padding: 2rem 1.5rem; font-weight: 700; font-size: 1.25rem; color: var(--primary); }
.nav-links { flex: 1; padding: 0 1rem; }
.nav-link { display: flex; align-items: center; padding: 0.75rem 1rem; color: #cbd5e1; text-decoration: none; border-radius: 8px; margin-bottom: 0.5rem; transition: all 0.2s; }
.nav-link:hover, .nav-link.active { background: var(--sidebar-hover); color: white; }
.nav-footer { padding: 1.5rem; border-top: 1px solid #334155; }
.user-info { font-size: 0.875rem; color: #94a3b8; margin-bottom: 1rem; }
.logout-btn { color: #f87171; text-decoration: none; font-size: 0.875rem; font-weight: 600; }
/* Main Content */
main { flex: 1; display: flex; flex-direction: column; }
.top-bar { height: 64px; background: white; border-bottom: 1px solid var(--border); display: flex; align-items: center; justify-content: space-between; padding: 0 2rem; }
.content { padding: 2rem; overflow-y: auto; }
/* Cards & Stats */
.stats-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 1.5rem; margin-bottom: 2rem; }
.stat-card { background: white; padding: 1.5rem; border-radius: 12px; border: 1px solid var(--border); }
.stat-label { font-size: 0.875rem; color: var(--text-muted); font-weight: 500; }
.stat-value { font-size: 1.5rem; font-weight: 700; margin-top: 0.5rem; }
.card { background: white; border-radius: 12px; border: 1px solid var(--border); overflow: hidden; margin-bottom: 1.5rem; }
.card-header { padding: 1.25rem 1.5rem; border-bottom: 1px solid var(--border); display: flex; justify-content: space-between; align-items: center; }
.card-title { margin: 0; font-size: 1rem; font-weight: 600; }
.card-body { padding: 1.5rem; }
/* Table */
table { width: 100%; border-collapse: collapse; }
th { text-align: left; padding: 1rem; font-size: 0.875rem; color: var(--text-muted); border-bottom: 1px solid var(--border); }
td { padding: 1rem; border-bottom: 1px solid var(--border); font-size: 0.9375rem; }
tr:last-child td { border-bottom: none; }
/* Badges */
.badge { padding: 0.25rem 0.625rem; border-radius: 9999px; font-size: 0.75rem; font-weight: 600; }
.badge-active { background: #dcfce7; color: #166534; }
.badge-completed { background: #e0f2fe; color: #0369a1; }
.badge-on_hold { background: #fef3c7; color: #92400e; }
.btn { padding: 0.5rem 1rem; border-radius: 6px; font-weight: 600; font-size: 0.875rem; cursor: pointer; border: none; text-decoration: none; display: inline-block; }
.btn-primary { background: var(--primary); color: white; }
.btn-outline { border: 1px solid var(--border); background: white; color: var(--text); }
/* Log Items */
.log-entry { padding: 1rem; border-left: 3px solid var(--primary); background: #f8fafc; margin-bottom: 1rem; border-radius: 0 8px 8px 0; }
.log-meta { display: flex; justify-content: space-between; font-size: 0.8rem; color: var(--text-muted); margin-bottom: 0.5rem; }
</style>
</head>
<body>
<nav>
<div class="nav-header">PEF CMS</div>
<div class="nav-links">
<a href="?view=dashboard" class="nav-link <?= $view === 'dashboard' ? 'active' : '' ?>">Overview</a>
<a href="?view=projects" class="nav-link <?= $view === 'projects' ? 'active' : '' ?>">Projects</a>
</div>
<div class="nav-footer">
<div class="user-info">
Logged in as: <strong><?= htmlspecialchars($user['full_name']) ?></strong><br>
<small><?= ucfirst($user['role']) ?></small>
</div>
<a href="logout.php" class="logout-btn">Sign Out</a>
</div>
</nav>
<main>
<div class="top-bar">
<h2 style="font-size: 1.125rem; margin: 0;"><?= ucfirst($view) ?></h2>
<div style="font-size: 0.875rem; color: var(--text-muted);">
<?= date('l, F j, Y') ?>
</div>
</div>
<div class="content">
<?php if ($view === 'dashboard'): ?>
<div class="stats-grid">
<div class="stat-card">
<div class="stat-label">Total Projects</div>
<div class="stat-value"><?= $stats['total_projects'] ?></div>
</div>
<div class="stat-card">
<div class="stat-label">Active Projects</div>
<div class="stat-value"><?= $stats['active_projects'] ?></div>
</div>
</div>
<div class="card">
<div class="card-header"><h3 class="card-title">Recent Activity</h3></div>
<div class="card-body">
<?php if (empty($stats['latest_logs'])): ?>
<p style="text-align:center; color:var(--text-muted); padding: 2rem;">No recent activity. Start by creating a project or adding a log.</p>
<?php else: ?>
<?php foreach ($stats['latest_logs'] as $log): ?>
<div class="log-entry">
<div class="log-meta">
<strong><?= htmlspecialchars($log['project_name']) ?> (v<?= htmlspecialchars($log['version']) ?>)</strong>
<span><?= $log['created_at'] ?></span>
</div>
<div style="font-size: 0.9rem;"><?= htmlspecialchars($log['log_entry']) ?></div>
<div style="font-size: 0.75rem; color: var(--text-muted); margin-top: 0.25rem;">By: <?= htmlspecialchars($log['author']) ?></div>
</div>
<?php endforeach; ?>
<?php endif; ?>
</div>
</div>
<?php elseif ($view === 'projects'): ?>
<?php if ($selectedProjectId): ?>
<!-- Project Detail View -->
<div style="margin-bottom: 1rem;">
<a href="?view=projects" class="btn btn-outline">← Back to Projects</a>
</div>
<div class="card">
<div class="card-header">
<h3 class="card-title"><?= htmlspecialchars($selectedProject['name']) ?></h3>
<div style="display:flex; gap:0.5rem; align-items:center;">
<span class="badge badge-<?= $selectedProject['status'] ?>"><?= ucfirst($selectedProject['status']) ?></span>
<?php if ($user['role'] !== 'viewer'): ?>
<button onclick="openEditModal()" class="btn btn-outline" style="padding: 0.25rem 0.5rem; font-size: 0.75rem;">Edit</button>
<?php endif; ?>
</div>
</div>
<div class="card-body">
<p><?= nl2br(htmlspecialchars($selectedProject['description'])) ?></p>
<div style="font-size: 0.875rem; color: var(--text-muted);">
Industry: <?= $selectedProject['industry'] ?> | Current Version: v<?= $selectedProject['current_version'] ?>
</div>
</div>
</div>
<?php if ($user['role'] !== 'viewer'): ?>
<div class="card">
<div class="card-header"><h3 class="card-title">Add New Log & Version</h3></div>
<div class="card-body">
<form action="add_log.php" method="POST" style="display: grid; gap: 1rem;">
<input type="hidden" name="project_id" value="<?= $selectedProjectId ?>">
<div>
<label style="display:block; font-size:0.8rem; font-weight:600; margin-bottom:0.25rem;">Version</label>
<input type="text" name="version" value="<?= htmlspecialchars($selectedProject['current_version']) ?>" style="width:100%; padding:0.5rem; border:1px solid var(--border); border-radius:4px;" required>
</div>
<div>
<label style="display:block; font-size:0.8rem; font-weight:600; margin-bottom:0.25rem;">What changed?</label>
<textarea name="log_entry" rows="3" style="width:100%; padding:0.5rem; border:1px solid var(--border); border-radius:4px;" required placeholder="Detailed log entry..."></textarea>
</div>
<button type="submit" class="btn btn-primary" style="width:fit-content;">Post Update</button>
</form>
</div>
</div>
<?php endif; ?>
<div class="card">
<div class="card-header"><h3 class="card-title">Version History</h3></div>
<div class="card-body">
<?php if (empty($logs)): ?>
<p style="text-align:center; color:var(--text-muted);">No logs available.</p>
<?php else: ?>
<?php foreach ($logs as $log): ?>
<div class="log-entry">
<div class="log-meta">
<strong>Version <?= htmlspecialchars($log['version']) ?></strong>
<span><?= $log['created_at'] ?></span>
</div>
<div><?= nl2br(htmlspecialchars($log['log_entry'])) ?></div>
<div style="font-size:0.75rem; color:var(--text-muted); margin-top:0.5rem;">Author: <?= htmlspecialchars($log['author']) ?></div>
</div>
<?php endforeach; ?>
<?php endif; ?>
</div>
</div>
<?php else: ?>
<!-- Projects List -->
<div class="card">
<div class="card-header">
<h3 class="card-title">Managed Projects</h3>
<?php if ($user['role'] !== 'viewer'): ?>
<button onclick="document.getElementById('addProjectModal').style.display='block'" class="btn btn-primary">+ New Project</button>
<?php endif; ?>
</div>
<div class="card-body" style="padding:0;">
<table>
<thead>
<tr>
<th>Project Name</th>
<th>Industry</th>
<th>Status</th>
<th>Version</th>
<th>Last Updated</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<?php foreach ($projects as $p): ?>
<tr>
<td><strong><?= htmlspecialchars($p['name']) ?></strong></td>
<td><?= $p['industry'] ?></td>
<td><span class="badge badge-<?= $p['status'] ?>"><?= ucfirst($p['status']) ?></span></td>
<td>v<?= htmlspecialchars($p['current_version']) ?></td>
<td><?= date('Y-m-d', strtotime($p['updated_at'])) ?></td>
<td>
<a href="?view=projects&project_id=<?= $p['id'] ?>" class="btn btn-outline" style="padding: 0.25rem 0.75rem;">View</a>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
<?php endif; ?>
<?php endif; ?>
</div>
</main>
<!-- Modals -->
<div id="addProjectModal" style="display:none; position:fixed; inset:0; background:rgba(0,0,0,0.5); z-index:100; align-items:center; justify-content:center;">
<div style="background:white; padding:2rem; border-radius:12px; width:450px; position:relative; margin: 10% auto;">
<h3 style="margin-top:0;">Create New Project</h3>
<form action="manage_project.php?action=create" method="POST" style="display:grid; gap:1rem;">
<div>
<label style="display:block; font-size:0.8rem; font-weight:600; margin-bottom:0.25rem;">Name</label>
<input type="text" name="name" required style="width:100%; padding:0.5rem; border:1px solid var(--border); border-radius:4px;">
</div>
<div>
<label style="display:block; font-size:0.8rem; font-weight:600; margin-bottom:0.25rem;">Industry</label>
<select name="industry" style="width:100%; padding:0.5rem; border:1px solid var(--border); border-radius:4px;">
<option>Construction</option>
<option>Education</option>
<option>Other</option>
</select>
</div>
<div>
<label style="display:block; font-size:0.8rem; font-weight:600; margin-bottom:0.25rem;">Description</label>
<textarea name="description" rows="3" style="width:100%; padding:0.5rem; border:1px solid var(--border); border-radius:4px;"></textarea>
</div>
<div>
<label style="display:block; font-size:0.8rem; font-weight:600; margin-bottom:0.25rem;">Initial Version</label>
<input type="text" name="version" value="1.0.0" style="width:100%; padding:0.5rem; border:1px solid var(--border); border-radius:4px;">
</div>
<div style="display:flex; gap:0.5rem; justify-content:flex-end; margin-top:1rem;">
<button type="button" onclick="this.closest('#addProjectModal').style.display='none'" class="btn btn-outline">Cancel</button>
<button type="submit" class="btn btn-primary">Create Project</button>
</div>
</form>
</div>
</div>
<!-- Edit Project Modal -->
<?php if ($selectedProject): ?>
<div id="editProjectModal" style="display:none; position:fixed; inset:0; background:rgba(0,0,0,0.5); z-index:100; align-items:center; justify-content:center;">
<div style="background:white; padding:2rem; border-radius:12px; width:450px; position:relative; margin: 10% auto;">
<h3 style="margin-top:0;">Edit Project</h3>
<form action="manage_project.php?action=update" method="POST" style="display:grid; gap:1rem;">
<input type="hidden" name="id" value="<?= $selectedProject['id'] ?>">
<div>
<label style="display:block; font-size:0.8rem; font-weight:600; margin-bottom:0.25rem;">Name</label>
<input type="text" name="name" value="<?= htmlspecialchars($selectedProject['name']) ?>" required style="width:100%; padding:0.5rem; border:1px solid var(--border); border-radius:4px;">
</div>
<div>
<label style="display:block; font-size:0.8rem; font-weight:600; margin-bottom:0.25rem;">Status</label>
<select name="status" style="width:100%; padding:0.5rem; border:1px solid var(--border); border-radius:4px;">
<option value="active" <?= $selectedProject['status'] === 'active' ? 'selected' : '' ?>>Active</option>
<option value="completed" <?= $selectedProject['status'] === 'completed' ? 'selected' : '' ?>>Completed</option>
<option value="on_hold" <?= $selectedProject['status'] === 'on_hold' ? 'selected' : '' ?>>On Hold</option>
<option value="archived" <?= $selectedProject['status'] === 'archived' ? 'selected' : '' ?>>Archived</option>
</select>
</div>
<div>
<label style="display:block; font-size:0.8rem; font-weight:600; margin-bottom:0.25rem;">Industry</label>
<select name="industry" style="width:100%; padding:0.5rem; border:1px solid var(--border); border-radius:4px;">
<option <?= $selectedProject['industry'] === 'Construction' ? 'selected' : '' ?>>Construction</option>
<option <?= $selectedProject['industry'] === 'Education' ? 'selected' : '' ?>>Education</option>
<option <?= $selectedProject['industry'] === 'Other' ? 'selected' : '' ?>>Other</option>
</select>
</div>
<div>
<label style="display:block; font-size:0.8rem; font-weight:600; margin-bottom:0.25rem;">Description</label>
<textarea name="description" rows="3" style="width:100%; padding:0.5rem; border:1px solid var(--border); border-radius:4px;"><?= htmlspecialchars($selectedProject['description']) ?></textarea>
</div>
<div style="display:flex; gap:0.5rem; justify-content:space-between; margin-top:1rem;">
<button type="button" onclick="if(confirm('Delete project?')) window.location.href='manage_project.php?action=delete&id=<?= $selectedProject['id'] ?>'" class="btn btn-outline" style="color:red; border-color:red;">Delete</button>
<div style="display:flex; gap:0.5rem;">
<button type="button" onclick="closeEditModal()" class="btn btn-outline">Cancel</button>
<button type="submit" class="btn btn-primary">Save Changes</button>
</div>
</div>
</form>
</div>
</div>
<?php endif; ?>
<script>
function openEditModal() {
document.getElementById('editProjectModal').style.display = 'block';
}
function closeEditModal() {
document.getElementById('editProjectModal').style.display = 'none';
}
</script>
</body>
</html>