exec(" CREATE TABLE IF NOT EXISTS contact_requests ( id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, name VARCHAR(80) NOT NULL, email VARCHAR(120) NOT NULL, message TEXT NOT NULL, status ENUM('new','read','archived') NOT NULL DEFAULT 'new', created_at DATETIME NOT NULL, ip VARCHAR(45) NULL, user_agent VARCHAR(255) NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci "); } catch (Throwable $e) { $tableError = 'Could not ensure contact table exists.'; } $statusFilter = (string)($_GET['status'] ?? 'all'); $validStatuses = ['all', 'new', 'read', 'archived']; if (!in_array($statusFilter, $validStatuses, true)) $statusFilter = 'all'; $counts = ['total' => 0, 'new' => 0, 'read' => 0, 'archived' => 0]; try { $counts['total'] = (int)pdo()->query("SELECT COUNT(*) FROM contact_requests")->fetchColumn(); $counts['new'] = (int)pdo()->query("SELECT COUNT(*) FROM contact_requests WHERE status='new'")->fetchColumn(); $counts['read'] = (int)pdo()->query("SELECT COUNT(*) FROM contact_requests WHERE status='read'")->fetchColumn(); $counts['archived'] = (int)pdo()->query("SELECT COUNT(*) FROM contact_requests WHERE status='archived'")->fetchColumn(); } catch (Throwable $e) {} if ($_SERVER['REQUEST_METHOD'] === 'POST') { if (!csrf_check((string)($_POST['csrf'] ?? ''))) { flash_set('danger', 'Bad CSRF token.'); header('Location: /public/admin/contacts.php?status=' . urlencode($statusFilter)); exit; } $action = (string)($_POST['action'] ?? ''); $id = (int)($_POST['id'] ?? 0); if ($id > 0) { if ($action === 'set_status') { $newStatus = (string)($_POST['status'] ?? ''); if (in_array($newStatus, ['new', 'read', 'archived'], true)) { $st = pdo()->prepare("UPDATE contact_requests SET status=? WHERE id=?"); $st->execute([$newStatus, $id]); flash_set('success', 'Status updated.'); } } elseif ($action === 'delete') { $st = pdo()->prepare("DELETE FROM contact_requests WHERE id=?"); $st->execute([$id]); flash_set('success', 'Contact deleted.'); } } header('Location: /public/admin/contacts.php?status=' . urlencode($statusFilter)); exit; } $requests = []; if (!$tableError) { try { $sql = "SELECT id, name, email, message, status, created_at, ip FROM contact_requests"; $params = []; if ($statusFilter !== 'all') { $sql .= " WHERE status = ?"; $params[] = $statusFilter; } $sql .= " ORDER BY created_at DESC, id DESC LIMIT 200"; $st = pdo()->prepare($sql); $st->execute($params); $requests = $st->fetchAll() ?: []; } catch (Throwable $e) { $tableError = 'Could not load contact requests.'; } } $extraCss = ['/public/css/contacts.css']; include __DIR__ . '/_top.php'; ?>
Inbox

Contact Requests

Review and triage all incoming messages.
Dashboard
New
Inbox
Unread messages waiting for review.
Totals
messages
Read: Archived:
Latest messages
ID From Status Message Received Actions
#
No contact requests yet.