import { pool } from "@/lib/db"; import StopEditForm from "@/components/admin/StopEditForm"; import StopProductAssignment from "@/components/admin/StopProductAssignment"; import MessageCustomersSection from "@/components/admin/MessageCustomersSection"; import { getAdminUser } from "@/lib/admin-permissions"; import AdminAccessDenied from "@/components/admin/AdminAccessDenied"; import { PageHeader } from "@/components/admin/design-system"; import { redirect } from "next/navigation"; import Link from "next/link"; const StopIcon = () => ( ); type StopDetailPageProps = { params: Promise<{ id: string; }>; }; interface Stop { id: string; brand_id: string; city: string; state: string; address: string | null; zip: string | null; date: string; time: string; cutoff_date: string | null; cutoff_time: string | null; status: string; location: string; active: boolean; brands?: { name: string; slug: string }; } interface Product { id: string; name: string; type: string; price: number; image_url?: string | null; } interface ProductStop { id: string; product_id: string; products?: Product; } export default async function StopDetailPage({ params }: StopDetailPageProps) { const { id } = await params; const adminUser = await getAdminUser(); if (!adminUser) { return ; } if (!adminUser.can_manage_stops) redirect("/admin/pickup"); // Fetch stop const { rows: stopsRows } = await pool.query( `SELECT s.*, b.name as brand_name, b.slug as brand_slug FROM stops s LEFT JOIN brands b ON b.id = s.brand_id WHERE s.id = $1 LIMIT 1`, [id] ); const stopRow = stopsRows[0]; if (!stopRow) { return (

Operations

} />
                {id}
              
Back to Stops
); } if (adminUser.brand_id && stopRow.brand_id !== adminUser.brand_id) { return ; } const stop: Stop = { id: stopRow.id, brand_id: stopRow.brand_id, city: stopRow.city ?? "", state: stopRow.state ?? "", address: stopRow.address ?? null, zip: stopRow.zip ?? null, date: stopRow.date ? String(stopRow.date) : "", time: stopRow.time ?? "", cutoff_date: stopRow.cutoff_date ? String(stopRow.cutoff_date) : null, cutoff_time: stopRow.cutoff_date ? String(stopRow.cutoff_date) : null, status: stopRow.status ?? "active", location: stopRow.location ?? "", active: stopRow.status === "active", brands: { name: stopRow.brand_name ?? "", slug: stopRow.brand_slug ?? "" }, }; // Fetch all products for this brand const { rows: productRows } = await pool.query<{ id: string; name: string; type: string; price: number; image_url: string | null }>( `SELECT id, name, type, price, image_url FROM products WHERE brand_id = $1 AND active = true ORDER BY name`, [stop.brand_id] ); // Fetch product-stop assignments const { rows: productStopRows } = await pool.query<{ id: string; product_id: string; name: string; type: string; price: number; image_url: string | null }>( `SELECT ps.id, ps.product_id, p.name, p.type, p.price, p.image_url FROM product_stops ps JOIN products p ON p.id = ps.product_id WHERE ps.stop_id = $1`, [id] ); // Fetch brands list const { rows: brandRows } = await pool.query<{ id: string; name: string; slug: string }>( `SELECT id, name, slug FROM brands ORDER BY name` ); const allProducts = productRows.map((p) => ({ id: p.id, name: p.name, type: p.type, price: Number(p.price), image_url: p.image_url, })); const assignedProducts = productStopRows.map((ps) => ({ id: ps.id, product_id: ps.product_id, products: { name: ps.name, type: ps.type, price: Number(ps.price), image_url: ps.image_url, }, })); const detailSubtitle = stop.brands?.name ? `${stop.brands.name} ยท ${stop.location}` : stop.location; return (

Operations

} />
Back to Stops

{stop.brands?.name}

{stop.city}, {stop.state}

{stop.location}

{stop.active ? "Active" : "Inactive"}

Date

{stop.date}

Time

{stop.time}

{stop.address && (

Address

{stop.address} {stop.zip ? `, ${stop.zip}` : ""}

)} {stop.cutoff_date && (

Cutoff

{new Date(stop.cutoff_date + "T00:00:00").toLocaleDateString()}

)}

Assigned Products

Manage which products are available at this stop.

Edit Stop

Update stop details, location, and availability.

{/* Message Customers */}

Message Customers

Send updates to customers with pending pickups at this stop.

); }