"use client"; import { useCallback, useEffect, useState } from "react"; import Link from "next/link"; import { useParams, useRouter } from "next/navigation"; import { ArrowLeft, Edit, Plus, Trash2 } from "lucide-react"; import ConfirmDialog from "@/components/common/ConfirmDialog"; import DetailSection from "@/components/common/DetailSection"; import { useToast } from "@/components/common/ToastProvider"; import { Button } from "@/components/ui/button"; import CustomerContactFormDialog from "@/components/customers/CustomerContactFormDialog"; import CustomerFormDialog from "@/components/customers/CustomerFormDialog"; import CustomerStatusBadge from "@/components/customers/CustomerStatusBadge"; import { api } from "@/lib/api"; import { hasPermission } from "@/lib/permissions"; import type { CurrentUser } from "@/types/rbac"; import type { Customer, CustomerContact, CustomerContactPayload, CustomerPayload } from "@/types/customer"; function getErrorMessage(error: unknown) { if (typeof error === "object" && error !== null && "response" in error) { const response = (error as { response?: { data?: { detail?: string } } }).response; return response?.data?.detail ?? "Aktion konnte nicht abgeschlossen werden"; } return "Aktion konnte nicht abgeschlossen werden"; } function formatDateTime(value: string) { return new Intl.DateTimeFormat("de-DE", { dateStyle: "medium", timeStyle: "short", }).format(new Date(value)); } export default function CustomerDetailPage() { const { showToast } = useToast(); const params = useParams<{ id: string }>(); const router = useRouter(); const [customer, setCustomer] = useState(null); const [currentUser, setCurrentUser] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(""); const [pending, setPending] = useState(false); const [formOpen, setFormOpen] = useState(false); const [formError, setFormError] = useState(""); const [contactOpen, setContactOpen] = useState(false); const [contactError, setContactError] = useState(""); const [selectedContact, setSelectedContact] = useState(null); const [deleteContact, setDeleteContact] = useState(null); const [deleteCustomerOpen, setDeleteCustomerOpen] = useState(false); const [deleteError, setDeleteError] = useState(""); const loadCustomer = useCallback(async () => { try { const [customerResponse, meResponse] = await Promise.all([ api.get(`/customers/${params.id}`), api.get("/me"), ]); setCustomer(customerResponse.data); setCurrentUser(meResponse.data); } catch (err) { setError(getErrorMessage(err)); } finally { setLoading(false); } }, [params.id]); useEffect(() => { queueMicrotask(() => { void loadCustomer(); }); }, [loadCustomer]); async function saveCustomer(payload: CustomerPayload) { if (!customer) { return; } setPending(true); setFormError(""); try { const response = await api.put(`/customers/${customer.id}`, payload); setCustomer(response.data); setFormOpen(false); showToast({ type: "success", title: "Kunde aktualisiert", description: response.data.company_name }); } catch (err) { const message = getErrorMessage(err); setFormError(message); showToast({ type: "error", title: "Kunde konnte nicht gespeichert werden", description: message }); } finally { setPending(false); } } function openContactDialog(contact: CustomerContact | null) { setSelectedContact(contact); setContactError(""); setContactOpen(true); } async function saveContact(payload: CustomerContactPayload) { if (!customer) { return; } setPending(true); setContactError(""); try { if (selectedContact) { await api.put(`/customers/${customer.id}/contacts/${selectedContact.id}`, payload); showToast({ type: "success", title: "Ansprechpartner aktualisiert" }); } else { await api.post(`/customers/${customer.id}/contacts`, payload); showToast({ type: "success", title: "Ansprechpartner erstellt" }); } const response = await api.get(`/customers/${customer.id}`); setCustomer(response.data); setContactOpen(false); } catch (err) { const message = getErrorMessage(err); setContactError(message); showToast({ type: "error", title: "Ansprechpartner konnte nicht gespeichert werden", description: message }); } finally { setPending(false); } } async function confirmContactDelete() { if (!customer || !deleteContact) { return; } setPending(true); setDeleteError(""); try { await api.delete(`/customers/${customer.id}/contacts/${deleteContact.id}`); const response = await api.get(`/customers/${customer.id}`); setCustomer(response.data); showToast({ type: "success", title: "Ansprechpartner gelöscht", description: `${deleteContact.first_name} ${deleteContact.last_name}` }); setDeleteContact(null); } catch (err) { const message = getErrorMessage(err); setDeleteError(message); showToast({ type: "error", title: "Ansprechpartner konnte nicht gelöscht werden", description: message }); } finally { setPending(false); } } async function confirmCustomerDelete() { if (!customer) { return; } setPending(true); setDeleteError(""); try { const deletedCustomerName = customer.company_name; await api.delete(`/customers/${customer.id}`); showToast({ type: "success", title: "Kunde gelöscht", description: deletedCustomerName }); router.push("/customers"); } catch (err) { const message = getErrorMessage(err); setDeleteError(message); showToast({ type: "error", title: "Kunde konnte nicht gelöscht werden", description: message }); } finally { setPending(false); } } if (loading) { return
Kunde wird geladen...
; } if (error || !customer) { return (
Zurück zur Kundenliste
{error || "Kunde nicht gefunden"}
); } return (
Zurück zur Kundenliste

{customer.company_name}

{customer.customer_number}

{hasPermission(currentUser, "customers.update") && ( )} {hasPermission(currentUser, "customers.delete") && ( )}
{customer.addresses.length === 0 ? (

Noch keine Adressen vorhanden.

) : (
{customer.addresses.map((address) => (
{address.type} {address.is_primary && Primär}

{address.street || "-"}

{address.postal_code} {address.city}

{address.state}

{address.country}

))}
)}
openContactDialog(null)}> Ansprechpartner )} > {customer.contacts.length === 0 ? (

Noch keine Ansprechpartner vorhanden.

) : (
{customer.contacts.map((contact) => (

{contact.first_name} {contact.last_name}

{contact.position || "-"}

{contact.is_primary && Primär}

{contact.email || "-"}

{contact.phone || contact.mobile || "-"}

{hasPermission(currentUser, "customers.update") && (
)}
))}
)}

{customer.notes || "Noch keine Notizen vorhanden."}

{ if (!open) { setDeleteContact(null); setDeleteError(""); } }} onConfirm={confirmContactDelete} > {deleteContact &&

{deleteContact.first_name} {deleteContact.last_name}

} {deleteError &&

{deleteError}

}
{ setDeleteCustomerOpen(open); if (!open) { setDeleteError(""); } }} onConfirm={confirmCustomerDelete} >

{customer.customer_number} · {customer.company_name}

{deleteError &&

{deleteError}

}
); } function Detail({ label, value }: { label: string; value: string }) { return (
{label}
{value}
); }