mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-27 10:52:53 +00:00
75 lines
2.7 KiB
TypeScript
75 lines
2.7 KiB
TypeScript
import { useQuery } from "@tanstack/react-query";
|
|
import { useMemo } from "react";
|
|
|
|
import { api } from "@/services/api";
|
|
|
|
/** Dropdown-settings code holding the admin-managed IMPORT run numbers. */
|
|
export const IMPORT_TRAIN_NUMBERS_CODE = "import_train_numbers";
|
|
|
|
export interface ImportTrainNumberOption {
|
|
value: string;
|
|
label: string;
|
|
disabled?: boolean;
|
|
}
|
|
|
|
/**
|
|
* Selectable IMPORT run numbers for the Train Builder, sourced solely from the
|
|
* admin-managed `import_train_numbers` dropdown setting — admins add and remove
|
|
* runs from /dashboard/dropdown-settings and the pickers follow. There is no
|
|
* hardcoded fallback on purpose: a missing setting must be visible (see
|
|
* `settingMissing`) rather than masked by stale defaults.
|
|
*
|
|
* Numbers already claimed by an existing train are kept in the list but
|
|
* disabled and tagged "in use". Pass `currentNumber` when editing a train so
|
|
* its own number stays pickable, and so a legacy number that was removed from
|
|
* the setting still renders.
|
|
*/
|
|
export function useImportTrainNumberOptions(currentNumber?: string | null) {
|
|
const settingQuery = useQuery(
|
|
api.dropdownSettings.getByCode.queryOptions({
|
|
input: { code: IMPORT_TRAIN_NUMBERS_CODE },
|
|
staleTime: 5 * 60_000,
|
|
retry: false,
|
|
}),
|
|
);
|
|
const usedQuery = useQuery(
|
|
api.trainBuilder.usedTrainNumbers.queryOptions({ staleTime: 30_000 }),
|
|
);
|
|
|
|
const options = useMemo<ImportTrainNumberOption[]>(() => {
|
|
const base = [...(settingQuery.data?.children ?? [])]
|
|
.filter((option) => !option.disabled)
|
|
.sort((a, b) => (a.order ?? 0) - (b.order ?? 0))
|
|
.map((option) => ({
|
|
value: option.value,
|
|
label: option.label || option.value,
|
|
}));
|
|
|
|
const used = new Set(usedQuery.data?.importTrainNumbers ?? []);
|
|
if (currentNumber) used.delete(currentNumber);
|
|
|
|
const items: ImportTrainNumberOption[] = base.map((option) =>
|
|
used.has(option.value)
|
|
? { ...option, label: `${option.label} — in use`, disabled: true }
|
|
: option,
|
|
);
|
|
if (currentNumber && !items.some((option) => option.value === currentNumber)) {
|
|
items.unshift({ value: currentNumber, label: currentNumber });
|
|
}
|
|
return items;
|
|
}, [settingQuery.data, usedQuery.data, currentNumber]);
|
|
|
|
const settingMissing = settingQuery.isError;
|
|
|
|
return {
|
|
options,
|
|
isLoading: settingQuery.isLoading || usedQuery.isLoading,
|
|
/** True when the dropdown setting is absent — surfaced instead of silently
|
|
* falling back, so a broken config is visible rather than looking normal. */
|
|
settingMissing,
|
|
emptyMessage: settingMissing
|
|
? `Dropdown setting "${IMPORT_TRAIN_NUMBERS_CODE}" is missing — create it in Dropdown Settings`
|
|
: "No free run numbers — add more in Dropdown Settings",
|
|
};
|
|
}
|