Fix admin stops page: replace mock supabase with direct pool query
Deploy to route.crispygoat.com / deploy (push) Successful in 4m2s
Deploy to route.crispygoat.com / deploy (push) Successful in 4m2s
The page was importing from @/lib/supabase which is a mock client that returns empty results. Replaced with pool.query() against the real Postgres stops table. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -1,27 +1,11 @@
|
||||
import StopsDashboardClient from "@/components/admin/stops/StopsDashboardClient";
|
||||
import StopsHeaderActions from "@/components/admin/StopsHeaderActions";
|
||||
import { supabase } from "@/lib/supabase";
|
||||
import { getAdminUser } from "@/lib/admin-permissions";
|
||||
import AdminAccessDenied from "@/components/admin/AdminAccessDenied";
|
||||
import { PageHeader } from "@/components/admin/design-system";
|
||||
import { redirect } from "next/navigation";
|
||||
|
||||
interface Stop {
|
||||
id: string;
|
||||
city: string;
|
||||
state: string;
|
||||
date: string;
|
||||
time: string;
|
||||
location: string;
|
||||
active: boolean;
|
||||
deleted_at: string | null;
|
||||
brand_id: string;
|
||||
address: string | null;
|
||||
zip: string | null;
|
||||
cutoff_time: string | null;
|
||||
status: string;
|
||||
brands: { name: string } | { name: string }[];
|
||||
}
|
||||
import { pool } from "@/lib/db";
|
||||
import { type Stop } from "@/components/admin/stops/types";
|
||||
|
||||
const StopIcon = () => (
|
||||
<svg className="h-5 w-5 sm:h-6 sm:w-6 text-current" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||
@@ -39,35 +23,56 @@ export default async function AdminStopsPage() {
|
||||
redirect("/admin/pickup");
|
||||
}
|
||||
|
||||
let query = supabase
|
||||
.from("stops")
|
||||
.select(`
|
||||
id,
|
||||
city,
|
||||
state,
|
||||
date,
|
||||
time,
|
||||
location,
|
||||
active,
|
||||
deleted_at,
|
||||
brand_id,
|
||||
address,
|
||||
zip,
|
||||
cutoff_time,
|
||||
status,
|
||||
brands (
|
||||
name
|
||||
)
|
||||
`)
|
||||
.is("deleted_at", null)
|
||||
.order("date", { ascending: true });
|
||||
let stops: Stop[] = [];
|
||||
let error: { message: string } | null = null;
|
||||
|
||||
if (adminUser?.brand_id) {
|
||||
query = query.eq("brand_id", adminUser.brand_id);
|
||||
try {
|
||||
const brandFilter = adminUser.brand_id
|
||||
? `AND brand_id = '${adminUser.brand_id}'`
|
||||
: "";
|
||||
|
||||
const { rows } = await pool.query<Stop& { brand_name: string }>(`
|
||||
SELECT
|
||||
s.id,
|
||||
s.city,
|
||||
s.state,
|
||||
s.date,
|
||||
s.time,
|
||||
s.location,
|
||||
s.status,
|
||||
s.deleted_at,
|
||||
s.brand_id,
|
||||
s.address,
|
||||
s.zip,
|
||||
s.cutoff_time,
|
||||
b.name as brand_name
|
||||
FROM stops s
|
||||
LEFT JOIN brands b ON b.id = s.brand_id
|
||||
WHERE s.deleted_at IS NULL
|
||||
${brandFilter}
|
||||
ORDER BY s.date ASC
|
||||
`);
|
||||
|
||||
stops = rows.map((r) => ({
|
||||
id: r.id,
|
||||
city: r.city ?? "",
|
||||
state: r.state ?? "",
|
||||
date: r.date ? String(r.date) : "",
|
||||
time: r.time ?? "",
|
||||
location: r.location ?? "",
|
||||
active: r.status === "active",
|
||||
deleted_at: r.deleted_at,
|
||||
brand_id: r.brand_id,
|
||||
address: r.address,
|
||||
zip: r.zip,
|
||||
cutoff_time: r.cutoff_time,
|
||||
status: r.status ?? "active",
|
||||
brands: r.brand_name ? { name: r.brand_name } : { name: "" },
|
||||
}));
|
||||
} catch (e) {
|
||||
error = { message: e instanceof Error ? e.message : String(e) };
|
||||
}
|
||||
|
||||
const { data: stops, error } = await query as unknown as { data: Stop[] | null; error: { message: string } | null };
|
||||
|
||||
if (error) {
|
||||
return (
|
||||
<main className="min-h-screen bg-[var(--admin-bg)]">
|
||||
@@ -76,7 +81,7 @@ export default async function AdminStopsPage() {
|
||||
<nav className="flex items-center gap-2 text-xs sm:text-sm mb-6">
|
||||
<a href="/admin" className="text-[var(--admin-text-muted)] hover:text-[var(--admin-text-secondary)]">Admin</a>
|
||||
<span className="text-[var(--admin-text-muted)]">/</span>
|
||||
<span className="text-[var(--admin-text-primary)] font-medium">Stops & Routes</span>
|
||||
<span className="text-[var(--admin-text-primary)] font-medium">Stops& Routes</span>
|
||||
</nav>
|
||||
<h1 className="text-2xl sm:text-3xl font-black text-red-600 tracking-tight">
|
||||
Error loading stops
|
||||
@@ -107,7 +112,7 @@ export default async function AdminStopsPage() {
|
||||
|
||||
{/* Content */}
|
||||
<div className="px-4 sm:px-6 md:px-8 py-4 sm:py-6">
|
||||
<StopsDashboardClient stops={stops ?? []} />
|
||||
<StopsDashboardClient stops={stops} />
|
||||
</div>
|
||||
</main>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user