40161-vm/admin.php
Flatlogic Bot 7e76255737 0
2026-05-29 14:48:07 +00:00

143 lines
6.7 KiB
PHP

<?php
declare(strict_types=1);
session_start();
require_once __DIR__ . '/includes/leads.php';
$projectName = $_SERVER['PROJECT_NAME'] ?? 'Northline Studio';
$projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Admin dashboard for reviewing agency quote requests.';
$projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
$accessKey = getenv('ADMIN_ACCESS_KEY') ?: '';
$demoMode = $accessKey === '';
$loginError = '';
if (isset($_GET['logout'])) {
unset($_SESSION['admin_ok']);
header('Location: admin.php');
exit;
}
if (!$demoMode && $_SERVER['REQUEST_METHOD'] === 'POST') {
$submitted = (string)($_POST['access_key'] ?? '');
if (hash_equals($accessKey, $submitted)) {
$_SESSION['admin_ok'] = true;
header('Location: admin.php');
exit;
}
$loginError = 'Invalid access key.';
}
$authenticated = $demoMode || !empty($_SESSION['admin_ok']);
$status = isset($_GET['status']) ? (string)$_GET['status'] : '';
$statuses = lead_statuses();
$leads = [];
$counts = array_fill_keys(array_keys($statuses), 0);
$error = null;
if ($authenticated) {
try {
$leads = list_leads($status ?: null);
$counts = lead_counts();
} catch (Throwable $e) {
error_log('Admin lead load failed: ' . $e->getMessage());
$error = 'Lead data is unavailable. Check database configuration.';
}
}
function h(?string $value): string { return htmlspecialchars((string)$value, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); }
function status_label(array $statuses, string $status): string { return $statuses[$status] ?? ucfirst($status); }
?>
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Lead Dashboard | <?= h($projectName) ?></title>
<?php if ($projectDescription): ?>
<meta name="description" content="<?= h($projectDescription) ?>">
<meta property="og:description" content="<?= h($projectDescription) ?>">
<meta property="twitter:description" content="<?= h($projectDescription) ?>">
<?php endif; ?>
<?php if ($projectImageUrl): ?>
<meta property="og:image" content="<?= h($projectImageUrl) ?>">
<meta property="twitter:image" content="<?= h($projectImageUrl) ?>">
<?php endif; ?>
<meta name="robots" content="noindex, nofollow">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="assets/css/custom.css?v=2026052901">
</head>
<body class="admin-shell">
<header class="site-header">
<nav class="navbar">
<div class="container">
<a class="navbar-brand" href="/"><span class="brand-mark" aria-hidden="true">N</span><?= h($projectName) ?></a>
<div class="d-flex gap-2"><a class="btn btn-outline-dark btn-sm" href="/">Home</a><?php if ($authenticated && !$demoMode): ?><a class="btn btn-dark btn-sm" href="admin.php?logout=1">Logout</a><?php endif; ?></div>
</div>
</nav>
</header>
<main>
<section class="admin-hero">
<div class="container">
<p class="eyebrow">Admin dashboard</p>
<h1 class="h2 mb-2">Quote requests and lead follow-up.</h1>
<p class="text-secondary mb-0">Review incoming submissions, filter by status, and open each lead for notes.</p>
</div>
</section>
<div class="container pb-5">
<?php if (!$authenticated): ?>
<div class="row justify-content-center">
<div class="col-md-6 col-lg-5">
<form class="admin-card" method="post" action="admin.php">
<h2 class="h4">Enter admin access key</h2>
<p class="text-secondary">Set ADMIN_ACCESS_KEY in the environment to protect this dashboard.</p>
<?php if ($loginError): ?><div class="alert alert-danger"><?= h($loginError) ?></div><?php endif; ?>
<label class="form-label" for="access_key">Access key</label>
<input class="form-control" id="access_key" name="access_key" type="password" required autofocus>
<button class="btn btn-dark mt-3 w-100" type="submit">Open dashboard</button>
</form>
</div>
</div>
<?php else: ?>
<?php if ($demoMode): ?><div class="alert alert-warning">Demo admin mode is active because ADMIN_ACCESS_KEY is not set. Set it before sharing this site publicly.</div><?php endif; ?>
<?php if ($error): ?><div class="alert alert-danger"><?= h($error) ?></div><?php endif; ?>
<div class="stat-grid mb-3">
<?php foreach ($statuses as $key => $label): ?>
<a class="stat text-decoration-none text-reset" href="admin.php?status=<?= h($key) ?>"><span><?= h($label) ?></span><strong><?= h((string)$counts[$key]) ?></strong></a>
<?php endforeach; ?>
</div>
<section class="admin-card">
<div class="d-flex flex-column flex-md-row justify-content-between gap-2 mb-3">
<div>
<h2 class="h4 mb-1">Lead inbox</h2>
<p class="text-secondary mb-0"><?= $status && isset($statuses[$status]) ? 'Filtered by ' . h($statuses[$status]) : 'Showing latest quote requests.' ?></p>
</div>
<div class="d-flex gap-2"><a class="btn btn-outline-dark btn-sm" href="admin.php">All leads</a><a class="btn btn-dark btn-sm" href="/#quote">Add test lead</a></div>
</div>
<?php if (!$leads): ?>
<div class="empty-state"><h3>No leads yet.</h3><p>Submit the quote form on the homepage to see the workflow end-to-end.</p></div>
<?php else: ?>
<div class="table-responsive">
<table class="table align-middle">
<thead><tr><th>Lead</th><th>Service</th><th>Status</th><th>Created</th><th class="text-end">Action</th></tr></thead>
<tbody>
<?php foreach ($leads as $lead): ?>
<tr>
<td><strong><?= h($lead['name']) ?></strong><br><span class="text-secondary"><?= h($lead['email']) ?><?= $lead['company'] ? ' · ' . h($lead['company']) : '' ?></span></td>
<td><?= h($lead['service']) ?></td>
<td><span class="badge-soft"><?= h(status_label($statuses, $lead['status'])) ?></span></td>
<td><?= h(date('M j, Y H:i', strtotime($lead['created_at']))) ?></td>
<td class="text-end"><a class="btn btn-outline-dark btn-sm" href="admin_lead.php?id=<?= h((string)$lead['id']) ?>">Open</a></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php endif; ?>
</section>
<?php endif; ?>
</div>
</main>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
<script src="assets/js/main.js?v=2026052901" defer></script>
</body>
</html>