From 16d2fd794195d897bb5039b35eeff28a39a60f37 Mon Sep 17 00:00:00 2001 From: "CANCERYS\\kw093" Date: Mon, 11 May 2026 17:21:59 +0800 Subject: [PATCH] udpate bom search for WIP/FG --- .../ImportBom/ImportBomDetailTab.tsx | 84 +++++++++++-------- 1 file changed, 49 insertions(+), 35 deletions(-) diff --git a/src/components/ImportBom/ImportBomDetailTab.tsx b/src/components/ImportBom/ImportBomDetailTab.tsx index 227a980..583dc33 100644 --- a/src/components/ImportBom/ImportBomDetailTab.tsx +++ b/src/components/ImportBom/ImportBomDetailTab.tsx @@ -1,6 +1,6 @@ "use client"; -import React, { useEffect, useState } from "react"; +import React, { useEffect, useRef, useState } from "react"; import { Box, Stack, @@ -32,7 +32,6 @@ import { type EquipmentMasterRow, type ProcessMasterRow, } from "@/app/api/bom/client"; -import type { SelectChangeEvent } from "@mui/material/Select"; import { useTranslation } from "react-i18next"; import SearchBox, { Criterion } from "../SearchBox"; import { useMemo, useCallback } from "react"; @@ -70,6 +69,7 @@ const ImportBomDetailTab: React.FC = () => { const [loadingDetail, setLoadingDetail] = useState(false); const [filteredBoms, setFilteredBoms] = useState([]) const [currentBom, setCurrentBom] = useState(null); + const loadDetailInFlightRef = useRef(false); type EditMaterialRow = { key: string; @@ -195,15 +195,34 @@ const ImportBomDetailTab: React.FC = () => { [t], ); useEffect(() => { - setFilteredBoms(bomList); // 初始顯示全部 + setFilteredBoms([]); }, [bomList]); + const loadBomDetail = useCallback( + async (id: number) => { + if (!id || loadDetailInFlightRef.current) return; + loadDetailInFlightRef.current = true; + setSelectedBomId(id); + setCurrentBom(bomList.find((b) => b.id === id) ?? null); + setDetail(null); + setLoadingDetail(true); + try { + const d = await fetchBomDetailClient(id); + setDetail(d); + } finally { + setLoadingDetail(false); + loadDetailInFlightRef.current = false; + } + }, + [bomList], + ); + const handleSearchBom = useCallback( (inputs: Record) => { const code = (inputs.code ?? "").trim().toLowerCase(); const name = (inputs.name ?? "").trim().toLowerCase(); const result = bomList.filter((b) => { - const label = b.label.toLowerCase(); + const label = String(b.label ?? "").toLowerCase(); const okCode = !code || label.includes(code); const okName = !name || label.includes(name); return okCode && okName; @@ -213,16 +232,14 @@ const ImportBomDetailTab: React.FC = () => { // 如果只找到一個,直接載入明細 if (result.length === 1) { - const only = result[0]; - setSelectedBomId(only.id); + void loadBomDetail(result[0].id); + } else { + setSelectedBomId(""); + setCurrentBom(null); setDetail(null); - setLoadingDetail(true); - fetchBomDetailClient(only.id) - .then((d) => setDetail(d)) - .finally(() => setLoadingDetail(false)); } }, - [bomList], + [bomList, loadBomDetail], ); const renderAllergic = (v?: number) => { if (v === 0) return "有"; @@ -270,20 +287,6 @@ const ImportBomDetailTab: React.FC = () => { setDetail(null); }, [bomList]); */ - const handleChangeBom = async (event: SelectChangeEvent) => { - const id = Number(event.target.value); - setSelectedBomId(id); - setDetail(null); - if (!id) return; - setLoadingDetail(true); - try { - const d = await fetchBomDetailClient(id); - setDetail(d); - } finally { - setLoadingDetail(false); - } - }; - const genKey = () => Math.random().toString(36).slice(2); const startEdit = useCallback(async () => { @@ -555,16 +558,27 @@ const ImportBomDetailTab: React.FC = () => { //onReset={handleResetBom} /> -{currentBom && ( - - - CODE / NAME - - - {currentBom.label} ({t("Output Quantity")} {currentBom.outputQty} {currentBom.outputQtyUom}) - - -)} + + {filteredBoms.length > 1 && ( + + + 找到多筆 BOM,請選擇一筆載入明細 + + + {filteredBoms.map((b) => ( + + ))} + + + )} {loadingDetail && ( {t("Loading BOM Detail...")}