From 4e703d706847119d4d1432ec13395d425d190fa3 Mon Sep 17 00:00:00 2001 From: Simone Cavalli Date: Thu, 14 May 2026 21:43:41 +0200 Subject: [PATCH] feat(01-04): design tokens Tailwind v4 + wire ClientDashboard in page.tsx - globals.css: aggiunto @theme con palette light & clean (primary, secondary, tertiary, bg-subtle, border-light, accent, success, warning, info) - app/c/[token]/page.tsx: import ClientDashboard, generateMetadata dinamico, React.cache() per deduplicare DB call tra metadata e render --- src/app/c/[token]/page.tsx | 40 ++++++++++++++++++--------- src/app/globals.css | 56 ++++++++++++++++++++++++++------------ 2 files changed, 66 insertions(+), 30 deletions(-) diff --git a/src/app/c/[token]/page.tsx b/src/app/c/[token]/page.tsx index 06c9738..1133da4 100644 --- a/src/app/c/[token]/page.tsx +++ b/src/app/c/[token]/page.tsx @@ -1,28 +1,42 @@ +import { cache } from 'react'; import { getClientView } from '@/lib/client-view'; +import { ClientDashboard } from '@/components/client-dashboard'; import { notFound } from 'next/navigation'; -export const revalidate = 60; // ISR: revalidate every 60 seconds +export const revalidate = 60; // ISR: revalidate ogni 60 secondi -export default async function ClientDashboard({ +// React cache deduplicates DB calls within the same render +const getCachedClientView = cache(getClientView); + +export async function generateMetadata({ params, }: { params: Promise<{ token: string }>; }) { const { token } = await params; - const view = await getClientView(token); + const view = await getCachedClientView(token); + + if (!view) { + return { title: 'Not Found' }; + } + + return { + title: `${view.client.brand_name} — Stato Progetto | iamcavalli`, + description: view.client.brief || 'Dashboard stato progetto', + }; +} + +export default async function ClientPage({ + params, +}: { + params: Promise<{ token: string }>; +}) { + const { token } = await params; + const view = await getCachedClientView(token); if (!view) { notFound(); } - return ( -
- {/* Placeholder: Dashboard UI will be built in Plan 04 */} -
-

{view.client.brand_name}

-

{view.client.brief}

-

Token: {token}

-
-
- ); + return ; } \ No newline at end of file diff --git a/src/app/globals.css b/src/app/globals.css index a2dc41e..0aa95a5 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -1,26 +1,48 @@ @import "tailwindcss"; -:root { - --background: #ffffff; - --foreground: #171717; -} - +/* ========================================================= + Design tokens — light & clean palette (Tailwind v4 @theme) + ========================================================= */ @theme inline { - --color-background: var(--background); - --color-foreground: var(--foreground); - --font-sans: var(--font-geist-sans); + /* Colori base */ + --color-background: #ffffff; + --color-foreground: #171717; + + /* Font */ + --font-sans: var(--font-geist-sans), system-ui, -apple-system, BlinkMacSystemFont, + "Segoe UI", Roboto, "Helvetica Neue", sans-serif; --font-mono: var(--font-geist-mono); + + /* Palette brand iamcavalli — light & clean */ + --color-primary: #1a1a1a; /* charcoal per testo principale */ + --color-secondary: #666666; /* grigio medio per testo secondario */ + --color-tertiary: #999999; /* grigio chiaro per hint e timestamp */ + --color-bg-subtle: #f9f9f9; /* grigio molto chiaro per sfondi sezione */ + --color-border-light: #e5e5e5; /* bordo sottile */ + --color-accent: #0066cc; /* blu accent */ + --color-success: #16a34a; /* verde per done/saldato */ + --color-warning: #ca8a04; /* giallo per in_progress/inviata */ + --color-info: #2563eb; /* blu per pending/da_saldare */ } -@media (prefers-color-scheme: dark) { - :root { - --background: #0a0a0a; - --foreground: #ededed; - } +/* ========================================================= + Base styles + ========================================================= */ +*, +*::before, +*::after { + box-sizing: border-box; +} + +html { + scroll-behavior: smooth; } body { - background: var(--background); - color: var(--foreground); - font-family: Arial, Helvetica, sans-serif; -} + background-color: #ffffff; + color: #171717; + font-family: var(--font-sans); + line-height: 1.6; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} \ No newline at end of file