"use client"; import { clientAuthFetch } from "@/app/utils/clientAuthFetch"; import { NEXT_PUBLIC_API_URL } from "@/config/api"; import { useCallback, useEffect, useState } from "react"; const POLL_MS = 60_000; /** Match backend [PurchaseStockInAlertRow] JSON. */ export type PurchaseStockInAlertItem = { stockInLineId: number; purchaseOrderId: number; purchaseOrderLineId: number; poCode: string | null; itemNo: string | null; itemName: string | null; status: string | null; lineCreated: string | null; receiptDate: string | null; lotNo: string | null; }; function parseAlertsPayload(raw: unknown): PurchaseStockInAlertItem[] { if (!Array.isArray(raw)) return []; return raw.map((r) => { const o = r as Record; return { stockInLineId: Number(o.stockInLineId ?? o.stockinLineId ?? 0), purchaseOrderId: Number(o.purchaseOrderId ?? o.purchaseorderid ?? 0), purchaseOrderLineId: Number(o.purchaseOrderLineId ?? o.purchaseorderlineid ?? 0), poCode: o.poCode != null ? String(o.poCode) : null, itemNo: o.itemNo != null ? String(o.itemNo) : null, itemName: o.itemName != null ? String(o.itemName) : null, status: o.status != null ? String(o.status) : null, lineCreated: o.lineCreated != null ? String(o.lineCreated) : null, receiptDate: o.receiptDate != null ? String(o.receiptDate) : null, lotNo: o.lotNo != null ? String(o.lotNo) : null, }; }); } /** * Recent PO stock-in lines in pending / receiving (backend lookback window). * Fetches full list for alert dialog + count for badge. */ export function usePurchaseStockInAlerts(enabled: boolean, days?: number) { const [items, setItems] = useState([]); const [count, setCount] = useState(0); const [loading, setLoading] = useState(false); const load = useCallback(async () => { if (!enabled) { setItems([]); setCount(0); return; } setLoading(true); try { const listParams = new URLSearchParams(); if (days != null && Number.isFinite(days)) listParams.set("days", String(days)); listParams.set("limit", "80"); const listUrl = `${NEXT_PUBLIC_API_URL}/stockInLine/alerts/purchase-incomplete?${listParams}`; const countParams = new URLSearchParams(); if (days != null && Number.isFinite(days)) countParams.set("days", String(days)); const countSuffix = countParams.toString() ? `?${countParams}` : ""; const countUrl = `${NEXT_PUBLIC_API_URL}/stockInLine/alerts/purchase-incomplete-count${countSuffix}`; const [resList, resCount] = await Promise.all([ clientAuthFetch(listUrl), clientAuthFetch(countUrl), ]); if (!resList.ok) { setItems([]); } else { const data = await resList.json(); setItems(parseAlertsPayload(data)); } if (resCount.ok) { const c = (await resCount.json()) as { count?: number }; const n = Number(c.count ?? 0); setCount(Number.isFinite(n) && n > 0 ? n : 0); } else { setCount(0); } } catch { setItems([]); setCount(0); } finally { setLoading(false); } }, [enabled, days]); useEffect(() => { if (!enabled) { setItems([]); setCount(0); return; } void load(); const id = window.setInterval(() => void load(), POLL_MS); return () => window.clearInterval(id); }, [enabled, load]); return { items, count, loading, reload: load }; }