"use client"; import { useMutation, useQuery } from "@tanstack/react-query"; import { ArrowRight, Loader2, Search, Sparkles, UserRoundCheck } from "lucide-react"; import { useEffect, useMemo, useState } from "react"; import { useAuth } from "@/components/auth"; import { apiFetch, apiGet, Customer, Paginated, QuickStartCustomerData, ValidationItem } from "@/lib/api"; const validationTypeLabels: Record = { Erstvalidierung: "Erstvalidierung", Revalidierung: "Revalidierung", Leistungsbeurteilung: "Leistungsbeurteilung" }; export default function QuickStartValidationPage() { const { token, user } = useAuth(); const [search, setSearch] = useState(""); const [selectedCustomerId, setSelectedCustomerId] = useState(""); const [selectedLocationId, setSelectedLocationId] = useState(""); const [selectedContactId, setSelectedContactId] = useState(""); const [selectedDeviceId, setSelectedDeviceId] = useState(""); const [validationType, setValidationType] = useState("Erstvalidierung"); const [error, setError] = useState(""); const customers = useQuery({ queryKey: ["quickstart-customers", search, token], queryFn: () => apiGet>(`/customers?page=1&page_size=12${search.trim() ? `&search=${encodeURIComponent(search.trim())}` : ""}`, token ?? ""), enabled: Boolean(token) }); const customerData = useQuery({ queryKey: ["quickstart-customer-data", selectedCustomerId, token], queryFn: () => apiGet(`/customers/${selectedCustomerId}/quickstart-data`, token ?? ""), enabled: Boolean(token && selectedCustomerId) }); useEffect(() => { setSelectedLocationId(""); setSelectedContactId(""); setSelectedDeviceId(""); setError(""); }, [selectedCustomerId]); useEffect(() => { const data = customerData.data; if (!data) { return; } setSelectedLocationId((current) => { if (data.locations.length === 1) { return data.locations[0].id; } return current && data.locations.some((item) => item.id === current) ? current : ""; }); setSelectedContactId((current) => { if (data.contacts.length === 1) { return data.contacts[0].id; } return current && data.contacts.some((item) => item.id === current) ? current : ""; }); setSelectedDeviceId((current) => { if (data.devices.length === 1) { return data.devices[0].id; } if (current && data.devices.some((item) => item.id === current)) { return current; } if (validationType === "Revalidierung" || validationType === "Leistungsbeurteilung") { const previousDevice = data.validations.find((validation) => data.devices.some((device) => device.id === validation.device_id))?.device_id; return previousDevice ?? ""; } return ""; }); }, [customerData.data, validationType]); useEffect(() => { const data = customerData.data; if (!data || !selectedDeviceId || selectedLocationId) { return; } const device = data.devices.find((item) => item.id === selectedDeviceId); if (device?.location_id && data.locations.some((item) => item.id === device.location_id)) { setSelectedLocationId(device.location_id); } }, [customerData.data, selectedDeviceId, selectedLocationId]); const selectedCustomer = customers.data?.items.find((item) => item.id === selectedCustomerId) ?? customerData.data?.customer ?? null; const selectedDevice = customerData.data?.devices.find((item) => item.id === selectedDeviceId) ?? null; const currentExaminer = user ? `${user.first_name} ${user.last_name}` : "nicht angemeldet"; const locations = customerData.data?.locations ?? []; const contacts = customerData.data?.contacts ?? []; const devices = customerData.data?.devices ?? []; const hasValidLocation = Boolean(selectedLocationId && locations.some((item) => item.id === selectedLocationId)); const hasValidContact = !selectedContactId || contacts.some((item) => item.id === selectedContactId); const hasValidDevice = Boolean(selectedDeviceId && devices.some((item) => item.id === selectedDeviceId)); const latestValidation = useMemo(() => { if (!selectedDeviceId) { return null; } return customerData.data?.validations.find((item) => item.device_id === selectedDeviceId) ?? null; }, [customerData.data?.validations, selectedDeviceId]); const createMutation = useMutation({ mutationFn: async () => apiFetch( "/validations/quick-start", token ?? "", { method: "POST", body: JSON.stringify({ customer_id: selectedCustomerId, location_id: selectedLocationId || null, contact_id: selectedContactId || null, device_id: selectedDeviceId || null, validation_type: validationType }) } ), onSuccess: (created) => { window.location.replace(`/validations/${created.id}/edit`); }, onError: (err: Error) => setError(err.message) }); const customerCards = customers.data?.items ?? []; const canCreate = Boolean(selectedCustomerId) && Boolean(validationType) && Boolean(user) && hasValidDevice && hasValidLocation && hasValidContact && !createMutation.isPending; const disabledReason = !selectedCustomerId ? "Bitte Kunde auswählen" : !hasValidDevice ? "Bitte Gerät auswählen" : locations.length === 0 ? "Für den Kunden ist kein Standort vorhanden" : !hasValidLocation ? "Bitte Standort auswählen" : !hasValidContact ? "Bitte gültigen Ansprechpartner auswählen" : !user ? "Bitte anmelden" : undefined; return (

Quickstart

Neue Validierung starten

Wir fassen die wichtigsten Entscheidungen zusammen und öffnen danach direkt die bestehende Validierungsbearbeitung.

1 Kunde 2 Gerät 3 Validierungsart 4 Erstellen

1. Kunde

{selectedCustomer && Ausgewählt}
{customers.isError &&

Kunden konnten nicht geladen werden.

}
{customerCards.map((item) => { const active = item.id === selectedCustomerId; return ( ); })} {customers.isLoading &&

Kunden werden geladen...

} {!customers.isLoading && !customers.isError && customerCards.length === 0 &&

Keine Kunden gefunden.

}

2. Gerät

{selectedDevice && Ausgewählt}
{customerData.isError &&

Kundendaten konnten nicht geladen werden.

}
{(customerData.data?.devices ?? []).map((item) => { const active = item.id === selectedDeviceId; const latest = customerData.data?.validations.find((validation) => validation.device_id === item.id) ?? null; return ( ); })} {customerData.isLoading && selectedCustomerId &&

Geräte werden geladen...

} {selectedCustomerId && !customerData.isLoading && !customerData.isError && (customerData.data?.devices.length ?? 0) === 0 &&

Keine Geräte gefunden.

}

3. Validierungsart

{Object.entries(validationTypeLabels).map(([value, label]) => { const active = validationType === value; return ( ); })}

4. Übernahme vorhandener Daten

({ value: item.id, label: [item.name, item.room, item.city].filter(Boolean).join(" · ") }))} onChange={(value) => { setSelectedLocationId(value); setSelectedContactId(contacts.length === 1 ? contacts[0].id : ""); }} required /> ({ value: item.id, label: [item.full_name, item.function].filter(Boolean).join(" · ") }))} onChange={setSelectedContactId} />
{(customerData.data?.validations.length ?? 0) > 0 && (

Letzte Validierungen

{customerData.data?.validations.slice(0, 3).map((item) => (

{item.report_number}

{item.validation_type ?? "Validierung"} · {item.performed_on ?? "nicht erfasst"}

{item.next_validation_on ? `Naechste Revalidierung: ${item.next_validation_on}` : "Naechste Revalidierung nicht erfasst"}

))}
)} {selectedCustomer && (
{customerData.isLoading ? "Vorhandene Daten werden geladen..." : "Vorhandene Daten stehen bereit."}
)}
{error ?

{error}

:

Nach dem Erstellen öffnet sich direkt die Bearbeitungsseite.

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

{label}

{value}

); } function SelectionCard({ label, value, options, placeholder, emptyText, onChange, required = false }: { label: string; value: string; options: { value: string; label: string }[]; placeholder: string; emptyText: string; onChange: (value: string) => void; required?: boolean; }) { const disabled = options.length === 0; return ( ); }