"use client"; import { useMemo, useState, useTransition, type ChangeEventHandler, } from "react"; import { Pencil, Plus, Trash2 } from "lucide-react"; import { toast } from "sonner"; import { Button } from "@/components/ui/button"; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger, } from "@/components/ui/dialog"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { updateFamilyAction } from "./actions"; import { InvitationStatus } from "./invitation-status"; import type { FamilyInvitationView } from "@/lib/family-invitation-view"; type EditableParent = { id: string; firstName: string; lastName: string; email: string; invitation?: FamilyInvitationView; }; type EditableChild = { id: string; firstName: string; lastName: string; }; type DraftParent = EditableParent & { kind: "existing" | "new"; }; type DraftChild = EditableChild & { kind: "existing" | "new"; }; type EditableFamily = { id: string; name: string; parents: EditableParent[]; children: EditableChild[]; }; export function EditFamilyDialog({ family }: { family: EditableFamily }) { const [open, setOpen] = useState(false); const [isPending, startTransition] = useTransition(); const initialParents = useMemo( () => family.parents.map((parent) => ({ ...parent, kind: "existing" as const, })), [family.parents], ); const initialChildren = useMemo( () => family.children.map((child) => ({ ...child, kind: "existing" as const, })), [family.children], ); const [parents, setParents] = useState(initialParents); const [children, setChildren] = useState(initialChildren); const [removedChildIds, setRemovedChildIds] = useState([]); function resetState() { setParents(initialParents); setChildren(initialChildren); setRemovedChildIds([]); } function addParent() { if (parents.length >= 2) return; setParents((current) => [ ...current, { id: `new-parent-${crypto.randomUUID()}`, firstName: "", lastName: "", email: "", kind: "new", }, ]); } function removeNewParent(parent: DraftParent) { if (parent.kind !== "new") return; setParents((current) => current.filter((item) => item.id !== parent.id)); } function addChild() { setChildren((current) => [ ...current, { id: `new-child-${crypto.randomUUID()}`, firstName: "", lastName: "", kind: "new", }, ]); } function removeChild(child: DraftChild) { setChildren((current) => current.filter((item) => item.id !== child.id)); if (child.kind === "existing") { setRemovedChildIds((current) => [...current, child.id]); } } function handleSubmit(formData: FormData) { const payload = { familyId: family.id, familyName: String(formData.get("familyName") ?? ""), parents: parents .filter((parent) => parent.kind === "existing") .map((parent) => ({ id: parent.id, firstName: String(formData.get(`parentFirstName_${parent.id}`) ?? ""), lastName: String(formData.get(`parentLastName_${parent.id}`) ?? ""), email: String(formData.get(`parentEmail_${parent.id}`) ?? ""), })), newParents: parents .filter((parent) => parent.kind === "new") .map((parent) => ({ firstName: String(formData.get(`parentFirstName_${parent.id}`) ?? ""), lastName: String(formData.get(`parentLastName_${parent.id}`) ?? ""), email: String(formData.get(`parentEmail_${parent.id}`) ?? ""), })), children: children .filter((child) => child.kind === "existing") .map((child) => ({ id: child.id, firstName: String(formData.get(`childFirstName_${child.id}`) ?? ""), lastName: String(formData.get(`childLastName_${child.id}`) ?? ""), })), newChildren: children .filter((child) => child.kind === "new") .map((child) => ({ firstName: String(formData.get(`childFirstName_${child.id}`) ?? ""), lastName: String(formData.get(`childLastName_${child.id}`) ?? ""), })), removedChildIds, }; startTransition(async () => { const result = await updateFamilyAction(payload); if (result.error) { toast.error(result.error); return; } if (result.warning) toast.warning(result.warning); else toast.success("Familie aktualisiert. Geänderte E-Mail-Adressen müssen über einen neuen Einladungslink bestätigt werden."); setOpen(false); setRemovedChildIds([]); }); } return ( { if (isPending) return; resetState(); setOpen(nextOpen); }} >
{ event.preventDefault(); handleSubmit(new FormData(event.currentTarget)); }} > Familie bearbeiten Aktualisiere Haushalt, Elternteile und Kinder.
Elternteile {parents.length < 2 && ( )}
{parents.map((parent, index) => (

Elternteil {index + 1}

{parent.kind === "new" && ( )}
{ const email = event.target.value; setParents((current) => current.map((item) => item.id === parent.id ? { ...item, email } : item, ), ); }} />
{parent.kind === "existing" && parent.invitation && ( item.id === parent.id) ?.email } /> )} {parent.kind === "existing" && parent.invitation?.status !== "active" && parent.email !== family.parents.find((item) => item.id === parent.id) ?.email && (

Beim Speichern wird eine neue Einladung an die geänderte Adresse versendet.

)}
))}
Kinder
{children.length === 0 ? (

Keine Kinder verknüpft.

) : ( children.map((child, index) => (

Kind {index + 1}

)) )}
); } function Field({ id, name, label, type = "text", defaultValue, onChange, }: { id: string; name: string; label: string; type?: string; defaultValue: string; onChange?: ChangeEventHandler; }) { return (
); }