Files

76 lines
2.3 KiB
TypeScript

import { useCallback, useMemo, useRef } from "react";
import {
FormField,
SearchableSelect,
type ApiSettings,
type SearchableSelectOption
} from "@govoplan/core-webui";
import {
listDistributionLists,
type DistributionList
} from "../api/distLists";
import { DIST_LISTS_FIELD_DOCUMENTATION } from "../features/distributionLists/interfacePatterns";
export type DistributionListPickerProps = {
settings: ApiSettings;
value: string;
onChange: (listId: string, item: DistributionList | null) => void;
label?: string;
placeholder?: string;
disabled?: boolean;
required?: boolean;
selected?: DistributionList | null;
};
export default function DistributionListPicker({
settings,
value,
onChange,
label = "Distribution list",
placeholder = "Search distribution lists",
disabled = false,
required = false,
selected = null
}: DistributionListPickerProps) {
const cache = useRef(new Map<string, DistributionList>());
if (selected) cache.current.set(selected.id, selected);
const selectedOption = useMemo<SearchableSelectOption | null>(() => {
const item = selected ?? cache.current.get(value);
if (!item) return value ? { value, label: value } : null;
return optionFor(item);
}, [selected, value]);
const loadOptions = useCallback(async (query: string) => {
const items = await listDistributionLists(settings, query);
for (const item of items) cache.current.set(item.id, item);
return items.map(optionFor);
}, [settings]);
return (
<FormField label={label} documentation={DIST_LISTS_FIELD_DOCUMENTATION}>
<SearchableSelect
value={value}
selectedOption={selectedOption}
loadOptions={loadOptions}
onChange={(nextValue) =>
onChange(nextValue, cache.current.get(nextValue) ?? null)}
placeholder={placeholder}
searchPlaceholder="Search by list name"
emptyText="No matching distribution lists."
disabled={disabled}
required={required}
/>
</FormField>
);
}
function optionFor(item: DistributionList): SearchableSelectOption {
return {
value: item.id,
label: item.name,
description: `${item.revision.entries.length} entries · revision ${item.current_revision}`,
searchText: `${item.description ?? ""} ${item.scope_type}`
};
}