| import { createFileRoute } from "@tanstack/react-router"; |
| import { useEffect, useState } from "react"; |
| import { Card, CardContent } from "@/components/ui/card"; |
|
|
| export const Route = createFileRoute("/admin")({ |
| head: () => ({ |
| meta: [ |
| { title: "Admin — Contact Submissions" }, |
| { name: "robots", content: "noindex" }, |
| ], |
| }), |
| component: AdminContactsPage, |
| }); |
|
|
| function AdminContactsPage() { |
| const [items, setItems] = useState<Array<any>>([]); |
|
|
| async function load() { |
| try { |
| const res = await fetch('/data/contacts'); |
| if (!res.ok) throw new Error('failed to fetch'); |
| const json = await res.json(); |
| setItems(json || []); |
| } catch (err) { |
| console.error(err); |
| |
| try { |
| const key = 'safesight:contact_submissions'; |
| const existing = JSON.parse(localStorage.getItem(key) || '[]'); |
| setItems(existing); |
| } catch (e) { |
| setItems([]); |
| } |
| } |
| } |
|
|
| useEffect(() => { |
| load(); |
| }, []); |
|
|
| return ( |
| <div className="flex min-h-screen flex-col"> |
| <section className="bg-navy py-8"> |
| <div className="mx-auto max-w-4xl px-4 sm:px-6 lg:px-8"> |
| <h1 className="text-2xl font-bold text-navy-foreground">Admin: Contact Submissions</h1> |
| <p className="mt-2 text-sm text-navy-foreground/80">No password required. Anyone with this page URL may view submissions.</p> |
| </div> |
| </section> |
| |
| <section className="bg-background py-10"> |
| <div className="mx-auto max-w-4xl px-4 sm:px-6 lg:px-8"> |
| <div className="flex justify-between items-center mb-4"> |
| <h2 className="text-lg font-semibold text-foreground">Submissions ({items.length})</h2> |
| <button onClick={load} className="text-sm text-accent hover:underline">Refresh</button> |
| </div> |
| |
| <div className="space-y-4"> |
| {items.length === 0 ? ( |
| <Card className="border-0 bg-card shadow-sm"> |
| <CardContent className="p-6">No submissions yet.</CardContent> |
| </Card> |
| ) : ( |
| items.map((it, i) => ( |
| <Card key={i} className="border-0 bg-card shadow-sm"> |
| <CardContent className="p-6"> |
| <div className="flex justify-between"> |
| <div> |
| <p className="font-medium text-foreground">{it.subject}</p> |
| <p className="mt-1 text-sm text-muted-foreground">From: {it.name} — {it.email}</p> |
| </div> |
| <div className="text-sm text-muted-foreground">{it.createdAt ? new Date(it.createdAt).toLocaleString() : "—"}</div> |
| </div> |
| <div className="mt-4 text-sm text-foreground whitespace-pre-wrap">{it.message}</div> |
| </CardContent> |
| </Card> |
| )) |
| )} |
| </div> |
| </div> |
| </section> |
| </div> |
| ); |
| } |
|
|