143 lines
6.7 KiB
PHP
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>
|