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

126 lines
6.5 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 lead detail for agency quote requests.';
$projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
$accessKey = getenv('ADMIN_ACCESS_KEY') ?: '';
$demoMode = $accessKey === '';
$authenticated = $demoMode || !empty($_SESSION['admin_ok']);
if (!$authenticated) {
header('Location: admin.php');
exit;
}
if (empty($_SESSION['admin_csrf'])) {
$_SESSION['admin_csrf'] = bin2hex(random_bytes(32));
}
$statuses = lead_statuses();
$id = isset($_GET['id']) ? (int)$_GET['id'] : (int)($_POST['id'] ?? 0);
$error = null;
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$token = (string)($_POST['csrf'] ?? '');
if ($token === '' || !hash_equals((string)$_SESSION['admin_csrf'], $token)) {
$error = 'The form expired. Please try again.';
} else {
try {
update_lead($id, (string)($_POST['status'] ?? 'new'), (string)($_POST['admin_notes'] ?? ''));
header('Location: admin_lead.php?id=' . $id . '&saved=1');
exit;
} catch (Throwable $e) {
error_log('Lead update failed: ' . $e->getMessage());
$error = 'Could not update the lead.';
}
}
}
try {
$lead = $id > 0 ? get_lead($id) : null;
} catch (Throwable $e) {
error_log('Lead detail load failed: ' . $e->getMessage());
$lead = null;
$error = 'Lead data is unavailable.';
}
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 ? 'Lead #' . h((string)$lead['id']) : 'Lead Not Found' ?> | <?= 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="admin.php">Dashboard</a><a class="btn btn-dark btn-sm" href="/#quote">New quote</a></div>
</div>
</nav>
</header>
<main class="container py-4 py-md-5">
<?php if ($error): ?><div class="alert alert-danger"><?= h($error) ?></div><?php endif; ?>
<?php if (!$lead): ?>
<section class="admin-card empty-state"><h1 class="h3">Lead not found</h1><p>The requested lead may not exist.</p><a class="btn btn-dark" href="admin.php">Back to dashboard</a></section>
<?php else: ?>
<div class="d-flex flex-column flex-md-row justify-content-between gap-2 mb-3">
<div><p class="eyebrow">Lead #<?= h((string)$lead['id']) ?></p><h1 class="h2 mb-1"><?= h($lead['name']) ?></h1><p class="text-secondary mb-0"><?= h($lead['service']) ?> · <?= h(date('M j, Y H:i', strtotime($lead['created_at']))) ?></p></div>
<span class="badge-soft align-self-md-start"><?= h(status_label($statuses, $lead['status'])) ?></span>
</div>
<div class="row g-3">
<div class="col-lg-7">
<section class="detail-panel h-100">
<h2 class="h4">Request details</h2>
<div class="detail-meta my-3">
<div><span>Email</span><a href="mailto:<?= h($lead['email']) ?>"><?= h($lead['email']) ?></a></div>
<div><span>Phone</span><?= h($lead['phone'] ?: 'Not provided') ?></div>
<div><span>Company</span><?= h($lead['company'] ?: 'Not provided') ?></div>
<div><span>Budget</span><?= h($lead['budget'] ?: 'Not sure') ?></div>
<div><span>Timeline</span><?= h($lead['timeline'] ?: 'Flexible') ?></div>
<div><span>Source</span><?= h($lead['source'] ?: 'website') ?></div>
</div>
<h3 class="h5">Project notes</h3>
<p class="mb-0"><?= nl2br(h($lead['message'])) ?></p>
</section>
</div>
<div class="col-lg-5">
<form class="detail-panel needs-validation" method="post" action="admin_lead.php" novalidate>
<input type="hidden" name="csrf" value="<?= h($_SESSION['admin_csrf']) ?>">
<input type="hidden" name="id" value="<?= h((string)$lead['id']) ?>">
<h2 class="h4">Follow-up</h2>
<label class="form-label" for="status">Status</label>
<select class="form-select mb-3" id="status" name="status">
<?php foreach ($statuses as $key => $label): ?>
<option value="<?= h($key) ?>" <?= $lead['status'] === $key ? 'selected' : '' ?>><?= h($label) ?></option>
<?php endforeach; ?>
</select>
<label class="form-label" for="admin_notes">Internal notes</label>
<textarea class="form-control" id="admin_notes" name="admin_notes" rows="8" placeholder="Add call notes, next action, or proposal context."><?= h($lead['admin_notes'] ?? '') ?></textarea>
<button class="btn btn-dark w-100 mt-3" type="submit">Save lead</button>
</form>
</div>
</div>
<?php endif; ?>
</main>
<div class="toast-container position-fixed bottom-0 end-0 p-3"><div id="siteToast" class="toast" role="status" aria-live="polite" aria-atomic="true"><div class="toast-header"><strong class="me-auto">Dashboard</strong><button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button></div><div class="toast-body">Saved.</div></div></div>
<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>