Selaa lähdekoodia

translate and route schedule

Suggest doing  "Remove-Item -Recurse -Force .next" in frontend
production
tommy 2 viikkoa sitten
vanhempi
commit
44b2d30ac8
100 muutettua tiedostoa jossa 986 lisäystä ja 302 poistoa
  1. +267
    -0
      scripts/update-chart-i18n.js
  2. +2
    -2
      src/app/(main)/bag/page.tsx
  3. +6
    -8
      src/app/(main)/bagPrint/page.tsx
  4. +7
    -18
      src/app/(main)/chart/layout.tsx
  5. +1
    -1
      src/app/(main)/dashboard/page.tsx
  6. +1
    -1
      src/app/(main)/do/edit/page.tsx
  7. +1
    -1
      src/app/(main)/do/page.tsx
  8. +2
    -2
      src/app/(main)/doworkbench/edit/page.tsx
  9. +2
    -2
      src/app/(main)/doworkbench/page.tsx
  10. +1
    -1
      src/app/(main)/doworkbenchsearch/page.tsx
  11. +2
    -2
      src/app/(main)/finishedGood/detail/page.tsx
  12. +1
    -1
      src/app/(main)/finishedGood/management/page.tsx
  13. +2
    -2
      src/app/(main)/finishedGood/page.tsx
  14. +2
    -2
      src/app/(main)/inventory/page.tsx
  15. +1
    -1
      src/app/(main)/jo/edit/page.tsx
  16. +1
    -1
      src/app/(main)/jo/page.tsx
  17. +1
    -1
      src/app/(main)/jo/workbench/page.tsx
  18. +1
    -1
      src/app/(main)/jodetail/edit/page.tsx
  19. +1
    -1
      src/app/(main)/jodetail/page.tsx
  20. +6
    -8
      src/app/(main)/laserPrint/page.tsx
  21. +1
    -1
      src/app/(main)/layout.tsx
  22. +7
    -16
      src/app/(main)/m18Syn/layout.tsx
  23. +1
    -1
      src/app/(main)/pickOrder/detail/page.tsx
  24. +1
    -1
      src/app/(main)/pickOrder/page.tsx
  25. +1
    -1
      src/app/(main)/po/edit/page.tsx
  26. +1
    -1
      src/app/(main)/po/page.tsx
  27. +1
    -1
      src/app/(main)/po/workbench/page.tsx
  28. +2
    -2
      src/app/(main)/production/page.tsx
  29. +2
    -2
      src/app/(main)/productionProcess/page.tsx
  30. +2
    -2
      src/app/(main)/projects/create/page.tsx
  31. +2
    -2
      src/app/(main)/projects/page.tsx
  32. +13
    -0
      src/app/(main)/ps/layout.tsx
  33. +1
    -1
      src/app/(main)/ps/page.tsx
  34. +1
    -1
      src/app/(main)/putAway/page.tsx
  35. +1
    -1
      src/app/(main)/putAwayCam/page.tsx
  36. +13
    -0
      src/app/(main)/report/layout.tsx
  37. +1
    -1
      src/app/(main)/scheduling/detailed/edit/page.tsx
  38. +1
    -1
      src/app/(main)/scheduling/detailed/page.tsx
  39. +1
    -1
      src/app/(main)/scheduling/rough/edit/page.tsx
  40. +1
    -1
      src/app/(main)/scheduling/rough/page.tsx
  41. +2
    -2
      src/app/(main)/settings/bomWeighting/page.tsx
  42. +6
    -1
      src/app/(main)/settings/clientMonitor/page.tsx
  43. +2
    -2
      src/app/(main)/settings/deliveryOrderFloor/page.tsx
  44. +1
    -1
      src/app/(main)/settings/equipment/EquipmentTabs.tsx
  45. +3
    -3
      src/app/(main)/settings/equipment/MaintenanceEdit/page.tsx
  46. +2
    -2
      src/app/(main)/settings/equipment/create/page.tsx
  47. +3
    -3
      src/app/(main)/settings/equipment/edit/page.tsx
  48. +3
    -3
      src/app/(main)/settings/equipment/page.tsx
  49. +2
    -2
      src/app/(main)/settings/equipmentType/create/page.tsx
  50. +3
    -3
      src/app/(main)/settings/equipmentType/edit/page.tsx
  51. +3
    -3
      src/app/(main)/settings/equipmentType/page.tsx
  52. +4
    -4
      src/app/(main)/settings/importBom/MaintenanceEdit/page.tsx
  53. +1
    -1
      src/app/(main)/settings/importBom/create/page.tsx
  54. +3
    -6
      src/app/(main)/settings/importBom/edit/page.tsx
  55. +1
    -1
      src/app/(main)/settings/importBom/page.tsx
  56. +21
    -21
      src/app/(main)/settings/importExcel/page.tsx
  57. +3
    -3
      src/app/(main)/settings/itemPrice/page.tsx
  58. +1
    -1
      src/app/(main)/settings/items/create/page.tsx
  59. +1
    -1
      src/app/(main)/settings/items/edit/page.tsx
  60. +2
    -2
      src/app/(main)/settings/items/page.tsx
  61. +1
    -1
      src/app/(main)/settings/m18ImportTesting/page.tsx
  62. +1
    -1
      src/app/(main)/settings/mail/page.tsx
  63. +2
    -2
      src/app/(main)/settings/printer/create/page.tsx
  64. +2
    -2
      src/app/(main)/settings/printer/edit/page.tsx
  65. +2
    -2
      src/app/(main)/settings/printer/page.tsx
  66. +1
    -1
      src/app/(main)/settings/qcCategory/edit/page.tsx
  67. +1
    -1
      src/app/(main)/settings/qcItem/create/page.tsx
  68. +1
    -1
      src/app/(main)/settings/qcItem/edit/page.tsx
  69. +1
    -1
      src/app/(main)/settings/qcItem/page.tsx
  70. +1
    -1
      src/app/(main)/settings/qcItemAll/page.tsx
  71. +5
    -5
      src/app/(main)/settings/qrCodeHandle/page.tsx
  72. +2
    -3
      src/app/(main)/settings/rss/page.tsx
  73. +2
    -2
      src/app/(main)/settings/shop/board/page.tsx
  74. +2
    -2
      src/app/(main)/settings/shop/detail/page.tsx
  75. +2
    -2
      src/app/(main)/settings/shop/page.tsx
  76. +2
    -2
      src/app/(main)/settings/shop/truckdetail/page.tsx
  77. +1
    -1
      src/app/(main)/settings/user/create/page.tsx
  78. +1
    -1
      src/app/(main)/settings/user/edit/page.tsx
  79. +1
    -1
      src/app/(main)/settings/user/page.tsx
  80. +1
    -1
      src/app/(main)/settings/warehouse/create/page.tsx
  81. +1
    -1
      src/app/(main)/settings/warehouse/page.tsx
  82. +1
    -1
      src/app/(main)/stockIssue/page.tsx
  83. +5
    -11
      src/app/(main)/stockOutIssueRecord/detail/page.tsx
  84. +4
    -11
      src/app/(main)/stockOutIssueRecord/page.tsx
  85. +2
    -2
      src/app/(main)/stockRecord/page.tsx
  86. +2
    -2
      src/app/(main)/stocktakemanagement/page.tsx
  87. +1
    -1
      src/app/(main)/tasks/page.tsx
  88. +306
    -0
      src/app/api/shop/actions.ts
  89. +110
    -0
      src/app/api/shop/client.ts
  90. +1
    -1
      src/components/AppBar/AppBar.tsx
  91. +1
    -1
      src/components/AppBar/Profile.tsx
  92. +3
    -3
      src/components/BomScoreTable/BomScoreTable.tsx
  93. +2
    -2
      src/components/BomWeightingScoreTable/BomWeightingScoreTable.tsx
  94. +1
    -1
      src/components/BomWeightingTabs/BomWeightingTabs.tsx
  95. +67
    -56
      src/components/Breadcrumb/Breadcrumb.tsx
  96. +14
    -14
      src/components/CreateClaim/ClaimInputGrid.tsx
  97. +1
    -1
      src/components/CreateEquipment/CreateEquipment.tsx
  98. +1
    -1
      src/components/CreateEquipment/EquipmentDetails.tsx
  99. +1
    -1
      src/components/CreateEquipmentType/CreateEquipmentType.tsx
  100. +1
    -1
      src/components/CreateEquipmentType/EquipmentTypeDetails.tsx

+ 267
- 0
scripts/update-chart-i18n.js Näytä tiedosto

@@ -0,0 +1,267 @@
const fs = require('fs');
const path = require('path');

const en = {
"pageTitle_delivery": "Delivery & Dispatch",
"pageTitle_jobOrder": "Job Orders",
"pageTitle_forecast": "Forecast & Planning",
"pageTitle_warehouse": "Inventory & Warehouse",
"pageTitle_equipmentBoard": "Equipment Usage Board",
"pageTitle_processBoard": "Process Real-time Board",
"pageTitle_jobOrderBoard": "Job Order Real-time Board",
"pageTitle_purchase": "Purchase",

"all": "All",
"noData": "No data",
"exportExcel": "Export Excel",
"show": "Show",
"laneX": "Lane X",
"today": "Today",
"yesterday": "Yesterday",
"selectDate": "Select Date",
"refresh": "Refresh",
"otherBoards": "Other Boards",
"autoRefresh": "Auto Refresh",
"on": "On",
"off": "Off",
"intervalSeconds": "Interval (sec)",
"minutes": "minutes",
"minutesWithVal": "{{val}} min",
"minuteAbbr": "min",

"delivery_staffPerfDateError": "Staff performance start date cannot be later than end date",
"delivery_ordersByDate": "Delivery Orders by Date",
"delivery_ordersByDate_export": "Delivery_Orders_By_Date",
"delivery_orderCount": "Order Count",
"delivery_topItemsByCount": "Top Items by Delivery Count",
"delivery_item": "Item",
"delivery_itemPlaceholder": "Leave empty for all",
"delivery_staffPerformanceTitle": "Staff Delivery Performance (Daily Pick Count & Duration)",
"delivery_startDate": "Start Date",
"delivery_endDate": "End Date",
"delivery_store": "Store",
"delivery_staff": "Staff",
"delivery_staffPlaceholder": "Leave empty for all",
"delivery_staffPerfCaption": "Per-person pick count & total duration for period",
"delivery_colStaff": "Staff",
"delivery_colPickCount": "Pick Count",
"delivery_colTotalMin": "Total Min",
"delivery_colAvgMin": "Avg Min/Order",
"delivery_dailyByStaff": "Daily by Staff",
"delivery_noDataDesc": "No delivery data available for the selected period.",

"jo_byStatus": "Job Orders by Status",
"jo_byStatus_export": "Job_Orders_By_Status",
"jo_datePlanStart": "Date (Plan Start)",
"jo_createdVsCompleted": "Job Orders Created vs Completed by Date",
"jo_createdVsCompleted_export": "Job_Orders_Created_vs_Completed",
"jo_detailSection": "Job Order Material / Process / Equipment",
"jo_materialPendingPicked": "Material Pending / Picked (by Plan Date)",
"jo_materialPendingPicked_export": "Material_Pending_vs_Picked",
"jo_processPendingCompleted": "Process Pending / Completed (by Plan Date)",
"jo_processPendingCompleted_export": "Process_Pending_vs_Completed",
"jo_equipmentWorkingWorked": "Equipment In Use / Used (by Job Order)",
"jo_equipmentWorkingWorked_export": "Equipment_In_Use_vs_Used",

"board_jobOrderLive": "Job Order Live Board",
"board_equipmentUsage": "Equipment Usage Board",
"board_processLive": "Process Live Board",
"board_jobOrderChart": "Job Order Chart",

"forecast_plannedOutputByDate": "Planned Daily Output by Item (Forecast)",
"forecast_plannedOutputByDate_export": "Planned_Daily_Output_By_Item",
"forecast_itemCode": "Item Code",
"forecast_noScheduleData": "No scheduling data for this date range.",
"forecast_productionSchedule": "Production Schedule by Date (Estimated Output)",
"forecast_productionSchedule_export": "Production_Schedule_By_Date",

"warehouse_stockTxnByDate": "Stock Transactions by Date (In / Out / Total)",
"warehouse_stockTxnByDate_export": "Stock_Transactions_By_Date",
"warehouse_stockInOutByDate": "Stock In vs Out by Date",
"warehouse_stockInOutByDate_export": "Stock_In_vs_Out",
"warehouse_balanceTrend": "Stock Balance Trend",
"warehouse_balanceTrend_export": "Stock_Balance_Trend",
"warehouse_consumptionTrend": "Monthly Consumption Trend (Outbound)",
"warehouse_consumptionTrend_export": "Monthly_Consumption_Trend",
"warehouse_qty": "Qty",
"warehouse_optional": "Optional",
"warehouse_sumAll": "Sum all if empty",
"warehouse_addItem": "Add item to split",
"warehouse_exportFail": "Master export failed",

"equipment_status": "Status",
"equipment_equipment": "Equipment",
"equipment_jobOrder": "Job Order",
"equipment_process": "Process",
"equipment_planStart": "Plan Start",
"equipment_startTime": "Start Time",
"equipment_endTime": "End Time",
"equipment_operator": "Operator",
"equipment_boardTitle": "Equipment Usage Board",
"equipment_infoDescription1": "Shows equipment status in real-time: working, idle, or under maintenance.",
"equipment_infoDescription2": "Each equipment card displays the current job order and process.",
"equipment_infoDescription3": "Equipment with unclosed hours or missing time entries will be flagged.",
"equipment_searchAndList": "Search & List",
"equipment_notToday": "Not Today",
"equipment_unclosedHours": "Equipment hours not closed",
"equipment_missingHours": "Missing equipment hours",
"equipment_completed": "Completed",

"process_notStarted": "Not Started",
"process_inProgress": "In Progress",
"process_completed": "Completed",
"process_nonToday": "Not Today",

"dateRange_lastDays": "Last {{d}} days",

"series_inbound": "Inbound",
"series_outbound": "Outbound",
"series_total": "Total",
"series_balance": "Balance",
"series_consumption": "Consumption",
"series_created": "Created",
"series_completed": "Completed",
"series_month": "Month",

"requestFailed": "Request failed"
};

const zh = {
"pageTitle_delivery": "發貨與配送",
"pageTitle_jobOrder": "工單",
"pageTitle_forecast": "預測與計劃",
"pageTitle_warehouse": "庫存與倉儲",
"pageTitle_equipmentBoard": "設備使用看板",
"pageTitle_processBoard": "工序即時看板",
"pageTitle_jobOrderBoard": "工單即時看板",
"pageTitle_purchase": "採購",

"all": "全部",
"noData": "無數據",
"exportExcel": "匯出 Excel",
"show": "顯示",
"laneX": "車線-X",
"today": "今日",
"yesterday": "昨日",
"selectDate": "選擇日期",
"refresh": "重新整理",
"otherBoards": "其他看板",
"autoRefresh": "自動重新整理",
"on": "開啟",
"off": "關閉",
"intervalSeconds": "間隔(秒)",
"minutes": "分鐘",
"minutesWithVal": "{{val}} 分鐘",
"minuteAbbr": "分",

"delivery_staffPerfDateError": "員工發貨績效的起始日期不能晚於結束日期",
"delivery_ordersByDate": "按日期發貨單數量",
"delivery_ordersByDate_export": "發貨單數量_按日期",
"delivery_orderCount": "單數",
"delivery_topItemsByCount": "發貨數量排行(按物料)",
"delivery_item": "物料",
"delivery_itemPlaceholder": "不選則全部",
"delivery_staffPerformanceTitle": "員工發貨績效(每日揀貨數量與耗時)",
"delivery_startDate": "開始日期",
"delivery_endDate": "結束日期",
"delivery_store": "倉別",
"delivery_staff": "員工",
"delivery_staffPlaceholder": "不選則全部",
"delivery_staffPerfCaption": "週期內每人揀單數及總耗時(首揀至完成)",
"delivery_colStaff": "員工",
"delivery_colPickCount": "揀單數",
"delivery_colTotalMin": "總分鐘",
"delivery_colAvgMin": "平均分鐘/單",
"delivery_dailyByStaff": "每日按員工單數",
"delivery_noDataDesc": "所選期間內暫無發貨記錄,請調整日期範圍後再試。",

"jo_byStatus": "工單按狀態",
"jo_byStatus_export": "工單_按狀態",
"jo_datePlanStart": "日期(計劃開始)",
"jo_createdVsCompleted": "工單創建與完成按日期",
"jo_createdVsCompleted_export": "工單_創建與完成_按日期",
"jo_detailSection": "工單物料/工序/設備",
"jo_materialPendingPicked": "物料待領/已揀(按工單計劃日)",
"jo_materialPendingPicked_export": "物料_待領_已揀",
"jo_processPendingCompleted": "工序待完成/已完成(按工單計劃日)",
"jo_processPendingCompleted_export": "工序_待完成_已完成",
"jo_equipmentWorkingWorked": "設備使用中/已使用(按工單)",
"jo_equipmentWorkingWorked_export": "設備_使用中_已使用",

"board_jobOrderLive": "工單即時看板",
"board_equipmentUsage": "設備使用看板",
"board_processLive": "工序即時看板",
"board_jobOrderChart": "工單圖表",

"forecast_plannedOutputByDate": "按物料計劃日產量(預測)",
"forecast_plannedOutputByDate_export": "計劃日產量_按物料",
"forecast_itemCode": "物料編碼",
"forecast_noScheduleData": "此日期範圍內尚無排程資料。",
"forecast_productionSchedule": "按日期生產排程(預估產量)",
"forecast_productionSchedule_export": "生產排程_按日期",

"warehouse_stockTxnByDate": "按日期庫存流水(入/出/合計)",
"warehouse_stockTxnByDate_export": "庫存流水_按日期",
"warehouse_stockInOutByDate": "按日期入庫與出庫",
"warehouse_stockInOutByDate_export": "入庫_出庫_按日期",
"warehouse_balanceTrend": "庫存餘額趨勢",
"warehouse_balanceTrend_export": "庫存餘額趨勢",
"warehouse_consumptionTrend": "按月考勤消耗趨勢(出庫量)",
"warehouse_consumptionTrend_export": "月考勤消耗趨勢",
"warehouse_qty": "數量",
"warehouse_optional": "可選",
"warehouse_sumAll": "不選則全部合計",
"warehouse_addItem": "新增物料以分項顯示",
"warehouse_exportFail": "總表匯出失敗",

"equipment_status": "狀態",
"equipment_equipment": "設備",
"equipment_jobOrder": "工單",
"equipment_process": "工序",
"equipment_planStart": "工單計劃開始",
"equipment_startTime": "開工時間",
"equipment_endTime": "完工時間",
"equipment_operator": "操作員",
"equipment_boardTitle": "設備使用看板",
"equipment_infoDescription1": "即時顯示設備狀態:使用中、閒置或維護中。",
"equipment_infoDescription2": "每張設備卡片顯示當前工單和工序。",
"equipment_infoDescription3": "設備工時未結案或未填寫將被標記。",
"equipment_searchAndList": "查詢與列表",
"equipment_notToday": "非今日",
"equipment_unclosedHours": "設備工時未結案",
"equipment_missingHours": "未填設備工時",
"equipment_completed": "已完工",

"process_notStarted": "未開工",
"process_inProgress": "進行中",
"process_completed": "已完工",
"process_nonToday": "非今日",

"dateRange_lastDays": "最近 {{d}} 天",

"series_inbound": "入庫",
"series_outbound": "出庫",
"series_total": "合計",
"series_balance": "餘額",
"series_consumption": "消耗",
"series_created": "新建",
"series_completed": "完成",
"series_month": "月份",

"requestFailed": "請求失敗"
};

const i18nDir = path.join(__dirname, '..', 'src', 'i18n');
const enPath = path.join(i18nDir, 'en', 'chart.json');
const zhPath = path.join(i18nDir, 'zh', 'chart.json');

// Sort keys alphabetically
const sortKeys = (obj) => {
const sorted = {};
Object.keys(obj).sort().forEach(k => { sorted[k] = obj[k]; });
return sorted;
};

fs.writeFileSync(enPath, JSON.stringify(sortKeys(en), null, 2) + '\n');
fs.writeFileSync(zhPath, JSON.stringify(sortKeys(zh), null, 2) + '\n');
console.log('Updated chart.json with', Object.keys(en).length, 'keys for each language');

+ 2
- 2
src/app/(main)/bag/page.tsx Näytä tiedosto

@@ -9,7 +9,7 @@ export const metadata: Metadata = {
} }


const bagPage: React.FC = async () => { const bagPage: React.FC = async () => {
const { t } = await getServerI18n("jo");
const { t } = await getServerI18n("bagUsage");


return ( return (
<> <>
@@ -23,7 +23,7 @@ const bagPage: React.FC = async () => {
{t("Bag Usage")} {t("Bag Usage")}
</Typography> </Typography>
</Stack> </Stack>
<I18nProvider namespaces={["jo", "common"]}>
<I18nProvider namespaces={["bagUsage","navigation","common","jo"]}>
<Suspense fallback={<BagSearchWrapper.Loading />}> <Suspense fallback={<BagSearchWrapper.Loading />}>
<BagSearchWrapper /> <BagSearchWrapper />
</Suspense> </Suspense>


+ 6
- 8
src/app/(main)/bagPrint/page.tsx Näytä tiedosto

@@ -1,23 +1,21 @@
import { I18nProvider } from "@/i18n";
import { Metadata } from "next";
import BagPrintSearch from "@/components/BagPrint/BagPrintSearch"; import BagPrintSearch from "@/components/BagPrint/BagPrintSearch";
import { Stack, Typography } from "@mui/material"; import { Stack, Typography } from "@mui/material";
import { Metadata } from "next";
import React from "react";


export const metadata: Metadata = { export const metadata: Metadata = {
title: "打袋機", title: "打袋機",
}; };


const BagPrintPage: React.FC = () => {
export default async function BagPrintPage() {
return ( return (
<>
<I18nProvider namespaces={["bagPrint", "navigation", "common"]}>
<Stack direction="row" justifyContent="space-between" flexWrap="wrap" rowGap={2}> <Stack direction="row" justifyContent="space-between" flexWrap="wrap" rowGap={2}>
<Typography variant="h4" marginInlineEnd={2}> <Typography variant="h4" marginInlineEnd={2}>
打袋機 打袋機
</Typography> </Typography>
</Stack> </Stack>
<BagPrintSearch /> <BagPrintSearch />
</>
</I18nProvider>
); );
};

export default BagPrintPage;
}

+ 7
- 18
src/app/(main)/chart/layout.tsx Näytä tiedosto

@@ -1,24 +1,13 @@
import { Metadata } from "next";
import { getServerSession } from "next-auth";
import { redirect } from "next/navigation";
import { authOptions } from "@/config/authConfig";
import { AUTH } from "@/authorities";
import { I18nProvider } from "@/i18n";


export const metadata: Metadata = {
title: "圖表報告",
};

export default async function ChartLayout({
export default function ChartLayout({
children, children,
}: { }: {
children: React.ReactNode; children: React.ReactNode;
}) { }) {
const session = await getServerSession(authOptions);
const abilities = session?.user?.abilities ?? [];
const canViewCharts =
abilities.includes(AUTH.TESTING) || abilities.includes(AUTH.ADMIN);
if (!canViewCharts) {
redirect("/dashboard");
}
return <>{children}</>;
return (
<I18nProvider namespaces={["chart", "navigation", "common"]}>
{children}
</I18nProvider>
);
} }

+ 1
- 1
src/app/(main)/dashboard/page.tsx Näytä tiedosto

@@ -18,7 +18,7 @@ const Dashboard: React.FC<Props> = async ({ searchParams }) => {
fetchEscalationLogsByUser() fetchEscalationLogsByUser()


return ( return (
<I18nProvider namespaces={["dashboard", "common", "purchaseOrder"]}>
<I18nProvider namespaces={["dashboard","navigation","common","purchaseOrder"]}>
<Suspense fallback={<DashboardPage.Loading />}> <Suspense fallback={<DashboardPage.Loading />}>
<DashboardPage searchParams={searchParams} /> <DashboardPage searchParams={searchParams} />
</Suspense> </Suspense>


+ 1
- 1
src/app/(main)/do/edit/page.tsx Näytä tiedosto

@@ -24,7 +24,7 @@ const DoEdit: React.FC<Props> = async ({ searchParams }) => {
return ( return (
<> <>
<PageTitleBar title={t("Edit Delivery Order Detail")} className="mb-4" /> <PageTitleBar title={t("Edit Delivery Order Detail")} className="mb-4" />
<I18nProvider namespaces={["do", "common"]}>
<I18nProvider namespaces={["do","navigation","common"]}>
<Suspense fallback={<DoDetail.Loading />}> <Suspense fallback={<DoDetail.Loading />}>
<DoDetail id={parseInt(id)} /> <DoDetail id={parseInt(id)} />
</Suspense> </Suspense>


+ 1
- 1
src/app/(main)/do/page.tsx Näytä tiedosto

@@ -17,7 +17,7 @@ const DeliveryOrder: React.FC = async () => {
return ( return (
<> <>
<PageTitleBar title={t("Delivery Order")} className="mb-4" /> <PageTitleBar title={t("Delivery Order")} className="mb-4" />
<I18nProvider namespaces={["do", "common"]}>
<I18nProvider namespaces={["do","navigation","common"]}>
<Suspense fallback={<DoSearch.Loading />}> <Suspense fallback={<DoSearch.Loading />}>
<DoSearch /> <DoSearch />
</Suspense> </Suspense>


+ 2
- 2
src/app/(main)/doworkbench/edit/page.tsx Näytä tiedosto

@@ -15,7 +15,7 @@ export const metadata: Metadata = {
type Props = SearchParams; type Props = SearchParams;


const Page: React.FC<Props> = async ({ searchParams }) => { const Page: React.FC<Props> = async ({ searchParams }) => {
const { t } = await getServerI18n("do");
const { t } = await getServerI18n("doWorkbench");
const id = searchParams["id"]; const id = searchParams["id"];


if (!id || isArray(id) || !isFinite(parseInt(id))) { if (!id || isArray(id) || !isFinite(parseInt(id))) {
@@ -34,7 +34,7 @@ const Page: React.FC<Props> = async ({ searchParams }) => {
{t("DO Workbench Search", { defaultValue: "DO Workbench Search" })} {t("DO Workbench Search", { defaultValue: "DO Workbench Search" })}
</Link> </Link>
</p> </p>
<I18nProvider namespaces={["do", "common"]}>
<I18nProvider namespaces={["doWorkbench","navigation","common","do"]}>
<Suspense fallback={<DoDetail.Loading />}> <Suspense fallback={<DoDetail.Loading />}>
<DoDetail id={parseInt(id)} workbenchRelease /> <DoDetail id={parseInt(id)} workbenchRelease />
</Suspense> </Suspense>


+ 2
- 2
src/app/(main)/doworkbench/page.tsx Näytä tiedosto

@@ -9,13 +9,13 @@ export const metadata: Metadata = {
}; };


const DoWorkbenchPage: React.FC = async () => { const DoWorkbenchPage: React.FC = async () => {
const { t } = await getServerI18n("do");
const { t } = await getServerI18n("doWorkbench");
const printerCombo = await fetchPrinterCombo(); const printerCombo = await fetchPrinterCombo();


return ( return (
<> <>
<PageTitleBar title={t("DO Workbench", { defaultValue: "DO Workbench" })} className="mb-4" /> <PageTitleBar title={t("DO Workbench", { defaultValue: "DO Workbench" })} className="mb-4" />
<I18nProvider namespaces={["pickOrder", "common", "ticketReleaseTable", "do"]}>
<I18nProvider namespaces={["doWorkbench","navigation","common","pickOrder","ticketReleaseTable","do"]}>
<DoWorkbenchTabs printerCombo={printerCombo ?? []} /> <DoWorkbenchTabs printerCombo={printerCombo ?? []} />
</I18nProvider> </I18nProvider>
</> </>


+ 1
- 1
src/app/(main)/doworkbenchsearch/page.tsx Näytä tiedosto

@@ -19,7 +19,7 @@ const DoWorkbenchSearchPage: React.FC = async () => {
title={t("DO Workbench Search", { defaultValue: "DO Workbench Search" })} title={t("DO Workbench Search", { defaultValue: "DO Workbench Search" })}
className="mb-4" className="mb-4"
/> />
<I18nProvider namespaces={["do", "common"]}>
<I18nProvider namespaces={["doWorkbench","navigation","common","do"]}>
<Suspense fallback={<GeneralLoading />}> <Suspense fallback={<GeneralLoading />}>
<DoSearchWorkbench /> <DoSearchWorkbench />
</Suspense> </Suspense>


+ 2
- 2
src/app/(main)/finishedGood/detail/page.tsx Näytä tiedosto

@@ -12,13 +12,13 @@ export const metadata: Metadata = {
type Props = {} & SearchParams; type Props = {} & SearchParams;


const PickOrder: React.FC<Props> = async ({ searchParams }) => { const PickOrder: React.FC<Props> = async ({ searchParams }) => {
const { t } = await getServerI18n("pickOrder");
const { t } = await getServerI18n("finishedGood");






return ( return (
<> <>
<I18nProvider namespaces={["pickOrder", "common", "ticketReleaseTable"]}>
<I18nProvider namespaces={["finishedGood","navigation","common","pickOrder","ticketReleaseTable"]}>
<Suspense fallback={<FinishedGoodSearchWrapper.Loading />}> <Suspense fallback={<FinishedGoodSearchWrapper.Loading />}>
<FinishedGoodSearchWrapper /> <FinishedGoodSearchWrapper />
</Suspense> </Suspense>


+ 1
- 1
src/app/(main)/finishedGood/management/page.tsx Näytä tiedosto

@@ -18,7 +18,7 @@ const Page = async () => {
redirect("/dashboard"); redirect("/dashboard");
} }
return ( return (
<I18nProvider namespaces={["common"]}>
<I18nProvider namespaces={["finishedgoodmanagement", "navigation"]}>
<Suspense fallback={<FinishedGoodManagement.Loading />}> <Suspense fallback={<FinishedGoodManagement.Loading />}>
<FinishedGoodManagement /> <FinishedGoodManagement />
</Suspense> </Suspense>


+ 2
- 2
src/app/(main)/finishedGood/page.tsx Näytä tiedosto

@@ -11,13 +11,13 @@ export const metadata: Metadata = {
}; };


const PickOrder: React.FC = async () => { const PickOrder: React.FC = async () => {
const { t } = await getServerI18n("pickOrder");
const { t } = await getServerI18n("finishedGood");


//PreloadPickOrder(); //PreloadPickOrder();


return ( return (
<> <>
<I18nProvider namespaces={["pickOrder", "common", "ticketReleaseTable"]}>
<I18nProvider namespaces={["finishedGood","navigation","common","pickOrder","ticketReleaseTable"]}>
<Suspense fallback={<FinishedGoodSearch.Loading />}> <Suspense fallback={<FinishedGoodSearch.Loading />}>
<FinishedGoodSearch /> <FinishedGoodSearch />
</Suspense> </Suspense>


+ 2
- 2
src/app/(main)/inventory/page.tsx Näytä tiedosto

@@ -14,7 +14,7 @@ export const metadata: Metadata = {
}; };


const Inventory: React.FC = async () => { const Inventory: React.FC = async () => {
const { t } = await getServerI18n("inventory", "common");
const { t } = await getServerI18n("inventory");


preloadInventory(); preloadInventory();


@@ -30,7 +30,7 @@ const Inventory: React.FC = async () => {
{t("Inventory")} {t("Inventory")}
</Typography> </Typography>
</Stack> </Stack>
<I18nProvider namespaces={["common", "inventory"]}>
<I18nProvider namespaces={["inventory","navigation","common"]}>
<Suspense fallback={<InventorySearch.Loading />}> <Suspense fallback={<InventorySearch.Loading />}>
<InventorySearch /> <InventorySearch />
</Suspense> </Suspense>


+ 1
- 1
src/app/(main)/jo/edit/page.tsx Näytä tiedosto

@@ -39,7 +39,7 @@ const JoEdit: React.FC<Props> = async ({ searchParams }) => {
return ( return (
<> <>
<PageTitleBar title={t("Edit Job Order Detail")} className="mb-4" /> <PageTitleBar title={t("Edit Job Order Detail")} className="mb-4" />
<I18nProvider namespaces={["jo", "common"]}>
<I18nProvider namespaces={["jo","navigation","common"]}>
<Suspense fallback={<JoSave.Loading />}> <Suspense fallback={<JoSave.Loading />}>
<JoSave id={parseInt(id)} /> <JoSave id={parseInt(id)} />
</Suspense> </Suspense>


+ 1
- 1
src/app/(main)/jo/page.tsx Näytä tiedosto

@@ -32,7 +32,7 @@ const Jo: React.FC = async () => {
return ( return (
<> <>
<PageTitleBar title={t("Search Job Order/ Create Job Order")} className="mb-4" /> <PageTitleBar title={t("Search Job Order/ Create Job Order")} className="mb-4" />
<I18nProvider namespaces={["jo", "common", "purchaseOrder", "dashboard"]}>
<I18nProvider namespaces={["jo","navigation","common","purchaseOrder","dashboard"]}>
<Suspense fallback={<GeneralLoading />}> <Suspense fallback={<GeneralLoading />}>
<JoWorkbenchSearch <JoWorkbenchSearch
defaultInputs={defaultInputs} defaultInputs={defaultInputs}


+ 1
- 1
src/app/(main)/jo/workbench/page.tsx Näytä tiedosto

@@ -18,7 +18,7 @@ const JoWorkbenchPage = async () => {
return ( return (
<> <>
<PageTitleBar title={t("Job Order Pickexcution", { defaultValue: "Job Order Pickexcution" })} className="mb-4" /> <PageTitleBar title={t("Job Order Pickexcution", { defaultValue: "Job Order Pickexcution" })} className="mb-4" />
<I18nProvider namespaces={["jo", "common", "pickOrder", "purchaseOrder", "dashboard"]}>
<I18nProvider namespaces={["jo","navigation","common","pickOrder","purchaseOrder","dashboard"]}>
<Suspense fallback={<GeneralLoading />}> <Suspense fallback={<GeneralLoading />}>
<JoPickOrderList printerCombo={printerCombo ?? []} /> <JoPickOrderList printerCombo={printerCombo ?? []} />
</Suspense> </Suspense>


+ 1
- 1
src/app/(main)/jodetail/edit/page.tsx Näytä tiedosto

@@ -38,7 +38,7 @@ const JodetailEdit: React.FC<Props> = async ({ searchParams }) => {
return ( return (
<> <>
<PageTitleBar title={t("Edit Job Order Detail")} className="mb-4" /> <PageTitleBar title={t("Edit Job Order Detail")} className="mb-4" />
<I18nProvider namespaces={["jo", "common"]}>
<I18nProvider namespaces={["jo","navigation","common"]}>
<Suspense fallback={<GeneralLoading />}> <Suspense fallback={<GeneralLoading />}>
<JoSave id={parseInt(id)} defaultValues={undefined} /> <JoSave id={parseInt(id)} defaultValues={undefined} />
</Suspense> </Suspense>


+ 1
- 1
src/app/(main)/jodetail/page.tsx Näytä tiedosto

@@ -18,7 +18,7 @@ const Jodetail: React.FC = async () => {
return ( return (
<> <>
<PageTitleBar title={t("Job Order Pick Execution")} className="mb-4" /> <PageTitleBar title={t("Job Order Pick Execution")} className="mb-4" />
<I18nProvider namespaces={["jo", "common", "pickOrder"]}>
<I18nProvider namespaces={["jo","navigation","common","pickOrder"]}>
<Suspense fallback={<GeneralLoading />}> <Suspense fallback={<GeneralLoading />}>
<JodetailSearchWrapper /> <JodetailSearchWrapper />
</Suspense> </Suspense>


+ 6
- 8
src/app/(main)/laserPrint/page.tsx Näytä tiedosto

@@ -1,23 +1,21 @@
import { I18nProvider } from "@/i18n";
import { Metadata } from "next";
import LaserPrintSearch from "@/components/LaserPrint/LaserPrintSearch"; import LaserPrintSearch from "@/components/LaserPrint/LaserPrintSearch";
import { Stack, Typography } from "@mui/material"; import { Stack, Typography } from "@mui/material";
import { Metadata } from "next";
import React from "react";


export const metadata: Metadata = { export const metadata: Metadata = {
title: "檸檬機(激光機)", title: "檸檬機(激光機)",
}; };


const LaserPrintPage: React.FC = () => {
export default async function LaserPrintPage() {
return ( return (
<>
<I18nProvider namespaces={["laserPrint", "navigation", "common"]}>
<Stack direction="row" justifyContent="space-between" flexWrap="wrap" rowGap={2}> <Stack direction="row" justifyContent="space-between" flexWrap="wrap" rowGap={2}>
<Typography variant="h4" marginInlineEnd={2}> <Typography variant="h4" marginInlineEnd={2}>
檸檬機(激光機) 檸檬機(激光機)
</Typography> </Typography>
</Stack> </Stack>
<LaserPrintSearch /> <LaserPrintSearch />
</>
</I18nProvider>
); );
};

export default LaserPrintPage;
}

+ 1
- 1
src/app/(main)/layout.tsx Näytä tiedosto

@@ -48,7 +48,7 @@ export default async function MainLayout({
/> />
} }
mainContent={ mainContent={
<I18nProvider namespaces={["common"]}>
<I18nProvider namespaces={["navigation", "common"]}>
<MainContentArea>{children}</MainContentArea> <MainContentArea>{children}</MainContentArea>
</I18nProvider> </I18nProvider>
} }


+ 7
- 16
src/app/(main)/m18Syn/layout.tsx Näytä tiedosto

@@ -1,22 +1,13 @@
import { Metadata } from "next";
import { getServerSession } from "next-auth";
import { redirect } from "next/navigation";
import { authOptions } from "@/config/authConfig";
import { AUTH } from "@/authorities";
import { I18nProvider } from "@/i18n";


export const metadata: Metadata = {
title: "M18 Sync",
};

export default async function M18SynLayout({
export default function M18SyncLayout({
children, children,
}: { }: {
children: React.ReactNode; children: React.ReactNode;
}) { }) {
const session = await getServerSession(authOptions);
const abilities = session?.user?.abilities ?? [];
if (!abilities.includes(AUTH.ADMIN)) {
redirect("/dashboard");
}
return <>{children}</>;
return (
<I18nProvider namespaces={["m18Sync", "navigation", "common"]}>
{children}
</I18nProvider>
);
} }

+ 1
- 1
src/app/(main)/pickOrder/detail/page.tsx Näytä tiedosto

@@ -18,7 +18,7 @@ const PickOrder: React.FC<Props> = async ({ searchParams }) => {


return ( return (
<> <>
<I18nProvider namespaces={["pickOrder"]}>
<I18nProvider namespaces={["pickOrder","navigation","common"]}>
<Suspense fallback={<PickOrderDetail.Loading />}> <Suspense fallback={<PickOrderDetail.Loading />}>
<PickOrderDetail consoCode={`${searchParams["consoCode"]}`} /> <PickOrderDetail consoCode={`${searchParams["consoCode"]}`} />
</Suspense> </Suspense>


+ 1
- 1
src/app/(main)/pickOrder/page.tsx Näytä tiedosto

@@ -17,7 +17,7 @@ const PickOrder: React.FC = async () => {


return ( return (
<> <>
<I18nProvider namespaces={["pickOrder", "common"]}>
<I18nProvider namespaces={["pickOrder","navigation","common"]}>
<Suspense fallback={<PickOrderSearch.Loading />}> <Suspense fallback={<PickOrderSearch.Loading />}>
<PickOrderSearch /> <PickOrderSearch />
</Suspense> </Suspense>


+ 1
- 1
src/app/(main)/po/edit/page.tsx Näytä tiedosto

@@ -31,7 +31,7 @@ const PoEdit: React.FC<Props> = async ({ searchParams }) => {
return ( return (
<> <>
{/* <Typography variant="h4">{t("Create Material")}</Typography> */} {/* <Typography variant="h4">{t("Create Material")}</Typography> */}
<I18nProvider namespaces={[type, "dashboard"]}>
<I18nProvider namespaces={[type, "navigation", "common", "dashboard"]}>
<Suspense fallback={<PoDetail.Loading />}> <Suspense fallback={<PoDetail.Loading />}>
<PoDetail id={id} /> <PoDetail id={id} />
</Suspense> </Suspense>


+ 1
- 1
src/app/(main)/po/page.tsx Näytä tiedosto

@@ -17,7 +17,7 @@ const PurchaseOrder: React.FC = async () => {
// preloadClaims(); // preloadClaims();
return ( return (
<> <>
<I18nProvider namespaces={["purchaseOrder", "common", "items","dashboard"]}>
<I18nProvider namespaces={["purchaseOrder","navigation","common","dashboard"]}>
<Stack <Stack
direction="row" direction="row"
justifyContent="space-between" justifyContent="space-between"


+ 1
- 1
src/app/(main)/po/workbench/page.tsx Näytä tiedosto

@@ -17,7 +17,7 @@ export default function PoWorkbenchPage() {
flexDirection: "column", flexDirection: "column",
}} }}
> >
<I18nProvider namespaces={["poWorkbench", "purchaseOrder", "common"]}>
<I18nProvider namespaces={["poWorkbench","navigation","common","purchaseOrder"]}>
<PoWorkbenchPageClient /> <PoWorkbenchPageClient />
</I18nProvider> </I18nProvider>
</Box> </Box>


+ 2
- 2
src/app/(main)/production/page.tsx Näytä tiedosto

@@ -15,7 +15,7 @@ export const metadata: Metadata = {
}; };


const production: React.FC = async () => { const production: React.FC = async () => {
const { t } = await getServerI18n("common");
const { t } = await getServerI18n("production", "common");
const printerCombo = await fetchPrinterCombo(); const printerCombo = await fetchPrinterCombo();
return ( return (
<> <>
@@ -38,7 +38,7 @@ const production: React.FC = async () => {
{t("Create Process")} {t("Create Process")}
</Button> */} </Button> */}
</Stack> </Stack>
<I18nProvider namespaces={["common", "production","purchaseOrder","jo"]}>
<I18nProvider namespaces={["production","productionProcess","navigation","common","purchaseOrder","jo"]}>
<ProductionProcessPage printerCombo={printerCombo} /> {/* Use new component */} <ProductionProcessPage printerCombo={printerCombo} /> {/* Use new component */}
</I18nProvider> </I18nProvider>
</> </>


+ 2
- 2
src/app/(main)/productionProcess/page.tsx Näytä tiedosto

@@ -13,7 +13,7 @@ export const metadata: Metadata = {
}; };


const productionProcess: React.FC = async () => { const productionProcess: React.FC = async () => {
const { t } = await getServerI18n("common");
const { t } = await getServerI18n("productionProcess", "navigation", "common");
const printerCombo = await fetchPrinterCombo(); const printerCombo = await fetchPrinterCombo();
return ( return (
<> <>
@@ -36,7 +36,7 @@ const productionProcess: React.FC = async () => {
{t("Create Process")} {t("Create Process")}
</Button> */} </Button> */}
</Stack> </Stack>
<I18nProvider namespaces={["common", "production","purchaseOrder","jo","dashboard"]}>
<I18nProvider namespaces={["productionProcess","navigation","common","purchaseOrder","jo","dashboard"]}>
<Suspense fallback={<ProductionProcessLoading />}> <Suspense fallback={<ProductionProcessLoading />}>
<ProductionProcessPage printerCombo={printerCombo} /> <ProductionProcessPage printerCombo={printerCombo} />
</Suspense> </Suspense>


+ 2
- 2
src/app/(main)/projects/create/page.tsx Näytä tiedosto

@@ -11,12 +11,12 @@ export const metadata: Metadata = {
}; };


const Projects: React.FC = async () => { const Projects: React.FC = async () => {
const { t } = await getServerI18n("projects");
const { t } = await getServerI18n("project");


return ( return (
<> <>
<Typography variant="h4">{t("Create Project")}</Typography> <Typography variant="h4">{t("Create Project")}</Typography>
<I18nProvider namespaces={["projects"]}>
<I18nProvider namespaces={["project","navigation","common"]}>
<CreateProject /> <CreateProject />
</I18nProvider> </I18nProvider>
</> </>


+ 2
- 2
src/app/(main)/projects/page.tsx Näytä tiedosto

@@ -20,7 +20,7 @@ export const metadata: Metadata = {
}; };


const Projects: React.FC = async () => { const Projects: React.FC = async () => {
const { t } = await getServerI18n("projects");
const { t } = await getServerI18n("project");
preloadProjects(); preloadProjects();


return ( return (
@@ -43,7 +43,7 @@ const Projects: React.FC = async () => {
{t("Create Project")} {t("Create Project")}
</Button> </Button>
</Stack> </Stack>
<I18nProvider namespaces={["project"]}>
<I18nProvider namespaces={["project","navigation","common"]}>
<Suspense fallback={<ProjectSearch.Loading />}> <Suspense fallback={<ProjectSearch.Loading />}>
<ProjectSearch /> <ProjectSearch />
</Suspense> </Suspense>


+ 13
- 0
src/app/(main)/ps/layout.tsx Näytä tiedosto

@@ -0,0 +1,13 @@
import { I18nProvider } from "@/i18n";

export default function PsLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<I18nProvider namespaces={["scheduling", "navigation", "common"]}>
{children}
</I18nProvider>
);
}

+ 1
- 1
src/app/(main)/ps/page.tsx Näytä tiedosto

@@ -619,7 +619,7 @@ export default function ProductionSchedulePage() {
return ( return (
<div className="space-y-4"> <div className="space-y-4">
<PageTitleBar <PageTitleBar
title="排程"
title="生產排程"
actions={ actions={
<> <>
<button <button


+ 1
- 1
src/app/(main)/putAway/page.tsx Näytä tiedosto

@@ -28,7 +28,7 @@ const PutAway: React.FC = async () => {
{t("Put Away")} {t("Put Away")}
</Typography> </Typography>
</Stack> </Stack>
<I18nProvider namespaces={["putAway", "purchaseOrder", "common"]}>
<I18nProvider namespaces={["putAway","navigation","common","purchaseOrder"]}>
<Suspense fallback={<PutAwayScan.Loading />}> <Suspense fallback={<PutAwayScan.Loading />}>
<PutAwayScan /> <PutAwayScan />
</Suspense> </Suspense>


+ 1
- 1
src/app/(main)/putAwayCam/page.tsx Näytä tiedosto

@@ -24,7 +24,7 @@ const PutAwayCamPage: React.FC = async () => {
{t("Put Away")} {t("Put Away")}
</Typography> </Typography>
</Stack> </Stack>
<I18nProvider namespaces={["putAway", "purchaseOrder", "common"]}>
<I18nProvider namespaces={["putAway","navigation","common","purchaseOrder"]}>
<Suspense fallback={<PutAwayCamScanWrapper.Loading />}> <Suspense fallback={<PutAwayCamScanWrapper.Loading />}>
<PutAwayCamScanWrapper /> <PutAwayCamScanWrapper />
</Suspense> </Suspense>


+ 13
- 0
src/app/(main)/report/layout.tsx Näytä tiedosto

@@ -0,0 +1,13 @@
import { I18nProvider } from "@/i18n";

export default function ReportLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<I18nProvider namespaces={["report", "navigation", "common"]}>
{children}
</I18nProvider>
);
}

+ 1
- 1
src/app/(main)/scheduling/detailed/edit/page.tsx Näytä tiedosto

@@ -45,7 +45,7 @@ const DetailScheduling: React.FC<Props> = async ({ searchParams }) => {
<Typography variant="h4" marginInlineEnd={2}> <Typography variant="h4" marginInlineEnd={2}>
{t("FG Production Schedule")} {t("FG Production Schedule")}
</Typography> </Typography>
<I18nProvider namespaces={["schedule", "common"]}>
<I18nProvider namespaces={["schedule","navigation","common"]}>
<Suspense fallback={<DetailedScheduleDetail.Loading />}> <Suspense fallback={<DetailedScheduleDetail.Loading />}>
<DetailedScheduleDetail type={type} id={parseInt(id)} /> <DetailedScheduleDetail type={type} id={parseInt(id)} />
</Suspense> </Suspense>


+ 1
- 1
src/app/(main)/scheduling/detailed/page.tsx Näytä tiedosto

@@ -31,7 +31,7 @@ const DetailScheduling: React.FC = async () => {
{t("Detail Scheduling")} {t("Detail Scheduling")}
</Typography> </Typography>
</Stack> </Stack>
<I18nProvider namespaces={["schedule", "common"]}>
<I18nProvider namespaces={["schedule","navigation","common"]}>
<Suspense fallback={<DetailedSchedule.Loading />}> <Suspense fallback={<DetailedSchedule.Loading />}>
<DetailedSchedule type={type} /> <DetailedSchedule type={type} />
</Suspense> </Suspense>


+ 1
- 1
src/app/(main)/scheduling/rough/edit/page.tsx Näytä tiedosto

@@ -62,7 +62,7 @@ const roughSchedulingDetail: React.FC<Props> = async ({ searchParams }) => {
{t("Create product")} {t("Create product")}
</Button> */} </Button> */}
</Stack> </Stack>
<I18nProvider namespaces={["schedule", "common"]}>
<I18nProvider namespaces={["schedule","navigation","common"]}>
<Suspense fallback={<RoughScheduleDetailView.Loading />}> <Suspense fallback={<RoughScheduleDetailView.Loading />}>
<RoughScheduleDetailView type={type} id={parseInt(id)} /> <RoughScheduleDetailView type={type} id={parseInt(id)} />
</Suspense> </Suspense>


+ 1
- 1
src/app/(main)/scheduling/rough/page.tsx Näytä tiedosto

@@ -47,7 +47,7 @@ const roughScheduling: React.FC = async () => {
{t("Test Rough Scheduling")} {t("Test Rough Scheduling")}
</Button> */} </Button> */}
</Stack> </Stack>
<I18nProvider namespaces={["schedule", "common"]}>
<I18nProvider namespaces={["schedule","navigation","common"]}>
<Suspense fallback={<RoughSchedule.Loading />}> <Suspense fallback={<RoughSchedule.Loading />}>
<RoughSchedule type={type} /> <RoughSchedule type={type} />
</Suspense> </Suspense>


+ 2
- 2
src/app/(main)/settings/bomWeighting/page.tsx Näytä tiedosto

@@ -9,13 +9,13 @@ export const metadata: Metadata = {
}; };


const BomWeightingScorePage: React.FC = async () => { const BomWeightingScorePage: React.FC = async () => {
const { t } = await getServerI18n("common");
const { t } = await getServerI18n("bomWeighting");
const bomWeightingScores = await fetchBomWeightingScores(); const bomWeightingScores = await fetchBomWeightingScores();


return ( return (
<> <>
<PageTitleBar title={t("BOM Weighting Score List")} className="mb-4" /> <PageTitleBar title={t("BOM Weighting Score List")} className="mb-4" />
<I18nProvider namespaces={["common"]}>
<I18nProvider namespaces={["bomWeighting","navigation","common"]}>
<BomWeightingTabs bomWeightingScores={bomWeightingScores} /> <BomWeightingTabs bomWeightingScores={bomWeightingScores} />
</I18nProvider> </I18nProvider>
</> </>


+ 6
- 1
src/app/(main)/settings/clientMonitor/page.tsx Näytä tiedosto

@@ -1,3 +1,4 @@
import { I18nProvider } from "@/i18n";
import ClientMonitorPage from "@/components/ClientMonitor/ClientMonitorPage"; import ClientMonitorPage from "@/components/ClientMonitor/ClientMonitorPage";
import { isMonitoringEnabled } from "@/config/monitoring"; import { isMonitoringEnabled } from "@/config/monitoring";
import { Metadata } from "next"; import { Metadata } from "next";
@@ -11,5 +12,9 @@ export default function ClientMonitorRoutePage() {
if (!isMonitoringEnabled) { if (!isMonitoringEnabled) {
redirect("/settings/user"); redirect("/settings/user");
} }
return <ClientMonitorPage />;
return (
<I18nProvider namespaces={["clientMonitor", "navigation", "common"]}>
<ClientMonitorPage />
</I18nProvider>
);
} }

+ 2
- 2
src/app/(main)/settings/deliveryOrderFloor/page.tsx Näytä tiedosto

@@ -8,10 +8,10 @@ export const metadata: Metadata = {
}; };


export default async function DeliveryOrderFloorPage() { export default async function DeliveryOrderFloorPage() {
const { t } = await getServerI18n("deliveryOrderFloor", "common");
const { t } = await getServerI18n("deliveryOrderFloor");


return ( return (
<I18nProvider namespaces={["deliveryOrderFloor", "common"]}>
<I18nProvider namespaces={["deliveryOrderFloor","navigation"]}>
<Stack spacing={2}> <Stack spacing={2}>
<Typography variant="h4">{t("title")}</Typography> <Typography variant="h4">{t("title")}</Typography>
<DeliveryOrderFloorSettings /> <DeliveryOrderFloorSettings />


+ 1
- 1
src/app/(main)/settings/equipment/EquipmentTabs.tsx Näytä tiedosto

@@ -13,7 +13,7 @@ type EquipmentTabsProps = {
const EquipmentTabs: React.FC<EquipmentTabsProps> = ({ onTabChange }) => { const EquipmentTabs: React.FC<EquipmentTabsProps> = ({ onTabChange }) => {
const router = useRouter(); const router = useRouter();
const searchParams = useSearchParams(); const searchParams = useSearchParams();
const { t } = useTranslation("common");
const { t } = useTranslation(["equipment", "common"]);
const tabFromUrl = searchParams.get("tab"); const tabFromUrl = searchParams.get("tab");
const initialTabIndex = tabFromUrl ? parseInt(tabFromUrl, 10) : 0; const initialTabIndex = tabFromUrl ? parseInt(tabFromUrl, 10) : 0;


+ 3
- 3
src/app/(main)/settings/equipment/MaintenanceEdit/page.tsx Näytä tiedosto

@@ -9,8 +9,8 @@ import UpdateMaintenanceForm from "@/components/UpdateMaintenance/UpdateMaintena
type Props = {} & SearchParams; type Props = {} & SearchParams;


const MaintenanceEditPage: React.FC<Props> = async ({ searchParams }) => { const MaintenanceEditPage: React.FC<Props> = async ({ searchParams }) => {
const type = "common";
const { t } = await getServerI18n(type);
const type = "equipment";
const { t } = await getServerI18n(type, "navigation", "common");
const id = isString(searchParams["id"]) const id = isString(searchParams["id"])
? parseInt(searchParams["id"]) ? parseInt(searchParams["id"])
: undefined; : undefined;
@@ -20,7 +20,7 @@ const MaintenanceEditPage: React.FC<Props> = async ({ searchParams }) => {
return ( return (
<> <>
<Typography variant="h4">{t("Update Equipment Maintenance and Repair")}</Typography> <Typography variant="h4">{t("Update Equipment Maintenance and Repair")}</Typography>
<I18nProvider namespaces={[type]}>
<I18nProvider namespaces={[type, "navigation", "common"]}>
<UpdateMaintenanceForm id={id} /> <UpdateMaintenanceForm id={id} />
</I18nProvider> </I18nProvider>
</> </>


+ 2
- 2
src/app/(main)/settings/equipment/create/page.tsx Näytä tiedosto

@@ -9,11 +9,11 @@ type Props = {} & SearchParams;


const materialSetting: React.FC<Props> = async ({ searchParams }) => { const materialSetting: React.FC<Props> = async ({ searchParams }) => {
// const type = TypeEnum.PRODUCT; // const type = TypeEnum.PRODUCT;
const { t } = await getServerI18n("common");
const { t } = await getServerI18n("equipment", "navigation", "common");
return ( return (
<> <>
{/* <Typography variant="h4">{t("Create Material")}</Typography> */} {/* <Typography variant="h4">{t("Create Material")}</Typography> */}
<I18nProvider namespaces={["common"]}>
<I18nProvider namespaces={["equipment","navigation","common"]}>
<CreateEquipmentType /> <CreateEquipmentType />
</I18nProvider> </I18nProvider>
</> </>


+ 3
- 3
src/app/(main)/settings/equipment/edit/page.tsx Näytä tiedosto

@@ -9,8 +9,8 @@ import { notFound } from "next/navigation";
type Props = {} & SearchParams; type Props = {} & SearchParams;


const productSetting: React.FC<Props> = async ({ searchParams }) => { const productSetting: React.FC<Props> = async ({ searchParams }) => {
const type = "common";
const { t } = await getServerI18n(type);
const type = "equipment";
const { t } = await getServerI18n(type, "navigation", "common");
const id = isString(searchParams["id"]) const id = isString(searchParams["id"])
? parseInt(searchParams["id"]) ? parseInt(searchParams["id"])
: undefined; : undefined;
@@ -20,7 +20,7 @@ const productSetting: React.FC<Props> = async ({ searchParams }) => {
return ( return (
<> <>
{/* <Typography variant="h4">{t("Create Material")}</Typography> */} {/* <Typography variant="h4">{t("Create Material")}</Typography> */}
<I18nProvider namespaces={[type]}>
<I18nProvider namespaces={[type, "navigation", "common"]}>
<CreateEquipmentType id={id} /> <CreateEquipmentType id={id} />
</I18nProvider> </I18nProvider>
</> </>


+ 3
- 3
src/app/(main)/settings/equipment/page.tsx Näytä tiedosto

@@ -19,8 +19,8 @@ export const metadata: Metadata = {
}; };


const productSetting: React.FC = async () => { const productSetting: React.FC = async () => {
const type = "common";
const { t } = await getServerI18n(type);
const type = "equipment";
const { t } = await getServerI18n(type, "navigation", "common");


return ( return (
<> <>
@@ -35,7 +35,7 @@ const productSetting: React.FC = async () => {
</Typography> </Typography>
</Stack> </Stack>
<Suspense fallback={<EquipmentSearchLoading />}> <Suspense fallback={<EquipmentSearchLoading />}>
<I18nProvider namespaces={["common", "project"]}>
<I18nProvider namespaces={["equipment","navigation","common","project"]}>
<EquipmentSearchWrapper /> <EquipmentSearchWrapper />
</I18nProvider> </I18nProvider>
</Suspense> </Suspense>


+ 2
- 2
src/app/(main)/settings/equipmentType/create/page.tsx Näytä tiedosto

@@ -9,11 +9,11 @@ type Props = {} & SearchParams;


const materialSetting: React.FC<Props> = async ({ searchParams }) => { const materialSetting: React.FC<Props> = async ({ searchParams }) => {
// const type = TypeEnum.PRODUCT; // const type = TypeEnum.PRODUCT;
const { t } = await getServerI18n("common");
const { t } = await getServerI18n("equipment", "navigation", "common");
return ( return (
<> <>
{/* <Typography variant="h4">{t("Create Material")}</Typography> */} {/* <Typography variant="h4">{t("Create Material")}</Typography> */}
<I18nProvider namespaces={["common"]}>
<I18nProvider namespaces={["equipment","navigation","common"]}>
<CreateEquipmentType /> <CreateEquipmentType />
</I18nProvider> </I18nProvider>
</> </>


+ 3
- 3
src/app/(main)/settings/equipmentType/edit/page.tsx Näytä tiedosto

@@ -9,8 +9,8 @@ import { notFound } from "next/navigation";
type Props = {} & SearchParams; type Props = {} & SearchParams;


const productSetting: React.FC<Props> = async ({ searchParams }) => { const productSetting: React.FC<Props> = async ({ searchParams }) => {
const type = "common";
const { t } = await getServerI18n(type);
const type = "equipment";
const { t } = await getServerI18n(type, "navigation", "common");
const id = isString(searchParams["id"]) const id = isString(searchParams["id"])
? parseInt(searchParams["id"]) ? parseInt(searchParams["id"])
: undefined; : undefined;
@@ -20,7 +20,7 @@ const productSetting: React.FC<Props> = async ({ searchParams }) => {
return ( return (
<> <>
{/* <Typography variant="h4">{t("Create Material")}</Typography> */} {/* <Typography variant="h4">{t("Create Material")}</Typography> */}
<I18nProvider namespaces={[type]}>
<I18nProvider namespaces={[type, "navigation", "common"]}>
<CreateEquipmentType id={id} /> <CreateEquipmentType id={id} />
</I18nProvider> </I18nProvider>
</> </>


+ 3
- 3
src/app/(main)/settings/equipmentType/page.tsx Näytä tiedosto

@@ -15,8 +15,8 @@ export const metadata: Metadata = {
}; };


const productSetting: React.FC = async () => { const productSetting: React.FC = async () => {
const type = "common";
const { t } = await getServerI18n(type);
const type = "equipment";
const { t } = await getServerI18n(type, "navigation", "common");
const equipmentTypes = await fetchAllEquipmentTypes(); const equipmentTypes = await fetchAllEquipmentTypes();
// preloadClaims(); // preloadClaims();


@@ -41,7 +41,7 @@ const productSetting: React.FC = async () => {
</Button> */} </Button> */}
</Stack> </Stack>
<Suspense fallback={<EquipmentTypeSearch.Loading />}> <Suspense fallback={<EquipmentTypeSearch.Loading />}>
<I18nProvider namespaces={["common", "project"]}>
<I18nProvider namespaces={["equipment","navigation","common","project"]}>
<EquipmentTypeSearch /> <EquipmentTypeSearch />
</I18nProvider> </I18nProvider>
</Suspense> </Suspense>


+ 4
- 4
src/app/(main)/settings/importBom/MaintenanceEdit/page.tsx Näytä tiedosto

@@ -9,8 +9,8 @@ import UpdateMaintenanceForm from "@/components/UpdateMaintenance/UpdateMaintena
type Props = {} & SearchParams; type Props = {} & SearchParams;


const MaintenanceEditPage: React.FC<Props> = async ({ searchParams }) => { const MaintenanceEditPage: React.FC<Props> = async ({ searchParams }) => {
const type = "common";
const { t } = await getServerI18n(type);
const type = "importBom";
const { t } = await getServerI18n(type, "navigation", "common");
const id = isString(searchParams["id"]) const id = isString(searchParams["id"])
? parseInt(searchParams["id"]) ? parseInt(searchParams["id"])
: undefined; : undefined;
@@ -20,10 +20,10 @@ const MaintenanceEditPage: React.FC<Props> = async ({ searchParams }) => {
return ( return (
<> <>
<Typography variant="h4">{t("Update Equipment Maintenance and Repair")}</Typography> <Typography variant="h4">{t("Update Equipment Maintenance and Repair")}</Typography>
<I18nProvider namespaces={[type]}>
<I18nProvider namespaces={[type, "navigation", "common"]}>
<UpdateMaintenanceForm id={id} /> <UpdateMaintenanceForm id={id} />
</I18nProvider> </I18nProvider>
</> </>
); );
}; };
export default MaintenanceEditPage;
export default MaintenanceEditPage;

+ 1
- 1
src/app/(main)/settings/importBom/create/page.tsx Näytä tiedosto

@@ -13,7 +13,7 @@ const materialSetting: React.FC<Props> = async ({ searchParams }) => {
return ( return (
<> <>
{/* <Typography variant="h4">{t("Create Material")}</Typography> */} {/* <Typography variant="h4">{t("Create Material")}</Typography> */}
<I18nProvider namespaces={["common"]}>
<I18nProvider namespaces={["importBom","navigation","common"]}>
<CreateEquipmentType /> <CreateEquipmentType />
</I18nProvider> </I18nProvider>
</> </>


+ 3
- 6
src/app/(main)/settings/importBom/edit/page.tsx Näytä tiedosto

@@ -1,16 +1,14 @@
import { SearchParams } from "@/app/utils/fetchUtil"; import { SearchParams } from "@/app/utils/fetchUtil";
import { TypeEnum } from "@/app/utils/typeEnum";
import CreateEquipmentType from "@/components/CreateEquipment"; import CreateEquipmentType from "@/components/CreateEquipment";
import { I18nProvider, getServerI18n } from "@/i18n"; import { I18nProvider, getServerI18n } from "@/i18n";
import { Typography } from "@mui/material";
import isString from "lodash/isString"; import isString from "lodash/isString";
import { notFound } from "next/navigation"; import { notFound } from "next/navigation";


type Props = {} & SearchParams; type Props = {} & SearchParams;


const productSetting: React.FC<Props> = async ({ searchParams }) => { const productSetting: React.FC<Props> = async ({ searchParams }) => {
const type = "common";
const { t } = await getServerI18n(type);
const type = "importBom";
await getServerI18n(type, "navigation", "common");
const id = isString(searchParams["id"]) const id = isString(searchParams["id"])
? parseInt(searchParams["id"]) ? parseInt(searchParams["id"])
: undefined; : undefined;
@@ -19,8 +17,7 @@ const productSetting: React.FC<Props> = async ({ searchParams }) => {
} }
return ( return (
<> <>
{/* <Typography variant="h4">{t("Create Material")}</Typography> */}
<I18nProvider namespaces={[type]}>
<I18nProvider namespaces={[type, "navigation", "common"]}>
<CreateEquipmentType id={id} /> <CreateEquipmentType id={id} />
</I18nProvider> </I18nProvider>
</> </>


+ 1
- 1
src/app/(main)/settings/importBom/page.tsx Näytä tiedosto

@@ -21,7 +21,7 @@ export default async function ImportBomPage() {
Import BOM Import BOM
</Typography> </Typography>
</Stack> </Stack>
<I18nProvider namespaces={["common"]}>
<I18nProvider namespaces={["importBom","navigation","common","importExcel"]}>
<ImportBomWrapper /> <ImportBomWrapper />
</I18nProvider> </I18nProvider>
</> </>


+ 21
- 21
src/app/(main)/settings/importExcel/page.tsx Näytä tiedosto

@@ -1,34 +1,34 @@
import { Metadata } from "next";
import { getServerI18n } from "@/i18n";
import { I18nProvider, getServerI18n } from "@/i18n";
import Stack from "@mui/material/Stack"; import Stack from "@mui/material/Stack";
import Typography from "@mui/material/Typography"; import Typography from "@mui/material/Typography";
import { Metadata } from "next";
import { Suspense } from "react"; import { Suspense } from "react";
import ExcelFileImport from "@/components/ExcelFileImport"; import ExcelFileImport from "@/components/ExcelFileImport";


export const metadata: Metadata = { export const metadata: Metadata = {
title: "Excel File Import",
title: "Excel File Import",
}; };


const ImportExcel: React.FC = async () => { const ImportExcel: React.FC = async () => {
const { t } = await getServerI18n("common");
const { t } = await getServerI18n("importExcel", "navigation", "common");


return (
<>
<Stack
direction="row"
justifyContent="space-between"
flexWrap="wrap"
rowGap={2}
>
<Typography variant="h4" marginInlineEnd={2}>
{t("Excel File Import")}
</Typography>
</Stack>
<Suspense>
<ExcelFileImport />
</Suspense>
</>
)
return (
<I18nProvider namespaces={["importExcel", "navigation", "common"]}>
<Stack
direction="row"
justifyContent="space-between"
flexWrap="wrap"
rowGap={2}
>
<Typography variant="h4" marginInlineEnd={2}>
{t("title")}
</Typography>
</Stack>
<Suspense>
<ExcelFileImport />
</Suspense>
</I18nProvider>
);
}; };


export default ImportExcel; export default ImportExcel;

+ 3
- 3
src/app/(main)/settings/itemPrice/page.tsx Näytä tiedosto

@@ -9,13 +9,13 @@ export const metadata: Metadata = {
}; };


const ItemPriceSetting: React.FC = async () => { const ItemPriceSetting: React.FC = async () => {
const { t } = await getServerI18n("inventory", "common");
const { t } = await getServerI18n("itemPrice", "importExcel");


return ( return (
<> <>
<PageTitleBar title={t("Price Inquiry", { ns: "common" })} className="mb-4" />
<PageTitleBar title={t("Price Inquiry")} className="mb-4" />


<I18nProvider namespaces={["common", "inventory"]}>
<I18nProvider namespaces={["itemPrice","navigation","common","inventory","importExcel"]}>
<Suspense fallback={<ItemPriceSearch.Loading />}> <Suspense fallback={<ItemPriceSearch.Loading />}>
<ItemPriceSearch /> <ItemPriceSearch />
</Suspense> </Suspense>


+ 1
- 1
src/app/(main)/settings/items/create/page.tsx Näytä tiedosto

@@ -13,7 +13,7 @@ const materialSetting: React.FC<Props> = async ({ searchParams }) => {
return ( return (
<> <>
{/* <Typography variant="h4">{t("Create Material")}</Typography> */} {/* <Typography variant="h4">{t("Create Material")}</Typography> */}
<I18nProvider namespaces={["items"]}>
<I18nProvider namespaces={["items","navigation","common"]}>
<CreateItem /> <CreateItem />
</I18nProvider> </I18nProvider>
</> </>


+ 1
- 1
src/app/(main)/settings/items/edit/page.tsx Näytä tiedosto

@@ -24,7 +24,7 @@ const productSetting: React.FC<Props> = async ({ searchParams }) => {
return ( return (
<> <>
{/* <Typography variant="h4">{t("Create Material")}</Typography> */} {/* <Typography variant="h4">{t("Create Material")}</Typography> */}
<I18nProvider namespaces={[type]}>
<I18nProvider namespaces={[type, "navigation", "common"]}>
<CreateProductMaterial id={id} /> <CreateProductMaterial id={id} />
</I18nProvider> </I18nProvider>
</> </>


+ 2
- 2
src/app/(main)/settings/items/page.tsx Näytä tiedosto

@@ -16,7 +16,7 @@ export const metadata: Metadata = {


const productSetting: React.FC = async () => { const productSetting: React.FC = async () => {
const project = TypeEnum.PRODUCT; const project = TypeEnum.PRODUCT;
const { t } = await getServerI18n("project");
const { t } = await getServerI18n("items");
// preloadClaims(); // preloadClaims();


return ( return (
@@ -40,7 +40,7 @@ const productSetting: React.FC = async () => {
</Button> */} </Button> */}
</Stack> </Stack>
<I18nProvider namespaces={["project", "common", "items"]}>
<I18nProvider namespaces={["items","navigation","common"]}>
<Suspense fallback={<ItemsSearch.Loading />}> <Suspense fallback={<ItemsSearch.Loading />}>
<ItemsSearch /> <ItemsSearch />
</Suspense> </Suspense>


+ 1
- 1
src/app/(main)/settings/m18ImportTesting/page.tsx Näytä tiedosto

@@ -21,7 +21,7 @@ const M18ImportTestingPage: React.FC = async () => {
rowGap={2} rowGap={2}
></Stack> ></Stack>
<Suspense fallback={<M18ImportTesting.Loading />}> <Suspense fallback={<M18ImportTesting.Loading />}>
<I18nProvider namespaces={["common", "m18ImportTesting"]}>
<I18nProvider namespaces={["m18ImportTesting","navigation","common"]}>
<M18ImportTesting /> <M18ImportTesting />
</I18nProvider> </I18nProvider>
</Suspense> </Suspense>


+ 1
- 1
src/app/(main)/settings/mail/page.tsx Näytä tiedosto

@@ -29,7 +29,7 @@ const Customer: React.FC = async () => {
{t("Mail")} {t("Mail")}
</Typography> </Typography>
</Stack> </Stack>
<I18nProvider namespaces={["mail", "common"]}>
<I18nProvider namespaces={["mail","navigation","common"]}>
<Suspense fallback={<MailSetting.Loading />}> <Suspense fallback={<MailSetting.Loading />}>
<MailSetting /> <MailSetting />
</Suspense> </Suspense>


+ 2
- 2
src/app/(main)/settings/printer/create/page.tsx Näytä tiedosto

@@ -4,12 +4,12 @@ import { Suspense } from "react";
import CreatePrinter from "@/components/CreatePrinter"; import CreatePrinter from "@/components/CreatePrinter";


const CreatePrinterPage: React.FC = async () => { const CreatePrinterPage: React.FC = async () => {
const { t } = await getServerI18n("common");
const { t } = await getServerI18n("printer");


return ( return (
<> <>
<Typography variant="h4">{t("Create Printer") || "新增列印機"}</Typography> <Typography variant="h4">{t("Create Printer") || "新增列印機"}</Typography>
<I18nProvider namespaces={["common"]}>
<I18nProvider namespaces={["printer","navigation","common"]}>
<Suspense fallback={<CreatePrinter.Loading />}> <Suspense fallback={<CreatePrinter.Loading />}>
<CreatePrinter /> <CreatePrinter />
</Suspense> </Suspense>


+ 2
- 2
src/app/(main)/settings/printer/edit/page.tsx Näytä tiedosto

@@ -10,7 +10,7 @@ import { fetchPrinterDetails } from "@/app/api/settings/printer/actions";
type Props = {} & SearchParams; type Props = {} & SearchParams;


const EditPrinterPage: React.FC<Props> = async ({ searchParams }) => { const EditPrinterPage: React.FC<Props> = async ({ searchParams }) => {
const { t } = await getServerI18n("common");
const { t } = await getServerI18n("printer");
const id = isString(searchParams["id"]) const id = isString(searchParams["id"])
? parseInt(searchParams["id"]) ? parseInt(searchParams["id"])
: undefined; : undefined;
@@ -26,7 +26,7 @@ const EditPrinterPage: React.FC<Props> = async ({ searchParams }) => {
return ( return (
<> <>
<Typography variant="h4">{t("Edit")} {t("Printer")}</Typography> <Typography variant="h4">{t("Edit")} {t("Printer")}</Typography>
<I18nProvider namespaces={["common"]}>
<I18nProvider namespaces={["printer","navigation","common"]}>
<Suspense fallback={<div>Loading...</div>}> <Suspense fallback={<div>Loading...</div>}>
<EditPrinter printer={printer} /> <EditPrinter printer={printer} />
</Suspense> </Suspense>


+ 2
- 2
src/app/(main)/settings/printer/page.tsx Näytä tiedosto

@@ -13,7 +13,7 @@ export const metadata: Metadata = {
}; };


const Printer: React.FC = async () => { const Printer: React.FC = async () => {
const { t } = await getServerI18n("common");
const { t } = await getServerI18n("printer");
return ( return (
<> <>
@@ -35,7 +35,7 @@ const Printer: React.FC = async () => {
{t("Create Printer") || "新增列印機"} {t("Create Printer") || "新增列印機"}
</Button> </Button>
</Stack> </Stack>
<I18nProvider namespaces={["common", "dashboard"]}>
<I18nProvider namespaces={["printer","navigation","common","dashboard"]}>
<Suspense fallback={<PrinterSearch.Loading />}> <Suspense fallback={<PrinterSearch.Loading />}>
<PrinterSearch /> <PrinterSearch />
</Suspense> </Suspense>


+ 1
- 1
src/app/(main)/settings/qcCategory/edit/page.tsx Näytä tiedosto

@@ -43,7 +43,7 @@ const qcCategory: React.FC<Props> = async ({ searchParams }) => {
<Typography variant="h4" marginInlineEnd={2}> <Typography variant="h4" marginInlineEnd={2}>
{t("Edit Qc Category")} {t("Edit Qc Category")}
</Typography> </Typography>
<I18nProvider namespaces={["qcCategory"]}>
<I18nProvider namespaces={["qcCategory","navigation","common"]}>
<QcCategorySave id={id} /> <QcCategorySave id={id} />
</I18nProvider> </I18nProvider>
</> </>


+ 1
- 1
src/app/(main)/settings/qcItem/create/page.tsx Näytä tiedosto

@@ -16,7 +16,7 @@ const qcItem: React.FC = async () => {
<Typography variant="h4" marginInlineEnd={2}> <Typography variant="h4" marginInlineEnd={2}>
{t("Create Qc Item")} {t("Create Qc Item")}
</Typography> </Typography>
<I18nProvider namespaces={["qcItem"]}>
<I18nProvider namespaces={["qcItem","navigation","common"]}>
<QcItemSave /> <QcItemSave />
</I18nProvider> </I18nProvider>
</> </>


+ 1
- 1
src/app/(main)/settings/qcItem/edit/page.tsx Näytä tiedosto

@@ -43,7 +43,7 @@ const qcItem: React.FC<Props> = async ({ searchParams }) => {
<Typography variant="h4" marginInlineEnd={2}> <Typography variant="h4" marginInlineEnd={2}>
{t("Edit Qc Item")} {t("Edit Qc Item")}
</Typography> </Typography>
<I18nProvider namespaces={["qcItem"]}>
<I18nProvider namespaces={["qcItem","navigation","common"]}>
<QcItemSave id={id} /> <QcItemSave id={id} />
</I18nProvider> </I18nProvider>
</> </>


+ 1
- 1
src/app/(main)/settings/qcItem/page.tsx Näytä tiedosto

@@ -37,7 +37,7 @@ const qcItem: React.FC = async () => {
</Button> </Button>
</Stack> </Stack>
<Suspense fallback={<QcItemSearch.Loading />}> <Suspense fallback={<QcItemSearch.Loading />}>
<I18nProvider namespaces={["common", "qcItem"]}>
<I18nProvider namespaces={["qcItem","navigation","common"]}>
<QcItemSearch /> <QcItemSearch />
</I18nProvider> </I18nProvider>
</Suspense> </Suspense>


+ 1
- 1
src/app/(main)/settings/qcItemAll/page.tsx Näytä tiedosto

@@ -30,7 +30,7 @@ const qcItemAll: React.FC = async () => {
</Typography> </Typography>
</Stack> </Stack>
<Suspense fallback={<div>Loading...</div>}> <Suspense fallback={<div>Loading...</div>}>
<I18nProvider namespaces={["common", "qcItemAll", "qcCategory", "qcItem"]}>
<I18nProvider namespaces={["qcItemAll","navigation","common","qcCategory","qcItem"]}>
<QcItemAllTabs <QcItemAllTabs
tab0Content={<Tab0ItemQcCategoryMapping />} tab0Content={<Tab0ItemQcCategoryMapping />}
tab1Content={<Tab1QcCategoryQcItemMapping />} tab1Content={<Tab1QcCategoryQcItemMapping />}


+ 5
- 5
src/app/(main)/settings/qrCodeHandle/page.tsx Näytä tiedosto

@@ -12,7 +12,7 @@ import Box from "@mui/material/Box";
export const metadata: Metadata = { title: "QR Code Handle" }; export const metadata: Metadata = { title: "QR Code Handle" };


const QrCodeHandlePage: React.FC = async () => { const QrCodeHandlePage: React.FC = async () => {
const { t } = await getServerI18n("common");
const { t } = await getServerI18n("qrCodeHandle");
return ( return (
<Box sx={{ width: "100%" }}> <Box sx={{ width: "100%" }}>
@@ -20,25 +20,25 @@ const QrCodeHandlePage: React.FC = async () => {
{t("QR Code Handle")} {t("QR Code Handle")}
</Typography> </Typography>
<I18nProvider namespaces={["common", "user", "warehouse"]}>
<I18nProvider namespaces={["qrCodeHandle","navigation","common","user","warehouse"]}>
<QrCodeHandleTabs <QrCodeHandleTabs
userTabContent={ userTabContent={
<Suspense fallback={<QrCodeHandleSearchWrapper.Loading />}> <Suspense fallback={<QrCodeHandleSearchWrapper.Loading />}>
<I18nProvider namespaces={["user", "common", "dashboard"]}>
<I18nProvider namespaces={["qrCodeHandle","navigation","common","user","dashboard"]}>
<QrCodeHandleSearchWrapper /> <QrCodeHandleSearchWrapper />
</I18nProvider> </I18nProvider>
</Suspense> </Suspense>
} }
equipmentTabContent={ equipmentTabContent={
<Suspense fallback={<QrCodeHandleEquipmentSearchWrapper.Loading />}> <Suspense fallback={<QrCodeHandleEquipmentSearchWrapper.Loading />}>
<I18nProvider namespaces={["common", "project", "dashboard"]}>
<I18nProvider namespaces={["qrCodeHandle","navigation","common","project","dashboard"]}>
<QrCodeHandleEquipmentSearchWrapper /> <QrCodeHandleEquipmentSearchWrapper />
</I18nProvider> </I18nProvider>
</Suspense> </Suspense>
} }
warehouseTabContent={ warehouseTabContent={
<Suspense fallback={<QrCodeHandleWarehouseSearchWrapper.Loading />}> <Suspense fallback={<QrCodeHandleWarehouseSearchWrapper.Loading />}>
<I18nProvider namespaces={["warehouse", "common", "dashboard"]}>
<I18nProvider namespaces={["qrCodeHandle","navigation","common","warehouse","dashboard"]}>
<QrCodeHandleWarehouseSearchWrapper /> <QrCodeHandleWarehouseSearchWrapper />
</I18nProvider> </I18nProvider>
</Suspense> </Suspense>


+ 2
- 3
src/app/(main)/settings/rss/page.tsx Näytä tiedosto

@@ -18,8 +18,7 @@ export const metadata: Metadata = {


const roughScheduleSetting: React.FC = async () => { const roughScheduleSetting: React.FC = async () => {
//const project = TypeEnum.PRODUCT //const project = TypeEnum.PRODUCT
const project = "common"
const { t } = await getServerI18n(project);
const { t } = await getServerI18n("demandForecast", "navigation", "common");
// preloadClaims(); // preloadClaims();


return ( return (
@@ -43,7 +42,7 @@ const roughScheduleSetting: React.FC = async () => {
</Button> */} </Button> */}
</Stack> </Stack>
<Suspense fallback={<RoughScheduleSettingWrapper.Loading />}> <Suspense fallback={<RoughScheduleSettingWrapper.Loading />}>
<I18nProvider namespaces={[ "common", "project",]}>
<I18nProvider namespaces={["demandForecast", "navigation", "common", "project"]}>
<RoughScheduleSetting items={[]} /> <RoughScheduleSetting items={[]} />
</I18nProvider> </I18nProvider>
</Suspense> </Suspense>


+ 2
- 2
src/app/(main)/settings/shop/board/page.tsx Näytä tiedosto

@@ -5,7 +5,7 @@ import GeneralLoading from "@/components/General/GeneralLoading";
import RouteBoard from "@/components/Shop/RouteBoard"; import RouteBoard from "@/components/Shop/RouteBoard";


export default async function ShopRouteBoardPage() { export default async function ShopRouteBoardPage() {
await getServerI18n("shop", "common", "routeboard");
await getServerI18n("shop", "navigation");
return ( return (
<Box <Box
sx={{ sx={{
@@ -16,7 +16,7 @@ export default async function ShopRouteBoardPage() {
flexDirection: "column", flexDirection: "column",
}} }}
> >
<I18nProvider namespaces={["shop", "common", "routeboard"]}>
<I18nProvider namespaces={["shop","navigation"]}>
<Suspense fallback={<GeneralLoading />}> <Suspense fallback={<GeneralLoading />}>
<RouteBoard /> <RouteBoard />
</Suspense> </Suspense>


+ 2
- 2
src/app/(main)/settings/shop/detail/page.tsx Näytä tiedosto

@@ -4,9 +4,9 @@ import { I18nProvider, getServerI18n } from "@/i18n";
import GeneralLoading from "@/components/General/GeneralLoading"; import GeneralLoading from "@/components/General/GeneralLoading";


export default async function ShopDetailPage() { export default async function ShopDetailPage() {
const { t } = await getServerI18n("shop", "common");
await getServerI18n("shop");
return ( return (
<I18nProvider namespaces={["shop", "common"]}>
<I18nProvider namespaces={["shop","navigation"]}>
<Suspense fallback={<GeneralLoading />}> <Suspense fallback={<GeneralLoading />}>
<ShopDetail /> <ShopDetail />
</Suspense> </Suspense>


+ 2
- 2
src/app/(main)/settings/shop/page.tsx Näytä tiedosto

@@ -8,9 +8,9 @@ import { notFound } from "next/navigation";




export default async function ShopPage() { export default async function ShopPage() {
const { t } = await getServerI18n("shop", "common");
await getServerI18n("shop");
return ( return (
<I18nProvider namespaces={["shop", "common"]}>
<I18nProvider namespaces={["shop","navigation"]}>
<Suspense fallback={<ShopWrapper.Loading />}> <Suspense fallback={<ShopWrapper.Loading />}>
<ShopWrapper /> <ShopWrapper />
</Suspense> </Suspense>


+ 2
- 2
src/app/(main)/settings/shop/truckdetail/page.tsx Näytä tiedosto

@@ -4,9 +4,9 @@ import { I18nProvider, getServerI18n } from "@/i18n";
import GeneralLoading from "@/components/General/GeneralLoading"; import GeneralLoading from "@/components/General/GeneralLoading";


export default async function TruckLaneDetailPage() { export default async function TruckLaneDetailPage() {
const { t } = await getServerI18n("shop", "common");
await getServerI18n("shop");
return ( return (
<I18nProvider namespaces={["shop", "common"]}>
<I18nProvider namespaces={["shop","navigation"]}>
<Suspense fallback={<GeneralLoading />}> <Suspense fallback={<GeneralLoading />}>
<TruckLaneDetail /> <TruckLaneDetail />
</Suspense> </Suspense>


+ 1
- 1
src/app/(main)/settings/user/create/page.tsx Näytä tiedosto

@@ -17,7 +17,7 @@ const CreateStaffPage: React.FC = async () => {
return ( return (
<> <>
<Typography variant="h4">{t("Create User")}</Typography> <Typography variant="h4">{t("Create User")}</Typography>
<I18nProvider namespaces={["user", "common"]}>
<I18nProvider namespaces={["user","navigation","common"]}>
<Suspense fallback={<CreateUser.Loading />}> <Suspense fallback={<CreateUser.Loading />}>
<CreateUser /> <CreateUser />
</Suspense> </Suspense>


+ 1
- 1
src/app/(main)/settings/user/edit/page.tsx Näytä tiedosto

@@ -18,7 +18,7 @@ const User: React.FC<searchParamsProps> = async ({ searchParams }) => {
return ( return (
<> <>
<Typography variant="h4">{t("Edit User")}</Typography> <Typography variant="h4">{t("Edit User")}</Typography>
<I18nProvider namespaces={["user", "common"]}>
<I18nProvider namespaces={["user","navigation","common"]}>
<Suspense fallback={<EditUser.Loading />}> <Suspense fallback={<EditUser.Loading />}>
<EditUser searchParams={searchParams} /> <EditUser searchParams={searchParams} />
</Suspense> </Suspense>


+ 1
- 1
src/app/(main)/settings/user/page.tsx Näytä tiedosto

@@ -47,7 +47,7 @@ const User: React.FC = async () => {
{t("Create User")} {t("Create User")}
</Button> </Button>
</Stack> </Stack>
<I18nProvider namespaces={["user", "common", "dashboard"]}>
<I18nProvider namespaces={["user","navigation","common","dashboard"]}>
<UserExcelSheetView users={usersWithDetails} /> <UserExcelSheetView users={usersWithDetails} />
</I18nProvider> </I18nProvider>
</> </>


+ 1
- 1
src/app/(main)/settings/warehouse/create/page.tsx Näytä tiedosto

@@ -9,7 +9,7 @@ const CreateWarehousePage: React.FC = async () => {
return ( return (
<> <>
<Typography variant="h4">{t("Create Warehouse")}</Typography> <Typography variant="h4">{t("Create Warehouse")}</Typography>
<I18nProvider namespaces={["warehouse", "common"]}>
<I18nProvider namespaces={["warehouse","navigation","common"]}>
<Suspense fallback={<CreateWarehouse.Loading />}> <Suspense fallback={<CreateWarehouse.Loading />}>
<CreateWarehouse /> <CreateWarehouse />
</Suspense> </Suspense>


+ 1
- 1
src/app/(main)/settings/warehouse/page.tsx Näytä tiedosto

@@ -31,7 +31,7 @@ const Warehouse: React.FC = async () => {
{t("Create Warehouse")} {t("Create Warehouse")}
</Button> </Button>
</Stack> </Stack>
<I18nProvider namespaces={["warehouse", "common", "dashboard"]}>
<I18nProvider namespaces={["warehouse","navigation","common","dashboard"]}>
<Suspense fallback={null}> <Suspense fallback={null}>
<WarehouseTabs <WarehouseTabs
tab0Content={<WarehouseHandleWrapper />} tab0Content={<WarehouseHandleWrapper />}


+ 1
- 1
src/app/(main)/stockIssue/page.tsx Näytä tiedosto

@@ -11,7 +11,7 @@ export const metadata: Metadata = {
const SearchView: React.FC = async () => { const SearchView: React.FC = async () => {
return ( return (
<> <>
<I18nProvider namespaces={["inventory", "common"]}>
<I18nProvider namespaces={["stockIssue", "navigation", "common"]}>
<Suspense fallback={<SearchPage.Loading />}> <Suspense fallback={<SearchPage.Loading />}>
<SearchPage /> <SearchPage />
</Suspense> </Suspense>


+ 5
- 11
src/app/(main)/stockOutIssueRecord/detail/page.tsx Näytä tiedosto

@@ -1,24 +1,18 @@

import { SearchParams } from "@/app/utils/fetchUtil"; import { SearchParams } from "@/app/utils/fetchUtil";
import PickOrderDetail from "@/components/PickOrderDetail"; import PickOrderDetail from "@/components/PickOrderDetail";
import { getServerI18n, I18nProvider } from "@/i18n";
import { Stack, Typography } from "@mui/material";
import { I18nProvider } from "@/i18n";
import { Metadata } from "next"; import { Metadata } from "next";
import { Suspense } from "react"; import { Suspense } from "react";


export const metadata: Metadata = { export const metadata: Metadata = {
title: "Consolidated Pick Order Flow",
title: "Stock Out Issue Record Detail",
}; };
type Props = {} & SearchParams; type Props = {} & SearchParams;


const PickOrder: React.FC<Props> = async ({ searchParams }) => {
const { t } = await getServerI18n("pickOrder");



const StockOutIssueRecordDetail: React.FC<Props> = async ({ searchParams }) => {
return ( return (
<> <>
<I18nProvider namespaces={["pickOrder"]}>
<I18nProvider namespaces={["pickOrder", "navigation", "common"]}>
<Suspense fallback={<PickOrderDetail.Loading />}> <Suspense fallback={<PickOrderDetail.Loading />}>
<PickOrderDetail consoCode={`${searchParams["consoCode"]}`} /> <PickOrderDetail consoCode={`${searchParams["consoCode"]}`} />
</Suspense> </Suspense>
@@ -27,4 +21,4 @@ const PickOrder: React.FC<Props> = async ({ searchParams }) => {
); );
}; };


export default PickOrder;
export default StockOutIssueRecordDetail;

+ 4
- 11
src/app/(main)/stockOutIssueRecord/page.tsx Näytä tiedosto

@@ -1,23 +1,16 @@
import { PreloadPickOrder } from "@/app/api/pickOrder";
import PickOrderSearch from "@/components/PickOrderSearch"; import PickOrderSearch from "@/components/PickOrderSearch";
import { getServerI18n } from "@/i18n";
import { I18nProvider } from "@/i18n"; import { I18nProvider } from "@/i18n";
import { Stack, Typography } from "@mui/material";
import { Metadata } from "next"; import { Metadata } from "next";
import { Suspense } from "react"; import { Suspense } from "react";


export const metadata: Metadata = { export const metadata: Metadata = {
title: "Pick Order",
title: "Stock Out Issue Record",
}; };


const PickOrder: React.FC = async () => {
const { t } = await getServerI18n("pickOrder");

// PreloadPickOrder();

const StockOutIssueRecord: React.FC = async () => {
return ( return (
<> <>
<I18nProvider namespaces={["pickOrder", "common"]}>
<I18nProvider namespaces={["pickOrder", "navigation", "common"]}>
<Suspense fallback={<PickOrderSearch.Loading />}> <Suspense fallback={<PickOrderSearch.Loading />}>
<PickOrderSearch /> <PickOrderSearch />
</Suspense> </Suspense>
@@ -26,4 +19,4 @@ const PickOrder: React.FC = async () => {
); );
}; };


export default PickOrder;
export default StockOutIssueRecord;

+ 2
- 2
src/app/(main)/stockRecord/page.tsx Näytä tiedosto

@@ -9,11 +9,11 @@ export const metadata: Metadata = {
}; };


const SearchView: React.FC = async () => { const SearchView: React.FC = async () => {
const { t } = await getServerI18n("inventory");
const { t } = await getServerI18n("stockRecord");


return ( return (
<> <>
<I18nProvider namespaces={["inventory", "common"]}>
<I18nProvider namespaces={["stockRecord", "navigation", "common"]}>
<Suspense fallback={<SearchPage.Loading />}> <Suspense fallback={<SearchPage.Loading />}>
<SearchPage /> <SearchPage />
</Suspense> </Suspense>


+ 2
- 2
src/app/(main)/stocktakemanagement/page.tsx Näytä tiedosto

@@ -8,9 +8,9 @@ import { notFound } from "next/navigation";




export default async function InventoryManagementPage() { export default async function InventoryManagementPage() {
const { t } = await getServerI18n("inventory");
const { t } = await getServerI18n("stockTake");
return ( return (
<I18nProvider namespaces={["inventory","common"]}>
<I18nProvider namespaces={["stockTake", "navigation", "common"]}>
<Suspense fallback={<StockTakeManagementWrapper.Loading />}> <Suspense fallback={<StockTakeManagementWrapper.Loading />}>
<StockTakeManagementWrapper /> <StockTakeManagementWrapper />
</Suspense> </Suspense>


+ 1
- 1
src/app/(main)/tasks/page.tsx Näytä tiedosto

@@ -14,7 +14,7 @@ export const metadata: Metadata = {
}; };


const TaskTemplates: React.FC = async () => { const TaskTemplates: React.FC = async () => {
const { t } = await getServerI18n("projects");
const { t } = await getServerI18n("project");
preloadTaskTemplates(); preloadTaskTemplates();


return ( return (


+ 306
- 0
src/app/api/shop/actions.ts Näytä tiedosto

@@ -492,6 +492,7 @@ export interface TruckLaneVersionResponse {
truckLanceCode: string; truckLanceCode: string;
note: string | null; note: string | null;
created: string | null; created: string | null;
createdBy?: string | null;
/** truck_lane_version.modifiedBy(BaseEntity) */ /** truck_lane_version.modifiedBy(BaseEntity) */
modifiedBy?: string | null; modifiedBy?: string | null;
} }
@@ -602,4 +603,309 @@ export const updateTruckLaneVersionNoteAction = async (
body: JSON.stringify(data), body: JSON.stringify(data),
headers: { "Content-Type": "application/json" }, headers: { "Content-Type": "application/json" },
}); });
};

// ---- Truck lane schedule (server-side apply) ----

export type TruckLaneScheduleLineAction =
| "MOVE"
| "CREATE"
| "DELETE"
| "ENSURE_LANE";

export type TruckLaneMoveTargetRequest = {
truckRowId: number;
toTruckLanceCode: string;
toRemark?: string | null;
toStoreId: string;
toLoadingSequence: number;
toDistrictReference?: string | null;
};

export type TruckLaneScheduleLineRequest = {
action: TruckLaneScheduleLineAction;
truckRowId?: number | null;
toTruckLanceCode: string;
toRemark?: string | null;
toStoreId: string;
toLoadingSequence?: number | null;
toDistrictReference?: string | null;
shopId?: number | null;
shopCode?: string | null;
shopName?: string | null;
departureTime?: string | null;
logisticId?: number | null;
};

export type CreateTruckLaneScheduleRequest = {
executeAt: string;
note?: string | null;
lines?: TruckLaneScheduleLineRequest[] | null;
moves?: TruckLaneMoveTargetRequest[] | null;
};

export type TruckLaneScheduleLineResponse = {
id: number;
action: TruckLaneScheduleLineAction;
truckRowId: number | null;
shopCode: string | null;
shopName: string | null;
fromTruckLanceCode: string | null;
fromRemark: string | null;
fromStoreId: string | null;
fromLoadingSequence?: number | null;
fromDistrictReference?: string | null;
fromDepartureTime?: string | null;
toTruckLanceCode: string;
toRemark: string | null;
toStoreId: string;
toDistrictReference?: string | null;
toLoadingSequence?: number | null;
departureTime?: string | null;
lineStatus: string;
errorMessage: string | null;
appliedAt: string | null;
};

export type RouteExcelSchedulePlanPreviewRow = {
action: TruckLaneScheduleLineAction;
truckRowId: number | null;
shopCode: string | null;
shopName: string | null;
toTruckLanceCode: string;
toRemark: string | null;
toStoreId: string;
toLoadingSequence: number | null;
};

export type RouteExcelSchedulePlanError = {
shopCode: string;
shopName: string;
message: string;
};

export type RouteExcelSchedulePlanCounts = {
moves: number;
creates: number;
deletes: number;
ensureLanes: number;
};

export type RouteExcelSchedulePlanResponse = {
sheetCount: number;
rowCount: number;
lines: TruckLaneScheduleLineRequest[];
previews: RouteExcelSchedulePlanPreviewRow[];
errors: RouteExcelSchedulePlanError[];
counts: RouteExcelSchedulePlanCounts;
};

export type TruckLaneScheduleResponse = {
id: number;
executeAt: string;
status: string;
source: string;
note: string | null;
appliedAt: string | null;
errorMessage: string | null;
snapshotVersionId: number | null;
preApplySnapshotVersionId?: number | null;
created: string | null;
createdBy?: string | null;
modifiedBy: string | null;
lines?: TruckLaneScheduleLineResponse[] | null;
lineCounts?: {
total: number;
applied: number;
failed: number;
pending: number;
} | null;
};

export type PendingTruckRowIdsResponse = {
truckRowIds: number[];
};

export type TruckLaneScheduleExcelPreviewRow = {
rowIndex: number;
shopCode: string;
toTruckLanceCode: string;
toRemark: string | null;
toStoreId: string;
executeAt: string | null;
truckRowId: number | null;
};

export type TruckLaneScheduleExcelRowError = {
rowIndex: number;
message: string;
};

export type ParseTruckLaneScheduleExcelResponse = {
rowCount: number;
validCount: number;
errorCount: number;
rows: TruckLaneScheduleExcelPreviewRow[];
errors: TruckLaneScheduleExcelRowError[];
};

export const createTruckLaneScheduleAction = async (
data: CreateTruckLaneScheduleRequest,
): Promise<TruckLaneScheduleResponse> => {
const endpoint = `${BASE_API_URL}/truckLaneSchedule`;
return serverFetchJson<TruckLaneScheduleResponse>(endpoint, {
method: "POST",
body: JSON.stringify(data),
headers: { "Content-Type": "application/json" },
});
};

export const planTruckLaneScheduleFromRouteExcelAction = async (
formData: FormData,
): Promise<RouteExcelSchedulePlanResponse> => {
const response = await serverFetch(
`${BASE_API_URL}/truckLaneSchedule/planFromRouteExcel`,
{
method: "POST",
body: formData,
},
);
if (!response.ok) {
const text = await response.text().catch(() => "");
throw new ServerFetchError(
`Plan import failed: ${response.status} ${text}`.trim(),
response,
);
}
return (await response.json()) as RouteExcelSchedulePlanResponse;
};

export const listTruckLaneSchedulesAction = async (
status?: string[],
limit: number = 200,
): Promise<TruckLaneScheduleResponse[]> => {
const params = new URLSearchParams();
for (const s of status ?? []) {
params.append("status", s);
}
params.set("limit", String(limit));
const qs = params.toString();
const base = `${BASE_API_URL}/truckLaneSchedule`;
return serverFetchJson<TruckLaneScheduleResponse[]>(
`${base}${qs ? `?${qs}` : ""}`,
{
method: "GET",
headers: { "Content-Type": "application/json" },
},
);
};

export const getTruckLaneScheduleAction = async (
id: number,
): Promise<TruckLaneScheduleResponse> => {
const endpoint = `${BASE_API_URL}/truckLaneSchedule/${id}`;
return serverFetchJson<TruckLaneScheduleResponse>(endpoint, {
method: "GET",
headers: { "Content-Type": "application/json" },
});
};

export const pendingTruckLaneScheduleShopIdsAction =
async (): Promise<PendingTruckRowIdsResponse> => {
const endpoint = `${BASE_API_URL}/truckLaneSchedule/pendingShopIds`;
return serverFetchJson<PendingTruckRowIdsResponse>(endpoint, {
method: "GET",
headers: { "Content-Type": "application/json" },
});
};

export const cancelTruckLaneScheduleAction = async (
id: number,
): Promise<TruckLaneScheduleResponse> => {
const endpoint = `${BASE_API_URL}/truckLaneSchedule/${id}/cancel`;
return serverFetchJson<TruckLaneScheduleResponse>(endpoint, {
method: "POST",
headers: { "Content-Type": "application/json" },
});
};

export const applyNowTruckLaneScheduleAction = async (
id: number,
): Promise<TruckLaneScheduleResponse> => {
const endpoint = `${BASE_API_URL}/truckLaneSchedule/${id}/applyNow`;
return serverFetchJson<TruckLaneScheduleResponse>(endpoint, {
method: "POST",
headers: { "Content-Type": "application/json" },
});
};

export type RetryFailedTruckLaneScheduleRequest = {
executeAt?: string | null;
};

export const retryFailedTruckLaneScheduleAction = async (
id: number,
body?: RetryFailedTruckLaneScheduleRequest,
): Promise<TruckLaneScheduleResponse> => {
const endpoint = `${BASE_API_URL}/truckLaneSchedule/${id}/retry-failed`;
return serverFetchJson<TruckLaneScheduleResponse>(endpoint, {
method: "POST",
body: JSON.stringify(body ?? {}),
headers: { "Content-Type": "application/json" },
});
};

export const ignoreTruckLaneScheduleAction = async (
id: number,
): Promise<TruckLaneScheduleResponse> => {
const endpoint = `${BASE_API_URL}/truckLaneSchedule/${id}/ignore`;
return serverFetchJson<TruckLaneScheduleResponse>(endpoint, {
method: "POST",
headers: { "Content-Type": "application/json" },
});
};

export const parseTruckLaneScheduleExcelAction = async (
formData: FormData,
defaultExecuteAt?: string | null,
): Promise<ParseTruckLaneScheduleExcelResponse> => {
const qs =
defaultExecuteAt != null && defaultExecuteAt !== ""
? `?defaultExecuteAt=${encodeURIComponent(defaultExecuteAt)}`
: "";
const response = await serverFetch(
`${BASE_API_URL}/truckLaneSchedule/parseExcel${qs}`,
{ method: "POST", body: formData },
);
if (!response.ok) {
const text = await response.text().catch(() => "");
throw new ServerFetchError(
`Parse schedule Excel failed: ${response.status} ${text}`.trim(),
response,
);
}
return (await response.json()) as ParseTruckLaneScheduleExcelResponse;
};

export const importTruckLaneScheduleExcelAction = async (
formData: FormData,
defaultExecuteAt?: string | null,
note?: string | null,
): Promise<TruckLaneScheduleResponse[]> => {
const params = new URLSearchParams();
if (defaultExecuteAt) params.set("defaultExecuteAt", defaultExecuteAt);
if (note) params.set("note", note);
const qs = params.toString() ? `?${params.toString()}` : "";
const response = await serverFetch(
`${BASE_API_URL}/truckLaneSchedule/importExcel${qs}`,
{ method: "POST", body: formData },
);
if (!response.ok) {
const text = await response.text().catch(() => "");
throw new ServerFetchError(
`Import schedule Excel failed: ${response.status} ${text}`.trim(),
response,
);
}
return (await response.json()) as TruckLaneScheduleResponse[];
}; };

+ 110
- 0
src/app/api/shop/client.ts Näytä tiedosto

@@ -30,7 +30,29 @@ import {
diffTruckLaneVersionsAction, diffTruckLaneVersionsAction,
restoreTruckLaneVersionAction, restoreTruckLaneVersionAction,
updateTruckLaneVersionNoteAction, updateTruckLaneVersionNoteAction,
createTruckLaneScheduleAction,
planTruckLaneScheduleFromRouteExcelAction,
listTruckLaneSchedulesAction,
getTruckLaneScheduleAction,
pendingTruckLaneScheduleShopIdsAction,
cancelTruckLaneScheduleAction,
applyNowTruckLaneScheduleAction,
retryFailedTruckLaneScheduleAction,
ignoreTruckLaneScheduleAction,
type RetryFailedTruckLaneScheduleRequest,
parseTruckLaneScheduleExcelAction,
importTruckLaneScheduleExcelAction,
type CreateTruckLaneSnapshotRequest, type CreateTruckLaneSnapshotRequest,
type CreateTruckLaneScheduleRequest,
type TruckLaneScheduleResponse,
type TruckLaneScheduleLineRequest,
type RouteExcelSchedulePlanPreviewRow,
type RouteExcelSchedulePlanError,
type RouteExcelSchedulePlanResponse,
type RouteExcelSchedulePlanCounts,
type TruckLaneMoveTargetRequest,
type PendingTruckRowIdsResponse,
type ParseTruckLaneScheduleExcelResponse,
type UpdateTruckLaneVersionNoteRequest, type UpdateTruckLaneVersionNoteRequest,
type TruckLaneVersionResponse, type TruckLaneVersionResponse,
type TruckLaneVersionLineResponse, type TruckLaneVersionLineResponse,
@@ -184,4 +206,92 @@ export const updateTruckLaneVersionNoteClient = async (
return await updateTruckLaneVersionNoteAction(versionId, data); return await updateTruckLaneVersionNoteAction(versionId, data);
}; };


export const planTruckLaneScheduleFromRouteExcelClient = async (
formData: FormData,
): Promise<RouteExcelSchedulePlanResponse> => {
return await planTruckLaneScheduleFromRouteExcelAction(formData);
};

export const createTruckLaneScheduleClient = async (
data: CreateTruckLaneScheduleRequest,
): Promise<TruckLaneScheduleResponse> => {
return await createTruckLaneScheduleAction(data);
};

export const listTruckLaneSchedulesClient = async (
status?: string[],
limit: number = 200,
): Promise<TruckLaneScheduleResponse[]> => {
return await listTruckLaneSchedulesAction(status, limit);
};

export const getTruckLaneScheduleClient = async (
id: number,
): Promise<TruckLaneScheduleResponse> => {
return await getTruckLaneScheduleAction(id);
};

export const pendingTruckLaneScheduleShopIdsClient =
async (): Promise<PendingTruckRowIdsResponse> => {
return await pendingTruckLaneScheduleShopIdsAction();
};

export const cancelTruckLaneScheduleClient = async (
id: number,
): Promise<TruckLaneScheduleResponse> => {
return await cancelTruckLaneScheduleAction(id);
};

export const applyNowTruckLaneScheduleClient = async (
id: number,
): Promise<TruckLaneScheduleResponse> => {
return await applyNowTruckLaneScheduleAction(id);
};

export const retryFailedTruckLaneScheduleClient = async (
id: number,
body?: RetryFailedTruckLaneScheduleRequest,
): Promise<TruckLaneScheduleResponse> => {
return await retryFailedTruckLaneScheduleAction(id, body);
};

export const ignoreTruckLaneScheduleClient = async (
id: number,
): Promise<TruckLaneScheduleResponse> => {
return await ignoreTruckLaneScheduleAction(id);
};

export const parseTruckLaneScheduleExcelClient = async (
formData: FormData,
defaultExecuteAt?: string | null,
): Promise<ParseTruckLaneScheduleExcelResponse> => {
return await parseTruckLaneScheduleExcelAction(formData, defaultExecuteAt);
};

export const importTruckLaneScheduleExcelClient = async (
formData: FormData,
defaultExecuteAt?: string | null,
note?: string | null,
): Promise<TruckLaneScheduleResponse[]> => {
return await importTruckLaneScheduleExcelAction(
formData,
defaultExecuteAt,
note,
);
};

export type {
TruckLaneScheduleResponse,
TruckLaneScheduleLineResponse,
TruckLaneMoveTargetRequest,
TruckLaneScheduleLineRequest,
CreateTruckLaneScheduleRequest,
PendingTruckRowIdsResponse,
ParseTruckLaneScheduleExcelResponse,
RouteExcelSchedulePlanResponse,
RouteExcelSchedulePlanPreviewRow,
RouteExcelSchedulePlanError,
RouteExcelSchedulePlanCounts,
} from "./actions";

export default fetchAllShopsClient; export default fetchAllShopsClient;

+ 1
- 1
src/components/AppBar/AppBar.tsx Näytä tiedosto

@@ -16,7 +16,7 @@ export interface AppBarProps {


const AppBar: React.FC<AppBarProps> = ({ avatarImageSrc, profileName }) => { const AppBar: React.FC<AppBarProps> = ({ avatarImageSrc, profileName }) => {
return ( return (
<I18nProvider namespaces={["common"]}>
<I18nProvider namespaces={["navigation", "common"]}>
<MUIAppBar position="sticky" color="default" elevation={0}> <MUIAppBar position="sticky" color="default" elevation={0}>
<Toolbar sx={{ minHeight: { xs: 56, sm: 64 }, px: 2 }}> <Toolbar sx={{ minHeight: { xs: 56, sm: 64 }, px: 2 }}>
<NavigationToggle /> <NavigationToggle />


+ 1
- 1
src/components/AppBar/Profile.tsx Näytä tiedosto

@@ -29,7 +29,7 @@ const Profile: React.FC<Props> = ({ avatarImageSrc, profileName }) => {


return ( return (
<> <>
<IconButton aria-label="profile" onClick={openProfileMenu}>
<IconButton aria-label={t("profile")} onClick={openProfileMenu}>
<Avatar src={avatarImageSrc} /> <Avatar src={avatarImageSrc} />
</IconButton> </IconButton>
<Menu <Menu


+ 3
- 3
src/components/BomScoreTable/BomScoreTable.tsx Näytä tiedosto

@@ -12,19 +12,19 @@ interface Props {
} }


const BomScoreTable: React.FC<Props> = ({ boms }) => { const BomScoreTable: React.FC<Props> = ({ boms }) => {
const { t } = useTranslation("common");
const { t } = useTranslation(["bomWeighting", "common"]);


const columns = useMemo<GridColDef<BomScoreResult>[]>( const columns = useMemo<GridColDef<BomScoreResult>[]>(
() => [ () => [
{ {
field: "code", field: "code",
headerName: t("Code"),
headerName: t("Item Code"),
flex: 1, flex: 1,
minWidth: 150, minWidth: 150,
}, },
{ {
field: "name", field: "name",
headerName: t("Name"),
headerName: t("Item Name"),
flex: 1.5, flex: 1.5,
minWidth: 220, minWidth: 220,
}, },


+ 2
- 2
src/components/BomWeightingScoreTable/BomWeightingScoreTable.tsx Näytä tiedosto

@@ -20,7 +20,7 @@ interface Props {
} }


const BomWeightingScoreTable: React.FC<Props> & { Loading?: React.FC } = ({ bomWeightingScores: initialBomWeightingScores, onWeightingUpdated }) => { const BomWeightingScoreTable: React.FC<Props> & { Loading?: React.FC } = ({ bomWeightingScores: initialBomWeightingScores, onWeightingUpdated }) => {
const { t } = useTranslation("common");
const { t } = useTranslation(["bomWeighting", "common"]);
const [bomWeightingScores, setBomWeightingScores] = useState(initialBomWeightingScores); const [bomWeightingScores, setBomWeightingScores] = useState(initialBomWeightingScores);
const [isEditMode, setIsEditMode] = useState(false); const [isEditMode, setIsEditMode] = useState(false);
const [isSaving, setIsSaving] = useState(false); const [isSaving, setIsSaving] = useState(false);
@@ -173,7 +173,7 @@ const BomWeightingScoreTable: React.FC<Props> & { Loading?: React.FC } = ({ bomW
() => [ () => [
{ {
field: "name", field: "name",
headerName: t("Name"),
headerName: t("Scoring Item"),
flex: 1, flex: 1,
}, },
{ {


+ 1
- 1
src/components/BomWeightingTabs/BomWeightingTabs.tsx Näytä tiedosto

@@ -18,7 +18,7 @@ interface Props {
} }


const BomWeightingTabs: React.FC<Props> = ({ bomWeightingScores: initialBomWeightingScores }) => { const BomWeightingTabs: React.FC<Props> = ({ bomWeightingScores: initialBomWeightingScores }) => {
const { t } = useTranslation("common");
const { t } = useTranslation(["bomWeighting", "common"]);
const [tab, setTab] = useState(0); const [tab, setTab] = useState(0);
const [bomWeightingScores, setBomWeightingScores] = useState<BomWeightingScoreResult[]>(initialBomWeightingScores); const [bomWeightingScores, setBomWeightingScores] = useState<BomWeightingScoreResult[]>(initialBomWeightingScores);
const [bomScores, setBomScores] = useState<BomScoreResult[] | null>(null); const [bomScores, setBomScores] = useState<BomScoreResult[] | null>(null);


+ 67
- 56
src/components/Breadcrumb/Breadcrumb.tsx Näytä tiedosto

@@ -7,75 +7,86 @@ import MUILink from "@mui/material/Link";
import { usePathname } from "next/navigation"; import { usePathname } from "next/navigation";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";


const pathToLabelMap: { [path: string]: string } = {
"": "總覽",
"/chart": "圖表報告",
"/chart/warehouse": "庫存與倉儲",
"/chart/purchase": "採購",
"/chart/delivery": "發貨與配送",
"/chart/joborder": "工單",
"/chart/joborder/board": "工單即時看板",
"/chart/forecast": "預測與計劃",
"/projects": "Projects",
"/projects/create": "Create Project",
"/tasks": "Task Template",
"/tasks/create": "Create Task Template",
"/settings/qcItem": "Qc Item",
"/settings/qcItemAll": "QC Item All",
"/settings/qrCodeHandle": "QR Code Handle",
"/settings/rss": "Demand Forecast Setting",
"/settings/equipment": "Equipment",
"/settings/equipment/MaintenanceEdit": "MaintenanceEdit",
"/settings/shop": "ShopAndTruck",
"/settings/shop/board": "Route Board",
"/settings/shop/detail": "Shop Detail",
"/settings/shop/truckdetail": "Truck Lane Detail",
"/settings/printer": "Printer",
"/scheduling/rough": "Demand Forecast",
"/scheduling/rough/edit": "FG & Material Demand Forecast Detail",
"/scheduling/detailed": "Detail Scheduling",
"/scheduling/detailed/edit": "FG Production Schedule",
"/inventory": "Inventory",
"/settings/importTesting": "Import Testing",
"/do": "Delivery Order",
"/doworkbench": "DO Workbench",
"/doworkbenchsearch": "DO Workbench Search",
"/doworkbench/pick": "DO Workbench pick",
"/doworkbench/edit": "DO Workbench detail",
"/pickOrder": "Pick Order",
"/po": "Purchase Order",
"/po/workbench": "PO Workbench",
"/dashboard": "dashboard",
"/jo": "Job Order",
"/jo/edit": "Edit Job Order",
"/jo/testing": "Job order testing",
"/jo/workbench": "Job Order Workbench",
"/putAway": "Put Away",
"/stockIssue": "Stock Issue",
"/report": "Report",
"/m18Syn": "M18 Sync",
"/bagPrint": "打袋機",
"/laserPrint": "檸檬機(激光機)",
"/settings/itemPrice": "Price Inquiry",
"/finishedGood": "Finished Good Order",
"/finishedGood/management": "Finished Good Management",
const pathToLabelKey: { [path: string]: string } = {
"": "nav.breadcrumb.home",
"/chart": "nav.breadcrumb.chart",
"/chart/warehouse": "nav.breadcrumb.chartWarehouse",
"/chart/purchase": "nav.breadcrumb.chartPurchase",
"/chart/delivery": "nav.breadcrumb.chartDelivery",
"/chart/joborder": "nav.breadcrumb.chartJobOrder",
"/chart/joborder/board": "nav.breadcrumb.chartJobOrderBoard",
"/chart/forecast": "nav.breadcrumb.chartForecast",
"/projects": "nav.breadcrumb.projects",
"/projects/create": "nav.breadcrumb.projectsCreate",
"/tasks": "nav.breadcrumb.tasks",
"/tasks/create": "nav.breadcrumb.tasksCreate",
"/settings/qcItem": "nav.breadcrumb.qcItem",
"/settings/qcItemAll": "nav.breadcrumb.qcItemAll",
"/settings/qrCodeHandle": "nav.breadcrumb.qrCodeHandle",
"/settings/rss": "nav.breadcrumb.demandForecast",
"/settings/equipment": "nav.breadcrumb.equipment",
"/settings/equipment/MaintenanceEdit": "nav.breadcrumb.equipmentMaintenanceEdit",
"/settings/shop": "nav.breadcrumb.shop",
"/settings/shop/board": "nav.breadcrumb.routeBoard",
"/settings/shop/detail": "nav.breadcrumb.shopDetail",
"/settings/shop/truckdetail": "nav.breadcrumb.truckLaneDetail",
"/settings/printer": "nav.breadcrumb.printer",
"/scheduling/rough": "nav.breadcrumb.schedulingRough",
"/scheduling/rough/edit": "nav.breadcrumb.schedulingRoughEdit",
"/scheduling/detailed": "nav.breadcrumb.schedulingDetailed",
"/scheduling/detailed/edit": "nav.breadcrumb.schedulingDetailedEdit",
"/inventory": "nav.breadcrumb.inventory",
"/settings/importTesting": "nav.breadcrumb.importTesting",
"/settings/m18ImportTesting": "nav.breadcrumb.importTesting",
"/do": "nav.deliveryOrder",
"/doworkbench": "nav.store.doWorkbench",
"/doworkbenchsearch": "nav.breadcrumb.doWorkbenchSearch",
"/doworkbench/pick": "nav.breadcrumb.doWorkbenchPick",
"/doworkbench/edit": "nav.breadcrumb.doWorkbenchEdit",
"/pickOrder": "nav.store.pickOrder",
"/po": "nav.store.purchaseOrder",
"/po/edit": "nav.breadcrumb.poEdit",
"/po/workbench": "nav.breadcrumb.poWorkbench",
"/dashboard": "nav.dashboard",
"/jo": "nav.jobOrder.searchCreate",
"/jo/edit": "nav.breadcrumb.joEdit",
"/jo/testing": "nav.breadcrumb.joTesting",
"/jo/workbench": "nav.breadcrumb.joWorkbench",
"/putAway": "nav.store.putAwayScan",
"/stockIssue": "nav.store.stockIssue",
"/stocktakemanagement": "nav.store.stockTake",
"/stockRecord": "nav.store.stockRecord",
"/report": "nav.breadcrumb.report",
"/m18Syn": "nav.breadcrumb.m18Sync",
"/bagPrint": "nav.breadcrumb.bagPrint",
"/laserPrint": "nav.breadcrumb.laserPrint",
"/settings/itemPrice": "nav.breadcrumb.priceInquiry",
"/finishedGood": "nav.breadcrumb.finishedGood",
"/finishedGood/management": "nav.breadcrumb.finishedGoodManagement",
"/ps": "nav.scheduling",
"/productionProcess": "nav.jobOrder.productionProcess",
"/jodetail": "nav.jobOrder.pickExecution",
"/bag": "nav.jobOrder.bagUsage",
}; };


const Breadcrumb = () => { const Breadcrumb = () => {
const pathname = usePathname(); const pathname = usePathname();
const segments = pathname.split("/"); const segments = pathname.split("/");
const { t } = useTranslation("common");
const { t } = useTranslation(["navigation", "common"]);


return ( return (
<Breadcrumbs> <Breadcrumbs>
{segments.map((segment, index) => { {segments.map((segment, index) => {
const href = segments.slice(0, index + 1).join("/"); const href = segments.slice(0, index + 1).join("/");
const label = pathToLabelMap[href] || segment;
const labelKey = pathToLabelKey[href];
const label = labelKey
? t(labelKey)
: t(segment, { ns: "common", defaultValue: segment });


if (index === segments.length - 1) { if (index === segments.length - 1) {
return ( return (
<Typography key={index} color="text.primary"> <Typography key={index} color="text.primary">
{t(label)}
{label}
</Typography> </Typography>
); );
} else { } else {
@@ -87,7 +98,7 @@ const Breadcrumb = () => {
component={Link} component={Link}
href={href || "/"} href={href || "/"}
> >
{t(label)}
{label}
</MUILink> </MUILink>
); );
} }


+ 14
- 14
src/components/CreateClaim/ClaimInputGrid.tsx Näytä tiedosto

@@ -271,8 +271,8 @@ const ClaimInputGrid: React.FC<ClaimInputGridProps> = ({ ...props }) => {
<GridActionsCellItem <GridActionsCellItem
key={`actions-${id}-save`} key={`actions-${id}-save`}
icon={<SaveIcon />} icon={<SaveIcon />}
title="Save"
label="Save"
title={t("Save")}
label={t("Save")}
sx={{ sx={{
color: "primary.main", color: "primary.main",
}} }}
@@ -281,8 +281,8 @@ const ClaimInputGrid: React.FC<ClaimInputGridProps> = ({ ...props }) => {
<GridActionsCellItem <GridActionsCellItem
key={`actions-${id}-cancel`} key={`actions-${id}-cancel`}
icon={<CancelIcon />} icon={<CancelIcon />}
title="Cancel"
label="Cancel"
title={t("Cancel")}
label={t("Cancel")}
className="textPrimary" className="textPrimary"
onClick={handleCancelClick(id)} onClick={handleCancelClick(id)}
color="inherit" color="inherit"
@@ -294,16 +294,16 @@ const ClaimInputGrid: React.FC<ClaimInputGridProps> = ({ ...props }) => {
<GridActionsCellItem <GridActionsCellItem
key={`actions-${id}-edit`} key={`actions-${id}-edit`}
icon={<EditIcon />} icon={<EditIcon />}
title="Edit"
label="Edit"
title={t("Edit")}
label={t("Edit")}
className="textPrimary" className="textPrimary"
onClick={handleEditClick(id)} onClick={handleEditClick(id)}
color="inherit" color="inherit"
/>, />,
<GridActionsCellItem <GridActionsCellItem
key={`actions-${id}-delete`} key={`actions-${id}-delete`}
title="Delete"
label="Delete"
title={t("Delete")}
label={t("Delete")}
icon={<DeleteIcon />} icon={<DeleteIcon />}
onClick={handleDeleteClick(id)} onClick={handleDeleteClick(id)}
sx={{ color: "red" }} sx={{ color: "red" }}
@@ -313,7 +313,7 @@ const ClaimInputGrid: React.FC<ClaimInputGridProps> = ({ ...props }) => {
}, },
{ {
field: "date", field: "date",
headerName: "Invoice Date",
headerName: t("Invoice Date"),
// width: 220, // width: 220,
flex: 1, flex: 1,
editable: true, editable: true,
@@ -321,7 +321,7 @@ const ClaimInputGrid: React.FC<ClaimInputGridProps> = ({ ...props }) => {
}, },
{ {
field: "description", field: "description",
headerName: "Description",
headerName: t("Description"),
// width: 220, // width: 220,
flex: 2, flex: 2,
editable: true, editable: true,
@@ -329,7 +329,7 @@ const ClaimInputGrid: React.FC<ClaimInputGridProps> = ({ ...props }) => {
}, },
{ {
field: "cost", field: "cost",
headerName: "Cost (HKD)",
headerName: t("Cost (HKD)"),
editable: true, editable: true,
type: "number", type: "number",
valueFormatter: (params) => { valueFormatter: (params) => {
@@ -338,7 +338,7 @@ const ClaimInputGrid: React.FC<ClaimInputGridProps> = ({ ...props }) => {
}, },
{ {
field: "document", field: "document",
headerName: "Supporting Document",
headerName: t("Supporting Document"),
type: "string", type: "string",
editable: true, editable: true,
flex: 2, flex: 2,
@@ -360,7 +360,7 @@ const ClaimInputGrid: React.FC<ClaimInputGridProps> = ({ ...props }) => {
{params.value} {params.value}
</a> </a>
<Button <Button
title="Remove Document"
title={t("Remove Document")}
onClick={(event) => console.log(event)} onClick={(event) => console.log(event)}
> >
<ImageNotSupportedOutlinedIcon <ImageNotSupportedOutlinedIcon
@@ -369,7 +369,7 @@ const ClaimInputGrid: React.FC<ClaimInputGridProps> = ({ ...props }) => {
</Button> </Button>
</span> </span>
) : ( ) : (
<Button title="Add Document">
<Button title={t("Add Document")}>
<AddPhotoAlternateOutlinedIcon <AddPhotoAlternateOutlinedIcon
sx={{ fontSize: "25px", color: "green" }} sx={{ fontSize: "25px", color: "green" }}
/> />


+ 1
- 1
src/components/CreateEquipment/CreateEquipment.tsx Näytä tiedosto

@@ -49,7 +49,7 @@ const CreateItem: React.FC<Props> = ({
console.log(params.get("id")); console.log(params.get("id"));
const [serverError, setServerError] = useState(""); const [serverError, setServerError] = useState("");
const [tabIndex, setTabIndex] = useState(0); const [tabIndex, setTabIndex] = useState(0);
const { t } = useTranslation("common");
const { t } = useTranslation(["equipment", "common"]);
const router = useRouter(); const router = useRouter();
const title = "Equipment"; const title = "Equipment";
const [mode, redirPath] = useMemo(() => { const [mode, redirPath] = useMemo(() => {


+ 1
- 1
src/components/CreateEquipment/EquipmentDetails.tsx Näytä tiedosto

@@ -33,7 +33,7 @@ const ProductDetails: React.FC<Props> = ({ isEditMode }) => {
const { const {
t, t,
i18n: { language }, i18n: { language },
} = useTranslation();
} = useTranslation(["equipment", "common"]);


const { const {
register, register,


+ 1
- 1
src/components/CreateEquipmentType/CreateEquipmentType.tsx Näytä tiedosto

@@ -49,7 +49,7 @@ const CreateItem: React.FC<Props> = ({
console.log(params.get("id")); console.log(params.get("id"));
const [serverError, setServerError] = useState(""); const [serverError, setServerError] = useState("");
const [tabIndex, setTabIndex] = useState(0); const [tabIndex, setTabIndex] = useState(0);
const { t } = useTranslation("common");
const { t } = useTranslation(["equipment", "common"]);
const router = useRouter(); const router = useRouter();
const title = "Equipment Type"; const title = "Equipment Type";
const [mode, redirPath] = useMemo(() => { const [mode, redirPath] = useMemo(() => {


+ 1
- 1
src/components/CreateEquipmentType/EquipmentTypeDetails.tsx Näytä tiedosto

@@ -33,7 +33,7 @@ const ProductDetails: React.FC<Props> = ({ isEditMode }) => {
const { const {
t, t,
i18n: { language }, i18n: { language },
} = useTranslation();
} = useTranslation(["equipment", "common"]);


const { const {
register, register,


Some files were not shown because too many files changed in this diff

Ladataan…
Peruuta
Tallenna