Files
edr-platform/apps/edr-freight-web/backoffice/src/hooks/useImportTrainNumberOptions.ts

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",
};
}