feat(admin/stops): add tabbed dashboard with calendar and locations views
Replace the table-only stops view with a three-tab 'Harvest Dispatch' almanac dashboard. - Calendar tab: month grid with stops as status-colored pins, day-detail side panel, prev/next/today nav, weekend tint, sunrise gradient on the current day. - Locations tab: cards grouped by city+state with per-location stats (stops/active/upcoming), date range, next-stop ribbon, and inline expansion to list every stop at that location. Top of the tab shows a six-card almanac stats strip (Locations/Cities/Stops/Active/Upcoming/ Drafts). - List tab: condensed read-only list of all stops in date order. Typography: load Fraunces (display), Manrope (body), and Fragment Mono (mono) via next/font/google, wired into the Tailwind theme as --font-display, --font-sans, --font-mono. Add typescript to devDeps for tsc --noEmit in this environment. Visual signature: cream parchment cards, forest green + clay accents, Roman-numeral stat cells, paper-grain noise, binder-tab nav, route number watermarks on location cards, harvest-pin SVG markers. Verified with tsc --noEmit, eslint on the new files, and a 200 from GET /admin/stops in the dev server.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import StopTableClient from "@/components/admin/StopTableClient";
|
||||
import StopsDashboardClient from "@/components/admin/stops/StopsDashboardClient";
|
||||
import StopsHeaderActions from "@/components/admin/StopsHeaderActions";
|
||||
import { supabase } from "@/lib/supabase";
|
||||
import { getAdminUser } from "@/lib/admin-permissions";
|
||||
@@ -90,9 +90,7 @@ export default async function AdminStopsPage() {
|
||||
|
||||
{/* Content */}
|
||||
<div className="px-4 sm:px-6 md:px-8 py-4 sm:py-6">
|
||||
<div className="overflow-hidden rounded-2xl border border-[var(--admin-border)] bg-white shadow-sm">
|
||||
<StopTableClient stops={stops ?? []} />
|
||||
</div>
|
||||
<StopsDashboardClient stops={stops ?? []} />
|
||||
</div>
|
||||
</main>
|
||||
);
|
||||
|
||||
+6
-1
@@ -1,6 +1,11 @@
|
||||
@import "tailwindcss";
|
||||
|
||||
@theme {
|
||||
/* Custom typefaces — Field Almanac */
|
||||
--font-display: var(--font-fraunces, "Georgia"), Georgia, serif;
|
||||
--font-sans: var(--font-manrope, system-ui), system-ui, -apple-system, BlinkMacSystemFont, sans-serif;
|
||||
--font-mono: var(--font-fragment-mono, "JetBrains Mono"), ui-monospace, SFMono-Regular, Menlo, monospace;
|
||||
|
||||
/* Apple-inspired dark palette — sophisticated depth */
|
||||
--color-surface-50: #f5f5f7;
|
||||
--color-surface-100: #e8e8ed;
|
||||
@@ -85,7 +90,7 @@ html {
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, "SF Pro Display", "SF Pro Text", "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
font-family: var(--font-sans);
|
||||
background: #ffffff;
|
||||
background-attachment: fixed;
|
||||
color: #1a1a1a;
|
||||
|
||||
+23
-2
@@ -1,4 +1,5 @@
|
||||
import type { Metadata, Viewport } from "next";
|
||||
import { Fraunces, Manrope, Fragment_Mono } from "next/font/google";
|
||||
import "./globals.css";
|
||||
import { Providers } from "@/components/Providers";
|
||||
import ToastNotificationContainer from "@/components/notifications/ToastNotification";
|
||||
@@ -6,6 +7,26 @@ import CookieConsentBanner from "@/components/legal/CookieConsentBanner";
|
||||
|
||||
const BASE_URL = process.env.NEXT_PUBLIC_SITE_URL ?? "https://routecommerce.com";
|
||||
|
||||
const fraunces = Fraunces({
|
||||
subsets: ["latin"],
|
||||
display: "swap",
|
||||
variable: "--font-fraunces",
|
||||
axes: ["SOFT", "WONK", "opsz"],
|
||||
});
|
||||
|
||||
const manrope = Manrope({
|
||||
subsets: ["latin"],
|
||||
display: "swap",
|
||||
variable: "--font-manrope",
|
||||
});
|
||||
|
||||
const fragmentMono = Fragment_Mono({
|
||||
subsets: ["latin"],
|
||||
display: "swap",
|
||||
variable: "--font-fragment-mono",
|
||||
weight: "400",
|
||||
});
|
||||
|
||||
export const viewport: Viewport = {
|
||||
width: "device-width",
|
||||
initialScale: 1,
|
||||
@@ -50,8 +71,8 @@ export default function RootLayout({
|
||||
children: React.ReactNode;
|
||||
}>) {
|
||||
return (
|
||||
<html lang="en" suppressHydrationWarning>
|
||||
<body>
|
||||
<html lang="en" suppressHydrationWarning className={`${fraunces.variable} ${manrope.variable} ${fragmentMono.variable}`}>
|
||||
<body className="font-sans">
|
||||
<Providers>{children}</Providers>
|
||||
<ToastNotificationContainer />
|
||||
<CookieConsentBanner />
|
||||
|
||||
Reference in New Issue
Block a user