From 0a758038be5f790c535f9cc077805cc96063a967 Mon Sep 17 00:00:00 2001 From: tommy Date: Fri, 5 Jun 2026 18:33:00 +0800 Subject: [PATCH] translate --- src/components/Breadcrumb/Breadcrumb.tsx | 2 + .../PickOrderSearch/EscalationComponent.tsx | 12 +- .../PickQcStockInModalVer3.tsx | 6 +- src/components/PickOrderSearch/QcFormVer2.tsx | 14 +- src/components/Shop/TruckLane.tsx | 195 ++++++++---------- .../qrCodeHandles/qrCodeHandleTabs.tsx | 4 +- src/i18n/en/navigation.json | 4 +- src/i18n/en/pickOrder.json | 5 +- src/i18n/en/productionProcess.json | 1 + src/i18n/en/purchaseOrder.json | 5 +- src/i18n/en/qrCodeHandle.json | 3 +- src/i18n/en/stockRecord.json | 13 +- src/i18n/zh/masterDataIssue.json | 2 +- src/i18n/zh/navigation.json | 1 + src/i18n/zh/pickOrder.json | 5 +- src/i18n/zh/productionProcess.json | 1 + src/i18n/zh/purchaseOrder.json | 5 +- src/i18n/zh/qrCodeHandle.json | 3 +- src/i18n/zh/stockRecord.json | 13 +- 19 files changed, 159 insertions(+), 135 deletions(-) diff --git a/src/components/Breadcrumb/Breadcrumb.tsx b/src/components/Breadcrumb/Breadcrumb.tsx index e3383c2..73b2ad2 100644 --- a/src/components/Breadcrumb/Breadcrumb.tsx +++ b/src/components/Breadcrumb/Breadcrumb.tsx @@ -23,6 +23,8 @@ const pathToLabelKey: { [path: string]: string } = { "/settings/qcItem": "nav.breadcrumb.qcItem", "/settings/qcItemAll": "nav.breadcrumb.qcItemAll", "/settings/qrCodeHandle": "nav.breadcrumb.qrCodeHandle", + "/settings/deliveryOrderFloor": "nav.breadcrumb.deliveryOrderFloor", + "/settings/masterDataIssues": "nav.breadcrumb.masterDataIssues", "/settings/rss": "nav.breadcrumb.demandForecast", "/settings/equipment": "nav.breadcrumb.equipment", "/settings/equipment/MaintenanceEdit": "nav.breadcrumb.equipmentMaintenanceEdit", diff --git a/src/components/PickOrderSearch/EscalationComponent.tsx b/src/components/PickOrderSearch/EscalationComponent.tsx index 12e0b81..5edb2df 100644 --- a/src/components/PickOrderSearch/EscalationComponent.tsx +++ b/src/components/PickOrderSearch/EscalationComponent.tsx @@ -116,8 +116,8 @@ const EscalationComponent: React.FC = ({ defaultValue="pass" name="radio-buttons-group" > - } label="合格" /> - } label="不合格" /> + } label={t("passed")} /> + } label={t("failed")} /> ): undefined} @@ -140,24 +140,24 @@ const EscalationComponent: React.FC = ({ fullWidth id="quantity" name="quantity" - label="數量" + label={t("Quantity")} type="number" value={formData.quantity} onChange={handleInputChange} InputProps={{ inputProps: { min: 1 } }} - placeholder="請輸入數量" + placeholder={t("Enter quantity")} /> diff --git a/src/components/PickOrderSearch/PickQcStockInModalVer3.tsx b/src/components/PickOrderSearch/PickQcStockInModalVer3.tsx index 98c5b86..3385037 100644 --- a/src/components/PickOrderSearch/PickQcStockInModalVer3.tsx +++ b/src/components/PickOrderSearch/PickQcStockInModalVer3.tsx @@ -404,7 +404,7 @@ const PickQcStockInModalVer3: React.FC = ({ if (qcDecision === "1" && !qcData.qcItems.every((q) => q.isPassed)) { submitDialogWithWarning(() => { closeHandler?.({}, 'escapeKeyDown'); - }, t, {title:"有不合格檢查項目,確認接受出庫?", confirmButtonText: "Confirm", html: ""}); + }, t, {title: t("confirm_accept_with_fail"), confirmButtonText: t("Confirm"), html: ""}); return; } @@ -463,7 +463,7 @@ const PickQcStockInModalVer3: React.FC = ({ } - label="合格" + label={t("passed")} sx={{ color: current.qcPassed === true ? "green" : "inherit", "& .Mui-checked": {color: "green"} @@ -472,7 +472,7 @@ const PickQcStockInModalVer3: React.FC = ({ } - label="不合格" + label={t("failed")} sx={{ color: current.qcPassed === false ? "red" : "inherit", "& .Mui-checked": {color: "red"} diff --git a/src/components/PickOrderSearch/QcFormVer2.tsx b/src/components/PickOrderSearch/QcFormVer2.tsx index ebea29d..02cbb12 100644 --- a/src/components/PickOrderSearch/QcFormVer2.tsx +++ b/src/components/PickOrderSearch/QcFormVer2.tsx @@ -216,16 +216,16 @@ const QcFormVer2: React.FC = ({ qc, itemDetail, disabled, qcItems, setQcI } - label="合格" + label={t("passed")} sx={{ color: currentValue === true ? "green" : "inherit", "& .Mui-checked": {color: "green"} }} /> - } - label="不合格" + } + label={t("failed")} sx={{ color: currentValue === false ? "red" : "inherit", "& .Mui-checked": {color: "red"} @@ -419,7 +419,7 @@ const QcFormVer2: React.FC = ({ qc, itemDetail, disabled, qcItems, setQcI field.onChange(value); }} > - } label="接受" /> + } label={t("passed")} /> = ({ qc, itemDetail, disabled, qcItems, setQcI helperText={errors.acceptQty?.message} /> - } label="不接受及上報" /> + } label={t("failed")} /> )} /> diff --git a/src/components/Shop/TruckLane.tsx b/src/components/Shop/TruckLane.tsx index e859aa7..f6c99d6 100644 --- a/src/components/Shop/TruckLane.tsx +++ b/src/components/Shop/TruckLane.tsx @@ -5,14 +5,6 @@ import { Card, CardContent, Typography, - Table, - TableBody, - TableCell, - TableContainer, - TableHead, - TablePagination, - TableRow, - Paper, Button, CircularProgress, Alert, @@ -30,14 +22,20 @@ import { } from "@mui/material"; import AddIcon from "@mui/icons-material/Add"; import SaveIcon from "@mui/icons-material/Save"; -import { useState, useMemo } from "react"; +import { useState, useMemo, useCallback } from "react"; import { useRouter } from "next/navigation"; import { useTranslation } from "react-i18next"; import { findAllUniqueTruckLaneCombinationsClient, createTruckWithoutShopClient } from "@/app/api/shop/client"; import type { Truck } from "@/app/api/shop/actions"; import SearchBox, { Criterion } from "../SearchBox"; +import SearchResults, { + Column, + defaultPagingController, +} from "../SearchResults/SearchResults"; import { formatDepartureTime, normalizeStoreId } from "@/app/utils/formatUtil"; +type TruckRow = Omit & { id: string | number }; + type SearchQuery = { truckLanceCode: string; departureTime: string; @@ -53,8 +51,7 @@ const TruckLane: React.FC = () => { const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const [filters, setFilters] = useState>({}); - const [page, setPage] = useState(0); - const [rowsPerPage, setRowsPerPage] = useState(10); + const [pagingController, setPagingController] = useState(defaultPagingController); const [addDialogOpen, setAddDialogOpen] = useState(false); const [newTruck, setNewTruck] = useState({ truckLanceCode: "", @@ -93,11 +90,80 @@ const TruckLane: React.FC = () => { }); }, [truckData, filters]); - // Paginated rows - const paginatedRows = useMemo(() => { - const startIndex = page * rowsPerPage; - return filteredRows.slice(startIndex, startIndex + rowsPerPage); - }, [filteredRows, page, rowsPerPage]); + const tableRows = useMemo( + () => + filteredRows.map((truck) => ({ + ...truck, + id: truck.id ?? (String(truck.truckLanceCode ?? "").trim() || `truck-${truck.truckLanceCode}`), + })), + [filteredRows], + ); + + const handleViewDetail = useCallback( + (truck: TruckRow) => { + const truckLanceCode = String(truck.truckLanceCode || "").trim(); + if (truckLanceCode) { + const url = new URL(`/settings/shop/truckdetail`, window.location.origin); + url.searchParams.set("truckLanceCode", truckLanceCode); + router.push(url.pathname + url.search); + } + }, + [router], + ); + + const columns = useMemo[]>( + () => [ + { + name: "truckLanceCode", + label: t("TruckLance Code"), + sx: { width: "250px", minWidth: "250px", maxWidth: "250px" }, + renderCell: (item) => String(item.truckLanceCode ?? "-"), + }, + { + name: "departureTime", + label: t("Departure Time"), + sx: { width: "200px", minWidth: "200px", maxWidth: "200px" }, + renderCell: (item) => + formatDepartureTime( + Array.isArray(item.departureTime) + ? item.departureTime + : item.departureTime + ? String(item.departureTime) + : null, + ), + }, + { + name: "storeId", + label: t("Store ID"), + sx: { width: "150px", minWidth: "150px", maxWidth: "150px" }, + renderCell: (item) => + normalizeStoreId( + item.storeId + ? typeof item.storeId === "string" || item.storeId instanceof String + ? String(item.storeId) + : String(item.storeId) + : null, + ), + }, + { + name: "id", + label: t("Actions"), + align: "right", + headerAlign: "right", + sx: { width: "150px", minWidth: "150px", maxWidth: "150px" }, + renderCell: (item) => ( + + ), + }, + ], + [handleViewDetail, t], + ); const handleSearch = async (inputs: Record) => { setLoading(true); @@ -113,7 +179,7 @@ const TruckLane: React.FC = () => { }); setTruckData(Array.from(uniqueCodes.values())); setFilters(inputs); - setPage(0); + setPagingController(defaultPagingController); } catch (err: any) { console.error("Failed to load truck lanes:", err); setError(err?.message ?? String(err) ?? t("Failed to load truck lanes")); @@ -122,26 +188,6 @@ const TruckLane: React.FC = () => { } }; - const handlePageChange = (event: unknown, newPage: number) => { - setPage(newPage); - }; - - const handleRowsPerPageChange = (event: React.ChangeEvent) => { - setRowsPerPage(parseInt(event.target.value, 10)); - setPage(0); // Reset to first page when changing rows per page - }; - - const handleViewDetail = (truck: Truck) => { - // Navigate to truck lane detail page using truckLanceCode - const truckLanceCode = String(truck.truckLanceCode || "").trim(); - if (truckLanceCode) { - // Use router.push with proper URL encoding - const url = new URL(`/settings/shop/truckdetail`, window.location.origin); - url.searchParams.set("truckLanceCode", truckLanceCode); - router.push(url.pathname + url.search); - } - }; - const handleOpenAddDialog = () => { setNewTruck({ truckLanceCode: "", @@ -270,77 +316,12 @@ const TruckLane: React.FC = () => { ) : ( - - - - - - {t("TruckLance Code")} - - - {t("Departure Time")} - - - {t("Store ID")} - - - {t("Actions")} - - - - - {paginatedRows.length === 0 ? ( - - - - {t("No Truck Lane data available")} - - - - ) : ( - paginatedRows.map((truck) => ( - - - {String(truck.truckLanceCode ?? "-")} - - - {formatDepartureTime( - Array.isArray(truck.departureTime) - ? truck.departureTime - : (truck.departureTime ? String(truck.departureTime) : null) - )} - - - {normalizeStoreId( - truck.storeId ? (typeof truck.storeId === 'string' || truck.storeId instanceof String - ? String(truck.storeId) - : String(truck.storeId)) : null - )} - - - - - - )) - )} - -
- -
)} diff --git a/src/components/qrCodeHandles/qrCodeHandleTabs.tsx b/src/components/qrCodeHandles/qrCodeHandleTabs.tsx index 08eb2a0..3d08d48 100644 --- a/src/components/qrCodeHandles/qrCodeHandleTabs.tsx +++ b/src/components/qrCodeHandles/qrCodeHandleTabs.tsx @@ -38,7 +38,7 @@ const QrCodeHandleTabs: React.FC = ({ equipmentTabContent, warehouseTabContent, }) => { - const { t } = useTranslation("common"); + const { t: tQrCodeHandle } = useTranslation("qrCodeHandle"); const { t: tUser } = useTranslation("user"); const { t: tWarehouse } = useTranslation("warehouse"); const searchParams = useSearchParams(); @@ -80,7 +80,7 @@ const QrCodeHandleTabs: React.FC = ({ - + diff --git a/src/i18n/en/navigation.json b/src/i18n/en/navigation.json index d067423..8b6cbe0 100644 --- a/src/i18n/en/navigation.json +++ b/src/i18n/en/navigation.json @@ -44,7 +44,7 @@ "nav.settings.deliveryOrderFloor": "DO floor (supplier)", "nav.settings.demandForecast": "Demand Forecast Setting", "nav.settings.bomWeighting": "BOM Weighting Score List", - "nav.settings.masterDataIssues": "Master Data Issues", + "nav.settings.masterDataIssues": "BOM / Item UOM Issues", "nav.settings.qrCodeHandle": "QR Code Handle", "nav.settings.importTesting": "Import Testing", "nav.settings.importExcel": "Import Excel", @@ -65,6 +65,8 @@ "nav.breadcrumb.qcItemAll": "QC Item All", "nav.breadcrumb.qrCodeHandle": "QR Code Handle", "nav.breadcrumb.demandForecast": "Demand Forecast Setting", + "nav.breadcrumb.deliveryOrderFloor": "Delivery Order Floor", + "nav.breadcrumb.masterDataIssues": "BOM / Item UOM Issues", "nav.breadcrumb.equipment": "Equipment", "nav.breadcrumb.equipmentMaintenanceEdit": "Maintenance Edit", "nav.breadcrumb.shop": "Shop And Truck", diff --git a/src/i18n/en/pickOrder.json b/src/i18n/en/pickOrder.json index ae4f5ea..4e6026c 100644 --- a/src/i18n/en/pickOrder.json +++ b/src/i18n/en/pickOrder.json @@ -514,5 +514,8 @@ "No lot rows. Select a line in the table above.": "No lot rows. Select a line in the table above.", "No stock out line for this lot": "No stock out line for this lot", "No data available for this pick order.": "No data available for this pick order.", - "Report missing or bad items": "Report missing or bad items" + "Report missing or bad items": "Report missing or bad items", + "passed": "Passed", + "failed": "Failed", + "confirm_accept_with_fail": "There are failed QC items. Confirm to accept stock out?" } diff --git a/src/i18n/en/productionProcess.json b/src/i18n/en/productionProcess.json index 9309695..3e68fe4 100644 --- a/src/i18n/en/productionProcess.json +++ b/src/i18n/en/productionProcess.json @@ -71,6 +71,7 @@ "Job Order Info": "Job Order Info", "Job Order No.": "Job Order No.", "Job Order and Product": "Job Order and Product", + "Job Order Production Process": "Job Order Production Process", "Job Process Status Dashboard": "Job Process Status Dashboard", "Job Type": "Job Type", "Job process detail mode label": "Job process detail mode label", diff --git a/src/i18n/en/purchaseOrder.json b/src/i18n/en/purchaseOrder.json index e195563..96f848a 100644 --- a/src/i18n/en/purchaseOrder.json +++ b/src/i18n/en/purchaseOrder.json @@ -178,5 +178,8 @@ "Add Record": "Add Record", "Clean Record": "Reset", "Create Material": "Create Material", - "Will start binding procedure after scanning item qr code.": "Will start binding procedure after scanning item qr code." + "Will start binding procedure after scanning item qr code.": "Will start binding procedure after scanning item qr code.", + "Quantity": "Quantity", + "Enter quantity": "Enter quantity", + "Enter your remark": "Enter your remark" } diff --git a/src/i18n/en/qrCodeHandle.json b/src/i18n/en/qrCodeHandle.json index 5071a81..b5c8133 100644 --- a/src/i18n/en/qrCodeHandle.json +++ b/src/i18n/en/qrCodeHandle.json @@ -1,4 +1,5 @@ { "PDF Preview": "PDF Preview", - "QR Code Handle": "QR Code Handle" + "QR Code Handle": "QR Code Handle", + "Equipment": "Equipment" } diff --git a/src/i18n/en/stockRecord.json b/src/i18n/en/stockRecord.json index 7fa2a85..5b0ca0d 100644 --- a/src/i18n/en/stockRecord.json +++ b/src/i18n/en/stockRecord.json @@ -17,5 +17,16 @@ "Balance Qty": "Balance Qty", "Loading...": "Loading...", "Type": "Type", - "Status": "Status" + "Status": "Status", + "pending": "Pending", + "completed": "Completed", + "partially_completed": "Partially completed", + "receiving": "Receiving", + "rejected": "Rejected", + "checked": "Checked", + "determine1": "Determine 1", + "lot-change": "Lot change approval", + "qc1": "QC 1", + "qc2": "QC 2", + "qc3": "QC 3" } diff --git a/src/i18n/zh/masterDataIssue.json b/src/i18n/zh/masterDataIssue.json index 18f57bf..622c549 100644 --- a/src/i18n/zh/masterDataIssue.json +++ b/src/i18n/zh/masterDataIssue.json @@ -22,7 +22,7 @@ "masterDataIssue_scope_BOM": "BOM 總表", "masterDataIssue_scope_BOM_MATERIAL": "BOM 原材料", "masterDataIssue_scope_ITEM": "貨品", - "masterDataIssue_nav": "數據問題", + "masterDataIssue_nav": "BOM/貨品單位問題", "masterDataIssue_MISSING_BOM_CODE": "BOM 編號為空", "masterDataIssue_MISSING_BOM_NAME": "BOM 名稱為空", "masterDataIssue_MISSING_ITEM": "關聯貨品不存在或已刪除", diff --git a/src/i18n/zh/navigation.json b/src/i18n/zh/navigation.json index 6e4f372..bcfa455 100644 --- a/src/i18n/zh/navigation.json +++ b/src/i18n/zh/navigation.json @@ -10,6 +10,7 @@ "nav.breadcrumb.chartPurchase": "採購", "nav.breadcrumb.chartWarehouse": "庫存與倉儲", "nav.breadcrumb.demandForecast": "需求預測設定", + "nav.breadcrumb.deliveryOrderFloor": "送貨單樓層", "nav.breadcrumb.doWorkbenchEdit": "DO Workbench 詳情", "nav.breadcrumb.doWorkbenchPick": "DO Workbench 揀貨", "nav.breadcrumb.doWorkbenchSearch": "DO Workbench 搜索", diff --git a/src/i18n/zh/pickOrder.json b/src/i18n/zh/pickOrder.json index b43bee1..846ddbd 100644 --- a/src/i18n/zh/pickOrder.json +++ b/src/i18n/zh/pickOrder.json @@ -514,5 +514,8 @@ "No lot rows. Select a line in the table above.": "尚無批號資料。請在上方表格勾選一行提料單明細。", "No stock out line for this lot": "此批號尚無出庫行,無法提交。", "No data available for this pick order.": "此提料單沒有可用資料。", - "Report missing or bad items": "報告缺失或不良物品" + "Report missing or bad items": "報告缺失或不良物品", + "passed": "合格", + "failed": "不合格", + "confirm_accept_with_fail": "有不合格檢查項目,確認接受出庫?" } diff --git a/src/i18n/zh/productionProcess.json b/src/i18n/zh/productionProcess.json index ae14b0a..1ded5c0 100644 --- a/src/i18n/zh/productionProcess.json +++ b/src/i18n/zh/productionProcess.json @@ -71,6 +71,7 @@ "Job Order Info": "工單信息", "Job Order No.": "工單編號", "Job Order and Product": "工單及貨品", + "Job Order Production Process": "工單生產流程", "Job Process Status Dashboard": "儀表板 - 工單狀態", "Job Type": "工單類型", "Job process detail mode label": "工序格顯示", diff --git a/src/i18n/zh/purchaseOrder.json b/src/i18n/zh/purchaseOrder.json index dabca98..bcff183 100644 --- a/src/i18n/zh/purchaseOrder.json +++ b/src/i18n/zh/purchaseOrder.json @@ -177,5 +177,8 @@ "Total must equal Required Qty. Exceeds by": "總數量必須等於所需數量。超出:{{diff}}", "Add Record": "新增", "Clean Record": "重置", - "Will start binding procedure after scanning item qr code.": "掃描物品二維碼後將開始綁定流程。" + "Will start binding procedure after scanning item qr code.": "掃描物品二維碼後將開始綁定流程。", + "Quantity": "數量", + "Enter quantity": "請輸入數量", + "Enter your remark": "請輸入您的備註" } diff --git a/src/i18n/zh/qrCodeHandle.json b/src/i18n/zh/qrCodeHandle.json index 0c2f12f..7779211 100644 --- a/src/i18n/zh/qrCodeHandle.json +++ b/src/i18n/zh/qrCodeHandle.json @@ -1,4 +1,5 @@ { "PDF Preview": "PDF 預覽", - "QR Code Handle": "二維碼列印及下載" + "QR Code Handle": "二維碼列印及下載", + "Equipment": "設備" } diff --git a/src/i18n/zh/stockRecord.json b/src/i18n/zh/stockRecord.json index 9e3a474..204e11f 100644 --- a/src/i18n/zh/stockRecord.json +++ b/src/i18n/zh/stockRecord.json @@ -17,5 +17,16 @@ "Balance Qty": "庫存數量", "Loading...": "載入中...", "Type": "類別", - "Status": "狀態" + "Status": "狀態", + "pending": "待處理", + "completed": "已完成", + "partially_completed": "已部分完成", + "receiving": "收貨中", + "rejected": "已拒絕", + "checked": "已檢查", + "determine1": "上報1", + "lot-change": "批次更換審批", + "qc1": "質檢1", + "qc2": "質檢2", + "qc3": "質檢3" }