ソースを参照

Fix report date picker placeholders and ZH-only filter labels.

fix負數倉
CANCERYS\kw093 2週間前
コミット
a54f8d5f37
6個のファイルの変更128行の追加82行の削除
  1. +1
    -1
      src/app/(main)/report/ReportSelectionDashboard.tsx
  2. +58
    -13
      src/app/(main)/report/page.tsx
  3. +1
    -1
      src/app/(main)/report/reportCategories.ts
  4. +3
    -2
      src/app/(main)/report/reportI18n.ts
  5. +1
    -1
      src/config/reportConfig.ts
  6. +64
    -64
      src/i18n/zh/report.json

+ 1
- 1
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,


+ 58
- 13
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() {
</Typography>
<Divider sx={{ mb: 3 }} />

<LocalizationProvider
dateAdapter={AdapterDayjs}
adapterLocale={isZh ? 'zh-hk' : 'en'}
localeText={
isZh
? {
fieldDayPlaceholder: () => '日',
fieldMonthPlaceholder: () => '月',
fieldYearPlaceholder: () => '年',
}
: undefined
}
>
<Grid container spacing={3}>
{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 (
<Grid item {...gridSize} key={field.name}>
<DatePicker
label={translatedLabel}
format={dateDisplayFormat}
value={parsed?.isValid() ? parsed : null}
minDate={field.minDate === 'today' ? dayjs().startOf('day') : undefined}
disabled={disabledByCheckedCheckbox || disabledRep012Status || !!field.disabled}
onChange={(date) => {
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'
}
} : {},
},
}}
/>
</Grid>
);
}

if (field.type === 'checkbox') {
return (
<Grid item {...gridSize} key={field.name}>
@@ -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() {
);
})}
</Grid>
</LocalizationProvider>

<Box sx={{ mt: 4, display: 'flex', gap: 2, justifyContent: 'flex-end' }}>
{currentReport.id === 'rep-005' ? (


+ 1
- 1
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",


+ 3
- 2
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<ReportDefinition, "id" | "title">) =>
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(


+ 1
- 1
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",


+ 64
- 64
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": {


読み込み中…
キャンセル
保存