diff --git a/src/app/(main)/report/ReportSelectionDashboard.tsx b/src/app/(main)/report/ReportSelectionDashboard.tsx index 7db491c2..50f5331a 100644 --- a/src/app/(main)/report/ReportSelectionDashboard.tsx +++ b/src/app/(main)/report/ReportSelectionDashboard.tsx @@ -171,7 +171,7 @@ function CategoryColumn({ ); } -/** FP-MTMS Version Checklist | Functions Ref. No. 69 | v1.0.0 | 2026-08-31 */ +/** FP-MTMS Version Checklist | Functions Ref. No. 69 | v1.0.1 | 2026-08-31 */ export default function ReportSelectionDashboard({ selectedReportId, onSelectReport, diff --git a/src/app/(main)/report/page.tsx b/src/app/(main)/report/page.tsx index e94f38d2..639f62d0 100644 --- a/src/app/(main)/report/page.tsx +++ b/src/app/(main)/report/page.tsx @@ -30,6 +30,11 @@ import { NEXT_PUBLIC_API_URL } from '@/config/api'; import { clientAuthFetch } from '@/app/utils/clientAuthFetch'; import SemiFGProductionAnalysisReport from './SemiFGProductionAnalysisReport'; import ReportSelectionDashboard from './ReportSelectionDashboard'; +import { DatePicker, LocalizationProvider } from '@mui/x-date-pickers'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import dayjs from 'dayjs'; +import 'dayjs/locale/zh-hk'; +import { OUTPUT_DATE_FORMAT } from '@/app/utils/formatUtil'; import { useReportLabels } from './reportI18n'; import { fetchSemiFGItemCodes, @@ -51,10 +56,12 @@ interface ItemCodeWithName { /** FP-MTMS Version Checklist | Functions Ref. No. 39 | v1.0.0 | 2026-08-03 */ /** FP-MTMS Version Checklist | Functions Ref. No. 60 | v1.0.1 | 2026-08-11 */ -/** FP-MTMS Version Checklist | Functions Ref. No. 69 | v1.0.0 | 2026-08-31 */ +/** FP-MTMS Version Checklist | Functions Ref. No. 69 | v1.0.1 | 2026-08-31 */ export default function ReportPage() { const { data: session } = useSession() as { data: SessionWithTokens | null }; - const { t, reportTitle, fieldLabel, optionLabel } = useReportLabels(); + const { t, i18n, reportTitle, fieldLabel, optionLabel } = useReportLabels(); + const isZh = (i18n.language || 'zh').startsWith('zh'); + const dateDisplayFormat = isZh ? 'DD/MM/YYYY' : 'DD/MM/YYYY'; const includeGrnFinancialColumns = session?.abilities?.includes(AUTH.ADMIN) ?? false; @@ -506,6 +513,19 @@ export default function ReportPage() { + '日', + fieldMonthPlaceholder: () => '月', + fieldYearPlaceholder: () => '年', + } + : undefined + } + > {currentReport.fields.map((field) => { const translatedLabel = fieldLabel(currentReport.id, field); @@ -524,11 +544,6 @@ export default function ReportPage() { // Use larger grid size for 成品/半成品生產分析報告 const gridSize = currentReport.id === 'rep-005' ? { xs: 12, sm: 12, md: 6 } : { xs: 12, sm: 6 }; - const todayLocal = (() => { - const d = new Date(); - return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`; - })(); - const disabledByCheckedCheckbox = currentReport.fields.some((f) => { if (f.type !== 'checkbox' || criteria[f.name] !== 'true') return false; return f.disablesFieldsWhenChecked?.includes(field.name) ?? false; @@ -538,6 +553,41 @@ export default function ReportPage() { field.name === 'status' && rep012MultiRound; + if (field.type === 'date') { + const parsed = currentValue ? dayjs(currentValue) : null; + return ( + + { + handleFieldChange( + field.name, + date?.isValid() ? date.format(OUTPUT_DATE_FORMAT) : '', + ); + }} + slotProps={{ + textField: { + fullWidth: true, + sx: currentReport.id === 'rep-005' ? { + '& .MuiOutlinedInput-root': { + minHeight: '64px', + fontSize: '1rem' + }, + '& .MuiInputLabel-root': { + fontSize: '1rem' + } + } : {}, + }, + }} + /> + + ); + } + if (field.type === 'checkbox') { return ( @@ -653,12 +703,6 @@ export default function ReportPage() { type={field.type} placeholder={field.placeholder} disabled={disabledByCheckedCheckbox || disabledRep012Status || !!field.disabled} - InputLabelProps={field.type === 'date' ? { shrink: true } : {}} - inputProps={ - field.type === 'date' && field.minDate === 'today' - ? { min: todayLocal } - : undefined - } sx={currentReport.id === 'rep-005' ? { '& .MuiOutlinedInput-root': { minHeight: '64px', @@ -737,6 +781,7 @@ export default function ReportPage() { ); })} + {currentReport.id === 'rep-005' ? ( diff --git a/src/app/(main)/report/reportCategories.ts b/src/app/(main)/report/reportCategories.ts index d96ccc37..543e6186 100644 --- a/src/app/(main)/report/reportCategories.ts +++ b/src/app/(main)/report/reportCategories.ts @@ -9,7 +9,7 @@ export interface ReportCategoryConfig { reportIds: string[]; } -/** FP-MTMS Version Checklist | Functions Ref. No. 69 | v1.0.0 | 2026-08-31 */ +/** FP-MTMS Version Checklist | Functions Ref. No. 69 | v1.0.1 | 2026-08-31 */ export const REPORT_CATEGORIES: ReportCategoryConfig[] = [ { id: "inventory", diff --git a/src/app/(main)/report/reportI18n.ts b/src/app/(main)/report/reportI18n.ts index 39b7b606..86daf4e0 100644 --- a/src/app/(main)/report/reportI18n.ts +++ b/src/app/(main)/report/reportI18n.ts @@ -4,8 +4,9 @@ import { useTranslation } from "react-i18next"; import type { TFunction } from "i18next"; import type { ReportDefinition, ReportField } from "@/config/reportConfig"; +/** FP-MTMS Version Checklist | Functions Ref. No. 69 | v1.0.1 | 2026-08-31 */ export function useReportLabels() { - const { t } = useTranslation("report"); + const { t, i18n } = useTranslation("report"); const reportTitle = (report: Pick) => t(`reports.${report.id}.title`, { defaultValue: report.title }); @@ -34,7 +35,7 @@ export function useReportLabels() { const categoryTitle = (id: string, fallback: string) => t(`categories.${id}`, { defaultValue: fallback }); - return { t, reportTitle, fieldLabel, optionLabel, categoryTitle }; + return { t, i18n, reportTitle, fieldLabel, optionLabel, categoryTitle }; } export function reportExcelT( diff --git a/src/config/reportConfig.ts b/src/config/reportConfig.ts index e7e983bf..fcf74b84 100644 --- a/src/config/reportConfig.ts +++ b/src/config/reportConfig.ts @@ -34,7 +34,7 @@ export interface ReportDefinition { fields: ReportField[]; } -/** FP-MTMS Version Checklist | Functions Ref. No. 69 | v1.0.0 | 2026-08-31 */ +/** FP-MTMS Version Checklist | Functions Ref. No. 69 | v1.0.1 | 2026-08-31 */ export const REPORTS: ReportDefinition[] = [ //{ // id: "rep-001", diff --git a/src/i18n/zh/report.json b/src/i18n/zh/report.json index f4803a4f..3812c6a3 100644 --- a/src/i18n/zh/report.json +++ b/src/i18n/zh/report.json @@ -45,14 +45,14 @@ "rep-004": { "title": "入倉追蹤報告", "fields": { - "lastInDateStart": "入倉日期:由 Last In Date Start", - "lastInDateEnd": "入倉日期:至 Last In Date End", - "itemCode": "貨品編號 Item Code", - "storeId": "樓層 Store ID", - "warehouse": "倉庫 Warehouse", - "area": "區域 Area", - "slot": "儲位 Slot", - "lotNo": "批號 Lot No", + "lastInDateStart": "入倉日期:由", + "lastInDateEnd": "入倉日期:至", + "itemCode": "貨品編號", + "storeId": "樓層", + "warehouse": "倉庫", + "area": "區域", + "slot": "儲位", + "lotNo": "批號", "poPrefix": "PP/PF 分類" }, "options": { @@ -69,10 +69,10 @@ "rep-008": { "title": "成品出倉報告", "fields": { - "lastOutDateStart": "出貨日期:由 Last Out Date Start", - "lastOutDateEnd": "出貨日期:至 Last Out Date End", - "year": "年份 Year", - "itemCode": "貨品編號 Item Code" + "lastOutDateStart": "出貨日期:由", + "lastOutDateEnd": "出貨日期:至", + "year": "年份", + "itemCode": "貨品編號" } }, "rep-012": { @@ -109,42 +109,42 @@ "rep-011": { "title": "庫存明細報告", "fields": { - "lastInDateStart": "庫存日期:由 Last In Date Start", - "lastInDateEnd": "庫存日期:至 Last In Date End", - "itemCode": "貨品編號 Item Code" + "lastInDateStart": "庫存日期:由", + "lastInDateEnd": "庫存日期:至", + "itemCode": "貨品編號" } }, "rep-007": { "title": "庫存結餘報告", "fields": { - "stockDate": "庫存日期: Stock Date", - "itemCode": "貨品編號 Item Code" + "stockDate": "庫存日期", + "itemCode": "貨品編號" } }, "rep-014": { "title": "PO入倉記錄報告", "fields": { - "receiptDateStart": "收貨日期:由 Receipt Date Start", - "receiptDateEnd": "收貨日期:至 Receipt Date End", - "itemCode": "貨品編號 Item Code" + "receiptDateStart": "收貨日期:由", + "receiptDateEnd": "收貨日期:至", + "itemCode": "貨品編號" } }, "rep-009": { "title": "成品出倉追蹤報告", "fields": { - "lastOutDateStart": "出貨日期:由 Last Out Date Start", - "lastOutDateEnd": "出貨日期:至 Last Out Date End", - "itemCode": "貨品編號 Item Code", - "handler": "提料員 Handler" + "lastOutDateStart": "出貨日期:由", + "lastOutDateEnd": "出貨日期:至", + "itemCode": "貨品編號", + "handler": "提料員" } }, "rep-010": { "title": "庫存品質檢測報告", "fields": { - "lastInDateStart": "QC 檢測日期:由 QC Date Start", - "lastInDateEnd": "QC 檢測日期:至 QC Date End", + "lastInDateStart": "QC 檢測日期:由", + "lastInDateEnd": "QC 檢測日期:至", "qcType": "QC 類型", - "itemCode": "貨品編號 Item Code", + "itemCode": "貨品編號", "qcItemScope": "QC 項目範圍" }, "options": { @@ -162,71 +162,71 @@ "rep-013": { "title": "貨品出倉追蹤報告", "fields": { - "lastOutDateStart": "出倉日期:由 Last Out Date Start", - "lastOutDateEnd": "出倉日期:至 Last Out Date End", - "itemCode": "貨品編號 Item Code", - "handler": "提料人 Handler" + "lastOutDateStart": "出倉日期:由", + "lastOutDateEnd": "出倉日期:至", + "itemCode": "貨品編號", + "handler": "提料人" } }, "rep-006": { "title": "庫存材料消耗趨勢報告", "fields": { - "lastOutDateStart": "材料消耗日期:由 Last Out Date Start", - "lastOutDateEnd": "材料消耗日期:至 Last Out Date End", - "year": "年份 Year", - "stockCategory": "類別 Category", - "itemCode": "貨品編號 Item Code" + "lastOutDateStart": "材料消耗日期:由", + "lastOutDateEnd": "材料消耗日期:至", + "year": "年份", + "stockCategory": "類別", + "itemCode": "貨品編號" } }, "rep-005": { "title": "成品/半成品生產分析報告", "fields": { - "lastOutDateStart": "完成生產日期:由 Last Out Date Start", - "lastOutDateEnd": "完成生產日期:至 Last Out Date End", - "year": "年份 Year", - "stockCategory": "類別 Category", - "itemCode": "貨品編號 Item Code" + "lastOutDateStart": "完成生產日期:由", + "lastOutDateEnd": "完成生產日期:至", + "year": "年份", + "stockCategory": "類別", + "itemCode": "貨品編號" } }, "rep-015": { "title": "M18 BOM Shop 同步記錄", "fields": { - "syncDateStart": "同步日期:由 Sync Date Start", - "syncDateEnd": "同步日期:至 Sync Date End", - "finishedItemCode": "成品貨號 Finished Item Code", - "syncStatus": "同步狀態 Sync Status" + "syncDateStart": "同步日期:由", + "syncDateEnd": "同步日期:至", + "finishedItemCode": "成品貨號", + "syncStatus": "同步狀態" }, "options": { "syncStatus": { - "all": "全部 All", - "success": "成功 Success", - "failed": "失敗 Failed" + "all": "全部", + "success": "成功", + "failed": "失敗" } } }, "rep-016": { "title": "成品出倉揀貨合規報告", "fields": { - "dateStart": "日期 Date", - "handler": "提料人 Handler", + "dateStart": "日期", + "handler": "提料人", "ticketNo": "提票號碼", - "itemCode": "貨品編號 Item Code", + "itemCode": "貨品編號", "storeId": "樓層" } }, "rep-017": { "title": "店鋪訂單補貨記錄", "fields": { - "shopOrderDateStart": "店鋪訂單日期:由 Shop Order Date Start", - "shopOrderDateEnd": "店鋪訂單日期:至 Shop Order Date End", - "shopCode": "店鋪編號 Shop Code" + "shopOrderDateStart": "店鋪訂單日期:由", + "shopOrderDateEnd": "店鋪訂單日期:至", + "shopCode": "店鋪編號" } }, "rep-018": { "title": "送貨訂單與倉存單位不符報告", "fields": { - "deliveryDate": "預計送貨日期 Estimated Arrival Date", - "storeId": "送貨訂單樓層 Floor" + "deliveryDate": "預計送貨日期", + "storeId": "送貨訂單樓層" }, "options": { "storeId": { @@ -237,14 +237,14 @@ "rep-021": { "title": "庫存批次現況報告", "fields": { - "itemCode": "貨品編號 Item Code", - "storeId": "樓層 Store ID", - "warehouse": "倉庫 Warehouse", - "area": "區域 Area", - "slot": "儲位 Slot", - "stockTakeSectionDescription": "盤點區域說明 Stock Take Section", - "lotNo": "批號 Lot No", - "lotOrigin": "來源 Lot Origin" + "itemCode": "貨品編號", + "storeId": "樓層", + "warehouse": "倉庫", + "area": "區域", + "slot": "儲位", + "stockTakeSectionDescription": "盤點區域說明", + "lotNo": "批號", + "lotOrigin": "來源" }, "options": { "storeId": {