diff --git a/src/components/admin/catalog/ServiceTable.tsx b/src/components/admin/catalog/ServiceTable.tsx index 992c9e5..5252658 100644 --- a/src/components/admin/catalog/ServiceTable.tsx +++ b/src/components/admin/catalog/ServiceTable.tsx @@ -2,24 +2,30 @@ import { useState, useTransition } from "react"; import { useRouter } from "next/navigation"; -import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; -import { Label } from "@/components/ui/label"; -import { updateService, toggleServiceActive } from "@/app/admin/catalog/actions"; -import type { Service } from "@/db/schema"; +import { EditableCell } from "@/components/ui/editable-cell"; +import { TagMultiSelect } from "@/components/ui/tag-multi-select"; +import { updateServiceField, quickAddService } from "@/app/admin/catalog/actions"; +import type { ServiceWithTags } from "@/lib/admin-queries"; -function ServiceRow({ service }: { service: Service }) { - const [editing, setEditing] = useState(false); - const [error, setError] = useState(null); - const [, startTransition] = useTransition(); +function formatPrice(raw: string): string { + const num = parseFloat(raw); + return `€${(isNaN(num) ? 0 : num).toLocaleString("it-IT", { minimumFractionDigits: 2 })}`; +} + +function ServiceRow({ service }: { service: ServiceWithTags }) { const router = useRouter(); + const [, startTransition] = useTransition(); + const [error, setError] = useState(null); - function handleSave(fd: FormData) { + function saveField( + field: "name" | "description" | "category" | "unit_price" | "active", + value: string + ) { setError(null); startTransition(async () => { try { - await updateService(service.id, fd); - setEditing(false); + await updateServiceField(service.id, field, value); router.refresh(); } catch (e) { setError(e instanceof Error ? e.message : "Errore nel salvataggio"); @@ -27,148 +33,151 @@ function ServiceRow({ service }: { service: Service }) { }); } - function handleToggle() { - startTransition(async () => { - await toggleServiceActive(service.id, !service.active); - router.refresh(); - }); - } - - if (editing) { - return ( - - -
-
-
- - -
-
- - -
-
- - -
-
- - -
-
- {error &&

{error}

} -
- - -
-
- - - ); - } - return ( - {service.name} - - {service.description ?? "—"} + + saveField("name", v)} + /> - - {service.category ?? "—"} + + saveField("description", v)} + /> - - €{parseFloat(service.unit_price).toLocaleString("it-IT", { minimumFractionDigits: 2 })} + + saveField("category", v)} + /> - - {service.active ? ( - - Attivo - - ) : ( - - Disattivato - - )} + + saveField("unit_price", v)} + /> - -
- - -
+ + router.refresh()} + /> + + saveField("active", v)} + /> + + {error && ( + + {error} + + )} ); } -export function ServiceTable({ services }: { services: Service[] }) { +function QuickAddRow() { + const [name, setName] = useState(""); + const [, startTransition] = useTransition(); + const [error, setError] = useState(null); + const router = useRouter(); + + function handleKeyDown(e: React.KeyboardEvent) { + if (e.key !== "Enter") return; + const trimmed = name.trim(); + if (!trimmed) return; + e.preventDefault(); + setError(null); + startTransition(async () => { + try { + await quickAddService(trimmed); + setName(""); + router.refresh(); + } catch (err) { + setError(err instanceof Error ? err.message : "Errore nel salvataggio"); + } + }); + } + + return ( + + + setName(e.target.value)} + onKeyDown={handleKeyDown} + placeholder="+ Aggiungi servizio" + className="border-0 bg-transparent shadow-none h-8 text-sm placeholder:text-[#71717a] focus-visible:ring-1 focus-visible:ring-primary" + /> + {error &&

{error}

} + + + + ); +} + +const COLUMN_HEADERS = ["Nome", "Descrizione", "Categoria", "Prezzo", "Tag", "Stato"]; + +export function ServiceTable({ services }: { services: ServiceWithTags[] }) { + const activeServices = services.filter((s) => s.active); + const inactiveServices = services.filter((s) => !s.active); + return (
- - - - - - - - - - - - - {services.map((s) => ( - - ))} - -
NomeDescrizioneCategoriaPrezzoStato
+
+ + + + {COLUMN_HEADERS.map((header) => ( + + ))} + + + + {activeServices.map((s) => ( + + ))} + + + + {inactiveServices.length > 0 && ( + <> + + + + {inactiveServices.map((s) => ( + + ))} + + )} + +
+ {header} +
+ Servizi disattivati +
+
); }