import { useState } from "react"; import { useTranslation } from "react-i18next"; import type { components } from "../api/schema"; import { useFieldDefinitions, useDeleteFieldDefinition } from "../api/queries"; import { useLang } from "../lib/use-lang"; import { rowStateClass } from "../lib/class-recipes"; import { labelText } from "../lib/labels"; import { byLabel, compareStrings } from "../lib/sort"; import { focusRing } from "../lib/focus-ring"; import { DeleteConfirmDialog } from "../components/delete-confirm-dialog"; import { Badge } from "@/components/ui/badge"; import { cn } from "@/lib/utils"; import { Input } from "@/components/ui/input"; import { ListSkeleton } from "@/components/ui/skeletons"; type FieldDefinitionView = components["schemas"]["FieldDefinitionView"]; export function FieldList({ selectedKey, onSelect, }: { selectedKey: string | null; onSelect: (def: FieldDefinitionView) => void; }) { const { t } = useTranslation(); const { data, isLoading, isError } = useFieldDefinitions(); const deleteField = useDeleteFieldDefinition(); const lang = useLang(); const [filter, setFilter] = useState(""); if (isLoading) return ; if (isError) return

{t("fields.loadError")}

; if (!data || data.length === 0) return

{t("fields.empty")}

; const q = filter.trim().toLowerCase(); const filtered = (data ?? []).filter( (d) => !q || labelText(d.labels, lang).toLowerCase().includes(q) || d.key.toLowerCase().includes(q), ); const groups = new Map(); for (const def of filtered) { const key = def.group?.trim() ? def.group : t("fields.other"); const bucket = groups.get(key) ?? []; bucket.push(def); groups.set(key, bucket); } const otherLabel = t("fields.other"); const entries = [...groups.entries()].sort((a, b) => { if (a[0] === otherLabel) return 1; if (b[0] === otherLabel) return -1; return compareStrings(lang, a[0], b[0]); }); return (
setFilter(e.target.value)} />
{filtered.length === 0 ? (

{t("common.noMatches")}

) : (
    {entries.map(([group, defs]) => (
  • {group} {defs.length}
      {[...defs].sort(byLabel(lang)).map((def) => (
    • deleteField.mutateAsync(def.key)} />
    • ))}
  • ))}
)}
); }