"use client" // Per-item allowed-UOM lookup for document line forms. // // Every line on a document can reference a different item, so this caches by itemId and // fetches each one once. A naive refetch on every line edit would cost one request per line // on a 20-line invoice; the cache keeps it to one request per distinct item. import { useCallback, useEffect, useRef, useState } from "react" import { itemsApi } from "@/lib/api/items" import { AllowedUom } from "@/types/master-data" export interface AllowedUomLookup { /** Allowed units for an item, or `undefined` while it is still loading / unknown. */ get: (itemId: number | null | undefined) => AllowedUom[] | undefined /** Ensure an item's units are loaded. Safe to call repeatedly; in-flight requests are shared. */ load: (itemId: number | null | undefined) => void } export function useAllowedUoms(): AllowedUomLookup { const [cache, setCache] = useState>({}) // Tracks in-flight and failed ids so a repeated render never re-issues the same request. const pending = useRef>(new Set()) const load = useCallback((itemId: number | null | undefined) => { if (!itemId || pending.current.has(itemId)) return pending.current.add(itemId) itemsApi .allowedUoms(itemId) .then((uoms) => setCache((prev) => ({ ...prev, [itemId]: uoms }))) .catch(() => { // Leave the id marked so we don't hammer a failing endpoint. The picker falls back // to the global UOM list (see `pickerOptions`), and the server still rejects an // invalid unit on save — this is a degraded experience, not a correctness hole. }) }, []) const get = useCallback( (itemId: number | null | undefined) => (itemId ? cache[itemId] : undefined), [cache], ) return { get, load } } /** * Single-item variant for screens with one item in scope (the conversion editor, a stock * enquiry filtered to one item). */ export function useItemAllowedUoms(itemId: number | null | undefined): AllowedUom[] { const [uoms, setUoms] = useState([]) useEffect(() => { if (!itemId) { setUoms([]) return } let cancelled = false itemsApi .allowedUoms(itemId) .then((res) => { if (!cancelled) setUoms(res) }) .catch(() => { if (!cancelled) setUoms([]) }) return () => { cancelled = true } }, [itemId]) return uoms }