/** * `useFormCacheSelector` — server-state coordinator for the FormCacheSelector * component. * * Implements the mount-time auto-restore flow described in Architecture §9.4: * * 1. Fetch GetAllByUser via TanStack Query. * 2. On success: * a. If any record has lastInUse === true → fetch GetById, run safeParse, * call onSelected(restoredFilter, true). * b. Else → call onSelected(emptyFilter, false). * 3. On error → call onSelected(emptyFilter, false) (NFR-FFCS-STB-002). * * The mount-time call to `onSelected` MUST fire exactly once (FR-FFCS-011). * A `useRef` flag guards against duplicate fires when: * - React 18 StrictMode invokes effects twice in development. * - The query refetches because of focus / network reconnect. * - Parent re-renders cause the effect dependency array to re-evaluate. * * In S013 the hook gains its first real mutation (`handleUpsert`): * - Sets `isMutating` while the request is in-flight. * - On 200: pessimistically updates the local `caches` list using the * server-returned `id`, switches `activeId`, surfaces a success message * that auto-dismisses after 3 s (D-UX-006). * - On 409: routes the error into `saveNameError` (rendered inline in * SaveDialog) — the global error banner stays clear. * - On other errors: routes the error into `errorMessage` (global banner) * and leaves the dialog open. * * The auto-dismiss timer is cleaned up in a `useEffect` return so toggling * `successMessage` mid-life cancels any stale timer and unmounting cancels * the pending one (R-001 / no setState-after-unmount warnings). * * In S014 the hook gains `handleRename` plus the `renameDialogOpen` / * `renameError` state used by the RenameDialog subcomponent: * - On 200: list updates in-place (`id` unchanged, only `name` changes), the * dialog closes, success banner fires. * - On 409: `renameError` is set so the dialog renders inline conflict text * and stays open — the user can edit the name and retry. * - On 404 / other errors: dialog closes and the global error banner is set. * * In S015 the hook gains `handleDelete` plus the `deleteDialogOpen` / * `deletingCacheName` state used by the DeleteDialog subcomponent: * - `openDeleteDialog()` snapshots the active cache name (R-001) so the * dialog title cannot drift mid-confirmation. * - On 200: the entry is removed from the local `caches` list. If it was * the active cache, `activeId` resets to null AND `onSelected(emptyFilter, * false)` fires AFTER the local state update (R-002) so the parent form * observes a consistent local state. * - On error: dialog closes and the global error banner shows the message. */ import type { FormCacheDTO, FormCacheSelectorProps, HttpClient } from './FormCacheSelector.types'; /** Payload for the in-tree toast rendered via createPortal in FormCacheSelector. */ export interface ToastPayload { text: string; color: 'green' | 'red'; } export interface UseFormCacheSelectorResult { caches: FormCacheDTO[]; activeId: string | null; isLoading: boolean; isMutating: boolean; /** Save dialog open state — exposed so the root component can render it. */ saveDialogOpen: boolean; /** Setter for `saveDialogOpen` so the root component can open / close it. */ setSaveDialogOpen: (open: boolean) => void; /** i18n key for an inline 409 error inside the save dialog (or null). */ saveNameError: string | null; /** Clears `saveNameError` — called as the user edits the name input. */ clearSaveNameError: () => void; /** Rename dialog open state — exposed so the root component can render it. */ renameDialogOpen: boolean; /** Setter for `renameDialogOpen` so the root component can open / close it. */ setRenameDialogOpen: (open: boolean) => void; /** i18n key for an inline 409 error inside the rename dialog (or null). */ renameError: string | null; /** Clears `renameError` — called as the user edits the rename input. */ clearRenameError: () => void; /** Delete dialog open state — exposed so the root component can render it. */ deleteDialogOpen: boolean; /** Setter for `deleteDialogOpen` so the root component can dismiss it. */ setDeleteDialogOpen: (open: boolean) => void; /** * Cache name snapshot taken when the delete dialog was opened (R-001). The * dialog renders this verbatim so a concurrent rename can't relabel the * confirmation mid-flow. */ deletingCacheName: string; /** * Opens the DeleteDialog and snapshots the current active cache name. Use * this from the Delete button click handler instead of `setDeleteDialogOpen` * directly so the snapshot stays in sync with the open state. */ openDeleteDialog: () => void; /** Active toast to render via createPortal (null = no toast). */ activeToast: ToastPayload | null; handleSelectNoFilter: () => void; handleSelectCache: (cache: FormCacheDTO) => Promise; handleUpsert: (name: string) => Promise; handleUpdateLastInUse: (id: string) => Promise; handleDelete: () => Promise; handleRename: (newName: string) => Promise; setActiveId: (id: string | null) => void; } export declare function useFormCacheSelector(cacheId: string, filter: TFilter, onSelected: FormCacheSelectorProps['onSelected'], httpClient: HttpClient): UseFormCacheSelectorResult; //# sourceMappingURL=FormCacheSelector.hooks.d.ts.map