From 2afa8895ff0b7c9e370d8ee2399a2bb44dc6d02a Mon Sep 17 00:00:00 2001 From: "kelvin.yau" Date: Thu, 16 Oct 2025 15:32:37 +0800 Subject: [PATCH] batch release update --- src/components/DoSearch/DoSearch.tsx | 160 ++++++++++++--------------- src/i18n/zh/do.json | 4 +- 2 files changed, 75 insertions(+), 89 deletions(-) diff --git a/src/components/DoSearch/DoSearch.tsx b/src/components/DoSearch/DoSearch.tsx index b2acb47..f8b6e4c 100644 --- a/src/components/DoSearch/DoSearch.tsx +++ b/src/components/DoSearch/DoSearch.tsx @@ -26,12 +26,13 @@ import { SubmitHandler, useForm, } from "react-hook-form"; -import { Box, Button, Grid, Stack, Typography, TablePagination } from "@mui/material"; +import { Box, Button, Grid, Stack, Typography, TablePagination} from "@mui/material"; import StyledDataGrid from "../StyledDataGrid"; import { GridRowSelectionModel } from "@mui/x-data-grid"; import Swal from "sweetalert2"; import { useSession } from "next-auth/react"; import { SessionWithTokens } from "@/config/authConfig"; + type Props = { filterArgs?: Record; searchQuery?: Record; @@ -64,7 +65,7 @@ const DoSearch: React.FC = ({filterArgs, searchQuery, onDeliveryOrderSear const { data: session } = useSession() as { data: SessionWithTokens | null }; const currentUserId = session?.id ? parseInt(session.id) : undefined; console.log("🔍 DoSearch - session:", session); -console.log("🔍 DoSearch - currentUserId:", currentUserId); + console.log("🔍 DoSearch - currentUserId:", currentUserId); const [searchTimeout, setSearchTimeout] = useState(null); const [rowSelectionModel, setRowSelectionModel] = useState([]); @@ -356,43 +357,32 @@ console.log("🔍 DoSearch - currentUserId:", currentUserId); setSearchTimeout(timeout); }, [handleSearch, searchTimeout]); + const handleBatchRelease = useCallback(async () => { - const selectedIds = rowSelectionModel as number[]; - if (!selectedIds.length) return; - - console.log("🔍 handleBatchRelease - currentUserId:", currentUserId); - console.log("🔍 handleBatchRelease - selectedIds:", selectedIds); + const totalDeliveryOrderLines = searchAllDos.reduce((sum, doItem) => { + return sum + (doItem.deliveryOrderLines?.length || 0); + }, 0); + const result = await Swal.fire({ icon: "question", title: t("Batch Release"), html: `
-

${t("Selected items on current page")}: ${selectedIds.length}

-

${t("Total search results")}: ${searchAllDos.length}

-
-

${t("Choose release option")}:

+

${t("Selected Shop(s): ")}${searchAllDos.length}

+

${t("Selected Item(s): ")}${totalDeliveryOrderLines}

`, showCancelButton: true, - confirmButtonText: t("Release All Search Results"), - cancelButtonText: t("Release Selected Only"), - denyButtonText: t("Cancel"), - showDenyButton: true, + confirmButtonText: t("Confirm"), + cancelButtonText: t("Cancel"), confirmButtonColor: "#8dba00", - cancelButtonColor: "#2196f3", - denyButtonColor: "#F04438" + cancelButtonColor: "#F04438" }); - if (result.isDenied) return; - - let idsToRelease: number[]; if (result.isConfirmed) { - idsToRelease = searchAllDos.map(d => d.id); - } else { - idsToRelease = selectedIds; - } - + const idsToRelease = searchAllDos.map(d => d.id); + try { const startRes = await startBatchReleaseAsync({ ids: idsToRelease, userId: currentUserId ?? 1 }); const jobId = startRes?.entity?.jobId; @@ -401,70 +391,64 @@ console.log("🔍 DoSearch - currentUserId:", currentUserId); await Swal.fire({ icon: "error", title: t("Error"), text: t("Failed to start batch release") }); return; } - - await Swal.fire({ - title: t("Releasing"), - html: ` -
-
${t("Total")}: 0
-
${t("Finished")}: 0
-
-
-
-
- `, - allowOutsideClick: false, - allowEscapeKey: false, - showConfirmButton: false, - didOpen: async () => { - const update = (total:number, finished:number, success:number, failed:number) => { - const bar = document.getElementById("br-bar") as HTMLElement; - const pct = total > 0 ? Math.floor((finished / total) * 100) : 0; - (document.getElementById("br-total") as HTMLElement).innerText = `${t("Total")}: ${total}`; - (document.getElementById("br-finished") as HTMLElement).innerText = `${t("Finished")}: ${finished}`; - - if (bar) bar.style.width = `${pct}%`; - }; - - const timer = setInterval(async () => { - try { - const p = await getBatchReleaseProgress(jobId); - const e = p?.entity || {}; - update(e.total ?? 0, e.finished ?? 0, e.success ?? 0, e.failedCount ?? 0); - - if (p.code === "FINISHED" || e.running === false) { - clearInterval(timer); - Swal.close(); - - // 简化完成提示 - 只显示完成,不显示成功/失败统计 - await Swal.fire({ - icon: "success", - title: t("Completed"), - text: t("Batch release completed"), - confirmButtonText: t("OK") - }); - - if (currentSearchParams && Object.keys(currentSearchParams).length > 0) { - await handleSearch(currentSearchParams); - } - setRowSelectionModel([]); - } - } catch (err) { - console.error("progress poll error:", err); - } - }, 800); + + + const progressSwal = Swal.fire({ + title: t("Releasing"), + text: "0% (0 / 0)", + allowOutsideClick: false, + allowEscapeKey: false, + showConfirmButton: false, + didOpen: () => { + Swal.showLoading(); + } + }); + + const timer = setInterval(async () => { + try { + const p = await getBatchReleaseProgress(jobId); + + const e = p?.entity || {}; + const total = e.total ?? 0; + const finished = e.finished ?? 0; + const percentage = total > 0 ? Math.round((finished / total) * 100) : 0; + + const textContent = document.querySelector('.swal2-html-container'); + if (textContent) { + textContent.textContent = `${percentage}% (${finished} / ${total})`; } - }); - } catch (error) { - console.error("Batch release error:", error); - await Swal.fire({ - icon: "error", - title: t("Error"), - text: t("An error occurred during batch release"), - confirmButtonText: t("OK") - }); - } - }, [rowSelectionModel, t, currentUserId, searchAllDos, currentSearchParams, handleSearch]); + + if (p.code === "FINISHED" || e.running === false) { + clearInterval(timer); + await new Promise(resolve => setTimeout(resolve, 500)); + Swal.close(); + + await Swal.fire({ + icon: "success", + title: t("Completed"), + text: t("Batch release completed successfully."), + confirmButtonText: t("Confirm"), + confirmButtonColor: "#8dba00" + }); + + if (currentSearchParams && Object.keys(currentSearchParams).length > 0) { + await handleSearch(currentSearchParams); + } + } + } catch (err) { + console.error("progress poll error:", err); + } + }, 800); + } catch (error) { + console.error("Batch release error:", error); + await Swal.fire({ + icon: "error", + title: t("Error"), + text: t("An error occurred during batch release"), + confirmButtonText: t("OK") + }); + }} +}, [t, currentUserId, searchAllDos, currentSearchParams, handleSearch]); return ( diff --git a/src/i18n/zh/do.json b/src/i18n/zh/do.json index e21ebc7..a595912 100644 --- a/src/i18n/zh/do.json +++ b/src/i18n/zh/do.json @@ -55,5 +55,7 @@ "Pick Order Assignment": "提料單分配", "Release 2/F": "放單2/F", "Release 4/F": "放單4/F", - "Stock Status": "庫存狀態" + "Stock Status": "庫存狀態", + "Finished: ": "已放送貨訂單:", + "Total:": "已選擇送貨訂單:" } \ No newline at end of file