diff --git a/design-reference/DESIGN-SYSTEM.md b/design-reference/DESIGN-SYSTEM.md index 10ebe20..a41750d 100644 --- a/design-reference/DESIGN-SYSTEM.md +++ b/design-reference/DESIGN-SYSTEM.md @@ -220,6 +220,25 @@ righe `py-4 px-6` / `divide-y divide-border` / `hover:bg-muted/40`. (singolare/plurale gestiti). - Le righe archiviate restano `opacity-60` con pill "Archiviato". +### Offerte (lista) notes + +`/admin/offers` migrata a "Quiet Luxury" (replica `design-reference/pagina-offerte`). +Griglia responsive di card `bg-card rounded-xl border-border p-6 shadow-card` +(`hover:shadow-card-hover`), `md:grid-cols-2 lg:grid-cols-3`. + +- **Header**: `PageHeader` "Offerte" + sottotitolo, azione "+ Nuova Offerta" + (`Button` primario) che espande un form inline (`Input` nome + "Crea"). +- **Filtri**: pill categoria rettangolari (`rounded-lg px-4 py-2`) — attiva + `bg-primary text-primary-foreground`, inattiva `border-border bg-card + text-muted-foreground hover:bg-muted`. "Tutti" + `categoryOptions` dinamiche. + A destra checkbox "Mostra offerte archiviate". +- **Card**: nome interno + descrizione muted + badge categoria colorato per tipo + (Retainer→blue, Entry→purple, Signature→amber, tutti con variante dark) via + helper `categoryBadgeClass`. Le archiviate sono `opacity-60` con pill "Archiviata". +- **Tabella tier**: `border-border rounded-lg`, header uppercase muted + (Tier · Servizi · Pubblico), righe `font-mono` `divide-y divide-border`; solo i + tier con `servicesTotal > 0` o `public_price` valorizzato; "Pubblico" assente → `—`. + ### Client Portal restyle notes The `/client/[token]` portal was migrated to the same "Quiet Luxury" tokens diff --git a/src/components/admin/offers/OfferListClient.tsx b/src/components/admin/offers/OfferListClient.tsx index 636c0f0..cdac086 100644 --- a/src/components/admin/offers/OfferListClient.tsx +++ b/src/components/admin/offers/OfferListClient.tsx @@ -4,16 +4,28 @@ import { useState, useMemo, useTransition } from "react"; import { useRouter } from "next/navigation"; import Link from "next/link"; import { createOfferMacro } from "@/app/admin/offers/actions"; -import type { OfferListCard, OfferListTier } from "@/lib/offer-queries"; +import type { OfferListCard } from "@/lib/offer-queries"; import { Button } from "@/components/ui/button"; -import { Badge } from "@/components/ui/badge"; import { Input } from "@/components/ui/input"; import { PageHeader } from "@/components/admin/PageHeader"; +import { cn } from "@/lib/utils"; function formatEuro(value: number): string { return `€${value.toLocaleString("it-IT", { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`; } +/** Category → pill colors, light/dark. Falls back to a neutral badge. */ +function categoryBadgeClass(category: string): string { + const key = category.toLowerCase(); + if (key.includes("retainer")) + return "bg-blue-50 text-blue-600 border-blue-100 dark:bg-blue-950/40 dark:text-blue-300 dark:border-blue-900"; + if (key.includes("entry")) + return "bg-purple-50 text-purple-600 border-purple-100 dark:bg-purple-950/40 dark:text-purple-300 dark:border-purple-900"; + if (key.includes("signature")) + return "bg-amber-50 text-amber-700 border-amber-100 dark:bg-amber-950/40 dark:text-amber-300 dark:border-amber-900"; + return "bg-muted text-muted-foreground border-border"; +} + export function OfferListClient({ cards, categoryOptions, @@ -46,18 +58,14 @@ export function OfferListClient({ } const createCta = ( -