feat(orion): extend report layout settings to version 1.1
This commit is contained in:
parent
12e1761a5b
commit
613ffdc8b7
591 changed files with 3601 additions and 999 deletions
|
|
@ -45,28 +45,53 @@ export default function QuickStartValidationPage() {
|
|||
if (!data) {
|
||||
return;
|
||||
}
|
||||
if (data.locations.length === 1) {
|
||||
setSelectedLocationId(data.locations[0].id);
|
||||
}
|
||||
if (data.contacts.length === 1) {
|
||||
setSelectedContactId(data.contacts[0].id);
|
||||
}
|
||||
if (data.devices.length === 1) {
|
||||
setSelectedDeviceId(data.devices[0].id);
|
||||
}
|
||||
if (validationType === "Revalidierung" && data.devices.length > 0 && !selectedDeviceId) {
|
||||
const previousDevice = data.validations[0]?.device_id;
|
||||
if (previousDevice) {
|
||||
setSelectedDeviceId(previousDevice);
|
||||
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;
|
||||
}
|
||||
}, [customerData.data, selectedDeviceId, validationType]);
|
||||
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 selectedLocation = customerData.data?.locations.find((item) => item.id === selectedLocationId) ?? null;
|
||||
const selectedContact = customerData.data?.contacts.find((item) => item.id === selectedContactId) ?? 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;
|
||||
|
|
@ -99,10 +124,25 @@ export default function QuickStartValidationPage() {
|
|||
const customerCards = customers.data?.items ?? [];
|
||||
const canCreate =
|
||||
Boolean(selectedCustomerId) &&
|
||||
Boolean(selectedDeviceId) &&
|
||||
(customerData.data?.locations.length ?? 0) > 0 &&
|
||||
((customerData.data?.locations.length ?? 0) === 1 ? Boolean(selectedLocationId) : Boolean(selectedLocationId)) &&
|
||||
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 (
|
||||
<div className="space-y-6">
|
||||
|
|
@ -224,8 +264,26 @@ export default function QuickStartValidationPage() {
|
|||
<div className="rounded-lg border border-border bg-surface p-5 shadow-soft lg:col-span-2">
|
||||
<h2 className="text-xl font-semibold">4. Übernahme vorhandener Daten</h2>
|
||||
<div className="mt-4 grid gap-4 md:grid-cols-2">
|
||||
<InfoCard label="Standort" value={selectedLocation ? selectedLocation.name : customerData.data?.locations.length === 1 ? "Automatisch übernommen" : "Bitte auswählen"} />
|
||||
<InfoCard label="Ansprechpartner" value={selectedContact ? selectedContact.full_name : customerData.data?.contacts.length === 1 ? "Automatisch übernommen" : "Bitte auswählen"} />
|
||||
<SelectionCard
|
||||
label="Standort"
|
||||
value={selectedLocationId}
|
||||
placeholder="Bitte auswählen"
|
||||
emptyText={selectedCustomerId ? "Kein Standort für diesen Kunden vorhanden." : "Bitte zuerst einen Kunden auswählen."}
|
||||
options={locations.map((item) => ({ 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
|
||||
/>
|
||||
<SelectionCard
|
||||
label="Ansprechpartner"
|
||||
value={selectedContactId}
|
||||
placeholder="Optional auswählen"
|
||||
emptyText={selectedCustomerId ? "Kein Ansprechpartner für diesen Kunden vorhanden." : "Bitte zuerst einen Kunden auswählen."}
|
||||
options={contacts.map((item) => ({ value: item.id, label: [item.full_name, item.function].filter(Boolean).join(" · ") }))}
|
||||
onChange={setSelectedContactId}
|
||||
/>
|
||||
<InfoCard label="Prüfer" value={currentExaminer} />
|
||||
<InfoCard label="Vorherige Validierung" value={latestValidation ? latestValidation.report_number : "Keine vorhanden"} />
|
||||
</div>
|
||||
|
|
@ -261,7 +319,7 @@ export default function QuickStartValidationPage() {
|
|||
<button
|
||||
type="button"
|
||||
disabled={!canCreate}
|
||||
title={!canCreate ? "Bitte Kunde und Gerät auswählen" : undefined}
|
||||
title={!canCreate ? disabledReason : undefined}
|
||||
onClick={() => createMutation.mutate()}
|
||||
className="btn btn-primary h-12 min-w-64"
|
||||
>
|
||||
|
|
@ -282,3 +340,38 @@ function InfoCard({ label, value }: { label: string; value: string }) {
|
|||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
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 (
|
||||
<label className="block rounded-lg border border-border bg-white p-4 transition hover:border-primary/40 focus-within:border-primary focus-within:ring-2 focus-within:ring-primary/15">
|
||||
<span className="text-xs uppercase tracking-wide text-text-light">{label}{required && " *"}</span>
|
||||
<select
|
||||
value={value}
|
||||
onChange={(event) => onChange(event.target.value)}
|
||||
disabled={disabled}
|
||||
className="mt-2 h-11 w-full rounded-lg border border-border bg-background px-3 text-sm font-medium text-text outline-none transition hover:bg-white focus:border-primary disabled:cursor-not-allowed disabled:bg-border/30 disabled:text-text-light"
|
||||
>
|
||||
<option value="">{disabled ? emptyText : placeholder}</option>
|
||||
{options.map((item) => <option key={item.value} value={item.value}>{item.label}</option>)}
|
||||
</select>
|
||||
{disabled && <p className="mt-2 text-sm text-text-light">{emptyText}</p>}
|
||||
</label>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue