"use client"; import { useEffect, useState } from "react"; import { useQuery } from "@tanstack/react-query"; import { useConnectivity } from "@/lib/offline/connectivity"; import { fetchTreatmentPrefill } from "./api"; import type { TreatmentPrefill } from "./types"; const DEBOUNCE_MS = 500; const MIN_PRODUCT_LENGTH = 2; const MAX_PRODUCT_LENGTH = 200; /** * The beekeeper's own last values for the product typed so far. Waits until * typing pauses, needs at least two characters and asks only while online - * a prefill is a convenience, never a reason to block or queue anything. * While a request for the same product is pending or the device is offline, * the last answer for that product stays; for any other product it is dropped. */ export function useTreatmentPrefill(product: string): TreatmentPrefill | null { const trimmed = product.trim(); const [debounced, setDebounced] = useState(""); const connectivity = useConnectivity(); useEffect(() => { const timer = setTimeout(() => setDebounced(trimmed), DEBOUNCE_MS); return () => clearTimeout(timer); }, [trimmed]); const isSettled = debounced === trimmed; const isAskable = trimmed.length >= MIN_PRODUCT_LENGTH && trimmed.length <= MAX_PRODUCT_LENGTH; const enabled = connectivity === "online" && isSettled && isAskable; const { data } = useQuery({ queryKey: ["treatments", "prefill", debounced], queryFn: () => fetchTreatmentPrefill(debounced), enabled, }); // The last settled answer is kept only for the product it was fetched for // (pending request, offline). Once the product differs it is dropped at // once, so a failed request can never leave another product's values. const [held, setHeld] = useState<{ product: string; prefill: TreatmentPrefill | null } | null>( null, ); let settled: TreatmentPrefill | null | undefined; if (isSettled && !isAskable) settled = null; else if (enabled) settled = data; if (settled !== undefined && (held?.product !== trimmed || held.prefill !== settled)) { setHeld({ product: trimmed, prefill: settled }); } if (settled !== undefined) return settled; return held?.product === trimmed ? held.prefill : null; }