feat(05-02): /admin/offers RSC page + ServiceCheckboxList + NavBar update

- Create src/app/admin/offers/page.tsx — RSC with macro/micro/service CRUD sections
- Create src/components/admin/offers/ServiceCheckboxList.tsx — client checkbox UI for service-to-micro assignment
- Update src/components/admin/NavBar.tsx — add Forecast and Offerte links (order: Statistiche | Forecast | Catalogo | Offerte | Impostazioni)
This commit is contained in:
2026-05-30 16:22:19 +02:00
parent 56f084912a
commit ce8f95a163
3 changed files with 295 additions and 0 deletions
+6
View File
@@ -18,9 +18,15 @@ export function NavBar() {
<Link href="/admin/analytics" className="text-sm text-white/70 hover:text-white transition-colors">
Statistiche
</Link>
<Link href="/admin/forecast" className="text-sm text-white/70 hover:text-white transition-colors">
Forecast
</Link>
<Link href="/admin/catalog" className="text-sm text-white/70 hover:text-white transition-colors">
Catalogo
</Link>
<Link href="/admin/offers" className="text-sm text-white/70 hover:text-white transition-colors">
Offerte
</Link>
<Link href="/admin/impostazioni" className="text-sm text-white/70 hover:text-white transition-colors">
Impostazioni
</Link>
@@ -0,0 +1,51 @@
"use client";
import { useState, useTransition } from "react";
import { useRouter } from "next/navigation";
import { updateMicroOfferServices } from "@/app/admin/offers/actions";
export function ServiceCheckboxList({
allServices,
assignedIds,
microId,
}: {
allServices: Array<{ id: string; name: string; price: string }>;
assignedIds: string[];
microId: string;
}) {
const [selected, setSelected] = useState(new Set(assignedIds));
const [isPending, startTransition] = useTransition();
const router = useRouter();
function toggle(serviceId: string) {
const next = new Set(selected);
if (next.has(serviceId)) next.delete(serviceId);
else next.add(serviceId);
setSelected(next);
startTransition(async () => {
await updateMicroOfferServices(microId, [...next]);
router.refresh();
});
}
return (
<div className="space-y-1">
{allServices.map((svc) => (
<label key={svc.id} className="flex items-center gap-2 cursor-pointer text-sm">
<input
type="checkbox"
checked={selected.has(svc.id)}
onChange={() => toggle(svc.id)}
disabled={isPending}
className="rounded"
/>
<span>{svc.name}</span>
<span className="ml-auto text-xs text-[#71717a]">{parseFloat(svc.price).toFixed(2)}</span>
</label>
))}
{allServices.length === 0 && (
<p className="text-xs text-[#71717a]">Nessun servizio nel catalogo ancora.</p>
)}
</div>
);
}