From 3c5cb3f8b244ceb28bb16f91d5ceca45c2779b29 Mon Sep 17 00:00:00 2001 From: "MSI\\2Fi" Date: Wed, 9 Jul 2025 17:47:13 +0800 Subject: [PATCH] eslint suggested spacing --- next.config.js | 2 +- package.json | 3 +- postcss.config.js | 2 +- src/app/(main)/axios/AxiosProvider.tsx | 48 +- src/app/(main)/axios/axiosInstance.ts | 86 +- src/app/(main)/dashboard/page.tsx | 15 +- src/app/(main)/do/edit/page.tsx | 0 src/app/(main)/do/page.tsx | 43 +- src/app/(main)/inventory/page.tsx | 48 +- src/app/(main)/layout.tsx | 60 +- src/app/(main)/material/page.tsx | 7 +- src/app/(main)/pickOrder/detail/page.tsx | 4 +- src/app/(main)/pickOrder/page.tsx | 52 +- src/app/(main)/po/edit/page.tsx | 2 - src/app/(main)/po/page.tsx | 16 +- src/app/(main)/production/page.tsx | 15 +- .../scheduling/detail/edit/not-found.tsx | 4 +- .../(main)/scheduling/detail/edit/page.tsx | 63 +- src/app/(main)/scheduling/detail/page.tsx | 46 +- src/app/(main)/scheduling/page.tsx | 4 +- .../scheduling/rough/edit/not-found.tsx | 4 +- src/app/(main)/scheduling/rough/edit/page.tsx | 75 +- src/app/(main)/scheduling/rough/page.tsx | 56 +- src/app/(main)/settings/equipment/page.tsx | 4 +- .../(main)/settings/equipmentType/page.tsx | 4 +- src/app/(main)/settings/items/page.tsx | 2 +- .../(main)/settings/m18ImportTesting/page.tsx | 41 +- src/app/(main)/settings/mail/page.tsx | 48 +- src/app/(main)/settings/qcCategory/page.tsx | 54 +- .../settings/qcItem/create/not-found.tsx | 4 +- .../(main)/settings/qcItem/create/page.tsx | 24 +- .../(main)/settings/qcItem/edit/not-found.tsx | 4 +- src/app/(main)/settings/qcItem/edit/page.tsx | 64 +- src/app/(main)/settings/qcItem/page.tsx | 54 +- src/app/(main)/settings/rss/page.tsx | 51 +- src/app/(main)/settings/user/create/page.tsx | 2 +- src/app/(main)/settings/user/page.tsx | 2 +- src/app/api/dashboard/actions.ts | 172 +- src/app/api/dashboard/index.ts | 124 +- src/app/api/do/actions.tsx | 2 +- src/app/api/do/index.tsx | 24 +- src/app/api/group/actions.ts | 65 +- src/app/api/group/index.ts | 25 +- src/app/api/inventory/actions.ts | 29 +- src/app/api/inventory/index.ts | 40 +- src/app/api/jo/actions.ts | 63 +- src/app/api/jo/index.ts | 18 +- src/app/api/mail/actions.ts | 63 +- src/app/api/mail/index.ts | 58 +- src/app/api/pdf/actions.ts | 26 +- src/app/api/pickOrder/actions.ts | 286 +- src/app/api/pickOrder/index.ts | 167 +- src/app/api/po/actions.ts | 172 +- src/app/api/po/index.ts | 124 +- src/app/api/qc/actions.ts | 42 +- src/app/api/qc/index.ts | 32 +- src/app/api/qrcode/index.ts | 10 +- src/app/api/scheduling/actions.ts | 97 +- src/app/api/scheduling/index.ts | 133 +- src/app/api/settings/equipment/actions.ts | 32 +- src/app/api/settings/equipment/index.ts | 29 +- src/app/api/settings/equipmentType/actions.ts | 32 +- src/app/api/settings/equipmentType/index.ts | 32 +- src/app/api/settings/item/actions.ts | 38 +- src/app/api/settings/item/index.ts | 29 +- .../api/settings/m18ImportTesting/actions.ts | 76 +- .../api/settings/m18ImportTesting/index.ts | 2 +- src/app/api/settings/qcCategory/actions.ts | 18 +- src/app/api/settings/qcCategory/index.ts | 16 +- src/app/api/settings/qcCheck/actions.ts | 26 +- src/app/api/settings/qcItem/actions.ts | 64 +- src/app/api/settings/qcItem/index.ts | 30 +- src/app/api/settings/uom/index.ts | 28 +- src/app/api/user/actions.ts | 72 +- src/app/api/user/index.ts | 82 +- src/app/api/utils/index.ts | 8 +- src/app/api/warehouse/index.ts | 16 +- src/app/utils/commonUtil.ts | 20 +- src/app/utils/fetchUtil.ts | 17 +- src/app/utils/formatUtil.ts | 87 +- src/app/utils/typeEnum.ts | 18 +- src/authorties.ts | 10 +- src/components/Breadcrumb/Breadcrumb.tsx | 2 +- src/components/ClaimSearch/ClaimSearch.tsx | 93 - .../ClaimSearch/ClaimSearchLoading.tsx | 40 - .../ClaimSearch/ClaimSearchWrapper.tsx | 18 - src/components/ClaimSearch/index.ts | 1 - .../ControlledAutoComplete/index.ts | 2 +- .../CreateEquipment/CreateEquipment.tsx | 86 +- .../CreateEquipmentLoading.tsx | 3 +- .../CreateEquipmentWrapper.tsx | 26 +- .../CreateEquipment/EquipmentDetails.tsx | 67 +- .../CreateEquipment/NumberInputProps.ts | 4 +- src/components/CreateEquipment/index.ts | 2 +- .../CreateEquipmentType.tsx | 91 +- .../CreateEquipmentTypeLoading.tsx | 3 +- .../CreateEquipmentTypeWrapper.tsx | 19 +- .../EquipmentTypeDetails.tsx | 67 +- .../CreateEquipmentType/NumberInputProps.ts | 4 +- src/components/CreateEquipmentType/index.ts | 2 +- src/components/CreateItem/CreateItem.tsx | 128 +- .../CreateItem/CreateItemLoading.tsx | 3 +- .../CreateItem/CreateItemWrapper.tsx | 23 +- src/components/CreateItem/NumberInputProps.ts | 4 +- src/components/CreateItem/ProductDetails.tsx | 67 +- src/components/CreateItem/QcDetails.tsx | 66 +- src/components/CreateItem/index.ts | 2 +- src/components/CreateUser/AuthAllocation.tsx | 29 +- src/components/CreateUser/CreateUser.tsx | 14 +- .../CreateUser/CreateUserLoading.tsx | 5 +- .../CreateUser/CreateUserWrapper.tsx | 3 +- src/components/CreateUser/UserDetail.tsx | 14 +- .../DashboardPage/CollapsibleCard.tsx | 16 +- .../DashboardPage/DashboardLoading.tsx | 5 +- .../DashboardPage/DashboardPage.tsx | 99 +- .../DashboardPage/DashboardWrapper.tsx | 43 +- src/components/DashboardPage/Dashboardbox.tsx | 33 +- .../chart/ApplicationCompletionChart.tsx | 90 +- .../chart/DashboardLineChart.tsx | 126 +- .../chart/DashboardProgressChart.tsx | 230 +- .../chart/OrderCompletionChart.tsx | 143 +- .../chart/PendingInspectionChart.tsx | 47 +- .../chart/PendingStorageChart.tsx | 50 +- .../DetailScheduleSearchView.tsx | 479 +-- .../DetailSchedule/DetailScheduleWrapper.tsx | 19 +- src/components/DetailSchedule/index.ts | 2 +- .../DetailScheduleDetail/DetailInfoCard.tsx | 16 +- .../DetailScheduleDetailWrapper.tsx | 11 +- .../DetailScheudleDetailView.tsx | 76 +- .../DetailScheduleDetail/ViewByBomDetails.tsx | 1933 ++++++--- .../DetailScheduleDetail/ViewByFGDetails.tsx | 2770 +++++++++---- src/components/DetailScheduleDetail/index.ts | 2 +- src/components/DoDetail/DoDetail.tsx | 4 +- src/components/DoSearch/DoSearch.tsx | 75 +- src/components/DoSearch/DoSearchWrapper.tsx | 17 +- src/components/DoSearch/index.ts | 2 +- src/components/EditUser/AuthAllocation.tsx | 29 +- src/components/EditUser/EditUser.tsx | 12 +- src/components/EditUser/EditUserLoading.tsx | 5 +- src/components/EditUser/EditUserWrapper.tsx | 4 +- src/components/EditUser/UserDetail.tsx | 14 +- src/components/EnterLeave/EnterLeaveModal.tsx | 9 +- .../EnterTimesheet/EnterTimesheetModal.tsx | 9 +- .../EquipmentSearch/EquipmentSearch.tsx | 22 +- .../EquipmentSearchWrapper.tsx | 10 +- .../EquipmentTypeSearch.tsx | 22 +- .../EquipmentTypeSearchWrapper.tsx | 10 +- src/components/General/GeneralLoading.tsx | 59 +- .../InputDataGrid/InputDataGrid.tsx | 129 +- .../InventorySearch/InventorySearch.tsx | 249 +- .../InventorySearchWrapper.tsx | 18 +- src/components/InventorySearch/index.ts | 2 +- src/components/ItemsSearch/ItemsSearch.tsx | 14 +- .../ItemsSearch/ItemsSearchWrapper.tsx | 10 +- src/components/LoginPage/LoginForm.tsx | 37 +- src/components/LoginPage/LoginPage.tsx | 15 +- src/components/Logo/Logo.tsx | 6 +- .../M18ImportTesting/M18ImportDo.tsx | 257 +- .../M18ImportTesting/M18ImportMasterData.tsx | 256 +- .../M18ImportTesting/M18ImportPo.tsx | 257 +- .../M18ImportTesting/M18ImportPq.tsx | 257 +- .../M18ImportTesting/M18ImportTesting.tsx | 357 +- .../M18ImportTestingWrapper.tsx | 12 +- src/components/M18ImportTesting/index.ts | 2 +- src/components/MailField/MailField.tsx | 170 +- src/components/MailField/MailFieldWrapper.tsx | 15 +- src/components/MailField/MailToolbar.tsx | 866 +++-- src/components/MailField/index.ts | 2 +- src/components/MailSetting/MailSetting.tsx | 356 +- .../MailSetting/MailSettingLoading.tsx | 56 +- .../MailSetting/MailSettingWrapper.tsx | 55 +- src/components/MailSetting/SettingDetails.tsx | 243 +- .../MailSetting/TemplateDetails.tsx | 368 +- .../MailSetting/TimesheetMailDetails.tsx | 142 +- src/components/MailSetting/index.ts | 2 +- .../NavigationContent/NavigationContent.tsx | 13 +- src/components/Orderstatus/PoSearch.tsx | 39 +- .../Orderstatus/PoSearchWrapper.tsx | 25 +- .../PickOrderDetail/ApprovalContent.tsx | 27 +- .../PickOrderDetail/ApprovalForm.tsx | 8 +- .../PickOrderDetail/PickOrderDetail.tsx | 68 +- .../PickOrderDetailWrapper.tsx | 12 +- src/components/PickOrderDetail/QcContent.tsx | 8 +- src/components/PickOrderDetail/QcForm.tsx | 26 +- src/components/PickOrderDetail/index.ts | 2 +- .../ConsolidatePickOrderItemSum.tsx | 2 +- .../ConsolidatePickOrderSum.tsx | 7 +- .../ConsolidatedPickOrders.tsx | 28 +- .../PickOrderSearch/PickOrderSearch.tsx | 30 +- .../PickOrderSearchWrapper.tsx | 30 +- src/components/PickOrderSearch/PickOrders.tsx | 17 +- src/components/PickOrderSearch/index.ts | 2 +- src/components/PoDetail/EscalationForm.tsx | 49 +- src/components/PoDetail/PoDetail.tsx | 8 +- src/components/PoDetail/PoInfoCard.tsx | 6 +- src/components/PoDetail/PoInputGrid.tsx | 77 +- src/components/PoDetail/PoQcStockInModal.tsx | 26 +- src/components/PoDetail/PutawayForm.tsx | 90 +- src/components/PoDetail/QcForm.tsx | 14 +- src/components/PoDetail/QcSelect.tsx | 4 +- src/components/PoDetail/QrCoderScanner.tsx | 63 +- src/components/PoDetail/QrModal.tsx | 24 +- src/components/PoDetail/RejectForm.tsx | 31 +- src/components/PoDetail/StockInForm.tsx | 29 +- src/components/PoSearch/PoSearch.tsx | 39 +- src/components/PoSearch/PoSearchWrapper.tsx | 25 +- .../ProductionProcess/DefectsSection.tsx | 95 +- .../ProductionProcess/MachineScanner.tsx | 160 +- .../ProductionProcess/MaterialLotScanner.tsx | 216 +- .../ProductionProcess/OperatorScanner.tsx | 153 +- .../ProductionProcess/ProductionProcess.tsx | 109 +- .../ProductionProcessWrapper.tsx | 24 +- .../ProductionRecordingModal.tsx | 157 +- .../ProductionProcess/QualityCheckModal.tsx | 220 +- src/components/ProductionProcess/dummyData.ts | 253 +- src/components/ProductionProcess/index.ts | 2 +- src/components/ProductionProcess/types.ts | 17 +- .../utils/QualityCheckHelper.tsx | 38 +- .../QcCategorySearch/QcCategorySearch.tsx | 5 +- .../QcCategorySearchWrapper.tsx | 17 +- src/components/QcCategorySearch/index.ts | 2 +- src/components/QcItemSave/QcItemSave.tsx | 205 +- .../QcItemSave/QcItemSaveWrapper.tsx | 22 +- src/components/QcItemSave/index.ts | 2 +- src/components/QcItemSearch/QcItemSearch.tsx | 51 +- .../QcItemSearch/QcItemSearchWrapper.tsx | 17 +- src/components/QcItemSearch/index.ts | 2 +- src/components/QrCode/QrCode.tsx | 6 +- src/components/QrCode/index.ts | 2 +- .../QrCodeScanner/QrCodeScanner.tsx | 6 +- .../QrCodeScanner/QrCodeScannerModal.tsx | 2 +- src/components/QrCodeScanner/index.ts | 2 +- .../QrCodeScannerProvider.tsx | 188 +- .../ReactQrCodeScanner/ReactQrCodeScanner.tsx | 4 +- .../RoughSchedule/RoughSchedileSearchView.tsx | 455 ++- .../RoughSchedule/RoughScheduleWrapper.tsx | 25 +- src/components/RoughSchedule/index.ts | 2 +- .../RoughScheduleDetail/DetailInfoCard.tsx | 28 +- .../RoughScheduleDetailWrapper.tsx | 11 +- .../RoughScheudleDetailView.tsx | 93 +- .../RoughScheduleDetail/TempRecords.tsx | 3439 ++++++++++++++--- .../RoughScheduleDetail/ViewByBomDetails.tsx | 666 ++-- .../RoughScheduleDetail/ViewByFGDetails.tsx | 537 +-- src/components/RoughScheduleDetail/index.ts | 2 +- .../RoughScheduleSetting.tsx | 354 +- .../RoughScheduleSettingWrapper.tsx | 22 +- src/components/RoughScheduleSetting/index.ts | 2 +- .../ScheduleTable/BomMaterialTable.tsx | 85 +- .../ScheduleTable/ScheduleTable.tsx | 610 +-- src/components/ScheduleTable/index.ts | 2 +- src/components/SearchBox/MultiSelect.tsx | 121 +- src/components/SearchBox/SearchBox.tsx | 167 +- .../SearchResults/EditableSearchResults.tsx | 567 +-- .../SearchResults/SearchResults.tsx | 198 +- .../SearchResults/TempInputGridForMockUp.tsx | 87 +- .../SessionProviderWrapper.tsx | 10 +- src/components/Swal/CustomAlerts.tsx | 35 +- .../UploadProvider/UploadProvider.tsx | 93 +- .../UploadProvider/useUploadContext.tsx | 20 +- src/components/UserSearch/UserSearch.tsx | 32 +- .../UserSearch/UserSearchWrapper.tsx | 2 +- src/config/api.ts | 2 +- src/config/authConfig.ts | 5 +- src/middleware.ts | 12 +- src/routes.ts | 18 +- src/theme/ThemeRegistry.tsx | 1 - tailwind.config.js | 5 +- tsconfig.json | 2 +- types/next-auth.d.ts | 2 +- 269 files changed, 15964 insertions(+), 9655 deletions(-) delete mode 100644 src/app/(main)/do/edit/page.tsx delete mode 100644 src/components/ClaimSearch/ClaimSearch.tsx delete mode 100644 src/components/ClaimSearch/ClaimSearchLoading.tsx delete mode 100644 src/components/ClaimSearch/ClaimSearchWrapper.tsx delete mode 100644 src/components/ClaimSearch/index.ts diff --git a/next.config.js b/next.config.js index ff62a08..883f839 100644 --- a/next.config.js +++ b/next.config.js @@ -5,7 +5,7 @@ const withPWA = require("next-pwa")({ dest: "public", register: true, skipWaiting: true, - disable: process.env.NODE_ENV === 'development' + disable: process.env.NODE_ENV === "development", }); const nextConfig = { diff --git a/package.json b/package.json index bb714c3..7f04ff1 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,8 @@ "dev": "next dev", "build": "next build", "start": "NODE_OPTIONS='--inspect' next start", - "lint": "next lint" + "lint": "next lint", + "type-check": "tsc --noEmit" }, "dependencies": { "@emotion/cache": "^11.11.0", diff --git a/postcss.config.js b/postcss.config.js index 33ad091..12a703d 100644 --- a/postcss.config.js +++ b/postcss.config.js @@ -3,4 +3,4 @@ module.exports = { tailwindcss: {}, autoprefixer: {}, }, -} +}; diff --git a/src/app/(main)/axios/AxiosProvider.tsx b/src/app/(main)/axios/AxiosProvider.tsx index 224d40c..20832e8 100644 --- a/src/app/(main)/axios/AxiosProvider.tsx +++ b/src/app/(main)/axios/AxiosProvider.tsx @@ -1,38 +1,42 @@ "use client"; -import React, {createContext, useContext, useEffect, useState} from 'react'; -import axiosInstance, {SetupAxiosInterceptors} from './axiosInstance'; +import React, { createContext, useContext, useEffect, useState } from "react"; +import axiosInstance, { SetupAxiosInterceptors } from "./axiosInstance"; const AxiosContext = createContext(axiosInstance); const TokenContext = createContext({ - setAccessToken: (token: string | null) => {}, + setAccessToken: (token: string | null) => {}, }); -export const AxiosProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => { - const [accessToken, setAccessToken] = useState(localStorage.getItem("accessToken")); +export const AxiosProvider: React.FC<{ children: React.ReactNode }> = ({ + children, +}) => { + const [accessToken, setAccessToken] = useState( + localStorage.getItem("accessToken"), + ); - useEffect(() => { - if (accessToken) { - axiosInstance.defaults.headers.Authorization = `Bearer ${accessToken}`; - SetupAxiosInterceptors(accessToken); - console.log("[debug] Updated accessToken:", accessToken); - } - }, [accessToken]); + useEffect(() => { + if (accessToken) { + axiosInstance.defaults.headers.Authorization = `Bearer ${accessToken}`; + SetupAxiosInterceptors(accessToken); + console.log("[debug] Updated accessToken:", accessToken); + } + }, [accessToken]); - return ( - - - {children} - - - ); + return ( + + + {children} + + + ); }; // Custom hook to use Axios instance export const useAxios = () => { - return useContext(AxiosContext); + return useContext(AxiosContext); }; // Custom hook to manage access token export const useToken = () => { - return useContext(TokenContext); -}; \ No newline at end of file + return useContext(TokenContext); +}; diff --git a/src/app/(main)/axios/axiosInstance.ts b/src/app/(main)/axios/axiosInstance.ts index 4a5361c..1d24e5d 100644 --- a/src/app/(main)/axios/axiosInstance.ts +++ b/src/app/(main)/axios/axiosInstance.ts @@ -1,56 +1,56 @@ -import axios from 'axios'; +import axios from "axios"; const axiosInstance = axios.create({ - baseURL: process.env.API_URL, + baseURL: process.env.API_URL, }); // Clear existing interceptors to prevent multiple registrations const clearInterceptors = () => { - const requestInterceptor = axiosInstance.interceptors.request.use(); - const responseInterceptor = axiosInstance.interceptors.response.use(); + const requestInterceptor = axiosInstance.interceptors.request.use(); + const responseInterceptor = axiosInstance.interceptors.response.use(); - if (requestInterceptor) { - axiosInstance.interceptors.request.eject(requestInterceptor); - } + if (requestInterceptor) { + axiosInstance.interceptors.request.eject(requestInterceptor); + } - if (responseInterceptor) { - axiosInstance.interceptors.response.eject(responseInterceptor); - } + if (responseInterceptor) { + axiosInstance.interceptors.response.eject(responseInterceptor); + } }; export const SetupAxiosInterceptors = (inputToken: string | null) => { - console.log("[debug] set up interceptors", inputToken); - - // Clear existing interceptors - clearInterceptors(); - - // Request interceptor - axiosInstance.interceptors.request.use( - (config) => { - // Use the token passed in or retrieve from localStorage - const token = inputToken ?? localStorage.getItem('accessToken'); - if (token) { - config.headers.Authorization = `Bearer ${token}`; - } - return config; - }, - (error) => { - return Promise.reject(error); - } - ); - - console.log("[debug] set up interceptors2", inputToken); - - // Response interceptor - axiosInstance.interceptors.response.use( - (response) => { - return response; - }, - (error) => { - console.error('API Error:', error.response?.data || error); - return Promise.reject(error); - } - ); + console.log("[debug] set up interceptors", inputToken); + + // Clear existing interceptors + clearInterceptors(); + + // Request interceptor + axiosInstance.interceptors.request.use( + (config) => { + // Use the token passed in or retrieve from localStorage + const token = inputToken ?? localStorage.getItem("accessToken"); + if (token) { + config.headers.Authorization = `Bearer ${token}`; + } + return config; + }, + (error) => { + return Promise.reject(error); + }, + ); + + console.log("[debug] set up interceptors2", inputToken); + + // Response interceptor + axiosInstance.interceptors.response.use( + (response) => { + return response; + }, + (error) => { + console.error("API Error:", error.response?.data || error); + return Promise.reject(error); + }, + ); }; -export default axiosInstance; \ No newline at end of file +export default axiosInstance; diff --git a/src/app/(main)/dashboard/page.tsx b/src/app/(main)/dashboard/page.tsx index 84c79ad..ac1db4a 100644 --- a/src/app/(main)/dashboard/page.tsx +++ b/src/app/(main)/dashboard/page.tsx @@ -5,29 +5,22 @@ import { getServerI18n } from "@/i18n"; import DashboardPage from "@/components/DashboardPage"; import { SearchParams } from "@/app/utils/fetchUtil"; - export const metadata: Metadata = { title: "Dashboard", }; -type Props = { - -} & SearchParams +type Props = {} & SearchParams; -const Dashboard: React.FC = async ({ - searchParams -}) => { +const Dashboard: React.FC = async ({ searchParams }) => { const { t } = await getServerI18n("dashboard"); return ( }> - + - ) + ); }; export default Dashboard; diff --git a/src/app/(main)/do/edit/page.tsx b/src/app/(main)/do/edit/page.tsx deleted file mode 100644 index e69de29..0000000 diff --git a/src/app/(main)/do/page.tsx b/src/app/(main)/do/page.tsx index 9b69e37..8560496 100644 --- a/src/app/(main)/do/page.tsx +++ b/src/app/(main)/do/page.tsx @@ -1,36 +1,35 @@ // import DoSearch from "@/components/DoSearch"; // import { getServerI18n } from "@/i18n" import DoSearch from "../../../components/DoSearch"; -import { getServerI18n } from "../../../i18n" +import { getServerI18n } from "../../../i18n"; import { Stack, Typography } from "@mui/material"; import { I18nProvider } from "@/i18n"; import { Metadata } from "next"; import { Suspense } from "react"; export const metadata: Metadata = { - title: "Delivery Order" -} + title: "Delivery Order", +}; const DeliveryOrder: React.FC = async () => { - const { t } = await getServerI18n("do"); + const { t } = await getServerI18n("do"); - return ( - <> - - + return ( + <> + - - }> - - - - - ) -} + + }> + + + + + ); +}; -export default DeliveryOrder; \ No newline at end of file +export default DeliveryOrder; diff --git a/src/app/(main)/inventory/page.tsx b/src/app/(main)/inventory/page.tsx index 4ee9428..3b202f0 100644 --- a/src/app/(main)/inventory/page.tsx +++ b/src/app/(main)/inventory/page.tsx @@ -10,31 +10,33 @@ import { Metadata } from "next"; import { Suspense } from "react"; export const metadata: Metadata = { - title: "Inventory" -} + title: "Inventory", +}; const Inventory: React.FC = async () => { - const { t } = await getServerI18n("inventory", "common") + const { t } = await getServerI18n("inventory", "common"); - preloadInventory() + preloadInventory(); - return <> - - - {t("Inventory")} - - - - }> - - - - ; -} + return ( + <> + + + {t("Inventory")} + + + + }> + + + + + ); +}; -export default Inventory; \ No newline at end of file +export default Inventory; diff --git a/src/app/(main)/layout.tsx b/src/app/(main)/layout.tsx index f4b1a47..02da7f5 100644 --- a/src/app/(main)/layout.tsx +++ b/src/app/(main)/layout.tsx @@ -1,4 +1,3 @@ - import AppBar from "@/components/AppBar"; import { AuthOptions, getServerSession } from "next-auth"; import { authOptions, SessionWithTokens } from "@/config/authConfig"; @@ -15,13 +14,14 @@ import SessionProviderWrapper from "@/components/SessionProviderWrapper/SessionP import QrCodeScannerProvider from "@/components/QrCodeScannerProvider/QrCodeScannerProvider"; import { I18nProvider } from "@/i18n"; - export default async function MainLayout({ children, }: { children: React.ReactNode; }) { - const session = await getServerSession(authOptions); + const session = await getServerSession( + authOptions, + ); if (!session?.user) { redirect("/login"); @@ -36,33 +36,33 @@ export default async function MainLayout({ return ( - - - - - <> - - - - - - {children} - - - - - - - + + + + + <> + + + + + + {children} + + + + + + + ); diff --git a/src/app/(main)/material/page.tsx b/src/app/(main)/material/page.tsx index eb358d1..c45c745 100644 --- a/src/app/(main)/material/page.tsx +++ b/src/app/(main)/material/page.tsx @@ -11,13 +11,11 @@ export const metadata: Metadata = { title: "Material Setting", }; -type Props = { - -} & SearchParams +type Props = {} & SearchParams; const material: React.FC = async ({ searchParams }) => { const { t } = await getServerI18n("material"); - console.log(searchParams) + console.log(searchParams); return ( <> = async ({ searchParams }) => { > {t("Create Claim")} - {/* }> diff --git a/src/app/(main)/pickOrder/detail/page.tsx b/src/app/(main)/pickOrder/detail/page.tsx index fa4b09e..d40809a 100644 --- a/src/app/(main)/pickOrder/detail/page.tsx +++ b/src/app/(main)/pickOrder/detail/page.tsx @@ -1,4 +1,4 @@ -import { PreloadPickOrder } from "@/app/api/pickorder"; +import { PreloadPickOrder } from "@/app/api/pickOrder"; import { SearchParams } from "@/app/utils/fetchUtil"; import PickOrderDetail from "@/components/PickOrderDetail"; import { getServerI18n, I18nProvider } from "@/i18n"; @@ -20,7 +20,7 @@ const PickOrder: React.FC = async ({ searchParams }) => { <> }> - + diff --git a/src/app/(main)/pickOrder/page.tsx b/src/app/(main)/pickOrder/page.tsx index 60e2a0c..9d9e9ac 100644 --- a/src/app/(main)/pickOrder/page.tsx +++ b/src/app/(main)/pickOrder/page.tsx @@ -1,4 +1,4 @@ -import { PreloadPickOrder } from "@/app/api/pickorder"; +import { PreloadPickOrder } from "@/app/api/pickOrder"; import PickOrderSearch from "@/components/PickOrderSearch"; import { getServerI18n } from "@/i18n"; import { I18nProvider } from "@/i18n"; @@ -7,33 +7,33 @@ import { Metadata } from "next"; import { Suspense } from "react"; export const metadata: Metadata = { - title: "Pick Order" -} + title: "Pick Order", +}; const PickOrder: React.FC = async () => { - const { t } = await getServerI18n("pickOrder") + const { t } = await getServerI18n("pickOrder"); - PreloadPickOrder() + PreloadPickOrder(); - return ( - <> - - - {t("Pick Order")} - - - - }> - - - - - ) -} + return ( + <> + + + {t("Pick Order")} + + + + }> + + + + + ); +}; -export default PickOrder; \ No newline at end of file +export default PickOrder; diff --git a/src/app/(main)/po/edit/page.tsx b/src/app/(main)/po/edit/page.tsx index 9a2c637..f701caf 100644 --- a/src/app/(main)/po/edit/page.tsx +++ b/src/app/(main)/po/edit/page.tsx @@ -4,8 +4,6 @@ import CreateProductMaterial from "@/components/CreateItem"; import PoDetail from "@/components/PoDetail"; import { I18nProvider, getServerI18n } from "@/i18n"; - - import { Typography } from "@mui/material"; import isString from "lodash/isString"; import { notFound } from "next/navigation"; diff --git a/src/app/(main)/po/page.tsx b/src/app/(main)/po/page.tsx index f031c40..f9f33d9 100644 --- a/src/app/(main)/po/page.tsx +++ b/src/app/(main)/po/page.tsx @@ -1,10 +1,3 @@ -//import { preloadClaims } from "@/app/api/claims"; -// import ClaimSearch from "@/components/ClaimSearch"; -// import PoSearch from "@/components/PoSearch"; -// import { getServerI18n, I18nProvider } from "@/i18n"; - -import { preloadClaims } from "../../../app/api/claims"; -import ClaimSearch from "../../../components/ClaimSearch"; import PoSearch from "../../../components/PoSearch"; import { getServerI18n, I18nProvider } from "../../../i18n"; import Add from "@mui/icons-material/Add"; @@ -30,11 +23,10 @@ const PurchaseOrder: React.FC = async () => { justifyContent="space-between" flexWrap="wrap" rowGap={2} - > - - }> - - + > + }> + + ); diff --git a/src/app/(main)/production/page.tsx b/src/app/(main)/production/page.tsx index f391be0..f08ea76 100644 --- a/src/app/(main)/production/page.tsx +++ b/src/app/(main)/production/page.tsx @@ -1,10 +1,3 @@ -// import { preloadClaims } from "@/app/api/claims"; -// import ClaimSearch from "@/components/ClaimSearch"; -// import ProductionProcess from "@/components/ProductionProcess"; -//import { getServerI18n } from "@/i18n"; - -import { preloadClaims } from "../../../app/api/claims"; -import ClaimSearch from "../../../components/ClaimSearch"; import ProductionProcess from "../../../components/ProductionProcess"; import { getServerI18n } from "../../../i18n"; @@ -22,7 +15,7 @@ export const metadata: Metadata = { const production: React.FC = async () => { const { t } = await getServerI18n("claims"); -// preloadClaims(); + // preloadClaims(); return ( <> @@ -44,9 +37,9 @@ const production: React.FC = async () => { {t("Create Claim")} - }> - - + {/* }> */} + + {/* */} ); }; diff --git a/src/app/(main)/scheduling/detail/edit/not-found.tsx b/src/app/(main)/scheduling/detail/edit/not-found.tsx index 34de267..36708fc 100644 --- a/src/app/(main)/scheduling/detail/edit/not-found.tsx +++ b/src/app/(main)/scheduling/detail/edit/not-found.tsx @@ -8,7 +8,9 @@ export default async function NotFound() { return ( {t("Not Found")} - {t("The edit detail scheduling page was not found!")} + + {t("The edit detail scheduling page was not found!")} + {t("Return to all detail scheduling")} diff --git a/src/app/(main)/scheduling/detail/edit/page.tsx b/src/app/(main)/scheduling/detail/edit/page.tsx index f27ba0f..1212996 100644 --- a/src/app/(main)/scheduling/detail/edit/page.tsx +++ b/src/app/(main)/scheduling/detail/edit/page.tsx @@ -4,7 +4,10 @@ import { getServerI18n, I18nProvider } from "../../../../../i18n"; import Typography from "@mui/material/Typography"; // import { fetchQcItemDetails, preloadQcItem } from "@/app/api/settings/qcItem"; // import QcItemSave from "@/components/QcItemSave"; -import { fetchQcItemDetails, preloadQcItem } from "../../../../../app/api/settings/qcItem"; +import { + fetchQcItemDetails, + preloadQcItem, +} from "../../../../../app/api/settings/qcItem"; import QcItemSave from "../../../../../components/QcItemSave"; import { isArray } from "lodash"; import { notFound } from "next/navigation"; @@ -14,39 +17,41 @@ import { ServerFetchError } from "../../../../../app/utils/fetchUtil"; import DetailScheduleDetail from "../../../../../components/DetailScheduleDetail"; export const metadata: Metadata = { - title: "Qc Item", + title: "Qc Item", }; interface Props { - searchParams: { [key: string]: string | string[] | undefined }; + searchParams: { [key: string]: string | string[] | undefined }; } const DetailScheduling: React.FC = async ({ searchParams }) => { - const { t } = await getServerI18n("schedule") - - const id = searchParams["id"] - - if (!id || isArray(id)) { - notFound() - } - - // try { - // await fetchQcItemDetails(id) - // } catch (e) { - // if (e instanceof ServerFetchError && (e.response?.status === 404 || e.response?.status === 400)) { - // console.log(e) - // notFound(); - // } - // } - - return <> - - {t("FG Production Schedule")} - - - - - ; + const { t } = await getServerI18n("schedule"); + + const id = searchParams["id"]; + + if (!id || isArray(id)) { + notFound(); + } + + // try { + // await fetchQcItemDetails(id) + // } catch (e) { + // if (e instanceof ServerFetchError && (e.response?.status === 404 || e.response?.status === 400)) { + // console.log(e) + // notFound(); + // } + // } + + return ( + <> + + {t("FG Production Schedule")} + + + + + + ); }; -export default DetailScheduling; \ No newline at end of file +export default DetailScheduling; diff --git a/src/app/(main)/scheduling/detail/page.tsx b/src/app/(main)/scheduling/detail/page.tsx index e7c2762..52da5b9 100644 --- a/src/app/(main)/scheduling/detail/page.tsx +++ b/src/app/(main)/scheduling/detail/page.tsx @@ -11,33 +11,33 @@ import { Metadata } from "next"; import { Suspense } from "react"; export const metadata: Metadata = { - title: "Detail Scheduling", + title: "Detail Scheduling", }; const DetailScheduling: React.FC = async () => { - const { t } = await getServerI18n("schedule"); - const type = "detailed" - // preloadClaims(); + const { t } = await getServerI18n("schedule"); + const type = "detailed"; + // preloadClaims(); - return ( - <> - - - {t("Detail Scheduling")} - - - - }> - - - - - ); + return ( + <> + + + {t("Detail Scheduling")} + + + + }> + + + + + ); }; export default DetailScheduling; diff --git a/src/app/(main)/scheduling/page.tsx b/src/app/(main)/scheduling/page.tsx index a819690..51f5975 100644 --- a/src/app/(main)/scheduling/page.tsx +++ b/src/app/(main)/scheduling/page.tsx @@ -1,11 +1,11 @@ import { Metadata } from "next"; export const metadata: Metadata = { - title: "Scheduling", + title: "Scheduling", }; const Scheduling: React.FC = async () => { - return null; + return null; }; export default Scheduling; diff --git a/src/app/(main)/scheduling/rough/edit/not-found.tsx b/src/app/(main)/scheduling/rough/edit/not-found.tsx index 0a49845..6f1f86a 100644 --- a/src/app/(main)/scheduling/rough/edit/not-found.tsx +++ b/src/app/(main)/scheduling/rough/edit/not-found.tsx @@ -8,7 +8,9 @@ export default async function NotFound() { return ( {t("Not Found")} - {t("The production schedule detail page was not found!")} + + {t("The production schedule detail page was not found!")} + {t("Return to all scheduling")} diff --git a/src/app/(main)/scheduling/rough/edit/page.tsx b/src/app/(main)/scheduling/rough/edit/page.tsx index e3b693e..1096da1 100644 --- a/src/app/(main)/scheduling/rough/edit/page.tsx +++ b/src/app/(main)/scheduling/rough/edit/page.tsx @@ -15,42 +15,45 @@ import { notFound } from "next/navigation"; import { fetchProdScheduleDetail } from "@/app/api/scheduling"; export const metadata: Metadata = { - title: "Demand Forecast Detail", + title: "Demand Forecast Detail", }; -type Props = SearchParams +type Props = SearchParams; const roughSchedulingDetail: React.FC = async ({ searchParams }) => { - const { t } = await getServerI18n("schedule"); - const id = searchParams["id"] - const type = "rough" + const { t } = await getServerI18n("schedule"); + const id = searchParams["id"]; + const type = "rough"; - if (!id || isArray(id) || !isFinite(parseInt(id))) { - notFound() - } + if (!id || isArray(id) || !isFinite(parseInt(id))) { + notFound(); + } - try { - await fetchProdScheduleDetail(parseInt(id)) - } catch(e) { - if (e instanceof ServerFetchError && (e.response?.status === 404 || e.response?.status === 400)) { - console.log(e) - notFound(); - } + try { + await fetchProdScheduleDetail(parseInt(id)); + } catch (e) { + if ( + e instanceof ServerFetchError && + (e.response?.status === 404 || e.response?.status === 400) + ) { + console.log(e); + notFound(); } - // preloadClaims(); + } + // preloadClaims(); - return ( - <> - - - {t("FG & Material Demand Forecast Detail")} - - {/* */} - - - }> - - - - - ); + + + }> + + + + + ); }; export default roughSchedulingDetail; diff --git a/src/app/(main)/scheduling/rough/page.tsx b/src/app/(main)/scheduling/rough/page.tsx index e949b21..cc4e9f8 100644 --- a/src/app/(main)/scheduling/rough/page.tsx +++ b/src/app/(main)/scheduling/rough/page.tsx @@ -14,46 +14,46 @@ import Link from "next/link"; import { Suspense } from "react"; export const metadata: Metadata = { - title: "Demand Forecast", + title: "Demand Forecast", }; const roughScheduling: React.FC = async () => { - // const project = TypeEnum.PRODUCT - const { t } = await getServerI18n("schedule"); - const type = "rough" - // preloadClaims(); + // const project = TypeEnum.PRODUCT + const { t } = await getServerI18n("schedule"); + const type = "rough"; + // preloadClaims(); - // async function testingRoughSchedule() { - // await testRoughSchedule(); - // } + // async function testingRoughSchedule() { + // await testRoughSchedule(); + // } - return ( - <> - - - {t("Demand Forecast")} - + return ( + <> + + + {t("Demand Forecast")} + - {/* */} - - - }> - - - - - ); + + + }> + + + + + ); }; export default roughScheduling; diff --git a/src/app/(main)/settings/equipment/page.tsx b/src/app/(main)/settings/equipment/page.tsx index be47de9..4456a31 100644 --- a/src/app/(main)/settings/equipment/page.tsx +++ b/src/app/(main)/settings/equipment/page.tsx @@ -41,8 +41,8 @@ const productSetting: React.FC = async () => { */} }> - - + + diff --git a/src/app/(main)/settings/equipmentType/page.tsx b/src/app/(main)/settings/equipmentType/page.tsx index c2b511f..63803dc 100644 --- a/src/app/(main)/settings/equipmentType/page.tsx +++ b/src/app/(main)/settings/equipmentType/page.tsx @@ -41,8 +41,8 @@ const productSetting: React.FC = async () => { */} }> - - + + diff --git a/src/app/(main)/settings/items/page.tsx b/src/app/(main)/settings/items/page.tsx index 205cf4f..627b34d 100644 --- a/src/app/(main)/settings/items/page.tsx +++ b/src/app/(main)/settings/items/page.tsx @@ -14,7 +14,7 @@ export const metadata: Metadata = { }; const productSetting: React.FC = async () => { - const project = TypeEnum.PRODUCT + const project = TypeEnum.PRODUCT; const { t } = await getServerI18n(project); // preloadClaims(); diff --git a/src/app/(main)/settings/m18ImportTesting/page.tsx b/src/app/(main)/settings/m18ImportTesting/page.tsx index f234fe0..3aa4a35 100644 --- a/src/app/(main)/settings/m18ImportTesting/page.tsx +++ b/src/app/(main)/settings/m18ImportTesting/page.tsx @@ -6,28 +6,27 @@ import React, { Suspense } from "react"; import { I18nProvider } from "@/i18n"; export const metadata: Metadata = { - title: "Import Testing" -} + title: "Import Testing", +}; const M18ImportTestingPage: React.FC = async () => { - const { t } = await getServerI18n("m18ImportTesting"); + const { t } = await getServerI18n("m18ImportTesting"); - return ( - <> - - - }> - - - - - - ) -} + return ( + <> + + }> + + + + + + ); +}; -export default M18ImportTestingPage; \ No newline at end of file +export default M18ImportTestingPage; diff --git a/src/app/(main)/settings/mail/page.tsx b/src/app/(main)/settings/mail/page.tsx index 6eefa37..6bbb298 100644 --- a/src/app/(main)/settings/mail/page.tsx +++ b/src/app/(main)/settings/mail/page.tsx @@ -9,33 +9,33 @@ import { preloadMails } from "@/app/api/mail"; import MailSetting from "@/components/MailSetting"; export const metadata: Metadata = { - title: "Mail", + title: "Mail", }; const Customer: React.FC = async () => { - const { t } = await getServerI18n("mail"); - preloadMails(); - // const abilities = await fetchUserAbilities() + const { t } = await getServerI18n("mail"); + preloadMails(); + // const abilities = await fetchUserAbilities() - return ( - <> - - - {t("Mail")} - - - - }> - - - - - ); + return ( + <> + + + {t("Mail")} + + + + }> + + + + + ); }; -export default Customer; \ No newline at end of file +export default Customer; diff --git a/src/app/(main)/settings/qcCategory/page.tsx b/src/app/(main)/settings/qcCategory/page.tsx index 3f5e054..63f57ee 100644 --- a/src/app/(main)/settings/qcCategory/page.tsx +++ b/src/app/(main)/settings/qcCategory/page.tsx @@ -8,37 +8,39 @@ import QcCategorySearch from "@/components/QcCategorySearch"; import { preloadQcCategory } from "@/app/api/settings/qcCategory"; export const metadata: Metadata = { - title: "Qc Category", + title: "Qc Category", }; const qcCategory: React.FC = async () => { - const { t } = await getServerI18n("qcCategory") + const { t } = await getServerI18n("qcCategory"); - preloadQcCategory() + preloadQcCategory(); - return <> - + + + {t("Qc Category")} + + - - }> - - - ; + {t("Create Qc Category")} + + + }> + + + + ); }; -export default qcCategory; \ No newline at end of file +export default qcCategory; diff --git a/src/app/(main)/settings/qcItem/create/not-found.tsx b/src/app/(main)/settings/qcItem/create/not-found.tsx index c23e0db..b36d891 100644 --- a/src/app/(main)/settings/qcItem/create/not-found.tsx +++ b/src/app/(main)/settings/qcItem/create/not-found.tsx @@ -8,7 +8,9 @@ export default async function NotFound() { return ( {t("Not Found")} - {t("The create qc item page was not found!")} + + {t("The create qc item page was not found!")} + {t("Return to all qc items")} diff --git a/src/app/(main)/settings/qcItem/create/page.tsx b/src/app/(main)/settings/qcItem/create/page.tsx index f404e1d..1cb5c8a 100644 --- a/src/app/(main)/settings/qcItem/create/page.tsx +++ b/src/app/(main)/settings/qcItem/create/page.tsx @@ -5,20 +5,22 @@ import { preloadQcItem } from "@/app/api/settings/qcItem"; import QcItemSave from "@/components/QcItemSave"; export const metadata: Metadata = { - title: "Qc Item", + title: "Qc Item", }; const qcItem: React.FC = async () => { - const { t } = await getServerI18n("qcItem") + const { t } = await getServerI18n("qcItem"); - return <> - - {t("Create Qc Item")} - - - - - ; + return ( + <> + + {t("Create Qc Item")} + + + + + + ); }; -export default qcItem; \ No newline at end of file +export default qcItem; diff --git a/src/app/(main)/settings/qcItem/edit/not-found.tsx b/src/app/(main)/settings/qcItem/edit/not-found.tsx index ef2b2be..e9e09bc 100644 --- a/src/app/(main)/settings/qcItem/edit/not-found.tsx +++ b/src/app/(main)/settings/qcItem/edit/not-found.tsx @@ -8,7 +8,9 @@ export default async function NotFound() { return ( {t("Not Found")} - {t("The edit qc item page was not found!")} + + {t("The edit qc item page was not found!")} + {t("Return to all qc items")} diff --git a/src/app/(main)/settings/qcItem/edit/page.tsx b/src/app/(main)/settings/qcItem/edit/page.tsx index edc7aa8..0e433fb 100644 --- a/src/app/(main)/settings/qcItem/edit/page.tsx +++ b/src/app/(main)/settings/qcItem/edit/page.tsx @@ -8,42 +8,46 @@ import { notFound } from "next/navigation"; import { ServerFetchError } from "@/app/utils/fetchUtil"; export const metadata: Metadata = { - title: "Qc Item", + title: "Qc Item", }; interface Props { - searchParams: { [key: string]: string | string[] | undefined }; + searchParams: { [key: string]: string | string[] | undefined }; } const qcItem: React.FC = async ({ searchParams }) => { - const { t } = await getServerI18n("qcItem") - - const id = searchParams["id"] - - if (!id || isArray(id)) { - notFound() - } - - try { - console.log("first") - await fetchQcItemDetails(id) - console.log("firsts") - } catch (e) { - - if (e instanceof ServerFetchError && (e.response?.status === 404 || e.response?.status === 400)) { - console.log(e) - notFound(); - } + const { t } = await getServerI18n("qcItem"); + + const id = searchParams["id"]; + + if (!id || isArray(id)) { + notFound(); + } + + try { + console.log("first"); + await fetchQcItemDetails(id); + console.log("firsts"); + } catch (e) { + if ( + e instanceof ServerFetchError && + (e.response?.status === 404 || e.response?.status === 400) + ) { + console.log(e); + notFound(); } - - return <> - - {t("Edit Qc Item")} - - - - - ; + } + + return ( + <> + + {t("Edit Qc Item")} + + + + + + ); }; -export default qcItem; \ No newline at end of file +export default qcItem; diff --git a/src/app/(main)/settings/qcItem/page.tsx b/src/app/(main)/settings/qcItem/page.tsx index 00a041e..1afce1a 100644 --- a/src/app/(main)/settings/qcItem/page.tsx +++ b/src/app/(main)/settings/qcItem/page.tsx @@ -8,37 +8,39 @@ import { preloadQcItem } from "@/app/api/settings/qcItem"; import QcItemSearch from "@/components/QcItemSearch"; export const metadata: Metadata = { - title: "Qc Item", + title: "Qc Item", }; const qcItem: React.FC = async () => { - const { t } = await getServerI18n("qcItem") + const { t } = await getServerI18n("qcItem"); - preloadQcItem() + preloadQcItem(); - return <> - + + + {t("Qc Item")} + + - - }> - - - ; + {t("Create Qc Item")} + + + }> + + + + ); }; -export default qcItem; \ No newline at end of file +export default qcItem; diff --git a/src/app/(main)/settings/rss/page.tsx b/src/app/(main)/settings/rss/page.tsx index a5d77e8..c5daf2b 100644 --- a/src/app/(main)/settings/rss/page.tsx +++ b/src/app/(main)/settings/rss/page.tsx @@ -8,30 +8,29 @@ import Typography from "@mui/material/Typography"; import { Metadata } from "next"; import Link from "next/link"; import { Suspense } from "react"; -import RoughScheduleLoading from "@/components/RoughScheduleSetting/RoughScheduleLoading"; -import RoughScheduleSetting from "@/components/RoughScheduleSetting/RoughScheduleSetting"; +import RoughScheduleSetting from "@/components/RoughScheduleSetting"; import { I18nProvider } from "@/i18n"; export const metadata: Metadata = { - title: "Demand Forecast Setting", + title: "Demand Forecast Setting", }; const roughScheduleSetting: React.FC = async () => { - const project = TypeEnum.PRODUCT - const { t } = await getServerI18n(project); - // preloadClaims(); + const project = TypeEnum.PRODUCT; + const { t } = await getServerI18n(project); + // preloadClaims(); - return ( - <> - - - {t("Demand Forecast Setting")} - - {/* */} - - - }> - - - - - ); + + + }> + + + + + ); }; export default roughScheduleSetting; diff --git a/src/app/(main)/settings/user/create/page.tsx b/src/app/(main)/settings/user/create/page.tsx index a48bdec..88694b8 100644 --- a/src/app/(main)/settings/user/create/page.tsx +++ b/src/app/(main)/settings/user/create/page.tsx @@ -19,7 +19,7 @@ const CreateStaffPage: React.FC = async () => { {t("Create User")} }> - + diff --git a/src/app/(main)/settings/user/page.tsx b/src/app/(main)/settings/user/page.tsx index 81424a1..d66ba94 100644 --- a/src/app/(main)/settings/user/page.tsx +++ b/src/app/(main)/settings/user/page.tsx @@ -12,7 +12,7 @@ export const metadata: Metadata = { title: "User Management", }; -const User: React.FC = async() => { +const User: React.FC = async () => { const { t } = await getServerI18n("user"); return ( <> diff --git a/src/app/api/dashboard/actions.ts b/src/app/api/dashboard/actions.ts index d30135a..f3c4e6a 100644 --- a/src/app/api/dashboard/actions.ts +++ b/src/app/api/dashboard/actions.ts @@ -15,21 +15,21 @@ export interface PostStockInLiineResponse { id: number | null; name: string; code: string; - type?: string + type?: string; message: string | null; errorPosition: string | keyof T; - entity: T | T[] + entity: T | T[]; // entity: StockInLine | StockInLine[] } export interface StockInLineEntry { - id?: number - itemId: number - purchaseOrderId: number - purchaseOrderLineId: number - acceptedQty: number - status?: string - expiryDate?: string + id?: number; + itemId: number; + purchaseOrderId: number; + purchaseOrderLineId: number; + acceptedQty: number; + status?: string; + expiryDate?: string; } export interface PurchaseQcResult { @@ -37,37 +37,39 @@ export interface PurchaseQcResult { failQty: number; } export interface StockInInput { - status: string - productLotNo?: string, - receiptDate: string - acceptedQty: number - acceptedWeight?: number - productionDate?: string - expiryDate: string + status: string; + productLotNo?: string; + receiptDate: string; + acceptedQty: number; + acceptedWeight?: number; + productionDate?: string; + expiryDate: string; } export interface PurchaseQCInput { - status: string - acceptedQty: number + status: string; + acceptedQty: number; sampleRate: number; sampleWeight: number; totalWeight: number; qcResult: PurchaseQcResult[]; } export interface EscalationInput { - status: string - handler: string - acceptedQty: number // this is the qty to be escalated + status: string; + handler: string; + acceptedQty: number; // this is the qty to be escalated // escalationQty: number } export interface PutawayInput { - status: string - acceptedQty: number - warehouseId: number + status: string; + acceptedQty: number; + warehouseId: number; // handler: string // stockInLine: StockInLineEntry[] } -export type ModalFormInput = Partial +export type ModalFormInput = Partial< + PurchaseQCInput & StockInInput & EscalationInput & PutawayInput +>; export const testFetch = cache(async (id: number) => { return serverFetchJson(`${BASE_API_URL}/po/detail/${id}`, { @@ -76,50 +78,65 @@ export const testFetch = cache(async (id: number) => { }); export const fetchStockInLineInfo = cache(async (stockInLineId: number) => { - return serverFetchJson(`${BASE_API_URL}/stockInLine/${stockInLineId}`, { + return serverFetchJson( + `${BASE_API_URL}/stockInLine/${stockInLineId}`, + { next: { tags: ["stockInLine"] }, - }); + }, + ); }); export const createStockInLine = async (data: StockInLineEntry) => { - const stockInLine = await serverFetchJson>(`${BASE_API_URL}/stockInLine/create`, { + const stockInLine = await serverFetchJson< + PostStockInLiineResponse + >(`${BASE_API_URL}/stockInLine/create`, { method: "POST", body: JSON.stringify(data), headers: { "Content-Type": "application/json" }, }); // revalidateTag("po"); - return stockInLine -} + return stockInLine; +}; -export const updateStockInLine = async (data: StockInLineEntry & ModalFormInput) => { - const stockInLine = await serverFetchJson>(`${BASE_API_URL}/stockInLine/update`, { +export const updateStockInLine = async ( + data: StockInLineEntry & ModalFormInput, +) => { + const stockInLine = await serverFetchJson< + PostStockInLiineResponse + >(`${BASE_API_URL}/stockInLine/update`, { method: "POST", body: JSON.stringify(data), headers: { "Content-Type": "application/json" }, }); // revalidateTag("po"); - return stockInLine -} + return stockInLine; +}; export const startPo = async (poId: number) => { - const po = await serverFetchJson>(`${BASE_API_URL}/po/start/${poId}`, { - method: "POST", - body: JSON.stringify({ poId }), - headers: { "Content-Type": "application/json" }, - }); + const po = await serverFetchJson>( + `${BASE_API_URL}/po/start/${poId}`, + { + method: "POST", + body: JSON.stringify({ poId }), + headers: { "Content-Type": "application/json" }, + }, + ); revalidateTag("po"); - return po -} + return po; +}; export const checkPolAndCompletePo = async (poId: number) => { - const po = await serverFetchJson>(`${BASE_API_URL}/po/check/${poId}`, { - method: "POST", - body: JSON.stringify({ poId }), - headers: { "Content-Type": "application/json" }, - }); + const po = await serverFetchJson>( + `${BASE_API_URL}/po/check/${poId}`, + { + method: "POST", + body: JSON.stringify({ poId }), + headers: { "Content-Type": "application/json" }, + }, + ); revalidateTag("po"); - return po -} + return po; +}; export const fetchPoInClient = cache(async (id: number) => { return serverFetchJson(`${BASE_API_URL}/po/detail/${id}`, { @@ -127,33 +144,46 @@ export const fetchPoInClient = cache(async (id: number) => { }); }); - export const fetchPoListClient = cache(async (queryParams?: Record) => { +export const fetchPoListClient = cache( + async (queryParams?: Record) => { if (queryParams) { const queryString = new URLSearchParams(queryParams).toString(); - return serverFetchJson>(`${BASE_API_URL}/po/list?${queryString}`, { - method: 'GET', - next: { tags: ["po"] }, - }); + return serverFetchJson>( + `${BASE_API_URL}/po/list?${queryString}`, + { + method: "GET", + next: { tags: ["po"] }, + }, + ); } else { - return serverFetchJson>(`${BASE_API_URL}/po/list`, { - method: 'GET', - next: { tags: ["po"] }, - }); + return serverFetchJson>( + `${BASE_API_URL}/po/list`, + { + method: "GET", + next: { tags: ["po"] }, + }, + ); } - }); + }, +); - export const testing = cache(async (queryParams?: Record) => { - if (queryParams) { - const queryString = new URLSearchParams(queryParams).toString(); - return serverFetchJson>(`${BASE_API_URL}/po/testing?${queryString}`, { - method: 'GET', +export const testing = cache(async (queryParams?: Record) => { + if (queryParams) { + const queryString = new URLSearchParams(queryParams).toString(); + return serverFetchJson>( + `${BASE_API_URL}/po/testing?${queryString}`, + { + method: "GET", next: { tags: ["po"] }, - }); - } else { - return serverFetchJson>(`${BASE_API_URL}/po/testing`, { - method: 'GET', + }, + ); + } else { + return serverFetchJson>( + `${BASE_API_URL}/po/testing`, + { + method: "GET", next: { tags: ["po"] }, - }); - } - }); - + }, + ); + } +}); diff --git a/src/app/api/dashboard/index.ts b/src/app/api/dashboard/index.ts index 84ee091..9989faf 100644 --- a/src/app/api/dashboard/index.ts +++ b/src/app/api/dashboard/index.ts @@ -8,74 +8,76 @@ import { Uom } from "../settings/uom"; import { RecordsRes } from "../utils"; export interface PoResult { - id: number - code: string - orderDate: string - supplier: string - estimatedArrivalDate: string - completedDate: string - escalated: boolean - status: string - pol?: PurchaseOrderLine[] - } + id: number; + code: string; + orderDate: string; + supplier: string; + estimatedArrivalDate: string; + completedDate: string; + escalated: boolean; + status: string; + pol?: PurchaseOrderLine[]; +} export interface PurchaseOrderLine { - id: number - purchaseOrderId: number - itemId: number - itemNo: string - itemName: string - qty: number - processed: number - uom: Uom - price: number - status: string - stockInLine: StockInLine[] + id: number; + purchaseOrderId: number; + itemId: number; + itemNo: string; + itemName: string; + qty: number; + processed: number; + uom: Uom; + price: number; + status: string; + stockInLine: StockInLine[]; } export interface StockInLine { - id: number - stockInId: number - purchaseOrderId?: number - purchaseOrderLineId: number - itemId: number - itemNo: string - itemName: string - itemType: string - demandQty: number - acceptedQty: number - price: number - priceUnit: string - shelfLife?: number, - receiptDate?: string - productionDate?: string - expiryDate?: string - status: string - supplier: string - lotNo: string - poCode: string - uom: Uom - defaultWarehouseId: number // id for now + id: number; + stockInId: number; + purchaseOrderId?: number; + purchaseOrderLineId: number; + itemId: number; + itemNo: string; + itemName: string; + itemType: string; + demandQty: number; + acceptedQty: number; + price: number; + priceUnit: string; + shelfLife?: number; + receiptDate?: string; + productionDate?: string; + expiryDate?: string; + status: string; + supplier: string; + lotNo: string; + poCode: string; + uom: Uom; + defaultWarehouseId: number; // id for now } - - export const fetchPoList = cache(async (queryParams?: Record) => { - if (queryParams) { - const queryString = new URLSearchParams(queryParams).toString(); - return serverFetchJson>(`${BASE_API_URL}/po/list?${queryString}`, { - method: 'GET', +export const fetchPoList = cache(async (queryParams?: Record) => { + if (queryParams) { + const queryString = new URLSearchParams(queryParams).toString(); + return serverFetchJson>( + `${BASE_API_URL}/po/list?${queryString}`, + { + method: "GET", next: { tags: ["po"] }, - }); - } else { - return serverFetchJson>(`${BASE_API_URL}/po/list`, { - method: 'GET', - next: { tags: ["po"] }, - }); - } - }); - - export const fetchPoWithStockInLines = cache(async (id: number) => { - return serverFetchJson(`${BASE_API_URL}/po/detail/${id}`, { + }, + ); + } else { + return serverFetchJson>(`${BASE_API_URL}/po/list`, { + method: "GET", next: { tags: ["po"] }, }); - }); \ No newline at end of file + } +}); + +export const fetchPoWithStockInLines = cache(async (id: number) => { + return serverFetchJson(`${BASE_API_URL}/po/detail/${id}`, { + next: { tags: ["po"] }, + }); +}); diff --git a/src/app/api/do/actions.tsx b/src/app/api/do/actions.tsx index 96f1717..cd8c1bf 100644 --- a/src/app/api/do/actions.tsx +++ b/src/app/api/do/actions.tsx @@ -10,5 +10,5 @@ import { DoResult } from "."; import { GridRowId, GridRowSelectionModel } from "@mui/x-data-grid"; export interface CreateConsoDoInput { - ids: GridRowSelectionModel + ids: GridRowSelectionModel; } diff --git a/src/app/api/do/index.tsx b/src/app/api/do/index.tsx index 7834c3f..abef21d 100644 --- a/src/app/api/do/index.tsx +++ b/src/app/api/do/index.tsx @@ -5,20 +5,20 @@ import { BASE_API_URL } from "../../../config/api"; import { cache } from "react"; export interface DoResult { - id: number, - code: string, - orderDate: string, - estimatedArrivalDate: string, - status: string, - shopName: string, + id: number; + code: string; + orderDate: string; + estimatedArrivalDate: string; + status: string; + shopName: string; } export const preloadDo = () => { - fetchDoList(); -} + fetchDoList(); +}; export const fetchDoList = cache(async () => { - return serverFetchJson(`${BASE_API_URL}/do/list`, { - next: { tags: ["doList"] } - }) -}) \ No newline at end of file + return serverFetchJson(`${BASE_API_URL}/do/list`, { + next: { tags: ["doList"] }, + }); +}); diff --git a/src/app/api/group/actions.ts b/src/app/api/group/actions.ts index eadfe7d..219804c 100644 --- a/src/app/api/group/actions.ts +++ b/src/app/api/group/actions.ts @@ -1,55 +1,60 @@ "use server"; -import { serverFetchJson, serverFetchWithNoContent } from "@/app/utils/fetchUtil"; +import { + serverFetchJson, + serverFetchWithNoContent, +} from "@/app/utils/fetchUtil"; import { BASE_API_URL } from "@/config/api"; import { revalidateTag } from "next/cache"; import { cache } from "react"; - export interface CreateGroupInputs { - id?: number; - name: string; - description: string; - addUserIds?: number[]; - removeUserIds?: number[]; - addAuthIds?: number[]; - removeAuthIds?: number[]; - } + id?: number; + name: string; + description: string; + addUserIds?: number[]; + removeUserIds?: number[]; + addAuthIds?: number[]; + removeAuthIds?: number[]; +} export interface auth { - id: number; - module?: any | null; - authority: string; - name: string; - description: string | null; - v: number; - } + id: number; + module?: any | null; + authority: string; + name: string; + description: string | null; + v: number; +} export interface record { - records: auth[]; - } + records: auth[]; +} -export const fetchAuth = cache(async (target: string, id?: number ) => { - return serverFetchJson(`${BASE_API_URL}/group/auth/${target}/${id ?? 0}`, { +export const fetchAuth = cache(async (target: string, id?: number) => { + return serverFetchJson( + `${BASE_API_URL}/group/auth/${target}/${id ?? 0}`, + { next: { tags: ["auth"] }, - }); + }, + ); }); - + export const saveGroup = async (data: CreateGroupInputs) => { const newGroup = serverFetchJson(`${BASE_API_URL}/group/save`, { method: "POST", body: JSON.stringify(data), headers: { "Content-Type": "application/json" }, }); - revalidateTag("group") - return newGroup - }; - + revalidateTag("group"); + return newGroup; +}; + export const deleteGroup = async (id: number) => { const newGroup = serverFetchWithNoContent(`${BASE_API_URL}/group/${id}`, { method: "DELETE", headers: { "Content-Type": "application/json" }, }); - revalidateTag("group") - return newGroup -}; \ No newline at end of file + revalidateTag("group"); + return newGroup; +}; diff --git a/src/app/api/group/index.ts b/src/app/api/group/index.ts index 082b0f3..e730481 100644 --- a/src/app/api/group/index.ts +++ b/src/app/api/group/index.ts @@ -4,31 +4,30 @@ import { cache } from "react"; import "server-only"; export interface Records { - records: UserGroupResult[] + records: UserGroupResult[]; } export interface UserGroupResult { - id: number; - action: () => void; - name: string; - description: string; + id: number; + action: () => void; + name: string; + description: string; } export type IndivUserGroup = { authIds: number[]; data: any; userIds: number[]; -} +}; export const fetchGroup = cache(async () => { - return serverFetchJson(`${BASE_API_URL}/group`, { - next: { tags: ["group"] }, - }); + return serverFetchJson(`${BASE_API_URL}/group`, { + next: { tags: ["group"] }, }); - +}); export const fetchIndivGroup = cache(async (id: number) => { - return serverFetchJson(`${BASE_API_URL}/group/${id}`, { - next: { tags: ["group"] }, - }); + return serverFetchJson(`${BASE_API_URL}/group/${id}`, { + next: { tags: ["group"] }, }); +}); diff --git a/src/app/api/inventory/actions.ts b/src/app/api/inventory/actions.ts index d626720..216a3c2 100644 --- a/src/app/api/inventory/actions.ts +++ b/src/app/api/inventory/actions.ts @@ -9,18 +9,21 @@ import { RecordsRes } from "../utils"; // import { BASE_API_URL } from "@/config/api"; export interface LotLineInfo { - inventoryLotLineId: number, - itemId: number, - itemNo: string, - itemName: string, - lotNo: string, - remainingQty: number, - uom: string + inventoryLotLineId: number; + itemId: number; + itemNo: string; + itemName: string; + lotNo: string; + remainingQty: number; + uom: string; } - export const fetchLotDetail = cache(async (stockInLineId: number) => { - return serverFetchJson(`${BASE_API_URL}/inventoryLotLine/lot-detail/${stockInLineId}`, { - method: 'GET', - next: { tags: ["inventory"] }, - }); - }); +export const fetchLotDetail = cache(async (stockInLineId: number) => { + return serverFetchJson( + `${BASE_API_URL}/inventoryLotLine/lot-detail/${stockInLineId}`, + { + method: "GET", + next: { tags: ["inventory"] }, + }, + ); +}); diff --git a/src/app/api/inventory/index.ts b/src/app/api/inventory/index.ts index a7b0aca..cf807a0 100644 --- a/src/app/api/inventory/index.ts +++ b/src/app/api/inventory/index.ts @@ -4,27 +4,27 @@ import { cache } from "react"; import "server-only"; export interface InventoryResult { - id: number; - code: string; - name: string; - type: string; - qty: number; - uomCode: string; - uomUdfudesc: string; - // germPerSmallestUnit: number; - // qtyPerSmallestUnit: number; - // smallestUnit: string; - price: number; - currencyName: string; - status: string; + id: number; + code: string; + name: string; + type: string; + qty: number; + uomCode: string; + uomUdfudesc: string; + // germPerSmallestUnit: number; + // qtyPerSmallestUnit: number; + // smallestUnit: string; + price: number; + currencyName: string; + status: string; } export const preloadInventory = () => { - fetchInventories(); -} + fetchInventories(); +}; -export const fetchInventories = cache(async() => { - return serverFetchJson(`${BASE_API_URL}/inventory/list`, { - next: { tags: ["inventories"]} - }) -}) \ No newline at end of file +export const fetchInventories = cache(async () => { + return serverFetchJson(`${BASE_API_URL}/inventory/list`, { + next: { tags: ["inventories"] }, + }); +}); diff --git a/src/app/api/jo/actions.ts b/src/app/api/jo/actions.ts index 85eda7a..c43fe41 100644 --- a/src/app/api/jo/actions.ts +++ b/src/app/api/jo/actions.ts @@ -1,46 +1,51 @@ -'use server' +"use server"; import { serverFetchJson } from "@/app/utils/fetchUtil"; import { Machine, Operator } from "."; import { BASE_API_URL } from "@/config/api"; import { revalidateTag } from "next/cache"; export interface IsOperatorExistResponse { - id: number | null; - name: string; - code: string; - type?: string - message: string | null; - errorPosition: string | keyof T; - entity: T + id: number | null; + name: string; + code: string; + type?: string; + message: string | null; + errorPosition: string | keyof T; + entity: T; } export interface isCorrectMachineUsedResponse { - id: number | null; - name: string; - code: string; - type?: string - message: string | null; - errorPosition: string | keyof T; - entity: T + id: number | null; + name: string; + code: string; + type?: string; + message: string | null; + errorPosition: string | keyof T; + entity: T; } - export const isOperatorExist = async (username: string) => { - const isExist = await serverFetchJson>(`${BASE_API_URL}/jop/isOperatorExist`, { + const isExist = await serverFetchJson>( + `${BASE_API_URL}/jop/isOperatorExist`, + { method: "POST", body: JSON.stringify({ username }), headers: { "Content-Type": "application/json" }, - }); - revalidateTag("po"); - return isExist -} + }, + ); + revalidateTag("po"); + return isExist; +}; export const isCorrectMachineUsed = async (machineCode: string) => { - const isExist = await serverFetchJson>(`${BASE_API_URL}/jop/isCorrectMachineUsed`, { - method: "POST", - body: JSON.stringify({ machineCode }), - headers: { "Content-Type": "application/json" }, - }); - revalidateTag("po"); - return isExist -} \ No newline at end of file + const isExist = await serverFetchJson>( + `${BASE_API_URL}/jop/isCorrectMachineUsed`, + { + method: "POST", + body: JSON.stringify({ machineCode }), + headers: { "Content-Type": "application/json" }, + }, + ); + revalidateTag("po"); + return isExist; +}; diff --git a/src/app/api/jo/index.ts b/src/app/api/jo/index.ts index 5633d65..f15ae8c 100644 --- a/src/app/api/jo/index.ts +++ b/src/app/api/jo/index.ts @@ -1,14 +1,14 @@ -'server=only' +"server=only"; export interface Operator { - id: number; - name: string; - username: string; + id: number; + name: string; + username: string; } export interface Machine { - id: number; - name: string; - code: string; - qrCode: string; -} \ No newline at end of file + id: number; + name: string; + code: string; + qrCode: string; +} diff --git a/src/app/api/mail/actions.ts b/src/app/api/mail/actions.ts index bd5cca4..bc9be81 100644 --- a/src/app/api/mail/actions.ts +++ b/src/app/api/mail/actions.ts @@ -2,53 +2,56 @@ // import { serverFetchJson, serverFetchWithNoContent } from "@/app/utils/fetchUtil"; // import { BASE_API_URL } from "@/config/api"; -import { serverFetchJson, serverFetchWithNoContent } from "../../utils/fetchUtil"; +import { + serverFetchJson, + serverFetchWithNoContent, +} from "../../utils/fetchUtil"; import { BASE_API_URL } from "../../../config/api"; import { MailSetting, MailTemplate } from "."; export interface MailSave { - settings: MailSetting[]; - templates: MailTemplate[]; - // template: MailTemplate; + settings: MailSetting[]; + templates: MailTemplate[]; + // template: MailTemplate; } export const saveMail = async (data: MailSave) => { - return serverFetchJson(`${BASE_API_URL}/mails/save`, { - method: "POST", - body: JSON.stringify(data), - headers: { "Content-Type": "application/json" }, - }); + return serverFetchJson(`${BASE_API_URL}/mails/save`, { + method: "POST", + body: JSON.stringify(data), + headers: { "Content-Type": "application/json" }, + }); }; export const testSendMail = async () => { - return serverFetchWithNoContent(`${BASE_API_URL}/mails/test-send`, { - method: "GET", - // body: JSON.stringify(data), - headers: { "Content-Type": "application/json" }, - }); + return serverFetchWithNoContent(`${BASE_API_URL}/mails/test-send`, { + method: "GET", + // body: JSON.stringify(data), + headers: { "Content-Type": "application/json" }, + }); }; export const testEveryone = async () => { - return serverFetchWithNoContent(`${BASE_API_URL}/mails/testEveryone`, { - method: "GET", - // body: JSON.stringify(data), - headers: { "Content-Type": "application/json" }, - }); + return serverFetchWithNoContent(`${BASE_API_URL}/mails/testEveryone`, { + method: "GET", + // body: JSON.stringify(data), + headers: { "Content-Type": "application/json" }, + }); }; export const test7th = async () => { - return serverFetchWithNoContent(`${BASE_API_URL}/mails/test7th`, { - method: "GET", - // body: JSON.stringify(data), - headers: { "Content-Type": "application/json" }, - }); + return serverFetchWithNoContent(`${BASE_API_URL}/mails/test7th`, { + method: "GET", + // body: JSON.stringify(data), + headers: { "Content-Type": "application/json" }, + }); }; export const test15th = async () => { - return serverFetchWithNoContent(`${BASE_API_URL}/mails/test15th`, { - method: "GET", - // body: JSON.stringify(data), - headers: { "Content-Type": "application/json" }, - }); -}; \ No newline at end of file + return serverFetchWithNoContent(`${BASE_API_URL}/mails/test15th`, { + method: "GET", + // body: JSON.stringify(data), + headers: { "Content-Type": "application/json" }, + }); +}; diff --git a/src/app/api/mail/index.ts b/src/app/api/mail/index.ts index 91ff5e2..d861e37 100644 --- a/src/app/api/mail/index.ts +++ b/src/app/api/mail/index.ts @@ -7,32 +7,32 @@ import { cache } from "react"; import "server-only"; export interface MailSMTP { - host: string; - port: number; - username: string; - password: string; + host: string; + port: number; + username: string; + password: string; } export interface MailSetting { - id: number; - name: string; - value: string; - category: string; - type: string; + id: number; + name: string; + value: string; + category: string; + type: string; } export interface MailTemplate { - id: number; - to: string; - cc: string; - code: string; - description: string; - type: string; - params: string; - subjectCht: string; - subjectEng: string; - contentCht: string; - contentEng: string; + id: number; + to: string; + cc: string; + code: string; + description: string; + type: string; + params: string; + subjectCht: string; + subjectEng: string; + contentCht: string; + contentEng: string; } // export interface MailTemplate { @@ -43,21 +43,21 @@ export interface MailTemplate { // } export const preloadMails = () => { - fetchMailSetting(); - fetchMailTemplates(); - // fetchMailTimesheetTemplate(); + fetchMailSetting(); + fetchMailTemplates(); + // fetchMailTimesheetTemplate(); }; export const fetchMailSetting = cache(async () => { - return serverFetchJson(`${BASE_API_URL}/mails/setting`, { - next: { tags: ["mailSetting"] }, - }); + return serverFetchJson(`${BASE_API_URL}/mails/setting`, { + next: { tags: ["mailSetting"] }, + }); }); export const fetchMailTemplates = cache(async () => { - return serverFetchJson(`${BASE_API_URL}/mailTemplates`, { - next: { tags: ["mailTemplates"] }, - }); + return serverFetchJson(`${BASE_API_URL}/mailTemplates`, { + next: { tags: ["mailTemplates"] }, + }); }); // export const fetchMailTimesheetTemplate = cache(async () => { diff --git a/src/app/api/pdf/actions.ts b/src/app/api/pdf/actions.ts index e57c03c..174a1c4 100644 --- a/src/app/api/pdf/actions.ts +++ b/src/app/api/pdf/actions.ts @@ -5,22 +5,20 @@ import { serverFetchBlob } from "../../utils/fetchUtil"; import { BASE_API_URL } from "../../../config/api"; - export interface FileResponse { - filename: string; - blobValue: Uint8Array; + filename: string; + blobValue: Uint8Array; } - export const fetchPoQrcode = async (data: any) => { - const reportBlob = await serverFetchBlob( - `${BASE_API_URL}/stockInLine/print-label`, - { - method: "POST", - body: JSON.stringify(data), - headers: { "Content-Type": "application/json" }, - }, - ); + const reportBlob = await serverFetchBlob( + `${BASE_API_URL}/stockInLine/print-label`, + { + method: "POST", + body: JSON.stringify(data), + headers: { "Content-Type": "application/json" }, + }, + ); - return reportBlob -}; \ No newline at end of file + return reportBlob; +}; diff --git a/src/app/api/pickOrder/actions.ts b/src/app/api/pickOrder/actions.ts index 501f0a2..6991c39 100644 --- a/src/app/api/pickOrder/actions.ts +++ b/src/app/api/pickOrder/actions.ts @@ -6,177 +6,229 @@ import { cache } from "react"; import { serverFetchJson } from "@/app/utils/fetchUtil"; import { QcItemResult } from "../settings/qcItem"; import { RecordsRes } from "../utils"; -import { ConsoPickOrderResult, PickOrderLineWithSuggestedLot, PickOrderResult, PreReleasePickOrderSummary, StockOutLine } from "."; +import { + ConsoPickOrderResult, + PickOrderLineWithSuggestedLot, + PickOrderResult, + PreReleasePickOrderSummary, + StockOutLine, +} from "."; import { PurchaseQcResult } from "../po/actions"; // import { BASE_API_URL } from "@/config/api"; export interface PostStockOutLiineResponse { id: number | null; name: string; code: string; - type?: string + type?: string; message: string | null; errorPosition: string | keyof T; - entity: T | T[] + entity: T | T[]; } export interface ReleasePickOrderInputs { - consoCode: string - assignTo: number, + consoCode: string; + assignTo: number; } export interface CreateStockOutLine { - consoCode: string, - pickOrderLineId: number, - inventoryLotLineId: number, - qty: number, + consoCode: string; + pickOrderLineId: number; + inventoryLotLineId: number; + qty: number; } export interface UpdateStockOutLine { - id: number, + id: number; // consoCode: String, - itemId: number, - qty: number, - pickOrderLineId: number, - inventoryLotLineId?: number, - status: string, - pickTime?: string, + itemId: number; + qty: number; + pickOrderLineId: number; + inventoryLotLineId?: number; + status: string; + pickTime?: string; // pickerId: number? } export interface PickOrderQcInput { - qty: number - status: string + qty: number; + status: string; qcResult: PurchaseQcResult[]; } export interface PickOrderApprovalInput { - allowQty: number - rejectQty: number - status: string + allowQty: number; + rejectQty: number; + status: string; } export const consolidatePickOrder = async (ids: number[]) => { - const pickOrder = await serverFetchJson(`${BASE_API_URL}/pickOrder/conso`, { - method: "POST", - body: JSON.stringify({ ids: ids }), - headers: { "Content-Type": "application/json" }, - }); -// revalidateTag("po"); - return pickOrder -} + const pickOrder = await serverFetchJson( + `${BASE_API_URL}/pickOrder/conso`, + { + method: "POST", + body: JSON.stringify({ ids: ids }), + headers: { "Content-Type": "application/json" }, + }, + ); + // revalidateTag("po"); + return pickOrder; +}; export const consolidatePickOrder_revert = async (ids: number[]) => { - const pickOrder = await serverFetchJson(`${BASE_API_URL}/pickOrder/deconso`, { - method: "POST", - body: JSON.stringify({ ids: ids }), - headers: { "Content-Type": "application/json" }, - }); -// revalidateTag("po"); - return pickOrder -} - - - export const fetchPickOrderClient = cache(async (queryParams?: Record) => { + const pickOrder = await serverFetchJson( + `${BASE_API_URL}/pickOrder/deconso`, + { + method: "POST", + body: JSON.stringify({ ids: ids }), + headers: { "Content-Type": "application/json" }, + }, + ); + // revalidateTag("po"); + return pickOrder; +}; + +export const fetchPickOrderClient = cache( + async (queryParams?: Record) => { if (queryParams) { const queryString = new URLSearchParams(queryParams).toString(); - return serverFetchJson>(`${BASE_API_URL}/pickOrder/getRecordByPage?${queryString}`, { - method: 'GET', - next: { tags: ["pickorder"] }, - }); + return serverFetchJson>( + `${BASE_API_URL}/pickOrder/getRecordByPage?${queryString}`, + { + method: "GET", + next: { tags: ["pickorder"] }, + }, + ); } else { - return serverFetchJson>(`${BASE_API_URL}/pickOrder/getRecordByPage`, { - method: 'GET', - next: { tags: ["pickorder"] }, - }); + return serverFetchJson>( + `${BASE_API_URL}/pickOrder/getRecordByPage`, + { + method: "GET", + next: { tags: ["pickorder"] }, + }, + ); } - }); + }, +); - export const fetchConsoPickOrderClient = cache(async (queryParams?: Record) => { +export const fetchConsoPickOrderClient = cache( + async (queryParams?: Record) => { if (queryParams) { const queryString = new URLSearchParams(queryParams).toString(); - return serverFetchJson>(`${BASE_API_URL}/pickOrder/getRecordByPage-conso?${queryString}`, { - method: 'GET', - next: { tags: ["pickorder"] }, - }); + return serverFetchJson>( + `${BASE_API_URL}/pickOrder/getRecordByPage-conso?${queryString}`, + { + method: "GET", + next: { tags: ["pickorder"] }, + }, + ); } else { - return serverFetchJson>(`${BASE_API_URL}/pickOrder/getRecordByPage-conso`, { - method: 'GET', - next: { tags: ["pickorder"] }, - }); + return serverFetchJson>( + `${BASE_API_URL}/pickOrder/getRecordByPage-conso`, + { + method: "GET", + next: { tags: ["pickorder"] }, + }, + ); } - }); + }, +); - export const fetchPickOrderLineClient = cache(async (queryParams?: Record) => { +export const fetchPickOrderLineClient = cache( + async (queryParams?: Record) => { if (queryParams) { const queryString = new URLSearchParams(queryParams).toString(); - return serverFetchJson>(`${BASE_API_URL}/pickOrder/get-pickorder-line-byPage?${queryString}`, { - method: 'GET', - next: { tags: ["pickorder"] }, - }); + return serverFetchJson>( + `${BASE_API_URL}/pickOrder/get-pickorder-line-byPage?${queryString}`, + { + method: "GET", + next: { tags: ["pickorder"] }, + }, + ); } else { - return serverFetchJson>(`${BASE_API_URL}/pickOrder/get-pickorder-line-byPage`, { - method: 'GET', - next: { tags: ["pickorder"] }, - }); + return serverFetchJson>( + `${BASE_API_URL}/pickOrder/get-pickorder-line-byPage`, + { + method: "GET", + next: { tags: ["pickorder"] }, + }, + ); } - }); - - export const fetchStockOutLineClient = cache(async (pickOrderLineId: number) => { - return serverFetchJson(`${BASE_API_URL}/stockOutLine/getByPickOrderLineId/${pickOrderLineId}`, { - method: 'GET', - next: { tags: ["pickorder"] }, - }); - }); - - export const fetchConsoDetail = cache(async (consoCode: string) => { - return serverFetchJson(`${BASE_API_URL}/pickOrder/pre-release-info/${consoCode}`, { - method: 'GET', + }, +); + +export const fetchStockOutLineClient = cache( + async (pickOrderLineId: number) => { + return serverFetchJson( + `${BASE_API_URL}/stockOutLine/getByPickOrderLineId/${pickOrderLineId}`, + { + method: "GET", next: { tags: ["pickorder"] }, - }); - }); - - - export const releasePickOrder = async (data: ReleasePickOrderInputs) => { - console.log(data) - console.log(JSON.stringify(data)) - const po = await serverFetchJson<{body: any, status: number}>(`${BASE_API_URL}/pickOrder/releaseConso`, { + }, + ); + }, +); + +export const fetchConsoDetail = cache(async (consoCode: string) => { + return serverFetchJson( + `${BASE_API_URL}/pickOrder/pre-release-info/${consoCode}`, + { + method: "GET", + next: { tags: ["pickorder"] }, + }, + ); +}); + +export const releasePickOrder = async (data: ReleasePickOrderInputs) => { + console.log(data); + console.log(JSON.stringify(data)); + const po = await serverFetchJson<{ body: any; status: number }>( + `${BASE_API_URL}/pickOrder/releaseConso`, + { method: "POST", body: JSON.stringify(data), headers: { "Content-Type": "application/json" }, - }); - revalidateTag("pickorder"); - return po - } - - export const createStockOutLine = async (data: CreateStockOutLine) => { - console.log("triggering") - const po = await serverFetchJson>(`${BASE_API_URL}/stockOutLine/create`, { + }, + ); + revalidateTag("pickorder"); + return po; +}; + +export const createStockOutLine = async (data: CreateStockOutLine) => { + console.log("triggering"); + const po = await serverFetchJson>( + `${BASE_API_URL}/stockOutLine/create`, + { method: "POST", body: JSON.stringify(data), headers: { "Content-Type": "application/json" }, - }); - revalidateTag("pickorder"); - return po - } - - export const updateStockOutLine = async (data: UpdateStockOutLine) => { - console.log(data) - const po = await serverFetchJson> - (`${BASE_API_URL}/stockOutLine/update`, { + }, + ); + revalidateTag("pickorder"); + return po; +}; + +export const updateStockOutLine = async (data: UpdateStockOutLine) => { + console.log(data); + const po = await serverFetchJson>( + `${BASE_API_URL}/stockOutLine/update`, + { method: "POST", body: JSON.stringify(data), headers: { "Content-Type": "application/json" }, - }); - revalidateTag("pickorder"); - return po - } - - export const completeConsoPickOrder = async (consoCode: string) => { - const po = await serverFetchJson> - (`${BASE_API_URL}/pickOrder/consoPickOrder/complete/${consoCode}`, { + }, + ); + revalidateTag("pickorder"); + return po; +}; + +export const completeConsoPickOrder = async (consoCode: string) => { + const po = await serverFetchJson>( + `${BASE_API_URL}/pickOrder/consoPickOrder/complete/${consoCode}`, + { method: "POST", headers: { "Content-Type": "application/json" }, - }); - revalidateTag("pickorder"); - return po - } \ No newline at end of file + }, + ); + revalidateTag("pickorder"); + return po; +}; diff --git a/src/app/api/pickOrder/index.ts b/src/app/api/pickOrder/index.ts index 5e97b74..850614e 100644 --- a/src/app/api/pickOrder/index.ts +++ b/src/app/api/pickOrder/index.ts @@ -5,106 +5,111 @@ import { cache } from "react"; import { String } from "lodash"; interface PickOrderItemInfo { - name: string, - type: string, + name: string; + type: string; } -export interface PickOrderResult{ - id: number, - code: string, - consoCode?: string, - targetDate: number[], - completeDate?: number[], - type: string, - status: string, - releasedBy: string, - items?: PickOrderItemInfo[] | null, - pickOrderLine?: PickOrderLine[] +export interface PickOrderResult { + id: number; + code: string; + consoCode?: string; + targetDate: number[]; + completeDate?: number[]; + type: string; + status: string; + releasedBy: string; + items?: PickOrderItemInfo[] | null; + pickOrderLine?: PickOrderLine[]; } export interface PickOrderLine { - id: number, - itemId: number, - itemCode: string, - itemName: string, - availableQty: number, - requiredQty: number, - uomCode: string, - uomDesc: string + id: number; + itemId: number; + itemCode: string; + itemName: string; + availableQty: number; + requiredQty: number; + uomCode: string; + uomDesc: string; } export interface StockOutLine { - id: number - itemId: number - itemName: string - itemNo: string - qty: number - stockOutId?: number - pickOrderLineId: number - lotNo?: string - inventoryLotLineId?: number - status: string - pickTime?: string + id: number; + itemId: number; + itemName: string; + itemNo: string; + qty: number; + stockOutId?: number; + pickOrderLineId: number; + lotNo?: string; + inventoryLotLineId?: number; + status: string; + pickTime?: string; } -export interface ConsoPickOrderResult{ - id: number, - code: string, - consoCode?: string, - targetDate: number[], - completeDate?: number[], - type: string, - status: string, - releasedBy: string, - items?: PickOrderItemInfo[] | null, +export interface ConsoPickOrderResult { + id: number; + code: string; + consoCode?: string; + targetDate: number[]; + completeDate?: number[]; + type: string; + status: string; + releasedBy: string; + items?: PickOrderItemInfo[] | null; } export interface FetchPickOrders extends Pageable { - code: string | undefined - targetDateFrom: string | undefined - targetDateTo: string | undefined - type: string | undefined - status: string | undefined - itemName: string | undefined + code: string | undefined; + targetDateFrom: string | undefined; + targetDateTo: string | undefined; + type: string | undefined; + status: string | undefined; + itemName: string | undefined; } export type ByItemsSummary = { - id: number, - code: string, - name: string, - uomDesc: string, - availableQty: number, - requiredQty: number, -} + id: number; + code: string; + name: string; + uomDesc: string; + availableQty: number; + requiredQty: number; +}; export interface PreReleasePickOrderSummary { - consoCode: string - pickOrders: Omit[] - items: ByItemsSummary[] + consoCode: string; + pickOrders: Omit[]; + items: ByItemsSummary[]; } export interface PickOrderLineWithSuggestedLot { - id: number, - itemName: string, - qty: number, - uom: string - status: string - warehouse: string - suggestedLotNo: string + id: number; + itemName: string; + qty: number; + uom: string; + status: string; + warehouse: string; + suggestedLotNo: string; } export const PreloadPickOrder = () => { - fetchPickOrders({ - code: undefined, - targetDateFrom: undefined, - targetDateTo: undefined, - type: undefined, - status: undefined, - itemName: undefined, - }) -} + fetchPickOrders({ + code: undefined, + targetDateFrom: undefined, + targetDateTo: undefined, + type: undefined, + status: undefined, + itemName: undefined, + }); +}; export const fetchPickOrders = cache(async (queryParams: FetchPickOrders) => { - const queryString = new URLSearchParams(queryParams as Record).toString(); - return serverFetchJson(`${BASE_API_URL}/pickOrder/list?${queryString}`, { - next: { - tags: ["pickOrders"] - } - }) -}) \ No newline at end of file + const queryString = new URLSearchParams( + queryParams as Record, + ).toString(); + return serverFetchJson( + `${BASE_API_URL}/pickOrder/list?${queryString}`, + { + next: { + tags: ["pickOrders"], + }, + }, + ); +}); diff --git a/src/app/api/po/actions.ts b/src/app/api/po/actions.ts index d30135a..f3c4e6a 100644 --- a/src/app/api/po/actions.ts +++ b/src/app/api/po/actions.ts @@ -15,21 +15,21 @@ export interface PostStockInLiineResponse { id: number | null; name: string; code: string; - type?: string + type?: string; message: string | null; errorPosition: string | keyof T; - entity: T | T[] + entity: T | T[]; // entity: StockInLine | StockInLine[] } export interface StockInLineEntry { - id?: number - itemId: number - purchaseOrderId: number - purchaseOrderLineId: number - acceptedQty: number - status?: string - expiryDate?: string + id?: number; + itemId: number; + purchaseOrderId: number; + purchaseOrderLineId: number; + acceptedQty: number; + status?: string; + expiryDate?: string; } export interface PurchaseQcResult { @@ -37,37 +37,39 @@ export interface PurchaseQcResult { failQty: number; } export interface StockInInput { - status: string - productLotNo?: string, - receiptDate: string - acceptedQty: number - acceptedWeight?: number - productionDate?: string - expiryDate: string + status: string; + productLotNo?: string; + receiptDate: string; + acceptedQty: number; + acceptedWeight?: number; + productionDate?: string; + expiryDate: string; } export interface PurchaseQCInput { - status: string - acceptedQty: number + status: string; + acceptedQty: number; sampleRate: number; sampleWeight: number; totalWeight: number; qcResult: PurchaseQcResult[]; } export interface EscalationInput { - status: string - handler: string - acceptedQty: number // this is the qty to be escalated + status: string; + handler: string; + acceptedQty: number; // this is the qty to be escalated // escalationQty: number } export interface PutawayInput { - status: string - acceptedQty: number - warehouseId: number + status: string; + acceptedQty: number; + warehouseId: number; // handler: string // stockInLine: StockInLineEntry[] } -export type ModalFormInput = Partial +export type ModalFormInput = Partial< + PurchaseQCInput & StockInInput & EscalationInput & PutawayInput +>; export const testFetch = cache(async (id: number) => { return serverFetchJson(`${BASE_API_URL}/po/detail/${id}`, { @@ -76,50 +78,65 @@ export const testFetch = cache(async (id: number) => { }); export const fetchStockInLineInfo = cache(async (stockInLineId: number) => { - return serverFetchJson(`${BASE_API_URL}/stockInLine/${stockInLineId}`, { + return serverFetchJson( + `${BASE_API_URL}/stockInLine/${stockInLineId}`, + { next: { tags: ["stockInLine"] }, - }); + }, + ); }); export const createStockInLine = async (data: StockInLineEntry) => { - const stockInLine = await serverFetchJson>(`${BASE_API_URL}/stockInLine/create`, { + const stockInLine = await serverFetchJson< + PostStockInLiineResponse + >(`${BASE_API_URL}/stockInLine/create`, { method: "POST", body: JSON.stringify(data), headers: { "Content-Type": "application/json" }, }); // revalidateTag("po"); - return stockInLine -} + return stockInLine; +}; -export const updateStockInLine = async (data: StockInLineEntry & ModalFormInput) => { - const stockInLine = await serverFetchJson>(`${BASE_API_URL}/stockInLine/update`, { +export const updateStockInLine = async ( + data: StockInLineEntry & ModalFormInput, +) => { + const stockInLine = await serverFetchJson< + PostStockInLiineResponse + >(`${BASE_API_URL}/stockInLine/update`, { method: "POST", body: JSON.stringify(data), headers: { "Content-Type": "application/json" }, }); // revalidateTag("po"); - return stockInLine -} + return stockInLine; +}; export const startPo = async (poId: number) => { - const po = await serverFetchJson>(`${BASE_API_URL}/po/start/${poId}`, { - method: "POST", - body: JSON.stringify({ poId }), - headers: { "Content-Type": "application/json" }, - }); + const po = await serverFetchJson>( + `${BASE_API_URL}/po/start/${poId}`, + { + method: "POST", + body: JSON.stringify({ poId }), + headers: { "Content-Type": "application/json" }, + }, + ); revalidateTag("po"); - return po -} + return po; +}; export const checkPolAndCompletePo = async (poId: number) => { - const po = await serverFetchJson>(`${BASE_API_URL}/po/check/${poId}`, { - method: "POST", - body: JSON.stringify({ poId }), - headers: { "Content-Type": "application/json" }, - }); + const po = await serverFetchJson>( + `${BASE_API_URL}/po/check/${poId}`, + { + method: "POST", + body: JSON.stringify({ poId }), + headers: { "Content-Type": "application/json" }, + }, + ); revalidateTag("po"); - return po -} + return po; +}; export const fetchPoInClient = cache(async (id: number) => { return serverFetchJson(`${BASE_API_URL}/po/detail/${id}`, { @@ -127,33 +144,46 @@ export const fetchPoInClient = cache(async (id: number) => { }); }); - export const fetchPoListClient = cache(async (queryParams?: Record) => { +export const fetchPoListClient = cache( + async (queryParams?: Record) => { if (queryParams) { const queryString = new URLSearchParams(queryParams).toString(); - return serverFetchJson>(`${BASE_API_URL}/po/list?${queryString}`, { - method: 'GET', - next: { tags: ["po"] }, - }); + return serverFetchJson>( + `${BASE_API_URL}/po/list?${queryString}`, + { + method: "GET", + next: { tags: ["po"] }, + }, + ); } else { - return serverFetchJson>(`${BASE_API_URL}/po/list`, { - method: 'GET', - next: { tags: ["po"] }, - }); + return serverFetchJson>( + `${BASE_API_URL}/po/list`, + { + method: "GET", + next: { tags: ["po"] }, + }, + ); } - }); + }, +); - export const testing = cache(async (queryParams?: Record) => { - if (queryParams) { - const queryString = new URLSearchParams(queryParams).toString(); - return serverFetchJson>(`${BASE_API_URL}/po/testing?${queryString}`, { - method: 'GET', +export const testing = cache(async (queryParams?: Record) => { + if (queryParams) { + const queryString = new URLSearchParams(queryParams).toString(); + return serverFetchJson>( + `${BASE_API_URL}/po/testing?${queryString}`, + { + method: "GET", next: { tags: ["po"] }, - }); - } else { - return serverFetchJson>(`${BASE_API_URL}/po/testing`, { - method: 'GET', + }, + ); + } else { + return serverFetchJson>( + `${BASE_API_URL}/po/testing`, + { + method: "GET", next: { tags: ["po"] }, - }); - } - }); - + }, + ); + } +}); diff --git a/src/app/api/po/index.ts b/src/app/api/po/index.ts index 84ee091..9989faf 100644 --- a/src/app/api/po/index.ts +++ b/src/app/api/po/index.ts @@ -8,74 +8,76 @@ import { Uom } from "../settings/uom"; import { RecordsRes } from "../utils"; export interface PoResult { - id: number - code: string - orderDate: string - supplier: string - estimatedArrivalDate: string - completedDate: string - escalated: boolean - status: string - pol?: PurchaseOrderLine[] - } + id: number; + code: string; + orderDate: string; + supplier: string; + estimatedArrivalDate: string; + completedDate: string; + escalated: boolean; + status: string; + pol?: PurchaseOrderLine[]; +} export interface PurchaseOrderLine { - id: number - purchaseOrderId: number - itemId: number - itemNo: string - itemName: string - qty: number - processed: number - uom: Uom - price: number - status: string - stockInLine: StockInLine[] + id: number; + purchaseOrderId: number; + itemId: number; + itemNo: string; + itemName: string; + qty: number; + processed: number; + uom: Uom; + price: number; + status: string; + stockInLine: StockInLine[]; } export interface StockInLine { - id: number - stockInId: number - purchaseOrderId?: number - purchaseOrderLineId: number - itemId: number - itemNo: string - itemName: string - itemType: string - demandQty: number - acceptedQty: number - price: number - priceUnit: string - shelfLife?: number, - receiptDate?: string - productionDate?: string - expiryDate?: string - status: string - supplier: string - lotNo: string - poCode: string - uom: Uom - defaultWarehouseId: number // id for now + id: number; + stockInId: number; + purchaseOrderId?: number; + purchaseOrderLineId: number; + itemId: number; + itemNo: string; + itemName: string; + itemType: string; + demandQty: number; + acceptedQty: number; + price: number; + priceUnit: string; + shelfLife?: number; + receiptDate?: string; + productionDate?: string; + expiryDate?: string; + status: string; + supplier: string; + lotNo: string; + poCode: string; + uom: Uom; + defaultWarehouseId: number; // id for now } - - export const fetchPoList = cache(async (queryParams?: Record) => { - if (queryParams) { - const queryString = new URLSearchParams(queryParams).toString(); - return serverFetchJson>(`${BASE_API_URL}/po/list?${queryString}`, { - method: 'GET', +export const fetchPoList = cache(async (queryParams?: Record) => { + if (queryParams) { + const queryString = new URLSearchParams(queryParams).toString(); + return serverFetchJson>( + `${BASE_API_URL}/po/list?${queryString}`, + { + method: "GET", next: { tags: ["po"] }, - }); - } else { - return serverFetchJson>(`${BASE_API_URL}/po/list`, { - method: 'GET', - next: { tags: ["po"] }, - }); - } - }); - - export const fetchPoWithStockInLines = cache(async (id: number) => { - return serverFetchJson(`${BASE_API_URL}/po/detail/${id}`, { + }, + ); + } else { + return serverFetchJson>(`${BASE_API_URL}/po/list`, { + method: "GET", next: { tags: ["po"] }, }); - }); \ No newline at end of file + } +}); + +export const fetchPoWithStockInLines = cache(async (id: number) => { + return serverFetchJson(`${BASE_API_URL}/po/detail/${id}`, { + next: { tags: ["po"] }, + }); +}); diff --git a/src/app/api/qc/actions.ts b/src/app/api/qc/actions.ts index fb8e38b..8181d02 100644 --- a/src/app/api/qc/actions.ts +++ b/src/app/api/qc/actions.ts @@ -8,32 +8,34 @@ import { serverFetchJson } from "../../utils/fetchUtil"; import { QcItemWithChecks } from "."; export interface QcResult { - id: number - qcItemId: number - name: string - code: string - stockInLineId?: number - stockOutLineId?: number - failQty: number + id: number; + qcItemId: number; + name: string; + code: string; + stockInLineId?: number; + stockOutLineId?: number; + failQty: number; } export const fetchQcItemCheck = cache(async (itemId?: number) => { - var url = `${BASE_API_URL}/qcCheck` - if (itemId) url +=`/${itemId}` - return serverFetchJson(url, { - next: { tags: ["qc"] }, - }); + let url = `${BASE_API_URL}/qcCheck`; + if (itemId) url += `/${itemId}`; + return serverFetchJson(url, { + next: { tags: ["qc"] }, }); - +}); export const fetchQcResult = cache(async (id: number) => { - return serverFetchJson(`${BASE_API_URL}/qcResult/${id}`, { - next: { tags: ["qc"] }, - }); + return serverFetchJson(`${BASE_API_URL}/qcResult/${id}`, { + next: { tags: ["qc"] }, + }); }); export const fetchPickOrderQcResult = cache(async (id: number) => { - return serverFetchJson(`${BASE_API_URL}/qcResult/pick-order/${id}`, { - next: { tags: ["qc"] }, - }); -}); \ No newline at end of file + return serverFetchJson( + `${BASE_API_URL}/qcResult/pick-order/${id}`, + { + next: { tags: ["qc"] }, + }, + ); +}); diff --git a/src/app/api/qc/index.ts b/src/app/api/qc/index.ts index 44bf8cb..26094c6 100644 --- a/src/app/api/qc/index.ts +++ b/src/app/api/qc/index.ts @@ -6,27 +6,25 @@ import { serverFetchJson } from "../../utils/fetchUtil"; import { BASE_API_URL } from "../../../config/api"; export interface QcItemWithChecks { - id: number; - code: string; - name: string; - itemId: number; - lowerLimit: number | undefined; - upperLimit: number | undefined; - description: string | undefined; - } + id: number; + code: string; + name: string; + itemId: number; + lowerLimit: number | undefined; + upperLimit: number | undefined; + description: string | undefined; +} - export const fetchQcItemCheckList = cache(async () => { - return serverFetchJson(`${BASE_API_URL}/qc/list`, { - next: { tags: ["qc"] }, - }); +export const fetchQcItemCheckList = cache(async () => { + return serverFetchJson(`${BASE_API_URL}/qc/list`, { + next: { tags: ["qc"] }, }); - - +}); export const fetchQcItemCheck = cache(async (itemId?: number) => { - var url = `${BASE_API_URL}/qcCheck` - if (itemId) url +=`/${itemId}` + let url = `${BASE_API_URL}/qcCheck`; + if (itemId) url += `/${itemId}`; return serverFetchJson(url, { next: { tags: ["qc"] }, }); -}); \ No newline at end of file +}); diff --git a/src/app/api/qrcode/index.ts b/src/app/api/qrcode/index.ts index 61339dc..2a09982 100644 --- a/src/app/api/qrcode/index.ts +++ b/src/app/api/qrcode/index.ts @@ -7,9 +7,9 @@ import { BASE_API_URL } from "../../../config/api"; export interface QrCodeInfo { // warehouse qrcode - warehouseId?: number - // item qrcode + warehouseId?: number; + // item qrcode stockInLineId?: number; - itemId: number - lotNo?: string -} \ No newline at end of file + itemId: number; + lotNo?: string; +} diff --git a/src/app/api/scheduling/actions.ts b/src/app/api/scheduling/actions.ts index d230ec0..4265533 100644 --- a/src/app/api/scheduling/actions.ts +++ b/src/app/api/scheduling/actions.ts @@ -1,64 +1,75 @@ -"use server" +"use server"; import { convertObjToURLSearchParams } from "@/app/utils/commonUtil"; -import { serverFetchJson } from "@/app/utils/fetchUtil" -import { BASE_API_URL } from "@/config/api" -import { cache } from "react" +import { serverFetchJson } from "@/app/utils/fetchUtil"; +import { BASE_API_URL } from "@/config/api"; +import { cache } from "react"; import { ScheduleType } from "."; export interface SearchProdSchedule { - scheduleAt?: string; - schedulePeriod?: string; - schedulePeriodTo?: string; - totalEstProdCount?: number; - types?: ScheduleType[]; - pageSize?: number; - pageNum?: number; + scheduleAt?: string; + schedulePeriod?: string; + schedulePeriodTo?: string; + totalEstProdCount?: number; + types?: ScheduleType[]; + pageSize?: number; + pageNum?: number; } export interface ProdScheduleResult { - id: number; - scheduleAt: number[]; - schedulePeriod: number[]; - schedulePeriodTo: number[]; - totalEstProdCount: number; - totalFGType: number; - type: string; + id: number; + scheduleAt: number[]; + schedulePeriod: number[]; + schedulePeriodTo: number[]; + totalEstProdCount: number; + totalFGType: number; + type: string; } export interface ProdScheduleResultByPage { - total: number; - records: ProdScheduleResult[]; + total: number; + records: ProdScheduleResult[]; } -export const fetchProdSchedules = cache(async (data: SearchProdSchedule | null) => { - const params = convertObjToURLSearchParams(data) +export const fetchProdSchedules = cache( + async (data: SearchProdSchedule | null) => { + const params = convertObjToURLSearchParams(data); // console.log(params) - return serverFetchJson(`${BASE_API_URL}/productionSchedule/getRecordByPage?${params}`, { + return serverFetchJson( + `${BASE_API_URL}/productionSchedule/getRecordByPage?${params}`, + { method: "GET", headers: { "Content-Type": "application/json" }, next: { - tags: ["prodSchedules"] - } - }) -}) + tags: ["prodSchedules"], + }, + }, + ); + }, +); export const testRoughSchedule = cache(async () => { - return serverFetchJson(`${BASE_API_URL}/productionSchedule/testRoughSchedule`, { - method: "GET", - headers: { "Content-Type": "application/json" }, - next: { - tags: ["prodSchedules"] - } - }) -}) + return serverFetchJson( + `${BASE_API_URL}/productionSchedule/testRoughSchedule`, + { + method: "GET", + headers: { "Content-Type": "application/json" }, + next: { + tags: ["prodSchedules"], + }, + }, + ); +}); export const testDetailSchedule = cache(async () => { - return serverFetchJson(`${BASE_API_URL}/productionSchedule/testDetailSchedule`, { - method: "GET", - headers: { "Content-Type": "application/json" }, - next: { - tags: ["prodSchedules"] - } - }) -}) \ No newline at end of file + return serverFetchJson( + `${BASE_API_URL}/productionSchedule/testDetailSchedule`, + { + method: "GET", + headers: { "Content-Type": "application/json" }, + next: { + tags: ["prodSchedules"], + }, + }, + ); +}); diff --git a/src/app/api/scheduling/index.ts b/src/app/api/scheduling/index.ts index 0d24edc..6a19d35 100644 --- a/src/app/api/scheduling/index.ts +++ b/src/app/api/scheduling/index.ts @@ -1,82 +1,89 @@ -import { serverFetchJson } from "@/app/utils/fetchUtil" -import { BASE_API_URL } from "@/config/api" -import { cache } from "react" -import "server-only" +import { serverFetchJson } from "@/app/utils/fetchUtil"; +import { BASE_API_URL } from "@/config/api"; +import { cache } from "react"; +import "server-only"; export type ScheduleType = "all" | "rough" | "detailed" | "manual"; export interface RoughProdScheduleResult { - id: number; - scheduleAt: number[]; - schedulePeriod: number[]; - schedulePeriodTo: number[]; - totalEstProdCount: number; - totalFGType: number; - type: string; - prodScheduleLinesByFg: RoughProdScheduleLineResultByFg[]; - prodScheduleLinesByFgByDate: { [assignDate: number]: RoughProdScheduleLineResultByFg[] }; - prodScheduleLinesByBom: RoughProdScheduleLineResultByBom[]; - prodScheduleLinesByBomByDate: { [assignDate: number]: RoughProdScheduleLineResultByBomByDate[] }; + id: number; + scheduleAt: number[]; + schedulePeriod: number[]; + schedulePeriodTo: number[]; + totalEstProdCount: number; + totalFGType: number; + type: string; + prodScheduleLinesByFg: RoughProdScheduleLineResultByFg[]; + prodScheduleLinesByFgByDate: { + [assignDate: number]: RoughProdScheduleLineResultByFg[]; + }; + prodScheduleLinesByBom: RoughProdScheduleLineResultByBom[]; + prodScheduleLinesByBomByDate: { + [assignDate: number]: RoughProdScheduleLineResultByBomByDate[]; + }; } export interface RoughProdScheduleLineResultByFg { - id: number; - code: string; - name: string; - type: string; - availableQty: number; - prodQty: number; - lastMonthAvgSales: number; - estCloseBal: number; - priority: number; - assignDate: number; - bomMaterials: RoughProdScheduleLineBomMaterialResult[]; + id: number; + code: string; + name: string; + type: string; + availableQty: number; + prodQty: number; + lastMonthAvgSales: number; + estCloseBal: number; + priority: number; + assignDate: number; + bomMaterials: RoughProdScheduleLineBomMaterialResult[]; } export interface RoughProdScheduleLineBomMaterialResult { - id: number; - code: string; - name: string; - type: string; - availableQty: number; - demandQty: number; - uomName: string; + id: number; + code: string; + name: string; + type: string; + availableQty: number; + demandQty: number; + uomName: string; } export interface RoughProdScheduleLineResultByBom { - id: number, - code: string, - name: string, - type: string, - availableQty: number, - totalDemandQty: number, - demandQty1: number, - demandQty2: number, - demandQty3: number, - demandQty4: number, - demandQty5: number, - demandQty6: number, - demandQty7: number, - uomName: string, + id: number; + code: string; + name: string; + type: string; + availableQty: number; + totalDemandQty: number; + demandQty1: number; + demandQty2: number; + demandQty3: number; + demandQty4: number; + demandQty5: number; + demandQty6: number; + demandQty7: number; + uomName: string; } export interface RoughProdScheduleLineResultByBomByDate { - id: number, - code: string, - name: string, - type: string, - availableQty: number, - demandQty: number, - assignDate: number, - uomName: string, + id: number; + code: string; + name: string; + type: string; + availableQty: number; + demandQty: number; + assignDate: number; + uomName: string; } export const fetchProdScheduleDetail = cache(async (id: number) => { - return serverFetchJson(`${BASE_API_URL}/productionSchedule/detail/${id}`, { - method: "GET", - headers: { "Content-Type": "application/json" }, - next: { - tags: ["prodSchedule"] - } - }) -}) \ No newline at end of file + return serverFetchJson( + `${BASE_API_URL}/productionSchedule/detail/${id}`, + { + method: "GET", + headers: { "Content-Type": "application/json" }, + next: { + tags: ["prodSchedule"], + }, + }, + ); +}); diff --git a/src/app/api/settings/equipment/actions.ts b/src/app/api/settings/equipment/actions.ts index d1315ea..688d04d 100644 --- a/src/app/api/settings/equipment/actions.ts +++ b/src/app/api/settings/equipment/actions.ts @@ -1,5 +1,9 @@ "use server"; -import { ServerFetchError, serverFetchJson, serverFetchWithNoContent } from "@/app/utils/fetchUtil"; +import { + ServerFetchError, + serverFetchJson, + serverFetchWithNoContent, +} from "@/app/utils/fetchUtil"; import { revalidateTag } from "next/cache"; import { BASE_API_URL } from "@/config/api"; import { CreateEquipmentTypeResponse } from "../../utils"; @@ -16,23 +20,23 @@ import { CreateEquipmentTypeResponse } from "../../utils"; // conversion: number // } - export type CreateEquipmentInputs = { - id?: string | number + id?: string | number; code: string; name: string; description?: string | undefined; equipmentTypeId?: string | number | undefined; - -} +}; export const saveEquipment = async (data: CreateEquipmentInputs) => { - // try { - const equipment = await serverFetchJson>(`${BASE_API_URL}/Equipment/save`, { - method: "POST", - body: JSON.stringify(data), - headers: { "Content-Type": "application/json" }, - }); - revalidateTag("EquipmentType"); - return equipment - }; \ No newline at end of file + // try { + const equipment = await serverFetchJson< + CreateEquipmentTypeResponse + >(`${BASE_API_URL}/Equipment/save`, { + method: "POST", + body: JSON.stringify(data), + headers: { "Content-Type": "application/json" }, + }); + revalidateTag("EquipmentType"); + return equipment; +}; diff --git a/src/app/api/settings/equipment/index.ts b/src/app/api/settings/equipment/index.ts index 8cd5e36..748f076 100644 --- a/src/app/api/settings/equipment/index.ts +++ b/src/app/api/settings/equipment/index.ts @@ -7,28 +7,29 @@ import { BASE_API_URL } from "../../../../config/api"; export { default } from "../../../../components/CreateEquipment/CreateEquipment"; // import { TypeInputs, UomInputs, WeightUnitInputs } from "./actions"; - export type EquipmentResult = { - id: string | number + id: string | number; code: string; name: string; description: string | undefined; equipmentTypeId: string | number | undefined; - action?: any -} + action?: any; +}; export type Result = { - equipment: EquipmentResult -} + equipment: EquipmentResult; +}; export const fetchAllEquipments = cache(async () => { - return serverFetchJson(`${BASE_API_URL}/Equipment`, { - next: { tags: ["equipments"] }, - }); + return serverFetchJson(`${BASE_API_URL}/Equipment`, { + next: { tags: ["equipments"] }, }); - +}); export const fetchEquipment = cache(async (id: number) => { - return serverFetchJson(`${BASE_API_URL}/Equipment/details/${id}`, { - next: { tags: ["equipments"] }, - }); -}); \ No newline at end of file + return serverFetchJson( + `${BASE_API_URL}/Equipment/details/${id}`, + { + next: { tags: ["equipments"] }, + }, + ); +}); diff --git a/src/app/api/settings/equipmentType/actions.ts b/src/app/api/settings/equipmentType/actions.ts index a9acc96..6cbb122 100644 --- a/src/app/api/settings/equipmentType/actions.ts +++ b/src/app/api/settings/equipmentType/actions.ts @@ -1,5 +1,9 @@ "use server"; -import { ServerFetchError, serverFetchJson, serverFetchWithNoContent } from "@/app/utils/fetchUtil"; +import { + ServerFetchError, + serverFetchJson, + serverFetchWithNoContent, +} from "@/app/utils/fetchUtil"; import { revalidateTag } from "next/cache"; import { BASE_API_URL } from "@/config/api"; import { CreateEquipmentTypeResponse } from "../../utils"; @@ -16,22 +20,22 @@ import { CreateEquipmentTypeResponse } from "../../utils"; // conversion: number // } - export type CreateEquipmentTypeInputs = { - id?: string | number + id?: string | number; code: string; name: string; description?: string | undefined; - -} +}; export const saveEquipmentType = async (data: CreateEquipmentTypeInputs) => { - // try { - const equipmentType = await serverFetchJson>(`${BASE_API_URL}/EquipmentType/save`, { - method: "POST", - body: JSON.stringify(data), - headers: { "Content-Type": "application/json" }, - }); - revalidateTag("EquipmentType"); - return equipmentType - }; \ No newline at end of file + // try { + const equipmentType = await serverFetchJson< + CreateEquipmentTypeResponse + >(`${BASE_API_URL}/EquipmentType/save`, { + method: "POST", + body: JSON.stringify(data), + headers: { "Content-Type": "application/json" }, + }); + revalidateTag("EquipmentType"); + return equipmentType; +}; diff --git a/src/app/api/settings/equipmentType/index.ts b/src/app/api/settings/equipmentType/index.ts index 5ed7d75..ae2408e 100644 --- a/src/app/api/settings/equipmentType/index.ts +++ b/src/app/api/settings/equipmentType/index.ts @@ -7,27 +7,31 @@ import { BASE_API_URL } from "../../../../config/api"; export { default } from "../../../../components/CreateEquipmentType/CreateEquipmentType"; // import { TypeInputs, UomInputs, WeightUnitInputs } from "./actions"; - export type EquipmentTypeResult = { - id: string | number + id: string | number; code: string; name: string; description: string | undefined; - action?: any -} + action?: any; +}; export type Result = { - equipmentType: EquipmentTypeResult -} + equipmentType: EquipmentTypeResult; +}; export const fetchAllEquipmentTypes = cache(async () => { - return serverFetchJson(`${BASE_API_URL}/EquipmentType`, { + return serverFetchJson( + `${BASE_API_URL}/EquipmentType`, + { next: { tags: ["equipmentTypes"] }, - }); - }); - + }, + ); +}); export const fetchEquipmentType = cache(async (id: number) => { - return serverFetchJson(`${BASE_API_URL}/EquipmentType/details/${id}`, { - next: { tags: ["equipmentTypes"] }, - }); -}); \ No newline at end of file + return serverFetchJson( + `${BASE_API_URL}/EquipmentType/details/${id}`, + { + next: { tags: ["equipmentTypes"] }, + }, + ); +}); diff --git a/src/app/api/settings/item/actions.ts b/src/app/api/settings/item/actions.ts index 8449009..bdd6b9f 100644 --- a/src/app/api/settings/item/actions.ts +++ b/src/app/api/settings/item/actions.ts @@ -1,5 +1,9 @@ "use server"; -import { ServerFetchError, serverFetchJson, serverFetchWithNoContent } from "@/app/utils/fetchUtil"; +import { + ServerFetchError, + serverFetchJson, + serverFetchWithNoContent, +} from "@/app/utils/fetchUtil"; import { revalidateTag } from "next/cache"; import { BASE_API_URL } from "@/config/api"; import { CreateItemResponse } from "../../utils"; @@ -18,28 +22,30 @@ import { QcChecksInputs } from "../qcCheck/actions"; // conversion: number // } - export type CreateItemInputs = { - id?: string | number + id?: string | number; code: string; name: string; description?: string | undefined; remarks?: string | undefined; - shelfLife?: Number | undefined; + shelfLife?: number | undefined; countryOfOrigin?: string | undefined; maxQty: number; type: string; - qcChecks: QcChecksInputs[] - qcChecks_active: number[] -} + qcChecks: QcChecksInputs[]; + qcChecks_active: number[]; +}; export const saveItem = async (data: CreateItemInputs) => { - // try { - const item = await serverFetchJson>(`${BASE_API_URL}/items/new`, { - method: "POST", - body: JSON.stringify(data), - headers: { "Content-Type": "application/json" }, - }); - revalidateTag("items"); - return item - }; \ No newline at end of file + // try { + const item = await serverFetchJson>( + `${BASE_API_URL}/items/new`, + { + method: "POST", + body: JSON.stringify(data), + headers: { "Content-Type": "application/json" }, + }, + ); + revalidateTag("items"); + return item; +}; diff --git a/src/app/api/settings/item/index.ts b/src/app/api/settings/item/index.ts index 280bf3d..c0b0559 100644 --- a/src/app/api/settings/item/index.ts +++ b/src/app/api/settings/item/index.ts @@ -16,40 +16,39 @@ export type ItemQc = { lowerLimit: number | undefined; upperLimit: number | undefined; isActive: boolean | undefined; -} +}; export type ItemsResultResponse = { records: ItemsResult[]; total: number; -} +}; export type ItemsResult = { - id: string | number + id: string | number; code: string; name: string; description: string | undefined; remarks: string | undefined; - shelfLife: Number | undefined; + shelfLife: number | undefined; countryOfOrigin: string | undefined; maxQty: number | undefined; type: string; - qcChecks: ItemQc[] - action?: any -} + qcChecks: ItemQc[]; + action?: any; +}; export type Result = { - item: ItemsResult - qcChecks: ItemQc[] -} + item: ItemsResult; + qcChecks: ItemQc[]; +}; export const fetchAllItems = cache(async () => { - return serverFetchJson(`${BASE_API_URL}/items`, { - next: { tags: ["items"] }, - }); + return serverFetchJson(`${BASE_API_URL}/items`, { + next: { tags: ["items"] }, }); - +}); export const fetchItem = cache(async (id: number) => { return serverFetchJson(`${BASE_API_URL}/items/details/${id}`, { next: { tags: ["items"] }, }); -}); \ No newline at end of file +}); diff --git a/src/app/api/settings/m18ImportTesting/actions.ts b/src/app/api/settings/m18ImportTesting/actions.ts index 27b6448..9141ea6 100644 --- a/src/app/api/settings/m18ImportTesting/actions.ts +++ b/src/app/api/settings/m18ImportTesting/actions.ts @@ -6,60 +6,62 @@ import { serverFetchWithNoContent } from "../../../utils/fetchUtil"; import { BASE_API_URL } from "../../../../config/api"; export interface M18ImportPoForm { - modifiedDateFrom: string, - modifiedDateTo: string, + modifiedDateFrom: string; + modifiedDateTo: string; } export interface M18ImportDoForm { - modifiedDateFrom: string, - modifiedDateTo: string, + modifiedDateFrom: string; + modifiedDateTo: string; } export interface M18ImportPqForm { - modifiedDateFrom: string, - modifiedDateTo: string, + modifiedDateFrom: string; + modifiedDateTo: string; } export interface M18ImportMasterDataForm { - modifiedDateFrom: string, - modifiedDateTo: string, + modifiedDateFrom: string; + modifiedDateTo: string; } export interface M18ImportTestingForm { - po: M18ImportPoForm, - do: M18ImportDoForm, - pq: M18ImportPqForm, - masterData: M18ImportMasterDataForm, + po: M18ImportPoForm; + do: M18ImportDoForm; + pq: M18ImportPqForm; + masterData: M18ImportMasterDataForm; } export const testM18ImportPo = async (data: M18ImportPoForm) => { - return serverFetchWithNoContent(`${BASE_API_URL}/m18/po`, { - method: "POST", - body: JSON.stringify(data), - headers: { "Content-Type": "application/json" }, - }) -} + return serverFetchWithNoContent(`${BASE_API_URL}/m18/po`, { + method: "POST", + body: JSON.stringify(data), + headers: { "Content-Type": "application/json" }, + }); +}; export const testM18ImportDo = async (data: M18ImportDoForm) => { - return serverFetchWithNoContent(`${BASE_API_URL}/m18/do`, { - method: "POST", - body: JSON.stringify(data), - headers: { "Content-Type": "application/json" }, - }) -} + return serverFetchWithNoContent(`${BASE_API_URL}/m18/do`, { + method: "POST", + body: JSON.stringify(data), + headers: { "Content-Type": "application/json" }, + }); +}; export const testM18ImportPq = async (data: M18ImportPqForm) => { - return serverFetchWithNoContent(`${BASE_API_URL}/m18/pq`, { - method: "POST", - body: JSON.stringify(data), - headers: { "Content-Type": "application/json" }, - }) -} + return serverFetchWithNoContent(`${BASE_API_URL}/m18/pq`, { + method: "POST", + body: JSON.stringify(data), + headers: { "Content-Type": "application/json" }, + }); +}; -export const testM18ImportMasterData = async (data: M18ImportMasterDataForm) => { - return serverFetchWithNoContent(`${BASE_API_URL}/m18/master-data`, { - method: "POST", - body: JSON.stringify(data), - headers: { "Content-Type": "application/json" }, - }) -} \ No newline at end of file +export const testM18ImportMasterData = async ( + data: M18ImportMasterDataForm, +) => { + return serverFetchWithNoContent(`${BASE_API_URL}/m18/master-data`, { + method: "POST", + body: JSON.stringify(data), + headers: { "Content-Type": "application/json" }, + }); +}; diff --git a/src/app/api/settings/m18ImportTesting/index.ts b/src/app/api/settings/m18ImportTesting/index.ts index f77bda3..99077c0 100644 --- a/src/app/api/settings/m18ImportTesting/index.ts +++ b/src/app/api/settings/m18ImportTesting/index.ts @@ -1 +1 @@ -// "server only" \ No newline at end of file +// "server only" diff --git a/src/app/api/settings/qcCategory/actions.ts b/src/app/api/settings/qcCategory/actions.ts index bb3277e..e564628 100644 --- a/src/app/api/settings/qcCategory/actions.ts +++ b/src/app/api/settings/qcCategory/actions.ts @@ -1,17 +1,17 @@ -"use server" +"use server"; import { serverFetchJson } from "@/app/utils/fetchUtil"; import { BASE_API_URL } from "@/config/api"; export interface CreateQcCategoryInputs { - code: string; - name: string; + code: string; + name: string; } export const saveQcCategory = async (data: CreateQcCategoryInputs) => { - return serverFetchJson(`${BASE_API_URL}/qcCategories/save`, { - method: "POST", - body: JSON.stringify(data), - headers: { "Content-Type": "application/json" }, - }) -} \ No newline at end of file + return serverFetchJson(`${BASE_API_URL}/qcCategories/save`, { + method: "POST", + body: JSON.stringify(data), + headers: { "Content-Type": "application/json" }, + }); +}; diff --git a/src/app/api/settings/qcCategory/index.ts b/src/app/api/settings/qcCategory/index.ts index 0e466e8..451572c 100644 --- a/src/app/api/settings/qcCategory/index.ts +++ b/src/app/api/settings/qcCategory/index.ts @@ -4,17 +4,17 @@ import { cache } from "react"; import "server-only"; export interface QcCategoryResult { - id: number; - code: string; - name: string; + id: number; + code: string; + name: string; } export const preloadQcCategory = () => { - fetchQcCategories(); + fetchQcCategories(); }; export const fetchQcCategories = cache(async () => { - return serverFetchJson(`${BASE_API_URL}/qcCategories`, { - next: { tags: ["qcCategories"]} - }); -}); \ No newline at end of file + return serverFetchJson(`${BASE_API_URL}/qcCategories`, { + next: { tags: ["qcCategories"] }, + }); +}); diff --git a/src/app/api/settings/qcCheck/actions.ts b/src/app/api/settings/qcCheck/actions.ts index 90aa38f..57ef41d 100644 --- a/src/app/api/settings/qcCheck/actions.ts +++ b/src/app/api/settings/qcCheck/actions.ts @@ -7,18 +7,18 @@ import { BASE_API_URL } from "../../../../config/api"; import { CreateItemResponse } from "../../utils"; import { ItemQc } from "../item"; -export type QcChecksInputs = { - -} & Partial - +export type QcChecksInputs = {} & Partial; export const saveItemQcChecks = async (data: QcChecksInputs[]) => { - // try { - const res = await serverFetchJson>(`${BASE_API_URL}/qcCheck/new`, { - method: "POST", - body: JSON.stringify(data), - headers: { "Content-Type": "application/json" }, - }); - revalidateTag("items"); - return res - }; \ No newline at end of file + // try { + const res = await serverFetchJson>( + `${BASE_API_URL}/qcCheck/new`, + { + method: "POST", + body: JSON.stringify(data), + headers: { "Content-Type": "application/json" }, + }, + ); + revalidateTag("items"); + return res; +}; diff --git a/src/app/api/settings/qcItem/actions.ts b/src/app/api/settings/qcItem/actions.ts index 63b1ce9..6d9b910 100644 --- a/src/app/api/settings/qcItem/actions.ts +++ b/src/app/api/settings/qcItem/actions.ts @@ -1,4 +1,4 @@ -"use server" +"use server"; // import { serverFetchJson } from "@/app/utils/fetchUtil"; // import { BASE_API_URL } from "@/config/api"; @@ -7,43 +7,49 @@ import { BASE_API_URL } from "../../../../config/api"; import { revalidatePath, revalidateTag } from "next/cache"; //import { QcItemResult } from '@/app/api/settings/qcItem'; -import { QcItemResult } from '../../../api/settings/qcItem'; +import { QcItemResult } from "../../../api/settings/qcItem"; export interface SaveQcItemInputs { - id?: number; - code: string; - name: string; - description?: string; + id?: number; + code: string; + name: string; + description?: string; } export interface SaveQcItemResponse { - id?: number; - code: string; - name: string; - description?: string; - errors: Record + id?: number; + code: string; + name: string; + description?: string; + errors: Record; } export const saveQcItem = async (data: SaveQcItemInputs) => { - const response = await serverFetchJson(`${BASE_API_URL}/qcItems/save`, { - method: "POST", - body: JSON.stringify(data), - headers: { "Content-Type": "application/json" }, - }) + const response = await serverFetchJson( + `${BASE_API_URL}/qcItems/save`, + { + method: "POST", + body: JSON.stringify(data), + headers: { "Content-Type": "application/json" }, + }, + ); - revalidateTag("qcItems") + revalidateTag("qcItems"); - return response -} + return response; +}; export const deleteQcItem = async (id: number) => { - const response = await serverFetchJson(`${BASE_API_URL}/qcItems/${id}`, { - method: "DELETE", - headers: { "Content-Type": "application/json" }, - }) - - revalidateTag("qcItems") - revalidatePath("/(main)/settings/qcItem") - - return response -} \ No newline at end of file + const response = await serverFetchJson( + `${BASE_API_URL}/qcItems/${id}`, + { + method: "DELETE", + headers: { "Content-Type": "application/json" }, + }, + ); + + revalidateTag("qcItems"); + revalidatePath("/(main)/settings/qcItem"); + + return response; +}; diff --git a/src/app/api/settings/qcItem/index.ts b/src/app/api/settings/qcItem/index.ts index d6e0783..359270a 100644 --- a/src/app/api/settings/qcItem/index.ts +++ b/src/app/api/settings/qcItem/index.ts @@ -9,27 +9,27 @@ import { SaveQcItemInputs } from "./actions"; import next from "next"; export interface QcItemResult { - id: number; - code: string; - name: string; - description: string; + id: number; + code: string; + name: string; + description: string; } export const preloadQcItem = () => { - fetchQcItems(); + fetchQcItems(); }; export const fetchQcItems = cache(async () => { - return serverFetchJson(`${BASE_API_URL}/qcItems`, { - next: { tags: ["qcItems"] } - }); + return serverFetchJson(`${BASE_API_URL}/qcItems`, { + next: { tags: ["qcItems"] }, + }); }); export const fetchQcItemDetails = cache(async (qcItemId: string) => { - return serverFetchJson( - `${BASE_API_URL}/qcItems/qcItemDetails/${qcItemId}`, - { - next: { tags: [`qcItemDetails_${qcItemId}`] } - } - ) -}) \ No newline at end of file + return serverFetchJson( + `${BASE_API_URL}/qcItems/qcItemDetails/${qcItemId}`, + { + next: { tags: [`qcItemDetails_${qcItemId}`] }, + }, + ); +}); diff --git a/src/app/api/settings/uom/index.ts b/src/app/api/settings/uom/index.ts index 7f6e81c..319ac11 100644 --- a/src/app/api/settings/uom/index.ts +++ b/src/app/api/settings/uom/index.ts @@ -6,17 +6,17 @@ import { serverFetchJson } from "../../../utils/fetchUtil"; import { BASE_API_URL } from "../../../../config/api"; export interface Uom { - id: number - code: string - name: string - unit1: string - unit1Qty: number - unit2?: string - unit2Qty: number - unit3?: string - unit3Qty: number - unit4?: string - unit4Qty: number - sizeInGram: number - gramPerSmallestUnit: number -} \ No newline at end of file + id: number; + code: string; + name: string; + unit1: string; + unit1Qty: number; + unit2?: string; + unit2Qty: number; + unit3?: string; + unit3Qty: number; + unit4?: string; + unit4Qty: number; + sizeInGram: number; + gramPerSmallestUnit: number; +} diff --git a/src/app/api/user/actions.ts b/src/app/api/user/actions.ts index f0a42fc..af33193 100644 --- a/src/app/api/user/actions.ts +++ b/src/app/api/user/actions.ts @@ -2,42 +2,45 @@ // import { serverFetchJson, serverFetchWithNoContent } from "@/app/utils/fetchUtil"; // import { BASE_API_URL } from "@/config/api"; -import { serverFetchJson, serverFetchWithNoContent } from "../../utils/fetchUtil"; +import { + serverFetchJson, + serverFetchWithNoContent, +} from "../../utils/fetchUtil"; import { BASE_API_URL } from "../../../config/api"; import { revalidateTag } from "next/cache"; import { UserDetail, UserResult } from "."; import { cache } from "react"; export interface UserInputs { - username: string; - // name: string; - addAuthIds?: number[]; - removeAuthIds?: number[]; - password?: string; + username: string; + // name: string; + addAuthIds?: number[]; + removeAuthIds?: number[]; + password?: string; } export interface PasswordInputs { - password: string; - newPassword: string; - newPasswordCheck: string; + password: string; + newPassword: string; + newPasswordCheck: string; } export interface NameList { - id: number - name: string + id: number; + name: string; } export const fetchUserDetails = cache(async (id: number) => { - return serverFetchJson(`${BASE_API_URL}/user/${id}`, { - next: { tags: ["user"] }, - }); + return serverFetchJson(`${BASE_API_URL}/user/${id}`, { + next: { tags: ["user"] }, }); +}); export const fetchNameList = cache(async () => { - return serverFetchJson(`${BASE_API_URL}/user/name-list`, { - next: { tags: ["user"] }, - }); + return serverFetchJson(`${BASE_API_URL}/user/name-list`, { + next: { tags: ["user"] }, }); +}); export const editUser = async (id: number, data: UserInputs) => { const newUser = serverFetchWithNoContent(`${BASE_API_URL}/user/${id}`, { @@ -45,8 +48,8 @@ export const editUser = async (id: number, data: UserInputs) => { body: JSON.stringify(data), headers: { "Content-Type": "application/json" }, }); - revalidateTag("user") - return newUser + revalidateTag("user"); + return newUser; }; export const createUser = async (data: UserInputs) => { @@ -55,8 +58,8 @@ export const createUser = async (data: UserInputs) => { body: JSON.stringify(data), headers: { "Content-Type": "application/json" }, }); - revalidateTag("user") - return newUser + revalidateTag("user"); + return newUser; }; export const deleteUser = async (id: number) => { @@ -64,22 +67,25 @@ export const deleteUser = async (id: number) => { method: "DELETE", headers: { "Content-Type": "application/json" }, }); - revalidateTag("user") - return newUser - }; + revalidateTag("user"); + return newUser; +}; export const changePassword = async (data: any) => { - return serverFetchWithNoContent(`${BASE_API_URL}/user/change-password`, { - method: "PATCH", - body: JSON.stringify(data), - headers: { "Content-Type": "application/json" }, - }); - }; + return serverFetchWithNoContent(`${BASE_API_URL}/user/change-password`, { + method: "PATCH", + body: JSON.stringify(data), + headers: { "Content-Type": "application/json" }, + }); +}; export const adminChangePassword = async (data: any) => { - return serverFetchWithNoContent(`${BASE_API_URL}/user/admin-change-password`, { + return serverFetchWithNoContent( + `${BASE_API_URL}/user/admin-change-password`, + { method: "PATCH", body: JSON.stringify(data), headers: { "Content-Type": "application/json" }, - }); - }; \ No newline at end of file + }, + ); +}; diff --git a/src/app/api/user/index.ts b/src/app/api/user/index.ts index 79fc62b..19396a7 100644 --- a/src/app/api/user/index.ts +++ b/src/app/api/user/index.ts @@ -4,11 +4,11 @@ import { cache } from "react"; import "server-only"; export interface UserResult { - action: any; - id: number; - username: string; - // name: string; - } + action: any; + id: number; + username: string; + // name: string; +} // export interface DetailedUser extends UserResult { // username: string; @@ -16,43 +16,43 @@ export interface UserResult { // } export interface UserDetail { - data: UserResult; - authIds: number[]; - groupIds: number[]; - auths: any[] - } - - export type passwordRule = { - min: number; - max: number; - number: boolean; - upperEng: boolean; - lowerEng: boolean; - specialChar: boolean; - } - - export const preloadUser = () => { - fetchUser(); - }; - - export const preloadUserDetail = (id: number) => { - fetchUserDetail(id); - }; - - export const fetchUser = cache(async () => { - return serverFetchJson(`${BASE_API_URL}/user`, { - next: { tags: ["user"] }, - }); + data: UserResult; + authIds: number[]; + groupIds: number[]; + auths: any[]; +} + +export type passwordRule = { + min: number; + max: number; + number: boolean; + upperEng: boolean; + lowerEng: boolean; + specialChar: boolean; +}; + +export const preloadUser = () => { + fetchUser(); +}; + +export const preloadUserDetail = (id: number) => { + fetchUserDetail(id); +}; + +export const fetchUser = cache(async () => { + return serverFetchJson(`${BASE_API_URL}/user`, { + next: { tags: ["user"] }, }); +}); - export const fetchUserDetail = cache(async (id: number) => { - return serverFetchJson(`${BASE_API_URL}/user/${id}`, { - next: { tags: ["user"] }, - }); +export const fetchUserDetail = cache(async (id: number) => { + return serverFetchJson(`${BASE_API_URL}/user/${id}`, { + next: { tags: ["user"] }, }); +}); - export const fetchPwRules = cache(async () => { - return serverFetchJson(`${BASE_API_URL}/user/password-rule`, { - next: { tags: ["pwRule"] }, - }); - }); \ No newline at end of file +export const fetchPwRules = cache(async () => { + return serverFetchJson(`${BASE_API_URL}/user/password-rule`, { + next: { tags: ["pwRule"] }, + }); +}); diff --git a/src/app/api/utils/index.ts b/src/app/api/utils/index.ts index 2b585ee..c8cf2b4 100644 --- a/src/app/api/utils/index.ts +++ b/src/app/api/utils/index.ts @@ -19,7 +19,7 @@ export interface CreateEquipmentResponse { message: string | null; errorPosition: string | keyof T; } -export interface RecordsRes{ - records: T - total: number -} \ No newline at end of file +export interface RecordsRes { + records: T; + total: number; +} diff --git a/src/app/api/warehouse/index.ts b/src/app/api/warehouse/index.ts index 46c33bc..db86d8f 100644 --- a/src/app/api/warehouse/index.ts +++ b/src/app/api/warehouse/index.ts @@ -4,14 +4,14 @@ import { serverFetchJson } from "@/app/utils/fetchUtil"; import { BASE_API_URL } from "@/config/api"; export interface WarehouseResult { - id: number - code: string - name: string - description: string + id: number; + code: string; + name: string; + description: string; } export const fetchWarehouseList = cache(async () => { - return serverFetchJson(`${BASE_API_URL}/warehouse`, { - next: { tags: ["warehouse"] }, - }); - }); \ No newline at end of file + return serverFetchJson(`${BASE_API_URL}/warehouse`, { + next: { tags: ["warehouse"] }, + }); +}); diff --git a/src/app/utils/commonUtil.ts b/src/app/utils/commonUtil.ts index 21d02f4..195b85e 100644 --- a/src/app/utils/commonUtil.ts +++ b/src/app/utils/commonUtil.ts @@ -1,4 +1,4 @@ -import { defaultPagingController } from './../../components/SearchResults/SearchResults'; +import { defaultPagingController } from "./../../components/SearchResults/SearchResults"; import { isNullOrUndefined } from "html5-qrcode/esm/core"; import { isEmpty } from "lodash"; @@ -8,19 +8,21 @@ export const downloadFile = (blobData: Uint8Array, filename: string) => { link.href = url; link.setAttribute("download", filename); link.click(); -} +}; -export const convertObjToURLSearchParams = (data: T | null): string => { +export const convertObjToURLSearchParams = ( + data: T | null, +): string => { if (isEmpty(data)) { - return '' + return ""; } - const params = new URLSearchParams() + const params = new URLSearchParams(); Object.entries(data).forEach(([key, value]) => { if (!isNullOrUndefined(value)) { - params.append(key, String(value)) + params.append(key, String(value)); } - }) + }); - return params.toString() -} \ No newline at end of file + return params.toString(); +}; diff --git a/src/app/utils/fetchUtil.ts b/src/app/utils/fetchUtil.ts index a925dd0..3f01795 100644 --- a/src/app/utils/fetchUtil.ts +++ b/src/app/utils/fetchUtil.ts @@ -4,13 +4,13 @@ import { headers } from "next/headers"; import { redirect } from "next/navigation"; export interface Pageable { - pageSize?: number - pageNum?: number + pageSize?: number; + pageNum?: number; } export type SearchParams = { searchParams: { [key: string]: string | string[] | undefined }; -} +}; export interface searchParamsProps { searchParams: { [key: string]: string | string[] | undefined }; @@ -66,19 +66,22 @@ type FetchParams = Parameters; export async function serverFetchJson(...args: FetchParams) { const response = await serverFetch(...args); - console.log(response.status) + console.log(response.status); if (response.ok) { if (response.status === 204) { - return response.status as T + return response.status as T; } - + return response.json() as T; } else { switch (response.status) { case 401: signOutUser(); default: - throw new ServerFetchError("Something went wrong fetching data in server.", response); + throw new ServerFetchError( + "Something went wrong fetching data in server.", + response, + ); } } } diff --git a/src/app/utils/formatUtil.ts b/src/app/utils/formatUtil.ts index 78f9834..040e5de 100644 --- a/src/app/utils/formatUtil.ts +++ b/src/app/utils/formatUtil.ts @@ -1,7 +1,15 @@ import dayjs, { ConfigType, Dayjs } from "dayjs"; import { Uom } from "../api/settings/uom"; -import { ListIterateeCustom, every, isArray, isNaN, isNull, isUndefined, take } from "lodash"; -import { Box, BoxProps, } from "@mui/material"; +import { + ListIterateeCustom, + every, + isArray, + isNaN, + isNull, + isUndefined, + take, +} from "lodash"; +import { Box, BoxProps } from "@mui/material"; export const manhourFormatter = new Intl.NumberFormat("en-HK", { minimumFractionDigits: 2, @@ -15,11 +23,9 @@ export const moneyFormatter = new Intl.NumberFormat("en-HK", { export const decimalFormatter = new Intl.NumberFormat("en-HK", { minimumFractionDigits: 2, -}) - -export const integerFormatter = new Intl.NumberFormat("en-HK", { +}); -}) +export const integerFormatter = new Intl.NumberFormat("en-HK", {}); export const INPUT_DATE_FORMAT = "YYYY-MM-DD"; @@ -28,71 +34,72 @@ export const OUTPUT_DATE_FORMAT = "YYYY/MM/DD"; export const OUTPUT_TIME_FORMAT = "HH:mm:ss"; export const arrayToDayjs = (arr: ConfigType | (number | undefined)[]) => { - const isValidNumber = (item: ListIterateeCustom): boolean => - typeof item === "number" && !isNaN(item) && isFinite(item) + const isValidNumber = ( + item: ListIterateeCustom, + ): boolean => typeof item === "number" && !isNaN(item) && isFinite(item); let tempArr = arr; if (isArray(arr) && every(arr, isValidNumber) && arr.length >= 3) { // [year, month, day] - tempArr = take(arr, 3) + tempArr = take(arr, 3); } - return dayjs(tempArr as ConfigType) -} + return dayjs(tempArr as ConfigType); +}; export const arrayToDateString = (arr: ConfigType | (number | undefined)[]) => { - return arrayToDayjs(arr).format(OUTPUT_DATE_FORMAT) -} + return arrayToDayjs(arr).format(OUTPUT_DATE_FORMAT); +}; export const dateStringToDayjs = (date: string) => { // Format: YYYY/MM/DD - return dayjs(date, OUTPUT_DATE_FORMAT) -} + return dayjs(date, OUTPUT_DATE_FORMAT); +}; export const dateTimeStringToDayjs = (dateTime: string) => { // Format: YYYY/MM/DD HH:mm:ss - return dayjs(dateTime, `${OUTPUT_DATE_FORMAT} ${OUTPUT_TIME_FORMAT}`) -} + return dayjs(dateTime, `${OUTPUT_DATE_FORMAT} ${OUTPUT_TIME_FORMAT}`); +}; export const dayjsToDateString = (date: Dayjs) => { - return date.format(OUTPUT_DATE_FORMAT) -} + return date.format(OUTPUT_DATE_FORMAT); +}; export const stockInLineStatusMap: { [status: string]: number } = { - "draft": 0, - "pending": 1, - "qc": 2, - "determine1": 3, - "determine2": 4, - "determine3": 5, - "receiving": 6, - "received": 7, - "completed": 8, - "rejected": 9, + draft: 0, + pending: 1, + qc: 2, + determine1: 3, + determine2: 4, + determine3: 5, + receiving: 6, + received: 7, + completed: 8, + rejected: 9, }; export const stockOutLineStatusMap: { [status: string]: number } = { - "draft": 0, - "pending": 1, // waiting for qc - "determine1": 2, // waiting for qc + draft: 0, + pending: 1, // waiting for qc + determine1: 2, // waiting for qc "lot-change": 3, // waiting for qc // after qc = completed - "completed": 4, - "rejected": 5, + completed: 4, + rejected: 5, }; export const pickOrderStatusMap: { [status: string]: number } = { - "pending": 1, - "consolidated": 2, - "released": 3, - "completed": 4, + pending: 1, + consolidated: 2, + released: 3, + completed: 4, }; export const calculateWeight = (qty: number, uom: Uom) => { return qty * (uom.unit2Qty || 1) * (uom.unit3Qty || 1) * (uom.unit4Qty || 1); -} +}; export const returnWeightUnit = (uom: Uom) => { return uom.unit4 || uom.unit3 || uom.unit2 || uom.unit1; -} +}; diff --git a/src/app/utils/typeEnum.ts b/src/app/utils/typeEnum.ts index 75e9bf4..f2fbd88 100644 --- a/src/app/utils/typeEnum.ts +++ b/src/app/utils/typeEnum.ts @@ -1,10 +1,10 @@ export enum TypeEnum { - MATERIAL = "material", - MATERIAL_ID = 1, - PRODUCT = "product", - PRODUCT_ID = 2, - BYPRODUCT = "byProduct", - BYPRODUCT_ID = 3, - CONSUMABLE = "consumables", - CONSUMABLE_ID = 4, -} \ No newline at end of file + MATERIAL = "material", + MATERIAL_ID = 1, + PRODUCT = "product", + PRODUCT_ID = 2, + BYPRODUCT = "byProduct", + BYPRODUCT_ID = 3, + CONSUMABLE = "consumables", + CONSUMABLE_ID = 4, +} diff --git a/src/authorties.ts b/src/authorties.ts index 925445f..0950252 100644 --- a/src/authorties.ts +++ b/src/authorties.ts @@ -1,12 +1,6 @@ - -export const [ - VIEW_USER, - MAINTAIN_USER, - VIEW_GROUP, - MAINTAIN_GROUP, - ] = [ +export const [VIEW_USER, MAINTAIN_USER, VIEW_GROUP, MAINTAIN_GROUP] = [ "VIEW_USER", "MAINTAIN_USER", "VIEW_GROUP", "MAINTAIN_GROUP", -] \ No newline at end of file +]; diff --git a/src/components/Breadcrumb/Breadcrumb.tsx b/src/components/Breadcrumb/Breadcrumb.tsx index b52993f..e1a09e6 100644 --- a/src/components/Breadcrumb/Breadcrumb.tsx +++ b/src/components/Breadcrumb/Breadcrumb.tsx @@ -30,7 +30,7 @@ const pathToLabelMap: { [path: string]: string } = { const Breadcrumb = () => { const pathname = usePathname(); const segments = pathname.split("/"); - const { t } = useTranslation("common") + const { t } = useTranslation("common"); return ( diff --git a/src/components/ClaimSearch/ClaimSearch.tsx b/src/components/ClaimSearch/ClaimSearch.tsx deleted file mode 100644 index 6ab02cf..0000000 --- a/src/components/ClaimSearch/ClaimSearch.tsx +++ /dev/null @@ -1,93 +0,0 @@ -"use client"; - -import { ClaimResult } from "@/app/api/claims"; -import React, { useCallback, useMemo, useState } from "react"; -import SearchBox, { Criterion } from "../SearchBox/index"; -import { useTranslation } from "react-i18next"; -import SearchResults, { Column } from "../SearchResults/index"; -import EditNote from "@mui/icons-material/EditNote"; - -interface Props { - claims: ClaimResult[]; -} - -type SearchQuery = Partial>; -type SearchParamNames = keyof SearchQuery; - -const ClaimSearch: React.FC = ({ claims }) => { - const { t } = useTranslation("claims"); - - // If claim searching is done on the server-side, then no need for this. - const [filteredClaims, setFilteredClaims] = useState(claims); - - const searchCriteria: Criterion[] = useMemo( - () => [ - { label: t("Creation Date"), paramName: "created", type: "dateRange" }, - { label: t("Related Project Name"), paramName: "name", type: "text" }, - { - label: t("Cost (HKD)"), - paramName: "cost", - type: "text", - }, - { - label: t("Expense Type"), - paramName: "type", - type: "select", - options: ["Expense", "Petty Cash"], - }, - { - label: t("Status"), - paramName: "status", - type: "select", - options: [ - "Not Submitted", - "Waiting for Approval", - "Approved", - "Rejected", - ], - }, - { - label: t("Remarks"), - paramName: "remarks", - type: "text", - }, - ], - [t], - ); - - const onClaimClick = useCallback((claim: ClaimResult) => { - console.log(claim); - }, []); - - const columns = useMemo[]>( - () => [ - // { - // name: "action", - // label: t("Actions"), - // onClick: onClaimClick, - // buttonIcon: , - // }, - { name: "created", label: t("Creation Date") }, - { name: "name", label: t("Related Project Name") }, - { name: "cost", label: t("Cost (HKD)") }, - { name: "type", label: t("Expense Type") }, - { name: "status", label: t("Status") }, - { name: "remarks", label: t("Remarks") }, - ], - [t, onClaimClick], - ); - - return ( - <> - { - console.log(query); - }} - /> - items={filteredClaims} columns={columns} /> - - ); -}; - -export default ClaimSearch; diff --git a/src/components/ClaimSearch/ClaimSearchLoading.tsx b/src/components/ClaimSearch/ClaimSearchLoading.tsx deleted file mode 100644 index 604aa7a..0000000 --- a/src/components/ClaimSearch/ClaimSearchLoading.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import Card from "@mui/material/Card"; -import CardContent from "@mui/material/CardContent"; -import Skeleton from "@mui/material/Skeleton"; -import Stack from "@mui/material/Stack"; -import React from "react"; - -// Can make this nicer -export const ClaimSearchLoading: React.FC = () => { - return ( - <> - - - - - - - - - - - - - - - - - - - - - - ); -}; - -export default ClaimSearchLoading; diff --git a/src/components/ClaimSearch/ClaimSearchWrapper.tsx b/src/components/ClaimSearch/ClaimSearchWrapper.tsx deleted file mode 100644 index c8a7f55..0000000 --- a/src/components/ClaimSearch/ClaimSearchWrapper.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import { fetchClaims } from "@/app/api/claims"; -import React from "react"; -import ClaimSearch from "./ClaimSearch"; -import ClaimSearchLoading from "./ClaimSearchLoading"; - -interface SubComponents { - Loading: typeof ClaimSearchLoading; -} - -const ClaimSearchWrapper: React.FC & SubComponents = async () => { - const claims = await fetchClaims(); - - return ; -}; - -ClaimSearchWrapper.Loading = ClaimSearchLoading; - -export default ClaimSearchWrapper; diff --git a/src/components/ClaimSearch/index.ts b/src/components/ClaimSearch/index.ts deleted file mode 100644 index 865400d..0000000 --- a/src/components/ClaimSearch/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from "./ClaimSearchWrapper"; diff --git a/src/components/ControlledAutoComplete/index.ts b/src/components/ControlledAutoComplete/index.ts index 7e12f58..77cbd6f 100644 --- a/src/components/ControlledAutoComplete/index.ts +++ b/src/components/ControlledAutoComplete/index.ts @@ -1 +1 @@ -export { default } from "./ControlledAutoComplete"; \ No newline at end of file +export { default } from "./ControlledAutoComplete"; diff --git a/src/components/CreateEquipment/CreateEquipment.tsx b/src/components/CreateEquipment/CreateEquipment.tsx index 470a246..e314aa7 100644 --- a/src/components/CreateEquipment/CreateEquipment.tsx +++ b/src/components/CreateEquipment/CreateEquipment.tsx @@ -14,7 +14,16 @@ import { useForm, } from "react-hook-form"; import { deleteDialog } from "../Swal/CustomAlerts"; -import { Box, Button, Grid, Stack, Tab, Tabs, TabsProps, Typography } from "@mui/material"; +import { + Box, + Button, + Grid, + Stack, + Tab, + Tabs, + TabsProps, + Typography, +} from "@mui/material"; import { Check, Close, EditNote } from "@mui/icons-material"; import { TypeEnum } from "@/app/utils/typeEnum"; import EquipmentDetails from "./EquipmentDetails"; @@ -33,31 +42,30 @@ const CreateItem: React.FC = ({ isEditMode, // type, defaultValues, - }) => { // console.log(type) const apiRef = useGridApiRef(); - const params = useSearchParams() - console.log(params.get("id")) + const params = useSearchParams(); + console.log(params.get("id")); const [serverError, setServerError] = useState(""); const [tabIndex, setTabIndex] = useState(0); const { t } = useTranslation("common"); const router = useRouter(); - const title = "Equipment" + const title = "Equipment"; const [mode, redirPath] = useMemo(() => { // var typeId = TypeEnum.CONSUMABLE_ID - var title = ""; - var mode = ""; - var redirPath = ""; + let title = ""; + let mode = ""; + let redirPath = ""; // if (type === TypeEnum.MATERIAL) { // typeId = TypeEnum.MATERIAL_ID // title = "Material"; // redirPath = "/settings/material"; // } // if (type === TypeEnum.PRODUCT) { - // typeId = TypeEnum.PRODUCT_ID - title = "Equipment"; - redirPath = "/settings/equipment"; + // typeId = TypeEnum.PRODUCT_ID + title = "Equipment"; + redirPath = "/settings/equipment"; // } // if (type === TypeEnum.BYPRODUCT) { // typeId = TypeEnum.BYPRODUCT_ID @@ -73,8 +81,7 @@ const CreateItem: React.FC = ({ }, [isEditMode]); // console.log(typeId) const formProps = useForm({ - defaultValues: defaultValues ? defaultValues : { - }, + defaultValues: defaultValues ? defaultValues : {}, }); const errors = formProps.formState.errors; @@ -90,8 +97,8 @@ const CreateItem: React.FC = ({ }; const onSubmit = useCallback>( async (data, event) => { - let hasErrors = false; - console.log(errors) + const hasErrors = false; + console.log(errors); // console.log(apiRef.current.getCellValue(2, "lowerLimit")) // apiRef.current. try { @@ -102,24 +109,25 @@ const CreateItem: React.FC = ({ console.log("data posted"); console.log(data); - - // TODO: + // TODO: // 1. check field ( directly modify col def / check here ) // 2. set error change tab index // return // do api - console.log("asdad") - var responseI = await saveEquipment(data); - console.log("asdad") + console.log("asdad"); + const responseI = await saveEquipment(data); + console.log("asdad"); // var responseQ = await saveItemQcChecks(qcCheck) if (responseI) { if (!Boolean(responseI.id)) { - formProps.setError(responseI.errorPosition!! as keyof CreateEquipmentInputs, { - message: responseI.message!!, - type: "required", - }) - + formProps.setError( + responseI.errorPosition! as keyof CreateEquipmentInputs, + { + message: responseI.message!, + type: "required", + }, + ); } else if (Boolean(responseI.id)) { router.replace(redirPath); } @@ -130,13 +138,13 @@ const CreateItem: React.FC = ({ console.log(e); } }, - [apiRef, router, t] + [apiRef, router, t], ); // multiple tabs const onSubmitError = useCallback>( (errors) => {}, - [] + [], ); return ( @@ -147,21 +155,25 @@ const CreateItem: React.FC = ({ component="form" onSubmit={formProps.handleSubmit(onSubmit, onSubmitError)} > - - - {t(`${mode} ${title}`)} - - - - - {/* */} - + + + {t(`${mode} ${title}`)} + + + + + {/* */} + {serverError && ( {serverError} )} - {tabIndex === 0 && } + {tabIndex === 0 && } {/* {tabIndex === 1 && } */} {/* {type === TypeEnum.MATERIAL && } */} {/* {type === TypeEnum.BYPRODUCT && } */} diff --git a/src/components/CreateEquipment/CreateEquipmentLoading.tsx b/src/components/CreateEquipment/CreateEquipmentLoading.tsx index 15896e9..5664e6a 100644 --- a/src/components/CreateEquipment/CreateEquipmentLoading.tsx +++ b/src/components/CreateEquipment/CreateEquipmentLoading.tsx @@ -23,7 +23,8 @@ export const CreateItemLoading: React.FC = () => { - CreateMaterial + + CreateMaterial diff --git a/src/components/CreateEquipment/CreateEquipmentWrapper.tsx b/src/components/CreateEquipment/CreateEquipmentWrapper.tsx index d60f59b..ef0337f 100644 --- a/src/components/CreateEquipment/CreateEquipmentWrapper.tsx +++ b/src/components/CreateEquipment/CreateEquipmentWrapper.tsx @@ -9,34 +9,32 @@ interface SubComponents { } type Props = { - id?: number + id?: number; // type: TypeEnum; }; -const CreateEquipmentWrapper: React.FC & - SubComponents = async ({ id }) => { - var result - var defaultValues: Partial | undefined +const CreateEquipmentWrapper: React.FC & SubComponents = async ({ + id, +}) => { + let result; + let defaultValues: Partial | undefined; // console.log(type) - var qcChecks + let qcChecks; if (id) { result = await fetchEquipment(id); - const equipment = result - console.log(equipment) + const equipment = result; + console.log(equipment); defaultValues = { id: equipment?.id, code: equipment?.code, name: equipment?.name, description: equipment?.description, - equipmentTypeId: equipment?.equipmentTypeId ?? equipment?.equipmentType?.id, + equipmentTypeId: equipment?.equipmentTypeId, }; } - + return ( - + ); }; CreateEquipmentWrapper.Loading = CreateEquipmentLoading; diff --git a/src/components/CreateEquipment/EquipmentDetails.tsx b/src/components/CreateEquipment/EquipmentDetails.tsx index 62c2ce1..8df0f72 100644 --- a/src/components/CreateEquipment/EquipmentDetails.tsx +++ b/src/components/CreateEquipment/EquipmentDetails.tsx @@ -26,10 +26,10 @@ type Props = { // type: TypeEnum; isEditMode: boolean; // type: TypeEnum; - defaultValues: Partial | undefined; + defaultValues?: Partial | undefined; }; -const ProductDetails: React.FC = ({isEditMode}) => { +const ProductDetails: React.FC = ({ isEditMode }) => { const { t, i18n: { language }, @@ -99,7 +99,8 @@ const ProductDetails: React.FC = ({isEditMode}) => { // [] // ); const handleCancel = () => { - router.replace(`/settings/equipment`); + // router.replace(`/settings/equipment`); + console.log("cancel"); }; return ( @@ -139,8 +140,7 @@ const ProductDetails: React.FC = ({isEditMode}) => { helperText={errors.code?.message} /> - */ - } + */} = ({isEditMode}) => { - - - - - - + + + + + + {/* _formKey={"type"} diff --git a/src/components/CreateEquipment/NumberInputProps.ts b/src/components/CreateEquipment/NumberInputProps.ts index eb8e9ea..2dc3de1 100644 --- a/src/components/CreateEquipment/NumberInputProps.ts +++ b/src/components/CreateEquipment/NumberInputProps.ts @@ -1,5 +1,5 @@ import { InputBaseComponentProps } from "@mui/material"; export var NumberInputProps: InputBaseComponentProps = { - step: 0.01, - }; \ No newline at end of file + step: 0.01, +}; diff --git a/src/components/CreateEquipment/index.ts b/src/components/CreateEquipment/index.ts index 1b4a991..3dffd9b 100644 --- a/src/components/CreateEquipment/index.ts +++ b/src/components/CreateEquipment/index.ts @@ -1 +1 @@ -export { default } from "./CreateEquipmentWrapper"; \ No newline at end of file +export { default } from "./CreateEquipmentWrapper"; diff --git a/src/components/CreateEquipmentType/CreateEquipmentType.tsx b/src/components/CreateEquipmentType/CreateEquipmentType.tsx index ea763da..84c70fb 100644 --- a/src/components/CreateEquipmentType/CreateEquipmentType.tsx +++ b/src/components/CreateEquipmentType/CreateEquipmentType.tsx @@ -14,7 +14,16 @@ import { useForm, } from "react-hook-form"; import { deleteDialog } from "../Swal/CustomAlerts"; -import { Box, Button, Grid, Stack, Tab, Tabs, TabsProps, Typography } from "@mui/material"; +import { + Box, + Button, + Grid, + Stack, + Tab, + Tabs, + TabsProps, + Typography, +} from "@mui/material"; import { Check, Close, EditNote } from "@mui/icons-material"; import { TypeEnum } from "@/app/utils/typeEnum"; import EquipmentTypeDetails from "./EquipmentTypeDetails"; @@ -33,31 +42,30 @@ const CreateItem: React.FC = ({ isEditMode, // type, defaultValues, - }) => { // console.log(type) const apiRef = useGridApiRef(); - const params = useSearchParams() - console.log(params.get("id")) + const params = useSearchParams(); + console.log(params.get("id")); const [serverError, setServerError] = useState(""); const [tabIndex, setTabIndex] = useState(0); const { t } = useTranslation("common"); const router = useRouter(); - const title = "Equipment Type" + const title = "Equipment Type"; const [mode, redirPath] = useMemo(() => { // var typeId = TypeEnum.CONSUMABLE_ID - var title = ""; - var mode = ""; - var redirPath = ""; + let title = ""; + let mode = ""; + let redirPath = ""; // if (type === TypeEnum.MATERIAL) { // typeId = TypeEnum.MATERIAL_ID // title = "Material"; // redirPath = "/settings/material"; // } // if (type === TypeEnum.PRODUCT) { - // typeId = TypeEnum.PRODUCT_ID - title = "Equipment Type"; - redirPath = "/settings/equipmentType"; + // typeId = TypeEnum.PRODUCT_ID + title = "Equipment Type"; + redirPath = "/settings/equipmentType"; // } // if (type === TypeEnum.BYPRODUCT) { // typeId = TypeEnum.BYPRODUCT_ID @@ -73,8 +81,7 @@ const CreateItem: React.FC = ({ }, [isEditMode]); // console.log(typeId) const formProps = useForm({ - defaultValues: defaultValues ? defaultValues : { - }, + defaultValues: defaultValues ? defaultValues : {}, }); const errors = formProps.formState.errors; @@ -90,8 +97,8 @@ const CreateItem: React.FC = ({ }; const onSubmit = useCallback>( async (data, event) => { - let hasErrors = false; - console.log(errors) + const hasErrors = false; + console.log(errors); // console.log(apiRef.current.getCellValue(2, "lowerLimit")) // apiRef.current. try { @@ -102,24 +109,25 @@ const CreateItem: React.FC = ({ console.log("data posted"); console.log(data); - - // TODO: + // TODO: // 1. check field ( directly modify col def / check here ) // 2. set error change tab index // return // do api - console.log("asdad") - var responseI = await saveEquipmentType(data); - console.log("asdad") + console.log("asdad"); + const responseI = await saveEquipmentType(data); + console.log("asdad"); // var responseQ = await saveItemQcChecks(qcCheck) if (responseI) { if (!Boolean(responseI.id)) { - formProps.setError(responseI.errorPosition!! as keyof CreateEquipmentTypeInputs, { - message: responseI.message!!, - type: "required", - }) - + formProps.setError( + responseI.errorPosition! as keyof CreateEquipmentTypeInputs, + { + message: responseI.message!, + type: "required", + }, + ); } else if (Boolean(responseI.id)) { router.replace(redirPath); } @@ -130,14 +138,13 @@ const CreateItem: React.FC = ({ console.log(e); } }, - [apiRef, router, t] + [apiRef, router, t], ); // multiple tabs - const onSubmitError = useCallback>( - (errors) => {}, - [] - ); + const onSubmitError = useCallback< + SubmitErrorHandler + >((errors) => {}, []); return ( <> @@ -147,21 +154,25 @@ const CreateItem: React.FC = ({ component="form" onSubmit={formProps.handleSubmit(onSubmit, onSubmitError)} > - - - {t(`${mode} ${title}`)} - - - - - {/* */} - + + + {t(`${mode} ${title}`)} + + + + + {/* */} + {serverError && ( {serverError} )} - {tabIndex === 0 && } + {tabIndex === 0 && } {/* {tabIndex === 1 && } */} {/* {type === TypeEnum.MATERIAL && } */} {/* {type === TypeEnum.BYPRODUCT && } */} diff --git a/src/components/CreateEquipmentType/CreateEquipmentTypeLoading.tsx b/src/components/CreateEquipmentType/CreateEquipmentTypeLoading.tsx index 15896e9..5664e6a 100644 --- a/src/components/CreateEquipmentType/CreateEquipmentTypeLoading.tsx +++ b/src/components/CreateEquipmentType/CreateEquipmentTypeLoading.tsx @@ -23,7 +23,8 @@ export const CreateItemLoading: React.FC = () => { - CreateMaterial + + CreateMaterial diff --git a/src/components/CreateEquipmentType/CreateEquipmentTypeWrapper.tsx b/src/components/CreateEquipmentType/CreateEquipmentTypeWrapper.tsx index 4ef16ac..83a1abd 100644 --- a/src/components/CreateEquipmentType/CreateEquipmentTypeWrapper.tsx +++ b/src/components/CreateEquipmentType/CreateEquipmentTypeWrapper.tsx @@ -9,20 +9,21 @@ interface SubComponents { } type Props = { - id?: number + id?: number; // type: TypeEnum; }; -const CreateEquipmentTypeWrapper: React.FC & - SubComponents = async ({ id }) => { - var result - var defaultValues: Partial | undefined +const CreateEquipmentTypeWrapper: React.FC & SubComponents = async ({ + id, +}) => { + let result; + let defaultValues: Partial | undefined; // console.log(type) - var qcChecks + let qcChecks; if (id) { result = await fetchEquipmentType(id); - const equipmentType = result - console.log(equipmentType) + const equipmentType = result; + console.log(equipmentType); defaultValues = { id: equipmentType?.id, code: equipmentType?.code, @@ -30,7 +31,7 @@ const CreateEquipmentTypeWrapper: React.FC & description: equipmentType?.description, }; } - + return ( | undefined; + defaultValues?: Partial | undefined; }; -const ProductDetails: React.FC = ({isEditMode}) => { +const ProductDetails: React.FC = ({ isEditMode }) => { const { t, i18n: { language }, @@ -99,7 +99,8 @@ const ProductDetails: React.FC = ({isEditMode}) => { // [] // ); const handleCancel = () => { - router.replace(`/settings/equipmentType`); + // router.replace(`/settings/equipmentType`); + console.log("cancel"); }; return ( @@ -132,8 +133,7 @@ const ProductDetails: React.FC = ({isEditMode}) => { helperText={errors.code?.message} /> - */ - } + */} = ({isEditMode}) => { - - - - - - + + + + + + {/* _formKey={"type"} diff --git a/src/components/CreateEquipmentType/NumberInputProps.ts b/src/components/CreateEquipmentType/NumberInputProps.ts index eb8e9ea..2dc3de1 100644 --- a/src/components/CreateEquipmentType/NumberInputProps.ts +++ b/src/components/CreateEquipmentType/NumberInputProps.ts @@ -1,5 +1,5 @@ import { InputBaseComponentProps } from "@mui/material"; export var NumberInputProps: InputBaseComponentProps = { - step: 0.01, - }; \ No newline at end of file + step: 0.01, +}; diff --git a/src/components/CreateEquipmentType/index.ts b/src/components/CreateEquipmentType/index.ts index f0529a5..3730d36 100644 --- a/src/components/CreateEquipmentType/index.ts +++ b/src/components/CreateEquipmentType/index.ts @@ -1 +1 @@ -export { default } from "./CreateEquipmentTypeWrapper"; \ No newline at end of file +export { default } from "./CreateEquipmentTypeWrapper"; diff --git a/src/components/CreateItem/CreateItem.tsx b/src/components/CreateItem/CreateItem.tsx index 9142128..7b8f592 100644 --- a/src/components/CreateItem/CreateItem.tsx +++ b/src/components/CreateItem/CreateItem.tsx @@ -3,10 +3,7 @@ import { useCallback, useEffect, useMemo, useState } from "react"; import { useRouter, useSearchParams } from "next/navigation"; import { useTranslation } from "react-i18next"; -import { - CreateItemInputs, - saveItem, -} from "@/app/api/settings/item/actions"; +import { CreateItemInputs, saveItem } from "@/app/api/settings/item/actions"; import { FormProvider, SubmitErrorHandler, @@ -14,7 +11,16 @@ import { useForm, } from "react-hook-form"; import { deleteDialog } from "../Swal/CustomAlerts"; -import { Box, Button, Grid, Stack, Tab, Tabs, TabsProps, Typography } from "@mui/material"; +import { + Box, + Button, + Grid, + Stack, + Tab, + Tabs, + TabsProps, + Typography, +} from "@mui/material"; import { Check, Close, EditNote } from "@mui/icons-material"; import { TypeEnum } from "@/app/utils/typeEnum"; import ProductDetails from "./ProductDetails"; @@ -28,38 +34,38 @@ type Props = { isEditMode: boolean; // type: TypeEnum; defaultValues: Partial | undefined; - qcChecks: ItemQc[] + qcChecks: ItemQc[]; }; const CreateItem: React.FC = ({ isEditMode, // type, defaultValues, - qcChecks + qcChecks, }) => { // console.log(type) const apiRef = useGridApiRef(); - const params = useSearchParams() - console.log(params.get("id")) + const params = useSearchParams(); + console.log(params.get("id")); const [serverError, setServerError] = useState(""); const [tabIndex, setTabIndex] = useState(0); const { t } = useTranslation("items"); const router = useRouter(); - const title = "Product / Material" + const title = "Product / Material"; const [mode, redirPath] = useMemo(() => { // var typeId = TypeEnum.CONSUMABLE_ID - var title = ""; - var mode = ""; - var redirPath = ""; + let title = ""; + let mode = ""; + let redirPath = ""; // if (type === TypeEnum.MATERIAL) { // typeId = TypeEnum.MATERIAL_ID // title = "Material"; // redirPath = "/settings/material"; // } // if (type === TypeEnum.PRODUCT) { - // typeId = TypeEnum.PRODUCT_ID - title = "Product"; - redirPath = "/settings/items"; + // typeId = TypeEnum.PRODUCT_ID + title = "Product"; + redirPath = "/settings/items"; // } // if (type === TypeEnum.BYPRODUCT) { // typeId = TypeEnum.BYPRODUCT_ID @@ -75,8 +81,7 @@ const CreateItem: React.FC = ({ }, [isEditMode]); // console.log(typeId) const formProps = useForm({ - defaultValues: defaultValues ? defaultValues : { - }, + defaultValues: defaultValues ? defaultValues : {}, }); const errors = formProps.formState.errors; @@ -92,8 +97,8 @@ const CreateItem: React.FC = ({ }; const onSubmit = useCallback>( async (data, event) => { - let hasErrors = false; - console.log(errors) + const hasErrors = false; + console.log(errors); // console.log(apiRef.current.getCellValue(2, "lowerLimit")) // apiRef.current. try { @@ -103,36 +108,45 @@ const CreateItem: React.FC = ({ } console.log("data posted"); console.log(data); - const qcCheck = data.qcChecks.length > 0 ? data.qcChecks.filter((q) => data.qcChecks_active.includes(q.id!!)).map((qc) => { - return { - qcItemId: qc.id, - instruction: qc.instruction, - lowerLimit: qc.lowerLimit, - upperLimit: qc.upperLimit, - itemId: parseInt(params.get("id")!.toString()) - } - }) : [] + const qcCheck = + data.qcChecks.length > 0 + ? data.qcChecks + .filter((q) => data.qcChecks_active.includes(q.id!)) + .map((qc) => { + return { + qcItemId: qc.id, + instruction: qc.instruction, + lowerLimit: qc.lowerLimit, + upperLimit: qc.upperLimit, + itemId: parseInt(params.get("id")!.toString()), + }; + }) + : []; - const test = data.qcChecks.filter((q) => data.qcChecks_active.includes(q.id!!)) - // TODO: + const test = data.qcChecks.filter((q) => + data.qcChecks_active.includes(q.id!), + ); + // TODO: // 1. check field ( directly modify col def / check here ) // 2. set error change tab index - console.log(test) - console.log(qcCheck) + console.log(test); + console.log(qcCheck); // return // do api - console.log("asdad") - var responseI = await saveItem(data); - console.log("asdad") - var responseQ = await saveItemQcChecks(qcCheck) + console.log("asdad"); + const responseI = await saveItem(data); + console.log("asdad"); + const responseQ = await saveItemQcChecks(qcCheck); if (responseI && responseQ) { if (!Boolean(responseI.id)) { - formProps.setError(responseI.errorPosition!! as keyof CreateItemInputs, { - message: responseI.message!!, - type: "required", - }); + formProps.setError( + responseI.errorPosition! as keyof CreateItemInputs, + { + message: responseI.message!, + type: "required", + }, + ); } else if (!Boolean(responseQ.id)) { - } else if (Boolean(responseI.id) && Boolean(responseQ.id)) { router.replace(redirPath); } @@ -143,13 +157,13 @@ const CreateItem: React.FC = ({ console.log(e); } }, - [apiRef, router, t] + [apiRef, router, t], ); // multiple tabs const onSubmitError = useCallback>( (errors) => {}, - [] + [], ); return ( @@ -160,23 +174,25 @@ const CreateItem: React.FC = ({ component="form" onSubmit={formProps.handleSubmit(onSubmit, onSubmitError)} > - - - {t(`${mode} ${title}`)} - - - - - - + + + {t(`${mode} ${title}`)} + + + + + + {serverError && ( {serverError} )} - {tabIndex === 0 && } + {tabIndex === 0 && } {tabIndex === 1 && } {/* {type === TypeEnum.MATERIAL && } */} {/* {type === TypeEnum.BYPRODUCT && } */} diff --git a/src/components/CreateItem/CreateItemLoading.tsx b/src/components/CreateItem/CreateItemLoading.tsx index 15896e9..5664e6a 100644 --- a/src/components/CreateItem/CreateItemLoading.tsx +++ b/src/components/CreateItem/CreateItemLoading.tsx @@ -23,7 +23,8 @@ export const CreateItemLoading: React.FC = () => { - CreateMaterial + + CreateMaterial diff --git a/src/components/CreateItem/CreateItemWrapper.tsx b/src/components/CreateItem/CreateItemWrapper.tsx index 9091889..23eb9b8 100644 --- a/src/components/CreateItem/CreateItemWrapper.tsx +++ b/src/components/CreateItem/CreateItemWrapper.tsx @@ -10,22 +10,21 @@ interface SubComponents { } type Props = { - id?: number + id?: number; // type: TypeEnum; }; -const CreateItemWrapper: React.FC & - SubComponents = async ({ id }) => { - var result - var defaultValues: Partial | undefined +const CreateItemWrapper: React.FC & SubComponents = async ({ id }) => { + let result; + let defaultValues: Partial | undefined; // console.log(type) - var qcChecks + let qcChecks; if (id) { result = await fetchItem(id); - const item = result.item - qcChecks = result.qcChecks - const activeRows = qcChecks.filter(it => it.isActive).map(i => i.id) - console.log(qcChecks) + const item = result.item; + qcChecks = result.qcChecks; + const activeRows = qcChecks.filter((it) => it.isActive).map((i) => i.id); + console.log(qcChecks); defaultValues = { type: item?.type, id: item?.id, @@ -37,10 +36,10 @@ const CreateItemWrapper: React.FC & countryOfOrigin: item?.countryOfOrigin, maxQty: item?.maxQty, qcChecks: qcChecks, - qcChecks_active: activeRows + qcChecks_active: activeRows, }; } - + return ( | undefined; - qcChecks: ItemQc[] + defaultValues?: Partial | undefined; + qcChecks?: ItemQc[]; }; -const ProductDetails: React.FC = ({isEditMode}) => { +const ProductDetails: React.FC = ({ isEditMode }) => { const { t, i18n: { language }, @@ -100,7 +101,8 @@ const ProductDetails: React.FC = ({isEditMode}) => { // [] // ); const handleCancel = () => { - router.replace(`/settings/product`); + // router.replace(`/settings/product`); + console.log("cancel"); }; return ( @@ -201,32 +203,37 @@ const ProductDetails: React.FC = ({isEditMode}) => { /> - - - - - - + + + + + + {/* _formKey={"type"} diff --git a/src/components/CreateItem/QcDetails.tsx b/src/components/CreateItem/QcDetails.tsx index d932ea4..38e12e6 100644 --- a/src/components/CreateItem/QcDetails.tsx +++ b/src/components/CreateItem/QcDetails.tsx @@ -20,7 +20,7 @@ import { GridApiCommunity } from "@mui/x-data-grid/internals"; import { RiceBowl } from "@mui/icons-material"; type Props = { - apiRef: MutableRefObject + apiRef: MutableRefObject; }; type EntryError = | { @@ -28,7 +28,7 @@ type EntryError = } | undefined; -type QcRow = TableRow, EntryError> +type QcRow = TableRow, EntryError>; const QcDetails: React.FC = ({ apiRef }) => { const { t, @@ -47,11 +47,11 @@ const QcDetails: React.FC = ({ apiRef }) => { setError, clearErrors, } = useFormContext(); -// const apiRef = useGridApiRef(); + // const apiRef = useGridApiRef(); const qcColumns = useMemo( () => [ { - field:"name", + field: "name", headerName: t("name"), flex: 1, // editable: true, @@ -81,7 +81,8 @@ const QcDetails: React.FC = ({ apiRef }) => { editable: true, type: "number", renderEditCell(params: GridRenderEditCellParams) { - const errorMessage = params.row._error?.[params.field as keyof QcChecksInputs]; + const errorMessage = + params.row._error?.[params.field as keyof QcChecksInputs]; const content = ( = ({ apiRef }) => { editable: true, type: "number", renderEditCell(params: GridRenderEditCellParams) { - const errorMessage = params.row._error?.[params.field as keyof QcChecksInputs]; - const content = ( - - ); - return errorMessage ? ( - - {content} - - ) : ( - content - ); - }, + const errorMessage = + params.row._error?.[params.field as keyof QcChecksInputs]; + const content = ( + + ); + return errorMessage ? ( + + {content} + + ) : ( + content + ); + }, }, ], - [] + [], ); const validationTest = useCallback( ( newRow: GridRowModel, EntryError>>, - // rowModel: GridRowSelectionModel + // rowModel: GridRowSelectionModel ): EntryError => { const error: EntryError = {}; console.log(newRow); if (!newRow.lowerLimit) { - error["lowerLimit"] = "lower limit cannot be null" + error["lowerLimit"] = "lower limit cannot be null"; } - // if (rowModel.find(r => r == newRow.id)) { + // if (rowModel.find(r => r == newRow.id)) { - // } - if (newRow.lowerLimit && newRow.upperLimit && newRow.lowerLimit > newRow.upperLimit) { - error["lowerLimit"] = "lower limit should not be greater than upper limit" - error["upperLimit"] = "lower limit should not be greater than upper limit" + // } + if ( + newRow.lowerLimit && + newRow.upperLimit && + newRow.lowerLimit > newRow.upperLimit + ) { + error["lowerLimit"] = + "lower limit should not be greater than upper limit"; + error["upperLimit"] = + "lower limit should not be greater than upper limit"; } return Object.keys(error).length > 0 ? error : undefined; }, - [] + [], ); return ( diff --git a/src/components/CreateItem/index.ts b/src/components/CreateItem/index.ts index 2fb406d..e74df26 100644 --- a/src/components/CreateItem/index.ts +++ b/src/components/CreateItem/index.ts @@ -1 +1 @@ -export { default } from "./CreateItemWrapper"; \ No newline at end of file +export { default } from "./CreateItemWrapper"; diff --git a/src/components/CreateUser/AuthAllocation.tsx b/src/components/CreateUser/AuthAllocation.tsx index fe6c5a9..574fc11 100644 --- a/src/components/CreateUser/AuthAllocation.tsx +++ b/src/components/CreateUser/AuthAllocation.tsx @@ -57,9 +57,9 @@ const AuthAllocation: React.FC = ({ auths }) => { const [selectedAuths, setSelectedAuths] = useState( () => { return filteredAuths.filter( - (s) => getValues("addAuthIds")?.includes(s.id) + (s) => getValues("addAuthIds")?.includes(s.id), ); - } + }, ); const [removeAuthIds, setRemoveAuthIds] = useState([]); @@ -77,8 +77,8 @@ const AuthAllocation: React.FC = ({ auths }) => { resetField("addAuthIds"); setSelectedAuths( initialAuths.filter( - (auth) => defaultValues.addAuthIds?.includes(auth.id) - ) + (auth) => defaultValues.addAuthIds?.includes(auth.id), + ), ); } }, [defaultValues]); @@ -87,7 +87,7 @@ const AuthAllocation: React.FC = ({ auths }) => { useEffect(() => { setValue( "addAuthIds", - selectedAuths.map((a) => a.id) + selectedAuths.map((a) => a.id), ); setValue("removeAuthIds", removeAuthIds); }, [selectedAuths, removeAuthIds, setValue]); @@ -103,7 +103,7 @@ const AuthAllocation: React.FC = ({ auths }) => { { label: t("authority"), name: "authority" }, { label: t("description"), name: "name" }, ], - [addAuth, t] + [addAuth, t], ); const allocatedAuthColumns = useMemo[]>( @@ -117,7 +117,7 @@ const AuthAllocation: React.FC = ({ auths }) => { { label: t("authority"), name: "authority" }, { label: t("description"), name: "name" }, ], - [removeAuth, selectedAuths, t] + [removeAuth, selectedAuths, t], ); const [query, setQuery] = React.useState(""); @@ -132,12 +132,11 @@ const AuthAllocation: React.FC = ({ auths }) => { React.useEffect(() => { setFilteredAuths( - initialAuths.filter((a) => - ( - a.authority.toLowerCase().includes(query.toLowerCase()) || - a.name?.toLowerCase().includes(query.toLowerCase()) - ) - ) + initialAuths.filter( + (a) => + a.authority.toLowerCase().includes(query.toLowerCase()) || + a.name?.toLowerCase().includes(query.toLowerCase()), + ), ); }, [auths, query]); @@ -154,7 +153,7 @@ const AuthAllocation: React.FC = ({ auths }) => { (_e, newValue) => { setTabIndex(newValue); }, - [] + [], ); return ( @@ -177,7 +176,7 @@ const AuthAllocation: React.FC = ({ auths }) => { onChange={onQueryInputChange} value={query} placeholder={t( - "Search by Authority or description or position." + "Search by Authority or description or position.", )} InputProps={{ endAdornment: query && ( diff --git a/src/components/CreateUser/CreateUser.tsx b/src/components/CreateUser/CreateUser.tsx index 8ec54dd..cd70be9 100644 --- a/src/components/CreateUser/CreateUser.tsx +++ b/src/components/CreateUser/CreateUser.tsx @@ -47,7 +47,7 @@ interface Props { } const CreateUser: React.FC = async ({ rules, auths }) => { - console.log(auths) + console.log(auths); const { t } = useTranslation("user"); const formProps = useForm(); const searchParams = useSearchParams(); @@ -67,7 +67,7 @@ const CreateUser: React.FC = async ({ rules, auths }) => { (_e, newValue) => { setTabIndex(newValue); }, - [] + [], ); const errors = formProps.formState.errors; @@ -95,7 +95,7 @@ const CreateUser: React.FC = async ({ rules, auths }) => { const hasErrorsInTab = ( tabIndex: number, - errors: FieldErrors + errors: FieldErrors, ) => { switch (tabIndex) { case 0: @@ -113,7 +113,7 @@ const CreateUser: React.FC = async ({ rules, auths }) => { async (data) => { try { let haveError = false; - let regex_pw = + const regex_pw = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*])[A-Za-z\d!@#$%^&*]{8,20}$/; let pw = ""; if (data.password && data.password.length > 0) { @@ -158,7 +158,7 @@ const CreateUser: React.FC = async ({ rules, auths }) => { return; } console.log("passed"); - console.log(userData) + console.log(userData); await createUser(userData); // if (data.password && data.password.length > 0) { // await adminChangePassword(pwData); @@ -169,13 +169,13 @@ const CreateUser: React.FC = async ({ rules, auths }) => { setServerError(t("An error has occurred. Please try again later.")); } }, - [router] + [router], ); const onSubmitError = useCallback>( (errors) => { console.log(errors); }, - [] + [], ); return ( diff --git a/src/components/CreateUser/CreateUserLoading.tsx b/src/components/CreateUser/CreateUserLoading.tsx index 6ff6088..0a9b97b 100644 --- a/src/components/CreateUser/CreateUserLoading.tsx +++ b/src/components/CreateUser/CreateUserLoading.tsx @@ -16,14 +16,15 @@ export const CreateUserLoading: React.FC = () => { - CreateUser + + CreateUser diff --git a/src/components/CreateUser/CreateUserWrapper.tsx b/src/components/CreateUser/CreateUserWrapper.tsx index 76d341d..084adbe 100644 --- a/src/components/CreateUser/CreateUserWrapper.tsx +++ b/src/components/CreateUser/CreateUserWrapper.tsx @@ -10,8 +10,7 @@ interface SubComponents { Loading: typeof CreateUserLoading; } -const CreateUserWrapper: React.FC & SubComponents = async ({ -}) => { +const CreateUserWrapper: React.FC & SubComponents = async ({}) => { const [pwRule, auths] = await Promise.all([ fetchPwRules(), fetchAuth("user"), diff --git a/src/components/CreateUser/UserDetail.tsx b/src/components/CreateUser/UserDetail.tsx index df1581a..135a34e 100644 --- a/src/components/CreateUser/UserDetail.tsx +++ b/src/components/CreateUser/UserDetail.tsx @@ -15,7 +15,6 @@ import { useFormContext } from "react-hook-form"; import { useTranslation } from "react-i18next"; const UserDetail: React.FC = () => { - const { t } = useTranslation(); const { register, @@ -46,10 +45,10 @@ const UserDetail: React.FC = () => { fullWidth {...register("password")} // helperText={ - // Boolean(errors.password) && + // Boolean(errors.password) && // (errors.password?.message // ? t(errors.password.message) - // : + // : // (<> // - 8-20 characters //
@@ -59,7 +58,7 @@ const UserDetail: React.FC = () => { //
// - Numbers //
- // - Symbols + // - Symbols // ) // ) // } @@ -90,8 +89,8 @@ const UserDetail: React.FC = () => { export default UserDetail; - -{/* <> +{ + /* <> - 8-20 characters
- Uppercase letters @@ -101,4 +100,5 @@ export default UserDetail; - Numbers
- Symbols - */} \ No newline at end of file + */ +} diff --git a/src/components/DashboardPage/CollapsibleCard.tsx b/src/components/DashboardPage/CollapsibleCard.tsx index 4214ae4..b3cda21 100644 --- a/src/components/DashboardPage/CollapsibleCard.tsx +++ b/src/components/DashboardPage/CollapsibleCard.tsx @@ -1,5 +1,11 @@ import React, { useState } from "react"; -import { Card, CardHeader, CardContent, IconButton, Collapse } from "@mui/material"; +import { + Card, + CardHeader, + CardContent, + IconButton, + Collapse, +} from "@mui/material"; import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; import ExpandLessIcon from "@mui/icons-material/ExpandLess"; @@ -9,7 +15,11 @@ interface CollapsibleCardProps { defaultOpen?: boolean; } -const CollapsibleCard: React.FC = ({ title, children, defaultOpen = true }) => { +const CollapsibleCard: React.FC = ({ + title, + children, + defaultOpen = true, +}) => { const [open, setOpen] = useState(defaultOpen); return ( @@ -29,4 +39,4 @@ const CollapsibleCard: React.FC = ({ title, children, defa ); }; -export default CollapsibleCard; \ No newline at end of file +export default CollapsibleCard; diff --git a/src/components/DashboardPage/DashboardLoading.tsx b/src/components/DashboardPage/DashboardLoading.tsx index 568a2ef..69e9a5e 100644 --- a/src/components/DashboardPage/DashboardLoading.tsx +++ b/src/components/DashboardPage/DashboardLoading.tsx @@ -16,14 +16,15 @@ export const DashboardLoading: React.FC = () => {
- EditUser + + EditUser diff --git a/src/components/DashboardPage/DashboardPage.tsx b/src/components/DashboardPage/DashboardPage.tsx index b2f06fd..6be3a93 100644 --- a/src/components/DashboardPage/DashboardPage.tsx +++ b/src/components/DashboardPage/DashboardPage.tsx @@ -12,7 +12,7 @@ import PendingInspectionChart from "./chart/PendingInspectionChart"; import PendingStorageChart from "./chart/PendingStorageChart"; import ApplicationCompletionChart from "./chart/ApplicationCompletionChart"; import OrderCompletionChart from "./chart/OrderCompletionChart"; -import DashboardBox from "./DashboardBox"; +import DashboardBox from "./Dashboardbox"; import CollapsibleCard from "./CollapsibleCard"; type Props = {}; @@ -23,57 +23,64 @@ const DashboardPage: React.FC = ({}) => { return ( - - - - - - + + + + + + + + + + + + + - - - - - - - - - - + + + - - + - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - - ); }; diff --git a/src/components/DashboardPage/DashboardWrapper.tsx b/src/components/DashboardPage/DashboardWrapper.tsx index dd1f990..87bf240 100644 --- a/src/components/DashboardPage/DashboardWrapper.tsx +++ b/src/components/DashboardPage/DashboardWrapper.tsx @@ -1,7 +1,7 @@ -import { authOptions } from "@/config/authConfig" -import { getServerSession, Session } from "next-auth" -import DashboardPage from "./DashboardPage" -import { Typography } from "@mui/material" +import { authOptions } from "@/config/authConfig"; +import { getServerSession, Session } from "next-auth"; +import DashboardPage from "./DashboardPage"; +import { Typography } from "@mui/material"; import { I18nProvider, getServerI18n } from "@/i18n"; import DashboardLoading from "./DashboardLoading"; @@ -10,29 +10,28 @@ import DashboardLoading from "./DashboardLoading"; // } & Session | null interface SubComponents { - Loading: typeof DashboardLoading; - } + Loading: typeof DashboardLoading; +} type Props = { - searchParams: { [key: string]: string | string[] | undefined }; - } - + searchParams: { [key: string]: string | string[] | undefined }; +}; + const DashboardWrapper: React.FC & SubComponents = async ({ - searchParams + searchParams, }) => { - const { t } = await getServerI18n("dashboard"); -// const session: SessionWithAbilities = await getServerSession(authOptions) + // const session: SessionWithAbilities = await getServerSession(authOptions) - return ( - <> - {t("Dashboard")} - - - ) -} + return ( + <> + {t("Dashboard")} + + + ); +}; DashboardWrapper.Loading = DashboardLoading; -export default DashboardWrapper \ No newline at end of file +export default DashboardWrapper; diff --git a/src/components/DashboardPage/Dashboardbox.tsx b/src/components/DashboardPage/Dashboardbox.tsx index 6db6682..73cfcff 100644 --- a/src/components/DashboardPage/Dashboardbox.tsx +++ b/src/components/DashboardPage/Dashboardbox.tsx @@ -1,4 +1,4 @@ -"use client" +"use client"; import React from "react"; interface DashboardBoxProps { @@ -8,17 +8,26 @@ interface DashboardBoxProps { time?: string; } -const DashboardBox: React.FC = ({ title, value, unit, time }) => { +const DashboardBox: React.FC = ({ + title, + value, + unit, + time, +}) => { return ( -
-
{title}
+
+
+ {title} +
{value} {unit}
@@ -27,4 +36,4 @@ const DashboardBox: React.FC = ({ title, value, unit, time }) ); }; -export default DashboardBox; \ No newline at end of file +export default DashboardBox; diff --git a/src/components/DashboardPage/chart/ApplicationCompletionChart.tsx b/src/components/DashboardPage/chart/ApplicationCompletionChart.tsx index 9c025b3..13d9204 100644 --- a/src/components/DashboardPage/chart/ApplicationCompletionChart.tsx +++ b/src/components/DashboardPage/chart/ApplicationCompletionChart.tsx @@ -1,4 +1,4 @@ -"use client" +"use client"; import React, { useState } from "react"; import dynamic from "next/dynamic"; const ApexCharts = dynamic(() => import("react-apexcharts"), { ssr: false }); @@ -14,7 +14,7 @@ const ApplicationCompletionChart: React.FC = () => { dataLabels: { enabled: true, formatter: () => `${percent}%`, - style: { fontSize: "32px", fontWeight: 600, color: "#1976d2" } + style: { fontSize: "32px", fontWeight: 600, color: "#1976d2" }, }, legend: { show: false }, plotOptions: { @@ -22,12 +22,12 @@ const ApplicationCompletionChart: React.FC = () => { donut: { size: "70%", labels: { - show: false - } - } - } + show: false, + }, + }, + }, }, - stroke: { show: true, width: 2, colors: ['#fff'] } + stroke: { show: true, width: 2, colors: ["#fff"] }, }; return ( @@ -67,55 +67,67 @@ const ApplicationCompletionChart: React.FC = () => {
+ > + {t("Raw material")} + + > + {t("Shipment")} +
- -
-
+ style={{ + width: "100%", + height: 320, + display: "flex", + alignItems: "center", + justifyContent: "center", + margin: "0 auto", + }} + > + +
+
{t("Processed application")}: 0
{t("Pending application")}: 0
@@ -123,4 +135,4 @@ const ApplicationCompletionChart: React.FC = () => { ); }; -export default ApplicationCompletionChart; \ No newline at end of file +export default ApplicationCompletionChart; diff --git a/src/components/DashboardPage/chart/DashboardLineChart.tsx b/src/components/DashboardPage/chart/DashboardLineChart.tsx index ab34d0f..12fc0ba 100644 --- a/src/components/DashboardPage/chart/DashboardLineChart.tsx +++ b/src/components/DashboardPage/chart/DashboardLineChart.tsx @@ -1,38 +1,39 @@ -"use client" -// npm install +"use client"; +// npm install import { Select, MenuItem, FormControl, InputLabel } from "@mui/material"; -import React,{useState} from "react"; +import React, { useState } from "react"; import dynamic from "next/dynamic"; const ApexCharts = dynamic(() => import("react-apexcharts"), { ssr: false }); import { useTranslation } from "react-i18next"; -interface Props { // params type - +interface Props { + // params type } const DashboardLineChart: React.FC = () => { - const { t } = useTranslation(); - const [warehouseType, setWarehouseType] = useState(t("Cold storage")); - const [timeRange, setTimeRange] = useState("6h"); - - const options = { - chart: { type: "line" as const }, - xaxis: { - categories: ["10:00", "11:00", "12:00", "13:00", "14:00", "15:00"] - }, - yaxis: { - title: { text: t("Temperature") } - }, - stroke: { curve: "smooth" as const } - }; - const series = [ - { - name: "溫度", - data: [] - } - ]; - - return ( -
{ boxShadow: "0 2px 8px rgba(0,0,0,0.04)", marginBottom: 16, width: "100%", - - }}> -
- {t("Warehouse temperature record")} - - {t("Warehouse type")} - - - - - -
- + }} + > +
+ + {t("Warehouse temperature record")} + + + {t("Warehouse type")} + + + + +
- ); - }; - -export default DashboardLineChart + +
+ ); +}; +export default DashboardLineChart; diff --git a/src/components/DashboardPage/chart/DashboardProgressChart.tsx b/src/components/DashboardPage/chart/DashboardProgressChart.tsx index 7a71053..01f844e 100644 --- a/src/components/DashboardPage/chart/DashboardProgressChart.tsx +++ b/src/components/DashboardPage/chart/DashboardProgressChart.tsx @@ -1,128 +1,158 @@ -"use client" +"use client"; import React, { useEffect, useState } from "react"; import dynamic from "next/dynamic"; import { PoResult } from "@/app/api/po"; import { fetchPoListClient } from "@/app/api/po/actions"; import { useTranslation } from "react-i18next"; -interface Props { // params type +interface Props { + // params type po: PoResult[]; } const ApexCharts = dynamic(() => import("react-apexcharts"), { ssr: false }); const DashboardProgressChart: React.FC = () => { - const { t } = useTranslation("dashboard"); - const [series, setSeries] = useState([]); - const [total, setTotal] = useState(0); - const [pending, setPending] = useState(0); - const [receiving, setReceiving] = useState(0); - - useEffect(() => { - const fetchData = async () => { - const res = await fetchPoListClient(); - const records = res?.records || []; - const pendingCount = records.filter((r: any) => r.status === "pending").length; - const receivingCount = records.filter((r: any) => r.status === "receiving").length; - const totalCount = records.length; - - setPending(pendingCount); - setReceiving(receivingCount); - setTotal(totalCount); - setSeries([pendingCount, receivingCount]); - }; - fetchData(); - }, []); - - const options = { - chart: { - type: "donut" as const, + const { t } = useTranslation("dashboard"); + const [series, setSeries] = useState([]); + const [total, setTotal] = useState(0); + const [pending, setPending] = useState(0); + const [receiving, setReceiving] = useState(0); + + useEffect(() => { + const fetchData = async () => { + const res = await fetchPoListClient(); + const records = res?.records || []; + const pendingCount = records.filter( + (r: any) => r.status === "pending", + ).length; + const receivingCount = records.filter( + (r: any) => r.status === "receiving", + ).length; + const totalCount = records.length; + + setPending(pendingCount); + setReceiving(receivingCount); + setTotal(totalCount); + setSeries([pendingCount, receivingCount]); + }; + fetchData(); + }, []); + + const options = { + chart: { + type: "donut" as const, + }, + labels: [t("pending"), t("receiving")], + dataLabels: { + formatter: (val: number) => `${val.toFixed(1)}%`, + dropShadow: { + enabled: false, }, - labels: [t("pending"), t("receiving")], - dataLabels: { - formatter: (val: number) => `${val.toFixed(1)}%`, - dropShadow: { - enabled: false, - }, - style: { - fontSize: '18px', - fontWeight: 'bold', - }, + style: { + fontSize: "18px", + fontWeight: "bold", }, - legend: { - position: "bottom" as const, - fontSize: '16px', - markers: { - width: 16, - height: 16, - radius: 8, - }, + }, + legend: { + position: "bottom" as const, + fontSize: "16px", + markers: { + width: 16, + height: 16, + radius: 8, }, - colors: ["#A3C9F9", "#8DD7A9"], - plotOptions: { - pie: { - donut: { - size: "70%", - labels: { + }, + colors: ["#A3C9F9", "#8DD7A9"], + plotOptions: { + pie: { + donut: { + size: "70%", + labels: { + show: true, + name: { show: false }, + value: { show: true, - name: { show: false }, - value: { - show: true, - fontSize: "32px", - fontWeight: 600, - color: "#333", - formatter: function (val: string) { - return `${val}%`; - } + fontSize: "32px", + fontWeight: 600, + color: "#333", + formatter: function (val: string) { + return `${val}%`; }, - total: { - show: false - } - } - } - } - }, - stroke: { - show: true, - width: 2, - colors: ['#fff'] + }, + total: { + show: false, + }, + }, + }, }, - }; - - return ( -
-
{t("採購訂單概覽")}
-
- {series.length > 0 ? ( - - ) : ( -
- 載入中... -
- )} + boxShadow: "0 2px 8px rgba(0,0,0,0.04)", + }} + > +
+ {t("採購訂單概覽")} +
+
+ {series.length > 0 ? ( + + ) : ( +
+ 載入中... +
+ )} +
+
+
+ {t("pending")}:{pending}
-
-
{t("pending")}:{pending}
-
{t("receiving")}:{receiving}
-
{t("total")}:{total}
+
+ {t("receiving")}:{receiving} +
+
+ {t("total")}:{total}
- ); - }; +
+ ); +}; - -export default DashboardProgressChart \ No newline at end of file +export default DashboardProgressChart; diff --git a/src/components/DashboardPage/chart/OrderCompletionChart.tsx b/src/components/DashboardPage/chart/OrderCompletionChart.tsx index 15e8467..8e0f75a 100644 --- a/src/components/DashboardPage/chart/OrderCompletionChart.tsx +++ b/src/components/DashboardPage/chart/OrderCompletionChart.tsx @@ -1,4 +1,4 @@ -"use client" +"use client"; import React, { useState } from "react"; import dynamic from "next/dynamic"; const ApexCharts = dynamic(() => import("react-apexcharts"), { ssr: false }); @@ -14,7 +14,7 @@ const OrderCompletionChart: React.FC = () => { dataLabels: { enabled: true, formatter: () => `${percent}%`, - style: { fontSize: "32px", fontWeight: 600, color: "#1976d2" } + style: { fontSize: "32px", fontWeight: 600, color: "#1976d2" }, }, legend: { show: false }, plotOptions: { @@ -22,93 +22,124 @@ const OrderCompletionChart: React.FC = () => { donut: { size: "70%", labels: { - show: false - } - } - } + show: false, + }, + }, + }, }, - stroke: { show: true, width: 2, colors: ['#fff'] } + stroke: { show: true, width: 2, colors: ["#fff"] }, }; return ( -
-
- {t("Order completion")} +
+
+ + {t("Order completion")} +
+ > + {t("Raw material")} + + > + {t("Consumable")} + + > + {t("Shipment")} +
- -
-
+ style={{ + width: "100%", + height: 320, + display: "flex", + alignItems: "center", + justifyContent: "center", + margin: "0 auto", + }} + > + +
+
{t("Extracted order")}: 0
{t("Pending order")}: 0
@@ -116,4 +147,4 @@ const OrderCompletionChart: React.FC = () => { ); }; -export default OrderCompletionChart; \ No newline at end of file +export default OrderCompletionChart; diff --git a/src/components/DashboardPage/chart/PendingInspectionChart.tsx b/src/components/DashboardPage/chart/PendingInspectionChart.tsx index 1dd3823..730ce0a 100644 --- a/src/components/DashboardPage/chart/PendingInspectionChart.tsx +++ b/src/components/DashboardPage/chart/PendingInspectionChart.tsx @@ -1,4 +1,4 @@ -"use client" +"use client"; import React from "react"; import dynamic from "next/dynamic"; const ApexCharts = dynamic(() => import("react-apexcharts"), { ssr: false }); @@ -25,26 +25,39 @@ const PendingInspectionChart: React.FC = () => { fontSize: "32px", fontWeight: 600, color: "#1976d2", - formatter: () => `${percent}%` + formatter: () => `${percent}%`, }, - total: { show: false } - } - } - } + total: { show: false }, + }, + }, + }, }, - stroke: { show: true, width: 2, colors: ['#fff'] } + stroke: { show: true, width: 2, colors: ["#fff"] }, }; return ( -
-
待品檢物料
-
+
+
+ 待品檢物料 +
+
{ ); }; -export default PendingInspectionChart; \ No newline at end of file +export default PendingInspectionChart; diff --git a/src/components/DashboardPage/chart/PendingStorageChart.tsx b/src/components/DashboardPage/chart/PendingStorageChart.tsx index 15b153f..d7dccf4 100644 --- a/src/components/DashboardPage/chart/PendingStorageChart.tsx +++ b/src/components/DashboardPage/chart/PendingStorageChart.tsx @@ -1,4 +1,4 @@ -"use client" +"use client"; import React from "react"; import dynamic from "next/dynamic"; import { useTranslation } from "react-i18next"; @@ -25,26 +25,39 @@ const PendingStorageChart: React.FC = () => { fontSize: "32px", fontWeight: 600, color: "#1976d2", - formatter: () => `${percent}%` + formatter: () => `${percent}%`, }, - total: { show: false } - } - } - } + total: { show: false }, + }, + }, + }, }, - stroke: { show: true, width: 2, colors: ['#fff'] } + stroke: { show: true, width: 2, colors: ["#fff"] }, }; return ( -
-
{t("Pending storage")}
-
+
+
+ {t("Pending storage")} +
+
{ />
-
 
{t("Pending storage")}: 15 +
 
{t("Pending storage")}: 15
{t("Total storage")}: 16
-
); }; -export default PendingStorageChart; \ No newline at end of file +export default PendingStorageChart; diff --git a/src/components/DetailSchedule/DetailScheduleSearchView.tsx b/src/components/DetailSchedule/DetailScheduleSearchView.tsx index 05effed..b666d4c 100644 --- a/src/components/DetailSchedule/DetailScheduleSearchView.tsx +++ b/src/components/DetailSchedule/DetailScheduleSearchView.tsx @@ -12,10 +12,14 @@ import axios from "axios"; import { BASE_API_URL, NEXT_PUBLIC_API_URL } from "@/config/api"; import { useTranslation } from "react-i18next"; import axiosInstance from "@/app/(main)/axios/axiosInstance"; -import Qs from 'qs'; +import Qs from "qs"; import EditableSearchResults from "@/components/SearchResults/EditableSearchResults"; // Make sure to import Qs import { ScheduleType } from "@/app/api/scheduling"; -import { ProdScheduleResult, SearchProdSchedule, fetchProdSchedules } from "@/app/api/scheduling/actions"; +import { + ProdScheduleResult, + SearchProdSchedule, + fetchProdSchedules, +} from "@/app/api/scheduling/actions"; import { defaultPagingController } from "../SearchResults/SearchResults"; import { arrayToDateString, decimalFormatter } from "@/app/utils/formatUtil"; import dayjs from "dayjs"; @@ -30,246 +34,285 @@ import { uniqBy } from "lodash"; // }; type Props = { - type: ScheduleType; - // records: RecordStructure[]; - defaultInputs: SearchProdSchedule; + type: ScheduleType; + // records: RecordStructure[]; + defaultInputs: SearchProdSchedule; }; -type SearchQuery = Partial>; +type SearchQuery = Partial< + Omit +>; type SearchParamNames = keyof SearchQuery; const DSOverview: React.FC = ({ type, defaultInputs }) => { - const [filteredSchedules, setFilteredSchedules] = useState([]); - const { t } = useTranslation("schedule"); + const [filteredSchedules, setFilteredSchedules] = useState< + ProdScheduleResult[] + >([]); + const { t } = useTranslation("schedule"); - const router = useRouter(); - // const [filterObj, setFilterObj] = useState({}); - // const [tempSelectedValue, setTempSelectedValue] = useState({}); - const [pagingController, setPagingController] = useState(defaultPagingController) - const [totalCount, setTotalCount] = useState(0) - const [inputs, setInputs] = useState(defaultInputs) - const typeOptions = [ - { - value: "detailed", - label: t("Detailed") - }, - { - value: "manual", - label: t("Manual") - }, - ] + const router = useRouter(); + // const [filterObj, setFilterObj] = useState({}); + // const [tempSelectedValue, setTempSelectedValue] = useState({}); + const [pagingController, setPagingController] = useState( + defaultPagingController, + ); + const [totalCount, setTotalCount] = useState(0); + const [inputs, setInputs] = useState(defaultInputs); + const typeOptions = [ + { + value: "detailed", + label: t("Detailed"), + }, + { + value: "manual", + label: t("Manual"), + }, + ]; - const searchCriteria: Criterion[] = useMemo( - () => { - var searchCriteria: Criterion[] = [ - { label: t("Schedule Period"), label2: t("Schedule Period To"), paramName: "schedulePeriod", type: "dateRange" }, - { label: t("Production Date"), paramName: "scheduleAt", type: "date" }, - { label: t("Product Count"), paramName: "totalEstProdCount", type: "text" }, - { label: t("Type"), paramName: "types", type: "autocomplete", options: typeOptions }, - ] - return searchCriteria - }, - [t] - ); + const searchCriteria: Criterion[] = useMemo(() => { + const searchCriteria: Criterion[] = [ + { + label: t("Schedule Period"), + label2: t("Schedule Period To"), + paramName: "schedulePeriod", + type: "dateRange", + }, + { label: t("Production Date"), paramName: "scheduleAt", type: "date" }, + { + label: t("Product Count"), + paramName: "totalEstProdCount", + type: "text", + }, + { + label: t("Type"), + paramName: "types", + type: "autocomplete", + options: typeOptions, + }, + ]; + return searchCriteria; + }, [t]); - // const onDetailClick = useCallback( - // (item: ItemsResult) => { - // router.push(`/settings/items/edit?id=${item.id}`); - // }, - // [router] - // ); + // const onDetailClick = useCallback( + // (item: ItemsResult) => { + // router.push(`/settings/items/edit?id=${item.id}`); + // }, + // [router] + // ); - // const onDeleteClick = useCallback( - // (item: ItemsResult) => {}, - // [router] - // ); + // const onDeleteClick = useCallback( + // (item: ItemsResult) => {}, + // [router] + // ); - const onDetailClick = (record: ProdScheduleResult) => { - console.log("[debug] record", record); - router.push(`/scheduling/detail/edit?id=${record.id}`); + const onDetailClick = (record: ProdScheduleResult) => { + console.log("[debug] record", record); + router.push(`/scheduling/detail/edit?id=${record.id}`); + }; - } - - const columns = useMemo[]>( - () => [ - { - name: "id", - label: t("Details"), - onClick: (record) => onDetailClick(record), - buttonIcon: , - }, - { - name: "schedulePeriod", - label: t("Demand Forecast Period"), - renderCell: (params) => { - return `${arrayToDateString(params.schedulePeriod)} - ${arrayToDateString(params.schedulePeriodTo)}` - } - }, - { - name: "scheduleAt", - label: t("Production Date"), - renderCell: (params) => { - return arrayToDateString(params.scheduleAt) - } - }, - { - name: "totalEstProdCount", - label: t("Product Count(s)"), - headerAlign: "right", - align: "right", - renderCell: (params) => { - return decimalFormatter.format(params.totalEstProdCount) - } - }, - { - name: "type", - label: t("Type"), - renderCell: (params) => { - return t(params.type) - } - }, - // { - // name: "action", - // label: t(""), - // buttonIcon: , - // onClick: onDeleteClick, - // }, - ], - [filteredSchedules] - ); + const columns = useMemo[]>( + () => [ + { + name: "id", + label: t("Details"), + onClick: (record) => onDetailClick(record), + buttonIcon: , + }, + { + name: "schedulePeriod", + label: t("Demand Forecast Period"), + renderCell: (params) => { + return `${arrayToDateString( + params.schedulePeriod, + )} - ${arrayToDateString(params.schedulePeriodTo)}`; + }, + }, + { + name: "scheduleAt", + label: t("Production Date"), + renderCell: (params) => { + return arrayToDateString(params.scheduleAt); + }, + }, + { + name: "totalEstProdCount", + label: t("Product Count(s)"), + headerAlign: "right", + align: "right", + renderCell: (params) => { + return decimalFormatter.format(params.totalEstProdCount); + }, + }, + { + name: "type", + label: t("Type"), + renderCell: (params) => { + return t(params.type); + }, + }, + // { + // name: "action", + // label: t(""), + // buttonIcon: , + // onClick: onDeleteClick, + // }, + ], + [filteredSchedules], + ); - const refetchData = useCallback(async (query: Record | SearchProdSchedule, actionType: "reset" | "search" | "paging") => { - // console.log(query) - const defaultTypes = ["detailed", "manual"] - const convertedTypes = (query.types == undefined || typeof (query.types) == "string" ? query.types?.toLowerCase() == "all" ? defaultTypes : [query.types] - : query.types.some((ele) => ele.toLowerCase() === "all") ? defaultTypes : query.types) as ScheduleType[]; + const refetchData = useCallback( + async ( + query: Record | SearchProdSchedule, + actionType: "reset" | "search" | "paging", + ) => { + // console.log(query) + const defaultTypes = ["detailed", "manual"]; + const convertedTypes = ( + query.types == undefined || typeof query.types == "string" + ? query.types?.toLowerCase() == "all" + ? defaultTypes + : [query.types] + : query.types.some((ele) => ele.toLowerCase() === "all") + ? defaultTypes + : query.types + ) as ScheduleType[]; - console.log(convertedTypes) - console.log(query.types) - const params: SearchProdSchedule = { - scheduleAt: dayjs(query?.scheduleAt).isValid() ? query?.scheduleAt : undefined, - schedulePeriod: dayjs(query?.schedulePeriod).isValid() ? query?.schedulePeriod : undefined, - schedulePeriodTo: dayjs(query?.schedulePeriodTo).isValid() ? query?.schedulePeriodTo : undefined, - totalEstProdCount: query?.totalEstProdCount ? Number(query?.totalEstProdCount) : undefined, - types: convertedTypes, - pageNum: pagingController.pageNum - 1, - pageSize: pagingController.pageSize - } - const response = await fetchProdSchedules(params) + console.log(convertedTypes); + console.log(query.types); + const params: SearchProdSchedule = { + scheduleAt: dayjs(query?.scheduleAt).isValid() + ? query?.scheduleAt + : undefined, + schedulePeriod: dayjs(query?.schedulePeriod).isValid() + ? query?.schedulePeriod + : undefined, + schedulePeriodTo: dayjs(query?.schedulePeriodTo).isValid() + ? query?.schedulePeriodTo + : undefined, + totalEstProdCount: query?.totalEstProdCount + ? Number(query?.totalEstProdCount) + : undefined, + types: convertedTypes, + pageNum: pagingController.pageNum - 1, + pageSize: pagingController.pageSize, + }; + const response = await fetchProdSchedules(params); - // console.log(response) - if (response) { - setTotalCount(response.total) - switch (actionType) { - case "reset": - case "search": - setFilteredSchedules(() => response.records) - break; - case "paging": - setFilteredSchedules((fs) => uniqBy([...fs, ...response.records], "id")) - break; - } + // console.log(response) + if (response) { + setTotalCount(response.total); + switch (actionType) { + case "reset": + case "search": + setFilteredSchedules(() => response.records); + break; + case "paging": + setFilteredSchedules((fs) => + uniqBy([...fs, ...response.records], "id"), + ); + break; } - }, [pagingController, setPagingController]) + } + }, + [pagingController, setPagingController], + ); - useEffect(() => { - refetchData(inputs, "paging") - }, [pagingController]) + useEffect(() => { + refetchData(inputs, "paging"); + }, [pagingController]); - // useEffect(() => { - // refetchData(filterObj); + // useEffect(() => { + // refetchData(filterObj); - // }, [filterObj, pagingController.pageNum, pagingController.pageSize]); + // }, [filterObj, pagingController.pageNum, pagingController.pageSize]); - // const refetchData = async (filterObj: SearchQuery | null) => { + // const refetchData = async (filterObj: SearchQuery | null) => { - // const authHeader = axiosInstance.defaults.headers['Authorization']; - // if (!authHeader) { - // return; // Exit the function if the token is not set - // } + // const authHeader = axiosInstance.defaults.headers['Authorization']; + // if (!authHeader) { + // return; // Exit the function if the token is not set + // } - // const params = { - // pageNum: pagingController.pageNum, - // pageSize: pagingController.pageSize, - // ...filterObj, - // ...tempSelectedValue, - // } + // const params = { + // pageNum: pagingController.pageNum, + // pageSize: pagingController.pageSize, + // ...filterObj, + // ...tempSelectedValue, + // } - // try { - // const response = await axiosInstance.get(`${NEXT_PUBLIC_API_URL}/items/getRecordByPage`, { - // params, - // paramsSerializer: (params) => { - // return Qs.stringify(params, { arrayFormat: 'repeat' }); - // }, - // }); - // //setFilteredItems(response.data.records); - // setFilteredItems([ - // { - // id: 1, - // scheduledPeriod: "2025-05-11 to 2025-05-17", - // scheduledAt: "2025-05-07", - // productCount: 13, - // }, - // { - // id: 2, - // scheduledPeriod: "2025-05-18 to 2025-05-24", - // scheduledAt: "2025-05-14", - // productCount: 15, - // }, - // { - // id: 3, - // scheduledPeriod: "2025-05-25 to 2025-05-31", - // scheduledAt: "2025-05-21", - // productCount: 13, - // }, - // ]) - // setPagingController({ - // ...pagingController, - // totalCount: response.data.total - // }) - // return response; // Return the data from the response - // } catch (error) { - // console.error('Error fetching items:', error); - // throw error; // Rethrow the error for further handling - // } - // }; + // try { + // const response = await axiosInstance.get(`${NEXT_PUBLIC_API_URL}/items/getRecordByPage`, { + // params, + // paramsSerializer: (params) => { + // return Qs.stringify(params, { arrayFormat: 'repeat' }); + // }, + // }); + // //setFilteredItems(response.data.records); + // setFilteredItems([ + // { + // id: 1, + // scheduledPeriod: "2025-05-11 to 2025-05-17", + // scheduledAt: "2025-05-07", + // productCount: 13, + // }, + // { + // id: 2, + // scheduledPeriod: "2025-05-18 to 2025-05-24", + // scheduledAt: "2025-05-14", + // productCount: 15, + // }, + // { + // id: 3, + // scheduledPeriod: "2025-05-25 to 2025-05-31", + // scheduledAt: "2025-05-21", + // productCount: 13, + // }, + // ]) + // setPagingController({ + // ...pagingController, + // totalCount: response.data.total + // }) + // return response; // Return the data from the response + // } catch (error) { + // console.error('Error fetching items:', error); + // throw error; // Rethrow the error for further handling + // } + // }; - const onReset = useCallback(() => { - //setFilteredItems(items ?? []); - // setFilterObj({}); - // setTempSelectedValue({}); - refetchData(inputs, "reset"); - }, []); + const onReset = useCallback(() => { + //setFilteredItems(items ?? []); + // setFilterObj({}); + // setTempSelectedValue({}); + refetchData(inputs, "reset"); + }, []); - return ( - <> - { - setInputs(() => ( - { - scheduleAt: query?.scheduleAt, - schedulePeriod: query?.schedulePeriod, - schedulePeriodTo: query?.schedulePeriodTo, - totalEstProdCount: Number(query?.totalEstProdCount), - types: query.types as unknown as ScheduleType[] - } - )) - refetchData(query, "search") - }} - onReset={onReset} - /> - - items={filteredSchedules} - columns={columns} - setPagingController={setPagingController} - pagingController={pagingController} - totalCount={totalCount} - // isAutoPaging={false} - // hasCollapse={false} - /> - - ); + return ( + <> + { + setInputs(() => ({ + scheduleAt: query?.scheduleAt, + schedulePeriod: query?.schedulePeriod, + schedulePeriodTo: query?.schedulePeriodTo, + totalEstProdCount: Number(query?.totalEstProdCount), + types: query.types as unknown as ScheduleType[], + })); + refetchData(query, "search"); + }} + onReset={onReset} + /> + + items={filteredSchedules} + columns={columns} + setPagingController={setPagingController} + pagingController={pagingController} + totalCount={totalCount} + // isAutoPaging={false} + // hasCollapse={false} + /> + + ); }; export default DSOverview; diff --git a/src/components/DetailSchedule/DetailScheduleWrapper.tsx b/src/components/DetailSchedule/DetailScheduleWrapper.tsx index f7e34d7..2d7037d 100644 --- a/src/components/DetailSchedule/DetailScheduleWrapper.tsx +++ b/src/components/DetailSchedule/DetailScheduleWrapper.tsx @@ -1,26 +1,25 @@ import React from "react"; -import {DetailScheduleLoading} from "./DetailScheduleLoading"; +import { DetailScheduleLoading } from "./DetailScheduleLoading"; import DSOverview from "./DetailScheduleSearchView"; import { ScheduleType } from "@/app/api/scheduling"; import { SearchProdSchedule } from "@/app/api/scheduling/actions"; interface SubComponents { - Loading: typeof DetailScheduleLoading; + Loading: typeof DetailScheduleLoading; } type Props = { - type: ScheduleType -} + type: ScheduleType; +}; const DetailScheduleWrapper: React.FC & SubComponents = async ({ - type + type, }) => { + const defaultInputs: SearchProdSchedule = { + types: ["detailed", "manual"], + }; - const defaultInputs: SearchProdSchedule = { - types: ["detailed", "manual"] - } - - return ; + return ; }; DetailScheduleWrapper.Loading = DetailScheduleLoading; diff --git a/src/components/DetailSchedule/index.ts b/src/components/DetailSchedule/index.ts index a9ce973..e6a0aee 100644 --- a/src/components/DetailSchedule/index.ts +++ b/src/components/DetailSchedule/index.ts @@ -1 +1 @@ -export { default } from "./DetailScheduleWrapper"; \ No newline at end of file +export { default } from "./DetailScheduleWrapper"; diff --git a/src/components/DetailScheduleDetail/DetailInfoCard.tsx b/src/components/DetailScheduleDetail/DetailInfoCard.tsx index ff5b994..44badf4 100644 --- a/src/components/DetailScheduleDetail/DetailInfoCard.tsx +++ b/src/components/DetailScheduleDetail/DetailInfoCard.tsx @@ -39,16 +39,16 @@ const DetailInfoCard: React.FC = ({ recordDetails, isEditing }) => { formState: { errors, defaultValues, touchedFields }, } = useFormContext(); - const [details, setDetails] = useState(null); + const [details, setDetails] = useState(null); useEffect(() => { - console.log("[debug] record details", recordDetails) + console.log("[debug] record details", recordDetails); setDetails(recordDetails); - }, [recordDetails]) + }, [recordDetails]); useEffect(() => { - console.log("[debug] isEdit", isEditing) - }, [isEditing]) + console.log("[debug] isEdit", isEditing); + }, [isEditing]); return ( @@ -94,7 +94,11 @@ const DetailInfoCard: React.FC = ({ recordDetails, isEditing }) => { label={t("Total Production Qty")} fullWidth disabled={!isEditing} - value={typeof (field.value) == "number" ? integerFormatter.format(field.value) : field.value} + value={ + typeof field.value == "number" + ? integerFormatter.format(field.value) + : field.value + } // defaultValue={typeof (details?.productionCount) == "number" ? integerFormatter.format(details?.productionCount) : details?.productionCount} // error={Boolean(errors.type)} // helperText={errors.type?.message} diff --git a/src/components/DetailScheduleDetail/DetailScheduleDetailWrapper.tsx b/src/components/DetailScheduleDetail/DetailScheduleDetailWrapper.tsx index 34652d2..d359468 100644 --- a/src/components/DetailScheduleDetail/DetailScheduleDetailWrapper.tsx +++ b/src/components/DetailScheduleDetail/DetailScheduleDetailWrapper.tsx @@ -8,21 +8,20 @@ interface SubComponents { } type EditDetailScheduleDetailProps = { - id?: string | number -} + id?: string | number; +}; -type Props = EditDetailScheduleDetailProps +type Props = EditDetailScheduleDetailProps; const DetailScheduleDetailWrapper: React.FC & SubComponents = async ({ - id + id, }) => { - const defaultValues = { id: 1, productionDate: "2025-05-07", totalJobOrders: 13, totalProductionQty: 21000, - } + }; return ( | undefined; - qcChecks: ItemQc[] + qcChecks: ItemQc[]; }; const DetailScheduleDetailView: React.FC = ({ @@ -47,11 +61,11 @@ const DetailScheduleDetailView: React.FC = ({ }) => { // console.log(type) const apiRef = useGridApiRef(); - const params = useSearchParams() - console.log(params.get("id")) + const params = useSearchParams(); + console.log(params.get("id")); const [serverError, setServerError] = useState(""); const [tabIndex, setTabIndex] = useState(0); - const { t } = useTranslation("schedule") + const { t } = useTranslation("schedule"); const router = useRouter(); const [isEdit, setIsEdit] = useState(false); //const title = "Demand Forecast Detail" @@ -84,12 +98,14 @@ const DetailScheduleDetailView: React.FC = ({ }, [isEditMode]); // console.log(typeId) const formProps = useForm({ - defaultValues: defaultValues ? defaultValues : { - id: 1, - productionDate: "2025-05-07", - totalJobOrders: 13, - totalProductionQty: 21000, - }, + defaultValues: defaultValues + ? defaultValues + : { + id: 1, + productionDate: "2025-05-07", + totalJobOrders: 13, + totalProductionQty: 21000, + }, }); const errors = formProps.formState.errors; @@ -100,14 +116,11 @@ const DetailScheduleDetailView: React.FC = ({ [], ); - - const [pagingController, setPagingController] = useState({ pageNum: 1, pageSize: 10, totalCount: 0, - }) - + }); const handleCancel = () => { router.replace(`/scheduling/Detail`); @@ -116,7 +129,7 @@ const DetailScheduleDetailView: React.FC = ({ const onSubmit = useCallback>( async (data, event) => { const hasErrors = false; - console.log(errors) + console.log(errors); // console.log(apiRef.current.getCellValue(2, "lowerLimit")) // apiRef.current. try { @@ -130,18 +143,18 @@ const DetailScheduleDetailView: React.FC = ({ console.log(e); } }, - [apiRef, router, t] + [apiRef, router, t], ); // multiple tabs const onSubmitError = useCallback>( - (errors) => { }, - [] + (errors) => {}, + [], ); const onClickEdit = () => { - setIsEdit(!isEdit) - } + setIsEdit(!isEdit); + }; return ( <> @@ -169,15 +182,14 @@ const DetailScheduleDetailView: React.FC = ({ - {/* @@ -196,7 +208,7 @@ const DetailScheduleDetailView: React.FC = ({ variant="contained" startIcon={} type="submit" - // disabled={submitDisabled} + // disabled={submitDisabled} > {isEditMode ? t("Save") : t("Confirm")} diff --git a/src/components/DetailScheduleDetail/ViewByBomDetails.tsx b/src/components/DetailScheduleDetail/ViewByBomDetails.tsx index 2d9ae8a..793bbc6 100644 --- a/src/components/DetailScheduleDetail/ViewByBomDetails.tsx +++ b/src/components/DetailScheduleDetail/ViewByBomDetails.tsx @@ -2,555 +2,1476 @@ import { CreateItemInputs } from "@/app/api/settings/item/actions"; import { - GridColDef, - GridRowModel, - GridRenderEditCellParams, - GridEditInputCell, - GridRowSelectionModel, - useGridApiRef, + GridColDef, + GridRowModel, + GridRenderEditCellParams, + GridEditInputCell, + GridRowSelectionModel, + useGridApiRef, } from "@mui/x-data-grid"; -import {MutableRefObject, useCallback, useEffect, useMemo, useState} from "react"; +import { + MutableRefObject, + useCallback, + useEffect, + useMemo, + useState, +} from "react"; import { useFormContext } from "react-hook-form"; import { useTranslation } from "react-i18next"; import InputDataGrid, { TableRow } from "../InputDataGrid/InputDataGrid"; -import {Box, Grid, Tooltip, Typography} from "@mui/material"; +import { Box, Grid, Tooltip, Typography } from "@mui/material"; import { ItemQc } from "@/app/api/settings/item"; import { QcChecksInputs } from "@/app/api/settings/qcCheck/actions"; import { GridApiCommunity } from "@mui/x-data-grid/internals"; import { RiceBowl } from "@mui/icons-material"; -import EditableSearchResults, {Column} from "@/components/SearchResults/EditableSearchResults"; +import EditableSearchResults, { + Column, +} from "@/components/SearchResults/EditableSearchResults"; import { decimalFormatter } from "@/app/utils/formatUtil"; import { GridRenderCellParams } from "@mui/x-data-grid"; type Props = { - apiRef: MutableRefObject + apiRef: MutableRefObject; }; type EntryError = - | { - [field in keyof QcChecksInputs]?: string; -} - | undefined; + | { + [field in keyof QcChecksInputs]?: string; + } + | undefined; export type FGRecord = { - id: string | number - code: string; - name: string; - inStockQty: number; - purchaseQty: number; -} + id: string | number; + code: string; + name: string; + inStockQty: number; + purchaseQty: number; +}; export type FGOverallRecord = { - id: string | number - code: string; - name: string; - type: string; - inStockQty: number; - purchaseQty: number; - purchaseQty1: number; - purchaseQty2: number; - purchaseQty3: number; - purchaseQty4: number; - purchaseQty5: number; - purchaseQty6: number; - purchaseQty7: number; - overallPurchaseQty: number; -} + id: string | number; + code: string; + name: string; + type: string; + inStockQty: number; + purchaseQty: number; + purchaseQty1: number; + purchaseQty2: number; + purchaseQty3: number; + purchaseQty4: number; + purchaseQty5: number; + purchaseQty6: number; + purchaseQty7: number; + overallPurchaseQty: number; +}; const ViewByBomDetails: React.FC = ({ apiRef, isEdit }) => { - const { - t, - i18n: { language }, - } = useTranslation("schedule"); - - const { - formState: { errors, defaultValues, touchedFields }, - } = useFormContext(); -// const apiRef = useGridApiRef(); + const { + t, + i18n: { language }, + } = useTranslation("schedule"); - const dayPeriod = [ - '2025-05-11', - '2025-05-12', - '2025-05-13', - '2025-05-14', - '2025-05-15', - '2025-05-16', - '2025-05-17', - ]; + const { + formState: { errors, defaultValues, touchedFields }, + } = useFormContext(); + // const apiRef = useGridApiRef(); - const fakeRecords = useMemo( - () => [ - [ - { id: 1, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 54.44 , purchaseQty: 972.12 }, - { id: 2, code: "GI3236", type: "Material", name: "清水(煮過牛腩)", inStockQty: 317.52 , purchaseQty: 3175.2 }, - { id: 3, code: "MG1700", type: "Material", name: "STERILTOM 意大利茄粒", inStockQty: 9.00 , purchaseQty: 90 }, - { id: 4, code: "FA0533", type: "Material", name: "乾蔥茸", inStockQty: 6.04 , purchaseQty: 60.4 }, - { id: 5, code: "FA0210", type: "Material", name: "薑茸", inStockQty: 6.04 , purchaseQty: 66.45 }, - { id: 6, code: "FA0608", type: "Material", name: "粗蒜茸", inStockQty: 6.04 , purchaseQty: 78.55 }, - { id: 7, code: "FA0056", type: "Material", name: "洋蔥肉", inStockQty: 241.98 , purchaseQty: 2419.8 }, - { id: 8, code: "PP1188", type: "Material", name: "咖喱膽", inStockQty: 36.00 , purchaseQty: 0 }, - { id: 9, code: "PP8001", type: "Material", name: "咖哩汁箱料粉", inStockQty: 77.42 , purchaseQty: 774.2 }, - { id: 10, code: "PP1096", type: "Material", name: "白麵撈", inStockQty: 60.00 , purchaseQty: 0 }, - { id: 11, code: "NA0476", type: "Material", name: "2磅份量三邊覆合袋 (0.1x225x260mm)個計", inStockQty: 600.00 , purchaseQty: 6000 }, - { id: 12, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 972.12 }, - { id: 13, code: "FA0161", type: "Material", name: "洋蔥粒", inStockQty: 0, purchaseQty: 28.15 }, - { id: 14, code: "MG1288", type: "Material", name: "炸紅蔥頭", inStockQty: 0, purchaseQty: 6.05 }, - { id: 15, code: "MG0066", type: "Material", name: "咖哩料(5斤x16包+2斤/包)", inStockQty: 0, purchaseQty: 241.98 }, - { id: 16, code: "MH0040", type: "Material", name: "星加坡綠富貴花牌幼白麵粉 (50磅/包)", inStockQty: 0, purchaseQty: 250.00 }, - ], - [ - { id: 1, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 54.44 , purchaseQty: 972.12 }, - { id: 2, code: "GI3236", type: "Material", name: "清水(煮過牛腩)", inStockQty: 317.52 , purchaseQty: 3175.2 }, - { id: 3, code: "MG1700", type: "Material", name: "STERILTOM 意大利茄粒", inStockQty: 9.00 , purchaseQty: 90 }, - { id: 4, code: "FA0533", type: "Material", name: "乾蔥茸", inStockQty: 6.04 , purchaseQty: 60.4 }, - { id: 5, code: "FA0210", type: "Material", name: "薑茸", inStockQty: 6.04 , purchaseQty: 66.45 }, - { id: 6, code: "FA0608", type: "Material", name: "粗蒜茸", inStockQty: 6.04 , purchaseQty: 78.55 }, - { id: 7, code: "FA0056", type: "Material", name: "洋蔥肉", inStockQty: 241.98 , purchaseQty: 2419.8 }, - { id: 8, code: "PP1188", type: "Material", name: "咖喱膽", inStockQty: 36.00 , purchaseQty: 0 }, - { id: 9, code: "PP8001", type: "Material", name: "咖哩汁箱料粉", inStockQty: 77.42 , purchaseQty: 774.2 }, - { id: 10, code: "PP1096", type: "Material", name: "白麵撈", inStockQty: 60.00 , purchaseQty: 0 }, - { id: 11, code: "NA0476", type: "Material", name: "2磅份量三邊覆合袋 (0.1x225x260mm)個計", inStockQty: 600.00 , purchaseQty: 6000 }, - { id: 12, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 972.12 }, - { id: 13, code: "FA0161", type: "Material", name: "洋蔥粒", inStockQty: 0, purchaseQty: 28.15 }, - { id: 14, code: "MG1288", type: "Material", name: "炸紅蔥頭", inStockQty: 0, purchaseQty: 6.05 }, - { id: 15, code: "MG0066", type: "Material", name: "咖哩料(5斤x16包+2斤/包)", inStockQty: 0, purchaseQty: 241.98 }, - { id: 16, code: "MH0040", type: "Material", name: "星加坡綠富貴花牌幼白麵粉 (50磅/包)", inStockQty: 0, purchaseQty: 250.00 }, - ], - [ - { id: 1, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 54.44 , purchaseQty: 972.12 }, - { id: 2, code: "GI3236", type: "Material", name: "清水(煮過牛腩)", inStockQty: 317.52 , purchaseQty: 3175.2 }, - { id: 3, code: "MG1700", type: "Material", name: "STERILTOM 意大利茄粒", inStockQty: 9.00 , purchaseQty: 90 }, - { id: 4, code: "FA0533", type: "Material", name: "乾蔥茸", inStockQty: 6.04 , purchaseQty: 60.4 }, - { id: 5, code: "FA0210", type: "Material", name: "薑茸", inStockQty: 6.04 , purchaseQty: 66.45 }, - { id: 6, code: "FA0608", type: "Material", name: "粗蒜茸", inStockQty: 6.04 , purchaseQty: 78.55 }, - { id: 7, code: "FA0056", type: "Material", name: "洋蔥肉", inStockQty: 241.98 , purchaseQty: 2419.8 }, - { id: 8, code: "PP1188", type: "Material", name: "咖喱膽", inStockQty: 36.00 , purchaseQty: 0 }, - { id: 9, code: "PP8001", type: "Material", name: "咖哩汁箱料粉", inStockQty: 77.42 , purchaseQty: 774.2 }, - { id: 10, code: "PP1096", type: "Material", name: "白麵撈", inStockQty: 60.00 , purchaseQty: 0 }, - { id: 11, code: "NA0476", type: "Material", name: "2磅份量三邊覆合袋 (0.1x225x260mm)個計", inStockQty: 600.00 , purchaseQty: 6000 }, - { id: 12, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 972.12 }, - { id: 13, code: "FA0161", type: "Material", name: "洋蔥粒", inStockQty: 0, purchaseQty: 28.15 }, - { id: 14, code: "MG1288", type: "Material", name: "炸紅蔥頭", inStockQty: 0, purchaseQty: 6.05 }, - { id: 15, code: "MG0066", type: "Material", name: "咖哩料(5斤x16包+2斤/包)", inStockQty: 0, purchaseQty: 241.98 }, - { id: 16, code: "MH0040", type: "Material", name: "星加坡綠富貴花牌幼白麵粉 (50磅/包)", inStockQty: 0, purchaseQty: 250.00 }, - ], - [ - { id: 1, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 54.44 , purchaseQty: 972.12 }, - { id: 2, code: "GI3236", type: "Material", name: "清水(煮過牛腩)", inStockQty: 317.52 , purchaseQty: 3175.2 }, - { id: 3, code: "MG1700", type: "Material", name: "STERILTOM 意大利茄粒", inStockQty: 9.00 , purchaseQty: 90 }, - { id: 4, code: "FA0533", type: "Material", name: "乾蔥茸", inStockQty: 6.04 , purchaseQty: 60.4 }, - { id: 5, code: "FA0210", type: "Material", name: "薑茸", inStockQty: 6.04 , purchaseQty: 66.45 }, - { id: 6, code: "FA0608", type: "Material", name: "粗蒜茸", inStockQty: 6.04 , purchaseQty: 78.55 }, - { id: 7, code: "FA0056", type: "Material", name: "洋蔥肉", inStockQty: 241.98 , purchaseQty: 2419.8 }, - { id: 8, code: "PP1188", type: "Material", name: "咖喱膽", inStockQty: 36.00 , purchaseQty: 0 }, - { id: 9, code: "PP8001", type: "Material", name: "咖哩汁箱料粉", inStockQty: 77.42 , purchaseQty: 774.2 }, - { id: 10, code: "PP1096", type: "Material", name: "白麵撈", inStockQty: 60.00 , purchaseQty: 0 }, - { id: 11, code: "NA0476", type: "Material", name: "2磅份量三邊覆合袋 (0.1x225x260mm)個計", inStockQty: 600.00 , purchaseQty: 6000 }, - { id: 12, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 972.12 }, - { id: 13, code: "FA0161", type: "Material", name: "洋蔥粒", inStockQty: 0, purchaseQty: 28.15 }, - { id: 14, code: "MG1288", type: "Material", name: "炸紅蔥頭", inStockQty: 0, purchaseQty: 6.05 }, - { id: 15, code: "MG0066", type: "Material", name: "咖哩料(5斤x16包+2斤/包)", inStockQty: 0, purchaseQty: 241.98 }, - { id: 16, code: "MH0040", type: "Material", name: "星加坡綠富貴花牌幼白麵粉 (50磅/包)", inStockQty: 0, purchaseQty: 250.00 }, - ], - [ - { id: 1, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 54.44 , purchaseQty: 972.12 }, - { id: 2, code: "GI3236", type: "Material", name: "清水(煮過牛腩)", inStockQty: 317.52 , purchaseQty: 3175.2 }, - { id: 3, code: "MG1700", type: "Material", name: "STERILTOM 意大利茄粒", inStockQty: 9.00 , purchaseQty: 90 }, - { id: 4, code: "FA0533", type: "Material", name: "乾蔥茸", inStockQty: 6.04 , purchaseQty: 60.4 }, - { id: 5, code: "FA0210", type: "Material", name: "薑茸", inStockQty: 6.04 , purchaseQty: 66.45 }, - { id: 6, code: "FA0608", type: "Material", name: "粗蒜茸", inStockQty: 6.04 , purchaseQty: 78.55 }, - { id: 7, code: "FA0056", type: "Material", name: "洋蔥肉", inStockQty: 241.98 , purchaseQty: 2419.8 }, - { id: 8, code: "PP1188", type: "Material", name: "咖喱膽", inStockQty: 36.00 , purchaseQty: 0 }, - { id: 9, code: "PP8001", type: "Material", name: "咖哩汁箱料粉", inStockQty: 77.42 , purchaseQty: 774.2 }, - { id: 10, code: "PP1096", type: "Material", name: "白麵撈", inStockQty: 60.00 , purchaseQty: 0 }, - { id: 11, code: "NA0476", type: "Material", name: "2磅份量三邊覆合袋 (0.1x225x260mm)個計", inStockQty: 600.00 , purchaseQty: 6000 }, - { id: 12, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 972.12 }, - { id: 13, code: "FA0161", type: "Material", name: "洋蔥粒", inStockQty: 0, purchaseQty: 28.15 }, - { id: 14, code: "MG1288", type: "Material", name: "炸紅蔥頭", inStockQty: 0, purchaseQty: 6.05 }, - { id: 15, code: "MG0066", type: "Material", name: "咖哩料(5斤x16包+2斤/包)", inStockQty: 0, purchaseQty: 241.98 }, - { id: 16, code: "MH0040", type: "Material", name: "星加坡綠富貴花牌幼白麵粉 (50磅/包)", inStockQty: 0, purchaseQty: 250.00 }, - ], - [ - { id: 1, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 54.44 , purchaseQty: 972.12 }, - { id: 2, code: "GI3236", type: "Material", name: "清水(煮過牛腩)", inStockQty: 317.52 , purchaseQty: 3175.2 }, - { id: 3, code: "MG1700", type: "Material", name: "STERILTOM 意大利茄粒", inStockQty: 9.00 , purchaseQty: 90 }, - { id: 4, code: "FA0533", type: "Material", name: "乾蔥茸", inStockQty: 6.04 , purchaseQty: 60.4 }, - { id: 5, code: "FA0210", type: "Material", name: "薑茸", inStockQty: 6.04 , purchaseQty: 66.45 }, - { id: 6, code: "FA0608", type: "Material", name: "粗蒜茸", inStockQty: 6.04 , purchaseQty: 78.55 }, - { id: 7, code: "FA0056", type: "Material", name: "洋蔥肉", inStockQty: 241.98 , purchaseQty: 2419.8 }, - { id: 8, code: "PP1188", type: "Material", name: "咖喱膽", inStockQty: 36.00 , purchaseQty: 0 }, - { id: 9, code: "PP8001", type: "Material", name: "咖哩汁箱料粉", inStockQty: 77.42 , purchaseQty: 774.2 }, - { id: 10, code: "PP1096", type: "Material", name: "白麵撈", inStockQty: 60.00 , purchaseQty: 0 }, - { id: 11, code: "NA0476", type: "Material", name: "2磅份量三邊覆合袋 (0.1x225x260mm)個計", inStockQty: 600.00 , purchaseQty: 6000 }, - { id: 12, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 972.12 }, - { id: 13, code: "FA0161", type: "Material", name: "洋蔥粒", inStockQty: 0, purchaseQty: 28.15 }, - { id: 14, code: "MG1288", type: "Material", name: "炸紅蔥頭", inStockQty: 0, purchaseQty: 6.05 }, - { id: 15, code: "MG0066", type: "Material", name: "咖哩料(5斤x16包+2斤/包)", inStockQty: 0, purchaseQty: 241.98 }, - { id: 16, code: "MH0040", type: "Material", name: "星加坡綠富貴花牌幼白麵粉 (50磅/包)", inStockQty: 0, purchaseQty: 250.00 }, - ], - [ - { id: 1, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 54.44 , purchaseQty: 972.12 }, - { id: 2, code: "GI3236", type: "Material", name: "清水(煮過牛腩)", inStockQty: 317.52 , purchaseQty: 3175.2 }, - { id: 3, code: "MG1700", type: "Material", name: "STERILTOM 意大利茄粒", inStockQty: 9.00 , purchaseQty: 90 }, - { id: 4, code: "FA0533", type: "Material", name: "乾蔥茸", inStockQty: 6.04 , purchaseQty: 60.4 }, - { id: 5, code: "FA0210", type: "Material", name: "薑茸", inStockQty: 6.04 , purchaseQty: 66.45 }, - { id: 6, code: "FA0608", type: "Material", name: "粗蒜茸", inStockQty: 6.04 , purchaseQty: 78.55 }, - { id: 7, code: "FA0056", type: "Material", name: "洋蔥肉", inStockQty: 241.98 , purchaseQty: 2419.8 }, - { id: 8, code: "PP1188", type: "Material", name: "咖喱膽", inStockQty: 36.00 , purchaseQty: 0 }, - { id: 9, code: "PP8001", type: "Material", name: "咖哩汁箱料粉", inStockQty: 77.42 , purchaseQty: 774.2 }, - { id: 10, code: "PP1096", type: "Material", name: "白麵撈", inStockQty: 60.00 , purchaseQty: 0 }, - { id: 11, code: "NA0476", type: "Material", name: "2磅份量三邊覆合袋 (0.1x225x260mm)個計", inStockQty: 600.00 , purchaseQty: 6000 }, - { id: 12, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 972.12 }, - { id: 13, code: "FA0161", type: "Material", name: "洋蔥粒", inStockQty: 0, purchaseQty: 28.15 }, - { id: 14, code: "MG1288", type: "Material", name: "炸紅蔥頭", inStockQty: 0, purchaseQty: 6.05 }, - { id: 15, code: "MG0066", type: "Material", name: "咖哩料(5斤x16包+2斤/包)", inStockQty: 0, purchaseQty: 241.98 }, - { id: 16, code: "MH0040", type: "Material", name: "星加坡綠富貴花牌幼白麵粉 (50磅/包)", inStockQty: 0, purchaseQty: 250.00 }, - ], - ], - [] - ); + const dayPeriod = [ + "2025-05-11", + "2025-05-12", + "2025-05-13", + "2025-05-14", + "2025-05-15", + "2025-05-16", + "2025-05-17", + ]; - const fakeOverallRecords = useMemo( - () => [ - { id: 1, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 54.44 , - purchaseQty1: 972.12, purchaseQty2: 972.12, purchaseQty3: 972.12, - purchaseQty4: 972.12, purchaseQty5: 972.12, purchaseQty6: 972.12, - purchaseQty7: 972.12, overallPurchaseQty: 6804.84 - }, - { id: 2, code: "GI3236", type: "Material", name: "清水(煮過牛腩)", inStockQty: 317.52 , - purchaseQty1: 3175.2, purchaseQty2: 3175.2, purchaseQty3: 3175.2, - purchaseQty4: 3175.2, purchaseQty5: 3175.2, purchaseQty6: 3175.2, - purchaseQty7: 3175.2, overallPurchaseQty: 22226.4 - }, - { id: 3, code: "MG1700", type: "Material", name: "STERILTOM 意大利茄粒", inStockQty: 9.00 , - purchaseQty1: 90, purchaseQty2: 90, purchaseQty3: 90, - purchaseQty4: 90, purchaseQty5: 90, purchaseQty6: 90, - purchaseQty7: 90, overallPurchaseQty: 630 - }, - { id: 4, code: "FA0533", type: "Material", name: "乾蔥茸", inStockQty: 6.04 , - purchaseQty1: 60.4, purchaseQty2: 60.4, purchaseQty3: 60.4, - purchaseQty4: 60.4, purchaseQty5: 60.4, purchaseQty6: 60.4, - purchaseQty7: 60.4, overallPurchaseQty: 422.8 - }, - { id: 5, code: "FA0210", type: "Material", name: "薑茸", inStockQty: 6.04 , - purchaseQty1: 66.45, purchaseQty2: 66.45, purchaseQty3: 66.45, - purchaseQty4: 66.45, purchaseQty5: 66.45, purchaseQty6: 66.45, - purchaseQty7: 66.45, overallPurchaseQty: 465.15 - }, - { id: 6, code: "FA0608", type: "Material", name: "粗蒜茸", inStockQty: 6.04 , - purchaseQty1: 78.55, purchaseQty2: 78.55, purchaseQty3: 78.55, - purchaseQty4: 78.55, purchaseQty5: 78.55, purchaseQty6: 78.55, - purchaseQty7: 78.55, overallPurchaseQty: 549.85 - }, - { id: 7, code: "FA0056", type: "Material", name: "洋蔥肉", inStockQty: 241.98 , purchaseQty: 2419.8 }, - { id: 8, code: "PP1188", type: "Material", name: "咖喱膽", inStockQty: 36.00 , purchaseQty: 0 }, - { id: 9, code: "PP8001", type: "Material", name: "咖哩汁箱料粉", inStockQty: 77.42 , purchaseQty: 774.2 }, - { id: 10, code: "PP1096", type: "Material", name: "白麵撈", inStockQty: 60.00 , purchaseQty: 0 }, - { id: 11, code: "NA0476", type: "Material", name: "2磅份量三邊覆合袋 (0.1x225x260mm)個計", inStockQty: 600.00 , purchaseQty: 6000 }, - { id: 12, code: "MH0040",type: "Material", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 972.12 }, - { id: 13, code: "FA0161",type: "Material", name: "洋蔥粒", inStockQty: 0, purchaseQty: 28.15 }, - { id: 14, code: "MG1288", type: "Material",name: "炸紅蔥頭", inStockQty: 0, purchaseQty: 6.05 }, - { id: 15, code: "MG0066", type: "Material",name: "咖哩料(5斤x16包+2斤/包)", inStockQty: 0, purchaseQty: 241.98 }, - { id: 16, code: "MH0040", type: "Material",name: "星加坡綠富貴花牌幼白麵粉 (50磅/包)", inStockQty: 0, purchaseQty: 250.00 }, - ], - [] - ); - - const [pagingController, setPagingController] = useState([ + const fakeRecords = useMemo( + () => [ + [ + { + id: 1, + code: "MH0040", + type: "Material", + name: "大豆油(1噸/桶)", + inStockQty: 54.44, + purchaseQty: 972.12, + }, + { + id: 2, + code: "GI3236", + type: "Material", + name: "清水(煮過牛腩)", + inStockQty: 317.52, + purchaseQty: 3175.2, + }, + { + id: 3, + code: "MG1700", + type: "Material", + name: "STERILTOM 意大利茄粒", + inStockQty: 9.0, + purchaseQty: 90, + }, + { + id: 4, + code: "FA0533", + type: "Material", + name: "乾蔥茸", + inStockQty: 6.04, + purchaseQty: 60.4, + }, + { + id: 5, + code: "FA0210", + type: "Material", + name: "薑茸", + inStockQty: 6.04, + purchaseQty: 66.45, + }, + { + id: 6, + code: "FA0608", + type: "Material", + name: "粗蒜茸", + inStockQty: 6.04, + purchaseQty: 78.55, + }, + { + id: 7, + code: "FA0056", + type: "Material", + name: "洋蔥肉", + inStockQty: 241.98, + purchaseQty: 2419.8, + }, + { + id: 8, + code: "PP1188", + type: "Material", + name: "咖喱膽", + inStockQty: 36.0, + purchaseQty: 0, + }, + { + id: 9, + code: "PP8001", + type: "Material", + name: "咖哩汁箱料粉", + inStockQty: 77.42, + purchaseQty: 774.2, + }, + { + id: 10, + code: "PP1096", + type: "Material", + name: "白麵撈", + inStockQty: 60.0, + purchaseQty: 0, + }, + { + id: 11, + code: "NA0476", + type: "Material", + name: "2磅份量三邊覆合袋 (0.1x225x260mm)個計", + inStockQty: 600.0, + purchaseQty: 6000, + }, + { + id: 12, + code: "MH0040", + type: "Material", + name: "大豆油(1噸/桶)", + inStockQty: 0, + purchaseQty: 972.12, + }, + { + id: 13, + code: "FA0161", + type: "Material", + name: "洋蔥粒", + inStockQty: 0, + purchaseQty: 28.15, + }, + { + id: 14, + code: "MG1288", + type: "Material", + name: "炸紅蔥頭", + inStockQty: 0, + purchaseQty: 6.05, + }, + { + id: 15, + code: "MG0066", + type: "Material", + name: "咖哩料(5斤x16包+2斤/包)", + inStockQty: 0, + purchaseQty: 241.98, + }, + { + id: 16, + code: "MH0040", + type: "Material", + name: "星加坡綠富貴花牌幼白麵粉 (50磅/包)", + inStockQty: 0, + purchaseQty: 250.0, + }, + ], + [ + { + id: 1, + code: "MH0040", + type: "Material", + name: "大豆油(1噸/桶)", + inStockQty: 54.44, + purchaseQty: 972.12, + }, + { + id: 2, + code: "GI3236", + type: "Material", + name: "清水(煮過牛腩)", + inStockQty: 317.52, + purchaseQty: 3175.2, + }, + { + id: 3, + code: "MG1700", + type: "Material", + name: "STERILTOM 意大利茄粒", + inStockQty: 9.0, + purchaseQty: 90, + }, + { + id: 4, + code: "FA0533", + type: "Material", + name: "乾蔥茸", + inStockQty: 6.04, + purchaseQty: 60.4, + }, + { + id: 5, + code: "FA0210", + type: "Material", + name: "薑茸", + inStockQty: 6.04, + purchaseQty: 66.45, + }, + { + id: 6, + code: "FA0608", + type: "Material", + name: "粗蒜茸", + inStockQty: 6.04, + purchaseQty: 78.55, + }, + { + id: 7, + code: "FA0056", + type: "Material", + name: "洋蔥肉", + inStockQty: 241.98, + purchaseQty: 2419.8, + }, + { + id: 8, + code: "PP1188", + type: "Material", + name: "咖喱膽", + inStockQty: 36.0, + purchaseQty: 0, + }, + { + id: 9, + code: "PP8001", + type: "Material", + name: "咖哩汁箱料粉", + inStockQty: 77.42, + purchaseQty: 774.2, + }, + { + id: 10, + code: "PP1096", + type: "Material", + name: "白麵撈", + inStockQty: 60.0, + purchaseQty: 0, + }, + { + id: 11, + code: "NA0476", + type: "Material", + name: "2磅份量三邊覆合袋 (0.1x225x260mm)個計", + inStockQty: 600.0, + purchaseQty: 6000, + }, + { + id: 12, + code: "MH0040", + type: "Material", + name: "大豆油(1噸/桶)", + inStockQty: 0, + purchaseQty: 972.12, + }, + { + id: 13, + code: "FA0161", + type: "Material", + name: "洋蔥粒", + inStockQty: 0, + purchaseQty: 28.15, + }, + { + id: 14, + code: "MG1288", + type: "Material", + name: "炸紅蔥頭", + inStockQty: 0, + purchaseQty: 6.05, + }, + { + id: 15, + code: "MG0066", + type: "Material", + name: "咖哩料(5斤x16包+2斤/包)", + inStockQty: 0, + purchaseQty: 241.98, + }, + { + id: 16, + code: "MH0040", + type: "Material", + name: "星加坡綠富貴花牌幼白麵粉 (50磅/包)", + inStockQty: 0, + purchaseQty: 250.0, + }, + ], + [ + { + id: 1, + code: "MH0040", + type: "Material", + name: "大豆油(1噸/桶)", + inStockQty: 54.44, + purchaseQty: 972.12, + }, + { + id: 2, + code: "GI3236", + type: "Material", + name: "清水(煮過牛腩)", + inStockQty: 317.52, + purchaseQty: 3175.2, + }, + { + id: 3, + code: "MG1700", + type: "Material", + name: "STERILTOM 意大利茄粒", + inStockQty: 9.0, + purchaseQty: 90, + }, + { + id: 4, + code: "FA0533", + type: "Material", + name: "乾蔥茸", + inStockQty: 6.04, + purchaseQty: 60.4, + }, + { + id: 5, + code: "FA0210", + type: "Material", + name: "薑茸", + inStockQty: 6.04, + purchaseQty: 66.45, + }, + { + id: 6, + code: "FA0608", + type: "Material", + name: "粗蒜茸", + inStockQty: 6.04, + purchaseQty: 78.55, + }, + { + id: 7, + code: "FA0056", + type: "Material", + name: "洋蔥肉", + inStockQty: 241.98, + purchaseQty: 2419.8, + }, + { + id: 8, + code: "PP1188", + type: "Material", + name: "咖喱膽", + inStockQty: 36.0, + purchaseQty: 0, + }, + { + id: 9, + code: "PP8001", + type: "Material", + name: "咖哩汁箱料粉", + inStockQty: 77.42, + purchaseQty: 774.2, + }, + { + id: 10, + code: "PP1096", + type: "Material", + name: "白麵撈", + inStockQty: 60.0, + purchaseQty: 0, + }, + { + id: 11, + code: "NA0476", + type: "Material", + name: "2磅份量三邊覆合袋 (0.1x225x260mm)個計", + inStockQty: 600.0, + purchaseQty: 6000, + }, + { + id: 12, + code: "MH0040", + type: "Material", + name: "大豆油(1噸/桶)", + inStockQty: 0, + purchaseQty: 972.12, + }, + { + id: 13, + code: "FA0161", + type: "Material", + name: "洋蔥粒", + inStockQty: 0, + purchaseQty: 28.15, + }, + { + id: 14, + code: "MG1288", + type: "Material", + name: "炸紅蔥頭", + inStockQty: 0, + purchaseQty: 6.05, + }, + { + id: 15, + code: "MG0066", + type: "Material", + name: "咖哩料(5斤x16包+2斤/包)", + inStockQty: 0, + purchaseQty: 241.98, + }, + { + id: 16, + code: "MH0040", + type: "Material", + name: "星加坡綠富貴花牌幼白麵粉 (50磅/包)", + inStockQty: 0, + purchaseQty: 250.0, + }, + ], + [ + { + id: 1, + code: "MH0040", + type: "Material", + name: "大豆油(1噸/桶)", + inStockQty: 54.44, + purchaseQty: 972.12, + }, + { + id: 2, + code: "GI3236", + type: "Material", + name: "清水(煮過牛腩)", + inStockQty: 317.52, + purchaseQty: 3175.2, + }, + { + id: 3, + code: "MG1700", + type: "Material", + name: "STERILTOM 意大利茄粒", + inStockQty: 9.0, + purchaseQty: 90, + }, + { + id: 4, + code: "FA0533", + type: "Material", + name: "乾蔥茸", + inStockQty: 6.04, + purchaseQty: 60.4, + }, + { + id: 5, + code: "FA0210", + type: "Material", + name: "薑茸", + inStockQty: 6.04, + purchaseQty: 66.45, + }, + { + id: 6, + code: "FA0608", + type: "Material", + name: "粗蒜茸", + inStockQty: 6.04, + purchaseQty: 78.55, + }, + { + id: 7, + code: "FA0056", + type: "Material", + name: "洋蔥肉", + inStockQty: 241.98, + purchaseQty: 2419.8, + }, + { + id: 8, + code: "PP1188", + type: "Material", + name: "咖喱膽", + inStockQty: 36.0, + purchaseQty: 0, + }, + { + id: 9, + code: "PP8001", + type: "Material", + name: "咖哩汁箱料粉", + inStockQty: 77.42, + purchaseQty: 774.2, + }, { - pageNum: 1, - pageSize: 10, - totalCount: 0, + id: 10, + code: "PP1096", + type: "Material", + name: "白麵撈", + inStockQty: 60.0, + purchaseQty: 0, }, { - pageNum: 1, - pageSize: 10, - totalCount: 0, + id: 11, + code: "NA0476", + type: "Material", + name: "2磅份量三邊覆合袋 (0.1x225x260mm)個計", + inStockQty: 600.0, + purchaseQty: 6000, }, { - pageNum: 1, - pageSize: 10, - totalCount: 0, + id: 12, + code: "MH0040", + type: "Material", + name: "大豆油(1噸/桶)", + inStockQty: 0, + purchaseQty: 972.12, }, { - pageNum: 1, - pageSize: 10, - totalCount: 0, + id: 13, + code: "FA0161", + type: "Material", + name: "洋蔥粒", + inStockQty: 0, + purchaseQty: 28.15, }, { - pageNum: 1, - pageSize: 10, - totalCount: 0, + id: 14, + code: "MG1288", + type: "Material", + name: "炸紅蔥頭", + inStockQty: 0, + purchaseQty: 6.05, }, { - pageNum: 1, - pageSize: 10, - totalCount: 0, + id: 15, + code: "MG0066", + type: "Material", + name: "咖哩料(5斤x16包+2斤/包)", + inStockQty: 0, + purchaseQty: 241.98, }, { - pageNum: 1, - pageSize: 10, - totalCount: 0, + id: 16, + code: "MH0040", + type: "Material", + name: "星加坡綠富貴花牌幼白麵粉 (50磅/包)", + inStockQty: 0, + purchaseQty: 250.0, }, + ], + [ { - pageNum: 1, - pageSize: 10, - totalCount: 0, + id: 1, + code: "MH0040", + type: "Material", + name: "大豆油(1噸/桶)", + inStockQty: 54.44, + purchaseQty: 972.12, }, - ]) + { + id: 2, + code: "GI3236", + type: "Material", + name: "清水(煮過牛腩)", + inStockQty: 317.52, + purchaseQty: 3175.2, + }, + { + id: 3, + code: "MG1700", + type: "Material", + name: "STERILTOM 意大利茄粒", + inStockQty: 9.0, + purchaseQty: 90, + }, + { + id: 4, + code: "FA0533", + type: "Material", + name: "乾蔥茸", + inStockQty: 6.04, + purchaseQty: 60.4, + }, + { + id: 5, + code: "FA0210", + type: "Material", + name: "薑茸", + inStockQty: 6.04, + purchaseQty: 66.45, + }, + { + id: 6, + code: "FA0608", + type: "Material", + name: "粗蒜茸", + inStockQty: 6.04, + purchaseQty: 78.55, + }, + { + id: 7, + code: "FA0056", + type: "Material", + name: "洋蔥肉", + inStockQty: 241.98, + purchaseQty: 2419.8, + }, + { + id: 8, + code: "PP1188", + type: "Material", + name: "咖喱膽", + inStockQty: 36.0, + purchaseQty: 0, + }, + { + id: 9, + code: "PP8001", + type: "Material", + name: "咖哩汁箱料粉", + inStockQty: 77.42, + purchaseQty: 774.2, + }, + { + id: 10, + code: "PP1096", + type: "Material", + name: "白麵撈", + inStockQty: 60.0, + purchaseQty: 0, + }, + { + id: 11, + code: "NA0476", + type: "Material", + name: "2磅份量三邊覆合袋 (0.1x225x260mm)個計", + inStockQty: 600.0, + purchaseQty: 6000, + }, + { + id: 12, + code: "MH0040", + type: "Material", + name: "大豆油(1噸/桶)", + inStockQty: 0, + purchaseQty: 972.12, + }, + { + id: 13, + code: "FA0161", + type: "Material", + name: "洋蔥粒", + inStockQty: 0, + purchaseQty: 28.15, + }, + { + id: 14, + code: "MG1288", + type: "Material", + name: "炸紅蔥頭", + inStockQty: 0, + purchaseQty: 6.05, + }, + { + id: 15, + code: "MG0066", + type: "Material", + name: "咖哩料(5斤x16包+2斤/包)", + inStockQty: 0, + purchaseQty: 241.98, + }, + { + id: 16, + code: "MH0040", + type: "Material", + name: "星加坡綠富貴花牌幼白麵粉 (50磅/包)", + inStockQty: 0, + purchaseQty: 250.0, + }, + ], + [ + { + id: 1, + code: "MH0040", + type: "Material", + name: "大豆油(1噸/桶)", + inStockQty: 54.44, + purchaseQty: 972.12, + }, + { + id: 2, + code: "GI3236", + type: "Material", + name: "清水(煮過牛腩)", + inStockQty: 317.52, + purchaseQty: 3175.2, + }, + { + id: 3, + code: "MG1700", + type: "Material", + name: "STERILTOM 意大利茄粒", + inStockQty: 9.0, + purchaseQty: 90, + }, + { + id: 4, + code: "FA0533", + type: "Material", + name: "乾蔥茸", + inStockQty: 6.04, + purchaseQty: 60.4, + }, + { + id: 5, + code: "FA0210", + type: "Material", + name: "薑茸", + inStockQty: 6.04, + purchaseQty: 66.45, + }, + { + id: 6, + code: "FA0608", + type: "Material", + name: "粗蒜茸", + inStockQty: 6.04, + purchaseQty: 78.55, + }, + { + id: 7, + code: "FA0056", + type: "Material", + name: "洋蔥肉", + inStockQty: 241.98, + purchaseQty: 2419.8, + }, + { + id: 8, + code: "PP1188", + type: "Material", + name: "咖喱膽", + inStockQty: 36.0, + purchaseQty: 0, + }, + { + id: 9, + code: "PP8001", + type: "Material", + name: "咖哩汁箱料粉", + inStockQty: 77.42, + purchaseQty: 774.2, + }, + { + id: 10, + code: "PP1096", + type: "Material", + name: "白麵撈", + inStockQty: 60.0, + purchaseQty: 0, + }, + { + id: 11, + code: "NA0476", + type: "Material", + name: "2磅份量三邊覆合袋 (0.1x225x260mm)個計", + inStockQty: 600.0, + purchaseQty: 6000, + }, + { + id: 12, + code: "MH0040", + type: "Material", + name: "大豆油(1噸/桶)", + inStockQty: 0, + purchaseQty: 972.12, + }, + { + id: 13, + code: "FA0161", + type: "Material", + name: "洋蔥粒", + inStockQty: 0, + purchaseQty: 28.15, + }, + { + id: 14, + code: "MG1288", + type: "Material", + name: "炸紅蔥頭", + inStockQty: 0, + purchaseQty: 6.05, + }, + { + id: 15, + code: "MG0066", + type: "Material", + name: "咖哩料(5斤x16包+2斤/包)", + inStockQty: 0, + purchaseQty: 241.98, + }, + { + id: 16, + code: "MH0040", + type: "Material", + name: "星加坡綠富貴花牌幼白麵粉 (50磅/包)", + inStockQty: 0, + purchaseQty: 250.0, + }, + ], + [ + { + id: 1, + code: "MH0040", + type: "Material", + name: "大豆油(1噸/桶)", + inStockQty: 54.44, + purchaseQty: 972.12, + }, + { + id: 2, + code: "GI3236", + type: "Material", + name: "清水(煮過牛腩)", + inStockQty: 317.52, + purchaseQty: 3175.2, + }, + { + id: 3, + code: "MG1700", + type: "Material", + name: "STERILTOM 意大利茄粒", + inStockQty: 9.0, + purchaseQty: 90, + }, + { + id: 4, + code: "FA0533", + type: "Material", + name: "乾蔥茸", + inStockQty: 6.04, + purchaseQty: 60.4, + }, + { + id: 5, + code: "FA0210", + type: "Material", + name: "薑茸", + inStockQty: 6.04, + purchaseQty: 66.45, + }, + { + id: 6, + code: "FA0608", + type: "Material", + name: "粗蒜茸", + inStockQty: 6.04, + purchaseQty: 78.55, + }, + { + id: 7, + code: "FA0056", + type: "Material", + name: "洋蔥肉", + inStockQty: 241.98, + purchaseQty: 2419.8, + }, + { + id: 8, + code: "PP1188", + type: "Material", + name: "咖喱膽", + inStockQty: 36.0, + purchaseQty: 0, + }, + { + id: 9, + code: "PP8001", + type: "Material", + name: "咖哩汁箱料粉", + inStockQty: 77.42, + purchaseQty: 774.2, + }, + { + id: 10, + code: "PP1096", + type: "Material", + name: "白麵撈", + inStockQty: 60.0, + purchaseQty: 0, + }, + { + id: 11, + code: "NA0476", + type: "Material", + name: "2磅份量三邊覆合袋 (0.1x225x260mm)個計", + inStockQty: 600.0, + purchaseQty: 6000, + }, + { + id: 12, + code: "MH0040", + type: "Material", + name: "大豆油(1噸/桶)", + inStockQty: 0, + purchaseQty: 972.12, + }, + { + id: 13, + code: "FA0161", + type: "Material", + name: "洋蔥粒", + inStockQty: 0, + purchaseQty: 28.15, + }, + { + id: 14, + code: "MG1288", + type: "Material", + name: "炸紅蔥頭", + inStockQty: 0, + purchaseQty: 6.05, + }, + { + id: 15, + code: "MG0066", + type: "Material", + name: "咖哩料(5斤x16包+2斤/包)", + inStockQty: 0, + purchaseQty: 241.98, + }, + { + id: 16, + code: "MH0040", + type: "Material", + name: "星加坡綠富貴花牌幼白麵粉 (50磅/包)", + inStockQty: 0, + purchaseQty: 250.0, + }, + ], + ], + [], + ); + + const fakeOverallRecords = useMemo( + () => [ + { + id: 1, + code: "MH0040", + type: "Material", + name: "大豆油(1噸/桶)", + inStockQty: 54.44, + purchaseQty1: 972.12, + purchaseQty2: 972.12, + purchaseQty3: 972.12, + purchaseQty4: 972.12, + purchaseQty5: 972.12, + purchaseQty6: 972.12, + purchaseQty7: 972.12, + overallPurchaseQty: 6804.84, + }, + { + id: 2, + code: "GI3236", + type: "Material", + name: "清水(煮過牛腩)", + inStockQty: 317.52, + purchaseQty1: 3175.2, + purchaseQty2: 3175.2, + purchaseQty3: 3175.2, + purchaseQty4: 3175.2, + purchaseQty5: 3175.2, + purchaseQty6: 3175.2, + purchaseQty7: 3175.2, + overallPurchaseQty: 22226.4, + }, + { + id: 3, + code: "MG1700", + type: "Material", + name: "STERILTOM 意大利茄粒", + inStockQty: 9.0, + purchaseQty1: 90, + purchaseQty2: 90, + purchaseQty3: 90, + purchaseQty4: 90, + purchaseQty5: 90, + purchaseQty6: 90, + purchaseQty7: 90, + overallPurchaseQty: 630, + }, + { + id: 4, + code: "FA0533", + type: "Material", + name: "乾蔥茸", + inStockQty: 6.04, + purchaseQty1: 60.4, + purchaseQty2: 60.4, + purchaseQty3: 60.4, + purchaseQty4: 60.4, + purchaseQty5: 60.4, + purchaseQty6: 60.4, + purchaseQty7: 60.4, + overallPurchaseQty: 422.8, + }, + { + id: 5, + code: "FA0210", + type: "Material", + name: "薑茸", + inStockQty: 6.04, + purchaseQty1: 66.45, + purchaseQty2: 66.45, + purchaseQty3: 66.45, + purchaseQty4: 66.45, + purchaseQty5: 66.45, + purchaseQty6: 66.45, + purchaseQty7: 66.45, + overallPurchaseQty: 465.15, + }, + { + id: 6, + code: "FA0608", + type: "Material", + name: "粗蒜茸", + inStockQty: 6.04, + purchaseQty1: 78.55, + purchaseQty2: 78.55, + purchaseQty3: 78.55, + purchaseQty4: 78.55, + purchaseQty5: 78.55, + purchaseQty6: 78.55, + purchaseQty7: 78.55, + overallPurchaseQty: 549.85, + }, + { + id: 7, + code: "FA0056", + type: "Material", + name: "洋蔥肉", + inStockQty: 241.98, + purchaseQty: 2419.8, + }, + { + id: 8, + code: "PP1188", + type: "Material", + name: "咖喱膽", + inStockQty: 36.0, + purchaseQty: 0, + }, + { + id: 9, + code: "PP8001", + type: "Material", + name: "咖哩汁箱料粉", + inStockQty: 77.42, + purchaseQty: 774.2, + }, + { + id: 10, + code: "PP1096", + type: "Material", + name: "白麵撈", + inStockQty: 60.0, + purchaseQty: 0, + }, + { + id: 11, + code: "NA0476", + type: "Material", + name: "2磅份量三邊覆合袋 (0.1x225x260mm)個計", + inStockQty: 600.0, + purchaseQty: 6000, + }, + { + id: 12, + code: "MH0040", + type: "Material", + name: "大豆油(1噸/桶)", + inStockQty: 0, + purchaseQty: 972.12, + }, + { + id: 13, + code: "FA0161", + type: "Material", + name: "洋蔥粒", + inStockQty: 0, + purchaseQty: 28.15, + }, + { + id: 14, + code: "MG1288", + type: "Material", + name: "炸紅蔥頭", + inStockQty: 0, + purchaseQty: 6.05, + }, + { + id: 15, + code: "MG0066", + type: "Material", + name: "咖哩料(5斤x16包+2斤/包)", + inStockQty: 0, + purchaseQty: 241.98, + }, + { + id: 16, + code: "MH0040", + type: "Material", + name: "星加坡綠富貴花牌幼白麵粉 (50磅/包)", + inStockQty: 0, + purchaseQty: 250.0, + }, + ], + [], + ); - const updatePagingController = (updatedObj) => { - setPagingController((prevState) => { - return prevState.map((item, index) => { - if (index === updatedObj?.index){ - return { - ...item, - pageNum: item.pageNum, - pageSize: item.pageSize, - totalCount: item.totalCount, - }; - } - else - return item - }); - }); - }; + const [pagingController, setPagingController] = useState([ + { + pageNum: 1, + pageSize: 10, + totalCount: 0, + }, + { + pageNum: 1, + pageSize: 10, + totalCount: 0, + }, + { + pageNum: 1, + pageSize: 10, + totalCount: 0, + }, + { + pageNum: 1, + pageSize: 10, + totalCount: 0, + }, + { + pageNum: 1, + pageSize: 10, + totalCount: 0, + }, + { + pageNum: 1, + pageSize: 10, + totalCount: 0, + }, + { + pageNum: 1, + pageSize: 10, + totalCount: 0, + }, + { + pageNum: 1, + pageSize: 10, + totalCount: 0, + }, + ]); - const overallColumns = useMemo[]>( - () => [ - { - field: "code", - label: t("code"), - type: 'read-only', - // editable: true, - }, - { - field: "name", - label: t("name"), - type: 'read-only', - }, - { - field: "type", - label: t("type"), - type: 'read-only', - // editable: true, - }, - { - field: "inStockQty", - label: t("Available Qty"), - type: 'read-only', - style: { - textAlign: "right", - }, - renderCell: (row: FGOverallRecord) => { - if (typeof(row.inStockQty) == "number") { - return decimalFormatter.format(row.inStockQty) - } - return row.inStockQty - } - // editable: true, - }, - { - field: "overallPurchaseQty", - label: t("Total Demand Qty"), - type: 'read-only', - style: { - textAlign: "right", - }, - renderCell: (row: FGOverallRecord) => { - if (typeof(row.overallPurchaseQty) == "number") { - return decimalFormatter.format(row.overallPurchaseQty) - } - return row.overallPurchaseQty - } - }, - { - field: "purchaseQty1", - label: t("Demand Qty (Day1)"), - type: 'read-only', - style: { - textAlign: "right", - }, - renderCell: (row: FGOverallRecord) => { - if (typeof(row.purchaseQty1) == "number") { - return decimalFormatter.format(row.purchaseQty1) - } - return row.purchaseQty1 - } - }, - { - field: "purchaseQty2", - label: t("Demand Qty (Day2)"), - type: 'read-only', - style: { - textAlign: "right", - }, - renderCell: (row: FGOverallRecord) => { - if (typeof(row.purchaseQty2) == "number") { - return decimalFormatter.format(row.purchaseQty2) - } - return row.purchaseQty2 - } - }, - { - field: "purchaseQty3", - label: t("Demand Qty (Day3)"), - type: 'read-only', - style: { - textAlign: "right", - }, - renderCell: (row: FGOverallRecord) => { - if (typeof(row.purchaseQty3) == "number") { - return decimalFormatter.format(row.purchaseQty3) - } - return row.purchaseQty3 - } - }, - { - field: "purchaseQty4", - label: t("Demand Qty (Day4)"), - type: 'read-only', - style: { - textAlign: "right", - }, - renderCell: (row: FGOverallRecord) => { - if (typeof(row.purchaseQty4) == "number") { - return decimalFormatter.format(row.purchaseQty4) - } - return row.purchaseQty4 - } - },{ - field: "purchaseQty5", - label: t("Demand Qty (Day5)"), - type: 'read-only', - style: { - textAlign: "right", - }, - renderCell: (row: FGOverallRecord) => { - if (typeof(row.purchaseQty5) == "number") { - return decimalFormatter.format(row.purchaseQty5) - } - return row.purchaseQty5 - } - }, - { - field: "purchaseQty6", - label: t("Demand Qty (Day6)"), - type: 'read-only', - style: { - textAlign: "right", - }, - renderCell: (row: FGOverallRecord) => { - if (typeof(row.purchaseQty6) == "number") { - return decimalFormatter.format(row.purchaseQty6) - } - return row.purchaseQty6 - } - }, - { - field: "purchaseQty7", - label: t("Demand Qty (Day7)"), - type: 'read-only', - style: { - textAlign: "right", - }, - renderCell: (row: FGOverallRecord) => { - if (typeof(row.purchaseQty7) == "number") { - return decimalFormatter.format(row.purchaseQty7) - } - return row.purchaseQty7 - } - }, - ], - [] - ); + const updatePagingController = (updatedObj) => { + setPagingController((prevState) => { + return prevState.map((item, index) => { + if (index === updatedObj?.index) { + return { + ...item, + pageNum: item.pageNum, + pageSize: item.pageSize, + totalCount: item.totalCount, + }; + } else return item; + }); + }); + }; - const columns = useMemo[]>( - () => [ - { - field: "code", - label: t("code"), - type: 'read-only', - // editable: true, - }, - { - field: "name", - label: t("name"), - type: 'read-only', - }, - { - field: "type", - label: t("type"), - type: 'read-only', - }, - { - field: "inStockQty", - label: t("Available Qty"), - type: 'read-only', - // editable: true, - style: { - textAlign: "right", - }, - renderCell: (row: FGRecord) => { - if (typeof(row.inStockQty) == "number") { - return decimalFormatter.format(row.inStockQty) - } - return row.inStockQty - } - }, - { - field: "purchaseQty", - label: t("Demand Qty"), - type: 'read-only', - style: { - textAlign: "right", - }, - renderCell: (row: FGRecord) => { - if (typeof(row.purchaseQty) == "number") { - return decimalFormatter.format(row.purchaseQty) - } - return row.purchaseQty - } - }, - ], - [] - ); + const overallColumns = useMemo[]>( + () => [ + { + field: "code", + label: t("code"), + type: "read-only", + // editable: true, + }, + { + field: "name", + label: t("name"), + type: "read-only", + }, + { + field: "type", + label: t("type"), + type: "read-only", + // editable: true, + }, + { + field: "inStockQty", + label: t("Available Qty"), + type: "read-only", + style: { + textAlign: "right", + }, + renderCell: (row: FGOverallRecord) => { + if (typeof row.inStockQty == "number") { + return decimalFormatter.format(row.inStockQty); + } + return row.inStockQty; + }, + // editable: true, + }, + { + field: "overallPurchaseQty", + label: t("Total Demand Qty"), + type: "read-only", + style: { + textAlign: "right", + }, + renderCell: (row: FGOverallRecord) => { + if (typeof row.overallPurchaseQty == "number") { + return decimalFormatter.format(row.overallPurchaseQty); + } + return row.overallPurchaseQty; + }, + }, + { + field: "purchaseQty1", + label: t("Demand Qty (Day1)"), + type: "read-only", + style: { + textAlign: "right", + }, + renderCell: (row: FGOverallRecord) => { + if (typeof row.purchaseQty1 == "number") { + return decimalFormatter.format(row.purchaseQty1); + } + return row.purchaseQty1; + }, + }, + { + field: "purchaseQty2", + label: t("Demand Qty (Day2)"), + type: "read-only", + style: { + textAlign: "right", + }, + renderCell: (row: FGOverallRecord) => { + if (typeof row.purchaseQty2 == "number") { + return decimalFormatter.format(row.purchaseQty2); + } + return row.purchaseQty2; + }, + }, + { + field: "purchaseQty3", + label: t("Demand Qty (Day3)"), + type: "read-only", + style: { + textAlign: "right", + }, + renderCell: (row: FGOverallRecord) => { + if (typeof row.purchaseQty3 == "number") { + return decimalFormatter.format(row.purchaseQty3); + } + return row.purchaseQty3; + }, + }, + { + field: "purchaseQty4", + label: t("Demand Qty (Day4)"), + type: "read-only", + style: { + textAlign: "right", + }, + renderCell: (row: FGOverallRecord) => { + if (typeof row.purchaseQty4 == "number") { + return decimalFormatter.format(row.purchaseQty4); + } + return row.purchaseQty4; + }, + }, + { + field: "purchaseQty5", + label: t("Demand Qty (Day5)"), + type: "read-only", + style: { + textAlign: "right", + }, + renderCell: (row: FGOverallRecord) => { + if (typeof row.purchaseQty5 == "number") { + return decimalFormatter.format(row.purchaseQty5); + } + return row.purchaseQty5; + }, + }, + { + field: "purchaseQty6", + label: t("Demand Qty (Day6)"), + type: "read-only", + style: { + textAlign: "right", + }, + renderCell: (row: FGOverallRecord) => { + if (typeof row.purchaseQty6 == "number") { + return decimalFormatter.format(row.purchaseQty6); + } + return row.purchaseQty6; + }, + }, + { + field: "purchaseQty7", + label: t("Demand Qty (Day7)"), + type: "read-only", + style: { + textAlign: "right", + }, + renderCell: (row: FGOverallRecord) => { + if (typeof row.purchaseQty7 == "number") { + return decimalFormatter.format(row.purchaseQty7); + } + return row.purchaseQty7; + }, + }, + ], + [], + ); + + const columns = useMemo[]>( + () => [ + { + field: "code", + label: t("code"), + type: "read-only", + // editable: true, + }, + { + field: "name", + label: t("name"), + type: "read-only", + }, + { + field: "type", + label: t("type"), + type: "read-only", + }, + { + field: "inStockQty", + label: t("Available Qty"), + type: "read-only", + // editable: true, + style: { + textAlign: "right", + }, + renderCell: (row: FGRecord) => { + if (typeof row.inStockQty == "number") { + return decimalFormatter.format(row.inStockQty); + } + return row.inStockQty; + }, + }, + { + field: "purchaseQty", + label: t("Demand Qty"), + type: "read-only", + style: { + textAlign: "right", + }, + renderCell: (row: FGRecord) => { + if (typeof row.purchaseQty == "number") { + return decimalFormatter.format(row.purchaseQty); + } + return row.purchaseQty; + }, + }, + ], + [], + ); - return ( - - - - {t("Material Demand List (7 Days)")} - - - index={7} - items={fakeOverallRecords} - isMockUp={true} - columns={overallColumns} - setPagingController={updatePagingController} - pagingController={pagingController[7]} - isAutoPaging={true} - isEditable={false} - isEdit={false} - /> - - {dayPeriod.map((date, index) => ( - - - {`${t("Material Demand Date")}: ${date}`} - - - index={index} - items={fakeRecords[index]} // Use the corresponding records for the day - columns={columns} - setPagingController={updatePagingController} - pagingController={pagingController[index]} - isAutoPaging={true} - isEditable={false} - isEdit={isEdit} - /> - - ))} + return ( + + + + {t("Material Demand List (7 Days)")} + + + index={7} + items={fakeOverallRecords} + isMockUp={true} + columns={overallColumns} + setPagingController={updatePagingController} + pagingController={pagingController[7]} + isAutoPaging={true} + isEditable={false} + isEdit={false} + /> + + {dayPeriod.map((date, index) => ( + + + {`${t("Material Demand Date")}: ${date}`} + + + index={index} + items={fakeRecords[index]} // Use the corresponding records for the day + columns={columns} + setPagingController={updatePagingController} + pagingController={pagingController[index]} + isAutoPaging={true} + isEditable={false} + isEdit={isEdit} + /> - ); + ))} + + ); }; export default ViewByBomDetails; diff --git a/src/components/DetailScheduleDetail/ViewByFGDetails.tsx b/src/components/DetailScheduleDetail/ViewByFGDetails.tsx index 37c00e8..8ceb04c 100644 --- a/src/components/DetailScheduleDetail/ViewByFGDetails.tsx +++ b/src/components/DetailScheduleDetail/ViewByFGDetails.tsx @@ -2,12 +2,12 @@ import { CreateItemInputs } from "@/app/api/settings/item/actions"; import { - GridColDef, - GridRowModel, - GridRenderEditCellParams, - GridEditInputCell, - GridRowSelectionModel, - useGridApiRef, + GridColDef, + GridRowModel, + GridRenderEditCellParams, + GridEditInputCell, + GridRowSelectionModel, + useGridApiRef, } from "@mui/x-data-grid"; import { MutableRefObject, useCallback, useMemo, useState } from "react"; import { useFormContext } from "react-hook-form"; @@ -18,667 +18,2143 @@ import { ItemQc } from "@/app/api/settings/item"; import { QcChecksInputs } from "@/app/api/settings/qcCheck/actions"; import { GridApiCommunity } from "@mui/x-data-grid/internals"; import { RiceBowl } from "@mui/icons-material"; -import EditableSearchResults, { Column } from "@/components/SearchResults/EditableSearchResults"; +import EditableSearchResults, { + Column, +} from "@/components/SearchResults/EditableSearchResults"; import { decimalFormatter, integerFormatter } from "@/app/utils/formatUtil"; type Props = { - apiRef: MutableRefObject - isEdit: Boolean + apiRef: MutableRefObject; + isEdit: boolean; }; type EntryError = - | { - [field in keyof QcChecksInputs]?: string; + | { + [field in keyof QcChecksInputs]?: string; } - | undefined; + | undefined; export type FGRecord = { - id: string | number - code: string; - name: string; - inStockQty: number; - productionQty?: number; - purchaseQty?: number -} - + id: string | number; + code: string; + name: string; + inStockQty: number; + productionQty?: number; + purchaseQty?: number; +}; const ViewByFGDetails: React.FC = ({ apiRef, isEdit }) => { - const { - t, - i18n: { language }, - } = useTranslation("schedule"); + const { + t, + i18n: { language }, + } = useTranslation("schedule"); - const { - formState: { errors, defaultValues, touchedFields }, - } = useFormContext(); - // const apiRef = useGridApiRef(); + const { + formState: { errors, defaultValues, touchedFields }, + } = useFormContext(); + // const apiRef = useGridApiRef(); - const dayPeriod = [ - '2025-05-07', - // '2025-05-12', - // '2025-05-13', - // '2025-05-14', - // '2025-05-15', - // '2025-05-16', - // '2025-05-17', - ]; - - const fakeRecordLine = useMemo( - () => [ - [ - { id: 1, code: "mt1", name: "material 1", inStockQty: 10, purchaseQty: 1 }, - { id: 2, code: "mt2", name: "material 2", inStockQty: 20, purchaseQty: 199 }, - ], - [ - { id: 3, code: "mt3", name: "material 3", inStockQty: 30, purchaseQty: 3 }, - { id: 4, code: "mt4", name: "material 4", inStockQty: 40, purchaseQty: 499 }, - ], - [ - { id: 5, code: "mt5", name: "material 5", inStockQty: 50, purchaseQty: 5 }, - { id: 6, code: "mt6", name: "material 6", inStockQty: 60, purchaseQty: 699 }, - ], - [ - { id: 7, code: "mt7", name: "material 7", inStockQty: 70, purchaseQty: 7 }, - { id: 8, code: "mt8", name: "material 8", inStockQty: 80, purchaseQty: 899 }, - ], - [ - { id: 9, code: "mt9", name: "material 9", inStockQty: 90, purchaseQty: 9 }, - { id: 10, code: "mt10", name: "material 10", inStockQty: 100, purchaseQty: 999 }, - ], - [ - { id: 11, code: "mt11", name: "material 11", inStockQty: 110, purchaseQty: 11 }, - { id: 12, code: "mt12", name: "material 12", inStockQty: 120, purchaseQty: 1299 }, - ], - [ - { id: 13, code: "mt13", name: "material 13", inStockQty: 130, purchaseQty: 13 }, - { id: 14, code: "mt14", name: "material 14", inStockQty: 140, purchaseQty: 1499 }, - ], - ], - [] - ); + const dayPeriod = [ + "2025-05-07", + // '2025-05-12', + // '2025-05-13', + // '2025-05-14', + // '2025-05-15', + // '2025-05-16', + // '2025-05-17', + ]; + const fakeRecordLine = useMemo( + () => [ + [ + { + id: 1, + code: "mt1", + name: "material 1", + inStockQty: 10, + purchaseQty: 1, + }, + { + id: 2, + code: "mt2", + name: "material 2", + inStockQty: 20, + purchaseQty: 199, + }, + ], + [ + { + id: 3, + code: "mt3", + name: "material 3", + inStockQty: 30, + purchaseQty: 3, + }, + { + id: 4, + code: "mt4", + name: "material 4", + inStockQty: 40, + purchaseQty: 499, + }, + ], + [ + { + id: 5, + code: "mt5", + name: "material 5", + inStockQty: 50, + purchaseQty: 5, + }, + { + id: 6, + code: "mt6", + name: "material 6", + inStockQty: 60, + purchaseQty: 699, + }, + ], + [ + { + id: 7, + code: "mt7", + name: "material 7", + inStockQty: 70, + purchaseQty: 7, + }, + { + id: 8, + code: "mt8", + name: "material 8", + inStockQty: 80, + purchaseQty: 899, + }, + ], + [ + { + id: 9, + code: "mt9", + name: "material 9", + inStockQty: 90, + purchaseQty: 9, + }, + { + id: 10, + code: "mt10", + name: "material 10", + inStockQty: 100, + purchaseQty: 999, + }, + ], + [ + { + id: 11, + code: "mt11", + name: "material 11", + inStockQty: 110, + purchaseQty: 11, + }, + { + id: 12, + code: "mt12", + name: "material 12", + inStockQty: 120, + purchaseQty: 1299, + }, + ], + [ + { + id: 13, + code: "mt13", + name: "material 13", + inStockQty: 130, + purchaseQty: 13, + }, + { + id: 14, + code: "mt14", + name: "material 14", + inStockQty: 140, + purchaseQty: 1499, + }, + ], + ], + [], + ); - const fakeRecords = useMemo( - () => [ - [ - { - id: 1, jobNo: "JO20250507001", estimatedProductionTime: "1 hr", priority: 85, code: "PP1193", type: "FG", name: "蔥油(1磅) ", inStockQty: 1322, productionQty: 661, - lines: [ - { id: 1, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 100, purchaseQty: 20 }, - { id: 2, code: "FA0161", type: "Material", name: "洋蔥粒", inStockQty: 80, purchaseQty: 10 } - ] - }, - { - id: 2, jobNo: "JO20250507002", estimatedProductionTime: "2 hrs", priority: 80, code: " PP1096", type: "FG", name: "白麵撈", inStockQty: 1040, productionQty: 520, - lines: [ - { id: 1, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 1000, purchaseQty: 190.00 }, - { id: 1, code: "MH0040", type: "Material", name: "星加坡綠富貴花牌幼白麵粉 (50磅/包)", inStockQty: 1000, purchaseQty: 250.00 }, - { id: 2, code: "FA0161", type: "Material", name: "蔥油", inStockQty: 1322, purchaseQty: 0 }, - ] - }, - { - id: 3, jobNo: "JO20250507003", estimatedProductionTime: "5 hrs : 15 mins", priority: 35, code: "PP1080", type: "FG", name: "咖哩汁", inStockQty: 2400, productionQty: 1200.0, - lines: [ - { id: 1, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 108.88 }, - { id: 2, code: "GI3236", type: "Material", name: "清水(煮過牛腩)", inStockQty: 317.52, purchaseQty: 635.04 }, - { id: 3, code: "MG1700", type: "Material", name: "STERILTOM 意大利茄粒", inStockQty: 9.00, purchaseQty: 18.00 }, - { id: 4, code: "FA0533", type: "Material", name: "乾蔥茸", inStockQty: 6.04, purchaseQty: 12.08 }, - { id: 5, code: "FA0210", type: "Material", name: "薑茸", inStockQty: 0, purchaseQty: 12.08 }, - { id: 6, code: "FA0608", type: "Material", name: "粗蒜茸", inStockQty: 0, purchaseQty: 12.08 }, - { id: 7, code: "FA0056", type: "Material", name: "洋蔥肉", inStockQty: 241.98, purchaseQty: 483.96 }, - { id: 8, code: "PP1188", type: "Material", name: "咖喱膽", inStockQty: 36.00, purchaseQty: 72.00 }, - { id: 9, code: "PP8001", type: "Material", name: "咖哩汁箱料粉", inStockQty: 77.42, purchaseQty: 154.84 }, - { id: 10, code: "PP1096", type: "Material", name: "白麵撈", inStockQty: 60.00, purchaseQty: 120.00 }, - { id: 10, code: "NA0476", type: "Material", name: "2磅份量三邊覆合袋 (0.1x225x260mm)個計", inStockQty: 600.00, purchaseQty: 200.0 }, - ] - }, - { - id: 4, jobNo: "JO20250507004", estimatedProductionTime: "3 hrs", priority: 20, code: " PP1188", type: "FG", name: "咖喱膽", inStockQty: 1016.2, productionQty: 508.1, - lines: [ - { id: 1, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 217.72 }, - { id: 2, code: "FA0161", type: "Material", name: "洋蔥粒", inStockQty: 0, purchaseQty: 18.15 }, - { id: 3, code: "FA0608", type: "Material", name: "粗蒜茸", inStockQty: 0, purchaseQty: 18.15 }, - { id: 4, code: "MG1288", type: "Material", name: "炸紅蔥頭", inStockQty: 0, purchaseQty: 6.05 }, - { id: 5, code: "FA0210", type: "Material", name: "薑茸", inStockQty: 0, purchaseQty: 6.05 }, - { id: 6, code: "MG0066", type: "Material", name: "咖哩料(5斤x16包+2斤/包)", inStockQty: 0, purchaseQty: 241.98 }, - ] - }, - ], - [ - { - id: 1, code: "PP1080", type: "FG", name: "咖哩汁", inStockQty: 2400, productionQty: 1200.0, - lines: [ - { id: 1, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 108.88 }, - { id: 2, code: "GI3236", type: "Material", name: "清水(煮過牛腩)", inStockQty: 317.52, purchaseQty: 635.04 }, - { id: 3, code: "MG1700", type: "Material", name: "STERILTOM 意大利茄粒", inStockQty: 9.00, purchaseQty: 18.00 }, - { id: 4, code: "FA0533", type: "Material", name: "乾蔥茸", inStockQty: 6.04, purchaseQty: 12.08 }, - { id: 5, code: "FA0210", type: "Material", name: "薑茸", inStockQty: 0, purchaseQty: 12.08 }, - { id: 6, code: "FA0608", type: "Material", name: "粗蒜茸", inStockQty: 0, purchaseQty: 12.08 }, - { id: 7, code: "FA0056", type: "Material", name: "洋蔥肉", inStockQty: 241.98, purchaseQty: 483.96 }, - { id: 8, code: "PP1188", type: "Material", name: "咖喱膽", inStockQty: 36.00, purchaseQty: 72.00 }, - { id: 9, code: "PP8001", type: "Material", name: "咖哩汁箱料粉", inStockQty: 77.42, purchaseQty: 154.84 }, - { id: 10, code: "PP1096", type: "Material", name: "白麵撈", inStockQty: 60.00, purchaseQty: 120.00 }, - { id: 10, code: "NA0476", type: "Material", name: "2磅份量三邊覆合袋 (0.1x225x260mm)個計", inStockQty: 600.00, purchaseQty: 200.0 }, - ] - }, - { - id: 2, code: "PP1193", type: "FG", name: "蔥油(1磅) ", inStockQty: 1322, productionQty: 661, - lines: [ - { id: 1, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 20 }, - { id: 2, code: "FA0161", type: "Material", name: "洋蔥粒", inStockQty: 0, purchaseQty: 10 } - ] - }, - { - id: 3, code: " PP1188", type: "FG", name: "咖喱膽", inStockQty: 1016.2, productionQty: 508.1, - lines: [ - { id: 1, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 217.72 }, - { id: 2, code: "FA0161", type: "Material", name: "洋蔥粒", inStockQty: 0, purchaseQty: 18.15 }, - { id: 3, code: "FA0608", type: "Material", name: "粗蒜茸", inStockQty: 0, purchaseQty: 18.15 }, - { id: 4, code: "MG1288", type: "Material", name: "炸紅蔥頭", inStockQty: 0, purchaseQty: 6.05 }, - { id: 5, code: "FA0210", type: "Material", name: "薑茸", inStockQty: 0, purchaseQty: 6.05 }, - { id: 6, code: "MG0066", type: "Material", name: "咖哩料(5斤x16包+2斤/包)", inStockQty: 0, purchaseQty: 241.98 }, - ] - }, - { - id: 4, code: " PP1096", type: "FG", name: "白麵撈", inStockQty: 1040, productionQty: 520, - lines: [ - { id: 1, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 190.00 }, - { id: 1, code: "MH0040", type: "Material", name: "星加坡綠富貴花牌幼白麵粉 (50磅/包)", inStockQty: 0, purchaseQty: 250.00 }, - { id: 2, code: "FA0161", type: "Material", name: "蔥油", inStockQty: 1322, purchaseQty: 0 }, - ] - }, - ], - [ - { - id: 1, code: "PP1080", type: "FG", name: "咖哩汁", inStockQty: 2400, productionQty: 1200.0, - lines: [ - { id: 1, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 108.88 }, - { id: 2, code: "GI3236", type: "Material", name: "清水(煮過牛腩)", inStockQty: 317.52, purchaseQty: 635.04 }, - { id: 3, code: "MG1700", type: "Material", name: "STERILTOM 意大利茄粒", inStockQty: 9.00, purchaseQty: 18.00 }, - { id: 4, code: "FA0533", type: "Material", name: "乾蔥茸", inStockQty: 6.04, purchaseQty: 12.08 }, - { id: 5, code: "FA0210", type: "Material", name: "薑茸", inStockQty: 0, purchaseQty: 12.08 }, - { id: 6, code: "FA0608", type: "Material", name: "粗蒜茸", inStockQty: 0, purchaseQty: 12.08 }, - { id: 7, code: "FA0056", type: "Material", name: "洋蔥肉", inStockQty: 241.98, purchaseQty: 483.96 }, - { id: 8, code: "PP1188", type: "Material", name: "咖喱膽", inStockQty: 36.00, purchaseQty: 72.00 }, - { id: 9, code: "PP8001", type: "Material", name: "咖哩汁箱料粉", inStockQty: 77.42, purchaseQty: 154.84 }, - { id: 10, code: "PP1096", type: "Material", name: "白麵撈", inStockQty: 60.00, purchaseQty: 120.00 }, - { id: 10, code: "NA0476", type: "Material", name: "2磅份量三邊覆合袋 (0.1x225x260mm)個計", inStockQty: 600.00, purchaseQty: 200.0 }, - ] - }, - { - id: 2, code: "PP1193", type: "FG", name: "蔥油(1磅) ", inStockQty: 1322, productionQty: 661, - lines: [ - { id: 1, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 20 }, - { id: 2, code: "FA0161", type: "Material", name: "洋蔥粒", inStockQty: 0, purchaseQty: 10 } - ] - }, - { - id: 3, code: " PP1188", type: "FG", name: "咖喱膽", inStockQty: 1016.2, productionQty: 508.1, - lines: [ - { id: 1, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 217.72 }, - { id: 2, code: "FA0161", type: "Material", name: "洋蔥粒", inStockQty: 0, purchaseQty: 18.15 }, - { id: 3, code: "FA0608", type: "Material", name: "粗蒜茸", inStockQty: 0, purchaseQty: 18.15 }, - { id: 4, code: "MG1288", type: "Material", name: "炸紅蔥頭", inStockQty: 0, purchaseQty: 6.05 }, - { id: 5, code: "FA0210", type: "Material", name: "薑茸", inStockQty: 0, purchaseQty: 6.05 }, - { id: 6, code: "MG0066", type: "Material", name: "咖哩料(5斤x16包+2斤/包)", inStockQty: 0, purchaseQty: 241.98 }, - ] - }, - { - id: 4, code: " PP1096", type: "FG", name: "白麵撈", inStockQty: 1040, productionQty: 520, - lines: [ - { id: 1, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 190.00 }, - { id: 1, code: "MH0040", type: "Material", name: "星加坡綠富貴花牌幼白麵粉 (50磅/包)", inStockQty: 0, purchaseQty: 250.00 }, - { id: 2, code: "FA0161", type: "Material", name: "蔥油", inStockQty: 1322, purchaseQty: 0 }, - ] - }, - ], - [ - { - id: 1, code: "PP1080", type: "FG", name: "咖哩汁", inStockQty: 2400, productionQty: 1200.0, - lines: [ - { id: 1, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 108.88 }, - { id: 2, code: "GI3236", type: "Material", name: "清水(煮過牛腩)", inStockQty: 317.52, purchaseQty: 635.04 }, - { id: 3, code: "MG1700", type: "Material", name: "STERILTOM 意大利茄粒", inStockQty: 9.00, purchaseQty: 18.00 }, - { id: 4, code: "FA0533", type: "Material", name: "乾蔥茸", inStockQty: 6.04, purchaseQty: 12.08 }, - { id: 5, code: "FA0210", type: "Material", name: "薑茸", inStockQty: 0, purchaseQty: 12.08 }, - { id: 6, code: "FA0608", type: "Material", name: "粗蒜茸", inStockQty: 0, purchaseQty: 12.08 }, - { id: 7, code: "FA0056", type: "Material", name: "洋蔥肉", inStockQty: 241.98, purchaseQty: 483.96 }, - { id: 8, code: "PP1188", type: "Material", name: "咖喱膽", inStockQty: 36.00, purchaseQty: 72.00 }, - { id: 9, code: "PP8001", type: "Material", name: "咖哩汁箱料粉", inStockQty: 77.42, purchaseQty: 154.84 }, - { id: 10, code: "PP1096", type: "Material", name: "白麵撈", inStockQty: 60.00, purchaseQty: 120.00 }, - { id: 10, code: "NA0476", type: "Material", name: "2磅份量三邊覆合袋 (0.1x225x260mm)個計", inStockQty: 600.00, purchaseQty: 200.0 }, - ] - }, - { - id: 2, code: "PP1193", type: "FG", name: "蔥油(1磅) ", inStockQty: 1322, productionQty: 661, - lines: [ - { id: 1, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 20 }, - { id: 2, code: "FA0161", type: "Material", name: "洋蔥粒", inStockQty: 0, purchaseQty: 10 } - ] - }, - { - id: 3, code: " PP1188", type: "FG", name: "咖喱膽", inStockQty: 1016.2, productionQty: 508.1, - lines: [ - { id: 1, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 217.72 }, - { id: 2, code: "FA0161", type: "Material", name: "洋蔥粒", inStockQty: 0, purchaseQty: 18.15 }, - { id: 3, code: "FA0608", type: "Material", name: "粗蒜茸", inStockQty: 0, purchaseQty: 18.15 }, - { id: 4, code: "MG1288", type: "Material", name: "炸紅蔥頭", inStockQty: 0, purchaseQty: 6.05 }, - { id: 5, code: "FA0210", type: "Material", name: "薑茸", inStockQty: 0, purchaseQty: 6.05 }, - { id: 6, code: "MG0066", type: "Material", name: "咖哩料(5斤x16包+2斤/包)", inStockQty: 0, purchaseQty: 241.98 }, - ] - }, - { - id: 4, code: " PP1096", type: "FG", name: "白麵撈", inStockQty: 1040, productionQty: 520, - lines: [ - { id: 1, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 190.00 }, - { id: 1, code: "MH0040", type: "Material", name: "星加坡綠富貴花牌幼白麵粉 (50磅/包)", inStockQty: 0, purchaseQty: 250.00 }, - { id: 2, code: "FA0161", type: "Material", name: "蔥油", inStockQty: 1322, purchaseQty: 0 }, - ] - }, - ], - [ - { - id: 1, code: "PP1080", name: "咖哩汁", inStockQty: 2400, productionQty: 1200.0, - lines: [ - { id: 1, code: "MH0040", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 108.88 }, - { id: 2, code: "GI3236", name: "清水(煮過牛腩)", inStockQty: 317.52, purchaseQty: 635.04 }, - { id: 3, code: "MG1700", name: "STERILTOM 意大利茄粒", inStockQty: 9.00, purchaseQty: 18.00 }, - { id: 4, code: "FA0533", name: "乾蔥茸", inStockQty: 6.04, purchaseQty: 12.08 }, - { id: 5, code: "FA0210", name: "薑茸", inStockQty: 0, purchaseQty: 12.08 }, - { id: 6, code: "FA0608", name: "粗蒜茸", inStockQty: 0, purchaseQty: 12.08 }, - { id: 7, code: "FA0056", name: "洋蔥肉", inStockQty: 241.98, purchaseQty: 483.96 }, - { id: 8, code: "PP1188", name: "咖喱膽", inStockQty: 36.00, purchaseQty: 72.00 }, - { id: 9, code: "PP8001", name: "咖哩汁箱料粉", inStockQty: 77.42, purchaseQty: 154.84 }, - { id: 10, code: "PP1096", name: "白麵撈", inStockQty: 60.00, purchaseQty: 120.00 }, - { id: 10, code: "NA0476", name: "2磅份量三邊覆合袋 (0.1x225x260mm)個計", inStockQty: 600.00, purchaseQty: 200.00 }, - ] - }, - { - id: 2, code: "PP1193", name: "蔥油(1磅) ", inStockQty: 1322, productionQty: 661, - lines: [ - { id: 1, code: "MH0040", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 20 }, - { id: 2, code: "FA0161", name: "洋蔥粒", inStockQty: 0, purchaseQty: 10 } - ] - }, - { - id: 3, code: " PP1188", name: "咖喱膽", inStockQty: 1016.2, productionQty: 508.1, - lines: [ - { id: 1, code: "MH0040", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 217.72 }, - { id: 2, code: "FA0161", name: "洋蔥粒", inStockQty: 0, purchaseQty: 18.15 }, - { id: 3, code: "FA0608", name: "粗蒜茸", inStockQty: 0, purchaseQty: 18.15 }, - { id: 4, code: "MG1288", name: "炸紅蔥頭", inStockQty: 0, purchaseQty: 6.05 }, - { id: 5, code: "FA0210", name: "薑茸", inStockQty: 0, purchaseQty: 6.05 }, - { id: 6, code: "MG0066", name: "咖哩料(5斤x16包+2斤/包)", inStockQty: 0, purchaseQty: 241.98 }, - ] - }, - { - id: 4, code: " PP1096", name: "白麵撈", inStockQty: 1040, productionQty: 520, - lines: [ - { id: 1, code: "MH0040", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 190.00 }, - { id: 1, code: "MH0040", name: "星加坡綠富貴花牌幼白麵粉 (50磅/包)", inStockQty: 0, purchaseQty: 250.00 }, - { id: 2, code: "FA0161", name: "蔥油", inStockQty: 1322, purchaseQty: 0 }, - ] - }, - ], - [ - { - id: 1, code: "PP1080", type: "FG", name: "咖哩汁", inStockQty: 2400, productionQty: 1200.0, - lines: [ - { id: 1, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 108.88 }, - { id: 2, code: "GI3236", type: "Material", name: "清水(煮過牛腩)", inStockQty: 317.52, purchaseQty: 635.04 }, - { id: 3, code: "MG1700", type: "Material", name: "STERILTOM 意大利茄粒", inStockQty: 9.00, purchaseQty: 18.00 }, - { id: 4, code: "FA0533", type: "Material", name: "乾蔥茸", inStockQty: 6.04, purchaseQty: 12.08 }, - { id: 5, code: "FA0210", type: "Material", name: "薑茸", inStockQty: 0, purchaseQty: 12.08 }, - { id: 6, code: "FA0608", type: "Material", name: "粗蒜茸", inStockQty: 0, purchaseQty: 12.08 }, - { id: 7, code: "FA0056", type: "Material", name: "洋蔥肉", inStockQty: 241.98, purchaseQty: 483.96 }, - { id: 8, code: "PP1188", type: "Material", name: "咖喱膽", inStockQty: 36.00, purchaseQty: 72.00 }, - { id: 9, code: "PP8001", type: "Material", name: "咖哩汁箱料粉", inStockQty: 77.42, purchaseQty: 154.84 }, - { id: 10, code: "PP1096", type: "Material", name: "白麵撈", inStockQty: 60.00, purchaseQty: 120.00 }, - { id: 10, code: "NA0476", type: "Material", name: "2磅份量三邊覆合袋 (0.1x225x260mm)個計", inStockQty: 600.00, purchaseQty: 200.0 }, - ] - }, - { - id: 2, code: "PP1193", type: "FG", name: "蔥油(1磅) ", inStockQty: 1322, productionQty: 661, - lines: [ - { id: 1, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 20 }, - { id: 2, code: "FA0161", type: "Material", name: "洋蔥粒", inStockQty: 0, purchaseQty: 10 } - ] - }, - { - id: 3, code: " PP1188", type: "FG", name: "咖喱膽", inStockQty: 1016.2, productionQty: 508.1, - lines: [ - { id: 1, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 217.72 }, - { id: 2, code: "FA0161", type: "Material", name: "洋蔥粒", inStockQty: 0, purchaseQty: 18.15 }, - { id: 3, code: "FA0608", type: "Material", name: "粗蒜茸", inStockQty: 0, purchaseQty: 18.15 }, - { id: 4, code: "MG1288", type: "Material", name: "炸紅蔥頭", inStockQty: 0, purchaseQty: 6.05 }, - { id: 5, code: "FA0210", type: "Material", name: "薑茸", inStockQty: 0, purchaseQty: 6.05 }, - { id: 6, code: "MG0066", type: "Material", name: "咖哩料(5斤x16包+2斤/包)", inStockQty: 0, purchaseQty: 241.98 }, - ] - }, - { - id: 4, code: " PP1096", type: "FG", name: "白麵撈", inStockQty: 1040, productionQty: 520, - lines: [ - { id: 1, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 190.00 }, - { id: 1, code: "MH0040", type: "Material", name: "星加坡綠富貴花牌幼白麵粉 (50磅/包)", inStockQty: 0, purchaseQty: 250.00 }, - { id: 2, code: "FA0161", type: "Material", name: "蔥油", inStockQty: 1322, purchaseQty: 0 }, - ] - }, - ], - [ - { - id: 1, code: "PP1080", type: "FG", name: "咖哩汁", inStockQty: 2400, productionQty: 1200.0, - lines: [ - { id: 1, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 108.88 }, - { id: 2, code: "GI3236", type: "Material", name: "清水(煮過牛腩)", inStockQty: 317.52, purchaseQty: 635.04 }, - { id: 3, code: "MG1700", type: "Material", name: "STERILTOM 意大利茄粒", inStockQty: 9.00, purchaseQty: 18.00 }, - { id: 4, code: "FA0533", type: "Material", name: "乾蔥茸", inStockQty: 6.04, purchaseQty: 12.08 }, - { id: 5, code: "FA0210", type: "Material", name: "薑茸", inStockQty: 0, purchaseQty: 12.08 }, - { id: 6, code: "FA0608", type: "Material", name: "粗蒜茸", inStockQty: 0, purchaseQty: 12.08 }, - { id: 7, code: "FA0056", type: "Material", name: "洋蔥肉", inStockQty: 241.98, purchaseQty: 483.96 }, - { id: 8, code: "PP1188", type: "Material", name: "咖喱膽", inStockQty: 36.00, purchaseQty: 72.00 }, - { id: 9, code: "PP8001", type: "Material", name: "咖哩汁箱料粉", inStockQty: 77.42, purchaseQty: 154.84 }, - { id: 10, code: "PP1096", type: "Material", name: "白麵撈", inStockQty: 60.00, purchaseQty: 120.00 }, - { id: 10, code: "NA0476", type: "Material", name: "2磅份量三邊覆合袋 (0.1x225x260mm)個計", inStockQty: 600.00, purchaseQty: 200.0 }, - ] - }, - { - id: 2, code: "PP1193", type: "FG", name: "蔥油(1磅) ", inStockQty: 1322, productionQty: 661, - lines: [ - { id: 1, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 20 }, - { id: 2, code: "FA0161", type: "Material", name: "洋蔥粒", inStockQty: 0, purchaseQty: 10 } - ] - }, - { - id: 3, code: " PP1188", type: "FG", name: "咖喱膽", inStockQty: 1016.2, productionQty: 508.1, - lines: [ - { id: 1, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 217.72 }, - { id: 2, code: "FA0161", type: "Material", name: "洋蔥粒", inStockQty: 0, purchaseQty: 18.15 }, - { id: 3, code: "FA0608", type: "Material", name: "粗蒜茸", inStockQty: 0, purchaseQty: 18.15 }, - { id: 4, code: "MG1288", type: "Material", name: "炸紅蔥頭", inStockQty: 0, purchaseQty: 6.05 }, - { id: 5, code: "FA0210", type: "Material", name: "薑茸", inStockQty: 0, purchaseQty: 6.05 }, - { id: 6, code: "MG0066", type: "Material", name: "咖哩料(5斤x16包+2斤/包)", inStockQty: 0, purchaseQty: 241.98 }, - ] - }, - { - id: 4, code: " PP1096", type: "FG", name: "白麵撈", inStockQty: 1040, productionQty: 520, - lines: [ - { id: 1, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 190.00 }, - { id: 1, code: "MH0040", type: "Material", name: "星加坡綠富貴花牌幼白麵粉 (50磅/包)", inStockQty: 0, purchaseQty: 250.00 }, - { id: 2, code: "FA0161", type: "Material", name: "蔥油", inStockQty: 1322, purchaseQty: 0 }, - ] - }, - ], - ], - [] - ); - - const [pagingController, setPagingController] = useState([ + const fakeRecords = useMemo( + () => [ + [ + { + id: 1, + jobNo: "JO20250507001", + estimatedProductionTime: "1 hr", + priority: 85, + code: "PP1193", + type: "FG", + name: "蔥油(1磅) ", + inStockQty: 1322, + productionQty: 661, + lines: [ + { + id: 1, + code: "MH0040", + type: "Material", + name: "大豆油(1噸/桶)", + inStockQty: 100, + purchaseQty: 20, + }, + { + id: 2, + code: "FA0161", + type: "Material", + name: "洋蔥粒", + inStockQty: 80, + purchaseQty: 10, + }, + ], + }, + { + id: 2, + jobNo: "JO20250507002", + estimatedProductionTime: "2 hrs", + priority: 80, + code: " PP1096", + type: "FG", + name: "白麵撈", + inStockQty: 1040, + productionQty: 520, + lines: [ + { + id: 1, + code: "MH0040", + type: "Material", + name: "大豆油(1噸/桶)", + inStockQty: 1000, + purchaseQty: 190.0, + }, + { + id: 1, + code: "MH0040", + type: "Material", + name: "星加坡綠富貴花牌幼白麵粉 (50磅/包)", + inStockQty: 1000, + purchaseQty: 250.0, + }, + { + id: 2, + code: "FA0161", + type: "Material", + name: "蔥油", + inStockQty: 1322, + purchaseQty: 0, + }, + ], + }, + { + id: 3, + jobNo: "JO20250507003", + estimatedProductionTime: "5 hrs : 15 mins", + priority: 35, + code: "PP1080", + type: "FG", + name: "咖哩汁", + inStockQty: 2400, + productionQty: 1200.0, + lines: [ + { + id: 1, + code: "MH0040", + type: "Material", + name: "大豆油(1噸/桶)", + inStockQty: 0, + purchaseQty: 108.88, + }, + { + id: 2, + code: "GI3236", + type: "Material", + name: "清水(煮過牛腩)", + inStockQty: 317.52, + purchaseQty: 635.04, + }, + { + id: 3, + code: "MG1700", + type: "Material", + name: "STERILTOM 意大利茄粒", + inStockQty: 9.0, + purchaseQty: 18.0, + }, + { + id: 4, + code: "FA0533", + type: "Material", + name: "乾蔥茸", + inStockQty: 6.04, + purchaseQty: 12.08, + }, + { + id: 5, + code: "FA0210", + type: "Material", + name: "薑茸", + inStockQty: 0, + purchaseQty: 12.08, + }, + { + id: 6, + code: "FA0608", + type: "Material", + name: "粗蒜茸", + inStockQty: 0, + purchaseQty: 12.08, + }, + { + id: 7, + code: "FA0056", + type: "Material", + name: "洋蔥肉", + inStockQty: 241.98, + purchaseQty: 483.96, + }, + { + id: 8, + code: "PP1188", + type: "Material", + name: "咖喱膽", + inStockQty: 36.0, + purchaseQty: 72.0, + }, + { + id: 9, + code: "PP8001", + type: "Material", + name: "咖哩汁箱料粉", + inStockQty: 77.42, + purchaseQty: 154.84, + }, + { + id: 10, + code: "PP1096", + type: "Material", + name: "白麵撈", + inStockQty: 60.0, + purchaseQty: 120.0, + }, + { + id: 10, + code: "NA0476", + type: "Material", + name: "2磅份量三邊覆合袋 (0.1x225x260mm)個計", + inStockQty: 600.0, + purchaseQty: 200.0, + }, + ], + }, + { + id: 4, + jobNo: "JO20250507004", + estimatedProductionTime: "3 hrs", + priority: 20, + code: " PP1188", + type: "FG", + name: "咖喱膽", + inStockQty: 1016.2, + productionQty: 508.1, + lines: [ + { + id: 1, + code: "MH0040", + type: "Material", + name: "大豆油(1噸/桶)", + inStockQty: 0, + purchaseQty: 217.72, + }, + { + id: 2, + code: "FA0161", + type: "Material", + name: "洋蔥粒", + inStockQty: 0, + purchaseQty: 18.15, + }, + { + id: 3, + code: "FA0608", + type: "Material", + name: "粗蒜茸", + inStockQty: 0, + purchaseQty: 18.15, + }, + { + id: 4, + code: "MG1288", + type: "Material", + name: "炸紅蔥頭", + inStockQty: 0, + purchaseQty: 6.05, + }, + { + id: 5, + code: "FA0210", + type: "Material", + name: "薑茸", + inStockQty: 0, + purchaseQty: 6.05, + }, + { + id: 6, + code: "MG0066", + type: "Material", + name: "咖哩料(5斤x16包+2斤/包)", + inStockQty: 0, + purchaseQty: 241.98, + }, + ], + }, + ], + [ + { + id: 1, + code: "PP1080", + type: "FG", + name: "咖哩汁", + inStockQty: 2400, + productionQty: 1200.0, + lines: [ + { + id: 1, + code: "MH0040", + type: "Material", + name: "大豆油(1噸/桶)", + inStockQty: 0, + purchaseQty: 108.88, + }, + { + id: 2, + code: "GI3236", + type: "Material", + name: "清水(煮過牛腩)", + inStockQty: 317.52, + purchaseQty: 635.04, + }, + { + id: 3, + code: "MG1700", + type: "Material", + name: "STERILTOM 意大利茄粒", + inStockQty: 9.0, + purchaseQty: 18.0, + }, + { + id: 4, + code: "FA0533", + type: "Material", + name: "乾蔥茸", + inStockQty: 6.04, + purchaseQty: 12.08, + }, + { + id: 5, + code: "FA0210", + type: "Material", + name: "薑茸", + inStockQty: 0, + purchaseQty: 12.08, + }, + { + id: 6, + code: "FA0608", + type: "Material", + name: "粗蒜茸", + inStockQty: 0, + purchaseQty: 12.08, + }, + { + id: 7, + code: "FA0056", + type: "Material", + name: "洋蔥肉", + inStockQty: 241.98, + purchaseQty: 483.96, + }, + { + id: 8, + code: "PP1188", + type: "Material", + name: "咖喱膽", + inStockQty: 36.0, + purchaseQty: 72.0, + }, + { + id: 9, + code: "PP8001", + type: "Material", + name: "咖哩汁箱料粉", + inStockQty: 77.42, + purchaseQty: 154.84, + }, + { + id: 10, + code: "PP1096", + type: "Material", + name: "白麵撈", + inStockQty: 60.0, + purchaseQty: 120.0, + }, + { + id: 10, + code: "NA0476", + type: "Material", + name: "2磅份量三邊覆合袋 (0.1x225x260mm)個計", + inStockQty: 600.0, + purchaseQty: 200.0, + }, + ], + }, { - pageNum: 1, - pageSize: 10, - totalCount: 0, + id: 2, + code: "PP1193", + type: "FG", + name: "蔥油(1磅) ", + inStockQty: 1322, + productionQty: 661, + lines: [ + { + id: 1, + code: "MH0040", + type: "Material", + name: "大豆油(1噸/桶)", + inStockQty: 0, + purchaseQty: 20, + }, + { + id: 2, + code: "FA0161", + type: "Material", + name: "洋蔥粒", + inStockQty: 0, + purchaseQty: 10, + }, + ], }, { - pageNum: 1, - pageSize: 10, - totalCount: 0, + id: 3, + code: " PP1188", + type: "FG", + name: "咖喱膽", + inStockQty: 1016.2, + productionQty: 508.1, + lines: [ + { + id: 1, + code: "MH0040", + type: "Material", + name: "大豆油(1噸/桶)", + inStockQty: 0, + purchaseQty: 217.72, + }, + { + id: 2, + code: "FA0161", + type: "Material", + name: "洋蔥粒", + inStockQty: 0, + purchaseQty: 18.15, + }, + { + id: 3, + code: "FA0608", + type: "Material", + name: "粗蒜茸", + inStockQty: 0, + purchaseQty: 18.15, + }, + { + id: 4, + code: "MG1288", + type: "Material", + name: "炸紅蔥頭", + inStockQty: 0, + purchaseQty: 6.05, + }, + { + id: 5, + code: "FA0210", + type: "Material", + name: "薑茸", + inStockQty: 0, + purchaseQty: 6.05, + }, + { + id: 6, + code: "MG0066", + type: "Material", + name: "咖哩料(5斤x16包+2斤/包)", + inStockQty: 0, + purchaseQty: 241.98, + }, + ], }, { - pageNum: 1, - pageSize: 10, - totalCount: 0, + id: 4, + code: " PP1096", + type: "FG", + name: "白麵撈", + inStockQty: 1040, + productionQty: 520, + lines: [ + { + id: 1, + code: "MH0040", + type: "Material", + name: "大豆油(1噸/桶)", + inStockQty: 0, + purchaseQty: 190.0, + }, + { + id: 1, + code: "MH0040", + type: "Material", + name: "星加坡綠富貴花牌幼白麵粉 (50磅/包)", + inStockQty: 0, + purchaseQty: 250.0, + }, + { + id: 2, + code: "FA0161", + type: "Material", + name: "蔥油", + inStockQty: 1322, + purchaseQty: 0, + }, + ], }, + ], + [ { - pageNum: 1, - pageSize: 10, - totalCount: 0, + id: 1, + code: "PP1080", + type: "FG", + name: "咖哩汁", + inStockQty: 2400, + productionQty: 1200.0, + lines: [ + { + id: 1, + code: "MH0040", + type: "Material", + name: "大豆油(1噸/桶)", + inStockQty: 0, + purchaseQty: 108.88, + }, + { + id: 2, + code: "GI3236", + type: "Material", + name: "清水(煮過牛腩)", + inStockQty: 317.52, + purchaseQty: 635.04, + }, + { + id: 3, + code: "MG1700", + type: "Material", + name: "STERILTOM 意大利茄粒", + inStockQty: 9.0, + purchaseQty: 18.0, + }, + { + id: 4, + code: "FA0533", + type: "Material", + name: "乾蔥茸", + inStockQty: 6.04, + purchaseQty: 12.08, + }, + { + id: 5, + code: "FA0210", + type: "Material", + name: "薑茸", + inStockQty: 0, + purchaseQty: 12.08, + }, + { + id: 6, + code: "FA0608", + type: "Material", + name: "粗蒜茸", + inStockQty: 0, + purchaseQty: 12.08, + }, + { + id: 7, + code: "FA0056", + type: "Material", + name: "洋蔥肉", + inStockQty: 241.98, + purchaseQty: 483.96, + }, + { + id: 8, + code: "PP1188", + type: "Material", + name: "咖喱膽", + inStockQty: 36.0, + purchaseQty: 72.0, + }, + { + id: 9, + code: "PP8001", + type: "Material", + name: "咖哩汁箱料粉", + inStockQty: 77.42, + purchaseQty: 154.84, + }, + { + id: 10, + code: "PP1096", + type: "Material", + name: "白麵撈", + inStockQty: 60.0, + purchaseQty: 120.0, + }, + { + id: 10, + code: "NA0476", + type: "Material", + name: "2磅份量三邊覆合袋 (0.1x225x260mm)個計", + inStockQty: 600.0, + purchaseQty: 200.0, + }, + ], }, { - pageNum: 1, - pageSize: 10, - totalCount: 0, + id: 2, + code: "PP1193", + type: "FG", + name: "蔥油(1磅) ", + inStockQty: 1322, + productionQty: 661, + lines: [ + { + id: 1, + code: "MH0040", + type: "Material", + name: "大豆油(1噸/桶)", + inStockQty: 0, + purchaseQty: 20, + }, + { + id: 2, + code: "FA0161", + type: "Material", + name: "洋蔥粒", + inStockQty: 0, + purchaseQty: 10, + }, + ], }, { - pageNum: 1, - pageSize: 10, - totalCount: 0, + id: 3, + code: " PP1188", + type: "FG", + name: "咖喱膽", + inStockQty: 1016.2, + productionQty: 508.1, + lines: [ + { + id: 1, + code: "MH0040", + type: "Material", + name: "大豆油(1噸/桶)", + inStockQty: 0, + purchaseQty: 217.72, + }, + { + id: 2, + code: "FA0161", + type: "Material", + name: "洋蔥粒", + inStockQty: 0, + purchaseQty: 18.15, + }, + { + id: 3, + code: "FA0608", + type: "Material", + name: "粗蒜茸", + inStockQty: 0, + purchaseQty: 18.15, + }, + { + id: 4, + code: "MG1288", + type: "Material", + name: "炸紅蔥頭", + inStockQty: 0, + purchaseQty: 6.05, + }, + { + id: 5, + code: "FA0210", + type: "Material", + name: "薑茸", + inStockQty: 0, + purchaseQty: 6.05, + }, + { + id: 6, + code: "MG0066", + type: "Material", + name: "咖哩料(5斤x16包+2斤/包)", + inStockQty: 0, + purchaseQty: 241.98, + }, + ], }, { - pageNum: 1, - pageSize: 10, - totalCount: 0, + id: 4, + code: " PP1096", + type: "FG", + name: "白麵撈", + inStockQty: 1040, + productionQty: 520, + lines: [ + { + id: 1, + code: "MH0040", + type: "Material", + name: "大豆油(1噸/桶)", + inStockQty: 0, + purchaseQty: 190.0, + }, + { + id: 1, + code: "MH0040", + type: "Material", + name: "星加坡綠富貴花牌幼白麵粉 (50磅/包)", + inStockQty: 0, + purchaseQty: 250.0, + }, + { + id: 2, + code: "FA0161", + type: "Material", + name: "蔥油", + inStockQty: 1322, + purchaseQty: 0, + }, + ], }, + ], + [ { - pageNum: 1, - pageSize: 10, - totalCount: 0, + id: 1, + code: "PP1080", + type: "FG", + name: "咖哩汁", + inStockQty: 2400, + productionQty: 1200.0, + lines: [ + { + id: 1, + code: "MH0040", + type: "Material", + name: "大豆油(1噸/桶)", + inStockQty: 0, + purchaseQty: 108.88, + }, + { + id: 2, + code: "GI3236", + type: "Material", + name: "清水(煮過牛腩)", + inStockQty: 317.52, + purchaseQty: 635.04, + }, + { + id: 3, + code: "MG1700", + type: "Material", + name: "STERILTOM 意大利茄粒", + inStockQty: 9.0, + purchaseQty: 18.0, + }, + { + id: 4, + code: "FA0533", + type: "Material", + name: "乾蔥茸", + inStockQty: 6.04, + purchaseQty: 12.08, + }, + { + id: 5, + code: "FA0210", + type: "Material", + name: "薑茸", + inStockQty: 0, + purchaseQty: 12.08, + }, + { + id: 6, + code: "FA0608", + type: "Material", + name: "粗蒜茸", + inStockQty: 0, + purchaseQty: 12.08, + }, + { + id: 7, + code: "FA0056", + type: "Material", + name: "洋蔥肉", + inStockQty: 241.98, + purchaseQty: 483.96, + }, + { + id: 8, + code: "PP1188", + type: "Material", + name: "咖喱膽", + inStockQty: 36.0, + purchaseQty: 72.0, + }, + { + id: 9, + code: "PP8001", + type: "Material", + name: "咖哩汁箱料粉", + inStockQty: 77.42, + purchaseQty: 154.84, + }, + { + id: 10, + code: "PP1096", + type: "Material", + name: "白麵撈", + inStockQty: 60.0, + purchaseQty: 120.0, + }, + { + id: 10, + code: "NA0476", + type: "Material", + name: "2磅份量三邊覆合袋 (0.1x225x260mm)個計", + inStockQty: 600.0, + purchaseQty: 200.0, + }, + ], }, - ]) + { + id: 2, + code: "PP1193", + type: "FG", + name: "蔥油(1磅) ", + inStockQty: 1322, + productionQty: 661, + lines: [ + { + id: 1, + code: "MH0040", + type: "Material", + name: "大豆油(1噸/桶)", + inStockQty: 0, + purchaseQty: 20, + }, + { + id: 2, + code: "FA0161", + type: "Material", + name: "洋蔥粒", + inStockQty: 0, + purchaseQty: 10, + }, + ], + }, + { + id: 3, + code: " PP1188", + type: "FG", + name: "咖喱膽", + inStockQty: 1016.2, + productionQty: 508.1, + lines: [ + { + id: 1, + code: "MH0040", + type: "Material", + name: "大豆油(1噸/桶)", + inStockQty: 0, + purchaseQty: 217.72, + }, + { + id: 2, + code: "FA0161", + type: "Material", + name: "洋蔥粒", + inStockQty: 0, + purchaseQty: 18.15, + }, + { + id: 3, + code: "FA0608", + type: "Material", + name: "粗蒜茸", + inStockQty: 0, + purchaseQty: 18.15, + }, + { + id: 4, + code: "MG1288", + type: "Material", + name: "炸紅蔥頭", + inStockQty: 0, + purchaseQty: 6.05, + }, + { + id: 5, + code: "FA0210", + type: "Material", + name: "薑茸", + inStockQty: 0, + purchaseQty: 6.05, + }, + { + id: 6, + code: "MG0066", + type: "Material", + name: "咖哩料(5斤x16包+2斤/包)", + inStockQty: 0, + purchaseQty: 241.98, + }, + ], + }, + { + id: 4, + code: " PP1096", + type: "FG", + name: "白麵撈", + inStockQty: 1040, + productionQty: 520, + lines: [ + { + id: 1, + code: "MH0040", + type: "Material", + name: "大豆油(1噸/桶)", + inStockQty: 0, + purchaseQty: 190.0, + }, + { + id: 1, + code: "MH0040", + type: "Material", + name: "星加坡綠富貴花牌幼白麵粉 (50磅/包)", + inStockQty: 0, + purchaseQty: 250.0, + }, + { + id: 2, + code: "FA0161", + type: "Material", + name: "蔥油", + inStockQty: 1322, + purchaseQty: 0, + }, + ], + }, + ], + [ + { + id: 1, + code: "PP1080", + name: "咖哩汁", + inStockQty: 2400, + productionQty: 1200.0, + lines: [ + { + id: 1, + code: "MH0040", + name: "大豆油(1噸/桶)", + inStockQty: 0, + purchaseQty: 108.88, + }, + { + id: 2, + code: "GI3236", + name: "清水(煮過牛腩)", + inStockQty: 317.52, + purchaseQty: 635.04, + }, + { + id: 3, + code: "MG1700", + name: "STERILTOM 意大利茄粒", + inStockQty: 9.0, + purchaseQty: 18.0, + }, + { + id: 4, + code: "FA0533", + name: "乾蔥茸", + inStockQty: 6.04, + purchaseQty: 12.08, + }, + { + id: 5, + code: "FA0210", + name: "薑茸", + inStockQty: 0, + purchaseQty: 12.08, + }, + { + id: 6, + code: "FA0608", + name: "粗蒜茸", + inStockQty: 0, + purchaseQty: 12.08, + }, + { + id: 7, + code: "FA0056", + name: "洋蔥肉", + inStockQty: 241.98, + purchaseQty: 483.96, + }, + { + id: 8, + code: "PP1188", + name: "咖喱膽", + inStockQty: 36.0, + purchaseQty: 72.0, + }, + { + id: 9, + code: "PP8001", + name: "咖哩汁箱料粉", + inStockQty: 77.42, + purchaseQty: 154.84, + }, + { + id: 10, + code: "PP1096", + name: "白麵撈", + inStockQty: 60.0, + purchaseQty: 120.0, + }, + { + id: 10, + code: "NA0476", + name: "2磅份量三邊覆合袋 (0.1x225x260mm)個計", + inStockQty: 600.0, + purchaseQty: 200.0, + }, + ], + }, + { + id: 2, + code: "PP1193", + name: "蔥油(1磅) ", + inStockQty: 1322, + productionQty: 661, + lines: [ + { + id: 1, + code: "MH0040", + name: "大豆油(1噸/桶)", + inStockQty: 0, + purchaseQty: 20, + }, + { + id: 2, + code: "FA0161", + name: "洋蔥粒", + inStockQty: 0, + purchaseQty: 10, + }, + ], + }, + { + id: 3, + code: " PP1188", + name: "咖喱膽", + inStockQty: 1016.2, + productionQty: 508.1, + lines: [ + { + id: 1, + code: "MH0040", + name: "大豆油(1噸/桶)", + inStockQty: 0, + purchaseQty: 217.72, + }, + { + id: 2, + code: "FA0161", + name: "洋蔥粒", + inStockQty: 0, + purchaseQty: 18.15, + }, + { + id: 3, + code: "FA0608", + name: "粗蒜茸", + inStockQty: 0, + purchaseQty: 18.15, + }, + { + id: 4, + code: "MG1288", + name: "炸紅蔥頭", + inStockQty: 0, + purchaseQty: 6.05, + }, + { + id: 5, + code: "FA0210", + name: "薑茸", + inStockQty: 0, + purchaseQty: 6.05, + }, + { + id: 6, + code: "MG0066", + name: "咖哩料(5斤x16包+2斤/包)", + inStockQty: 0, + purchaseQty: 241.98, + }, + ], + }, + { + id: 4, + code: " PP1096", + name: "白麵撈", + inStockQty: 1040, + productionQty: 520, + lines: [ + { + id: 1, + code: "MH0040", + name: "大豆油(1噸/桶)", + inStockQty: 0, + purchaseQty: 190.0, + }, + { + id: 1, + code: "MH0040", + name: "星加坡綠富貴花牌幼白麵粉 (50磅/包)", + inStockQty: 0, + purchaseQty: 250.0, + }, + { + id: 2, + code: "FA0161", + name: "蔥油", + inStockQty: 1322, + purchaseQty: 0, + }, + ], + }, + ], + [ + { + id: 1, + code: "PP1080", + type: "FG", + name: "咖哩汁", + inStockQty: 2400, + productionQty: 1200.0, + lines: [ + { + id: 1, + code: "MH0040", + type: "Material", + name: "大豆油(1噸/桶)", + inStockQty: 0, + purchaseQty: 108.88, + }, + { + id: 2, + code: "GI3236", + type: "Material", + name: "清水(煮過牛腩)", + inStockQty: 317.52, + purchaseQty: 635.04, + }, + { + id: 3, + code: "MG1700", + type: "Material", + name: "STERILTOM 意大利茄粒", + inStockQty: 9.0, + purchaseQty: 18.0, + }, + { + id: 4, + code: "FA0533", + type: "Material", + name: "乾蔥茸", + inStockQty: 6.04, + purchaseQty: 12.08, + }, + { + id: 5, + code: "FA0210", + type: "Material", + name: "薑茸", + inStockQty: 0, + purchaseQty: 12.08, + }, + { + id: 6, + code: "FA0608", + type: "Material", + name: "粗蒜茸", + inStockQty: 0, + purchaseQty: 12.08, + }, + { + id: 7, + code: "FA0056", + type: "Material", + name: "洋蔥肉", + inStockQty: 241.98, + purchaseQty: 483.96, + }, + { + id: 8, + code: "PP1188", + type: "Material", + name: "咖喱膽", + inStockQty: 36.0, + purchaseQty: 72.0, + }, + { + id: 9, + code: "PP8001", + type: "Material", + name: "咖哩汁箱料粉", + inStockQty: 77.42, + purchaseQty: 154.84, + }, + { + id: 10, + code: "PP1096", + type: "Material", + name: "白麵撈", + inStockQty: 60.0, + purchaseQty: 120.0, + }, + { + id: 10, + code: "NA0476", + type: "Material", + name: "2磅份量三邊覆合袋 (0.1x225x260mm)個計", + inStockQty: 600.0, + purchaseQty: 200.0, + }, + ], + }, + { + id: 2, + code: "PP1193", + type: "FG", + name: "蔥油(1磅) ", + inStockQty: 1322, + productionQty: 661, + lines: [ + { + id: 1, + code: "MH0040", + type: "Material", + name: "大豆油(1噸/桶)", + inStockQty: 0, + purchaseQty: 20, + }, + { + id: 2, + code: "FA0161", + type: "Material", + name: "洋蔥粒", + inStockQty: 0, + purchaseQty: 10, + }, + ], + }, + { + id: 3, + code: " PP1188", + type: "FG", + name: "咖喱膽", + inStockQty: 1016.2, + productionQty: 508.1, + lines: [ + { + id: 1, + code: "MH0040", + type: "Material", + name: "大豆油(1噸/桶)", + inStockQty: 0, + purchaseQty: 217.72, + }, + { + id: 2, + code: "FA0161", + type: "Material", + name: "洋蔥粒", + inStockQty: 0, + purchaseQty: 18.15, + }, + { + id: 3, + code: "FA0608", + type: "Material", + name: "粗蒜茸", + inStockQty: 0, + purchaseQty: 18.15, + }, + { + id: 4, + code: "MG1288", + type: "Material", + name: "炸紅蔥頭", + inStockQty: 0, + purchaseQty: 6.05, + }, + { + id: 5, + code: "FA0210", + type: "Material", + name: "薑茸", + inStockQty: 0, + purchaseQty: 6.05, + }, + { + id: 6, + code: "MG0066", + type: "Material", + name: "咖哩料(5斤x16包+2斤/包)", + inStockQty: 0, + purchaseQty: 241.98, + }, + ], + }, + { + id: 4, + code: " PP1096", + type: "FG", + name: "白麵撈", + inStockQty: 1040, + productionQty: 520, + lines: [ + { + id: 1, + code: "MH0040", + type: "Material", + name: "大豆油(1噸/桶)", + inStockQty: 0, + purchaseQty: 190.0, + }, + { + id: 1, + code: "MH0040", + type: "Material", + name: "星加坡綠富貴花牌幼白麵粉 (50磅/包)", + inStockQty: 0, + purchaseQty: 250.0, + }, + { + id: 2, + code: "FA0161", + type: "Material", + name: "蔥油", + inStockQty: 1322, + purchaseQty: 0, + }, + ], + }, + ], + [ + { + id: 1, + code: "PP1080", + type: "FG", + name: "咖哩汁", + inStockQty: 2400, + productionQty: 1200.0, + lines: [ + { + id: 1, + code: "MH0040", + type: "Material", + name: "大豆油(1噸/桶)", + inStockQty: 0, + purchaseQty: 108.88, + }, + { + id: 2, + code: "GI3236", + type: "Material", + name: "清水(煮過牛腩)", + inStockQty: 317.52, + purchaseQty: 635.04, + }, + { + id: 3, + code: "MG1700", + type: "Material", + name: "STERILTOM 意大利茄粒", + inStockQty: 9.0, + purchaseQty: 18.0, + }, + { + id: 4, + code: "FA0533", + type: "Material", + name: "乾蔥茸", + inStockQty: 6.04, + purchaseQty: 12.08, + }, + { + id: 5, + code: "FA0210", + type: "Material", + name: "薑茸", + inStockQty: 0, + purchaseQty: 12.08, + }, + { + id: 6, + code: "FA0608", + type: "Material", + name: "粗蒜茸", + inStockQty: 0, + purchaseQty: 12.08, + }, + { + id: 7, + code: "FA0056", + type: "Material", + name: "洋蔥肉", + inStockQty: 241.98, + purchaseQty: 483.96, + }, + { + id: 8, + code: "PP1188", + type: "Material", + name: "咖喱膽", + inStockQty: 36.0, + purchaseQty: 72.0, + }, + { + id: 9, + code: "PP8001", + type: "Material", + name: "咖哩汁箱料粉", + inStockQty: 77.42, + purchaseQty: 154.84, + }, + { + id: 10, + code: "PP1096", + type: "Material", + name: "白麵撈", + inStockQty: 60.0, + purchaseQty: 120.0, + }, + { + id: 10, + code: "NA0476", + type: "Material", + name: "2磅份量三邊覆合袋 (0.1x225x260mm)個計", + inStockQty: 600.0, + purchaseQty: 200.0, + }, + ], + }, + { + id: 2, + code: "PP1193", + type: "FG", + name: "蔥油(1磅) ", + inStockQty: 1322, + productionQty: 661, + lines: [ + { + id: 1, + code: "MH0040", + type: "Material", + name: "大豆油(1噸/桶)", + inStockQty: 0, + purchaseQty: 20, + }, + { + id: 2, + code: "FA0161", + type: "Material", + name: "洋蔥粒", + inStockQty: 0, + purchaseQty: 10, + }, + ], + }, + { + id: 3, + code: " PP1188", + type: "FG", + name: "咖喱膽", + inStockQty: 1016.2, + productionQty: 508.1, + lines: [ + { + id: 1, + code: "MH0040", + type: "Material", + name: "大豆油(1噸/桶)", + inStockQty: 0, + purchaseQty: 217.72, + }, + { + id: 2, + code: "FA0161", + type: "Material", + name: "洋蔥粒", + inStockQty: 0, + purchaseQty: 18.15, + }, + { + id: 3, + code: "FA0608", + type: "Material", + name: "粗蒜茸", + inStockQty: 0, + purchaseQty: 18.15, + }, + { + id: 4, + code: "MG1288", + type: "Material", + name: "炸紅蔥頭", + inStockQty: 0, + purchaseQty: 6.05, + }, + { + id: 5, + code: "FA0210", + type: "Material", + name: "薑茸", + inStockQty: 0, + purchaseQty: 6.05, + }, + { + id: 6, + code: "MG0066", + type: "Material", + name: "咖哩料(5斤x16包+2斤/包)", + inStockQty: 0, + purchaseQty: 241.98, + }, + ], + }, + { + id: 4, + code: " PP1096", + type: "FG", + name: "白麵撈", + inStockQty: 1040, + productionQty: 520, + lines: [ + { + id: 1, + code: "MH0040", + type: "Material", + name: "大豆油(1噸/桶)", + inStockQty: 0, + purchaseQty: 190.0, + }, + { + id: 1, + code: "MH0040", + type: "Material", + name: "星加坡綠富貴花牌幼白麵粉 (50磅/包)", + inStockQty: 0, + purchaseQty: 250.0, + }, + { + id: 2, + code: "FA0161", + type: "Material", + name: "蔥油", + inStockQty: 1322, + purchaseQty: 0, + }, + ], + }, + ], + ], + [], + ); - const updatePagingController = (updatedObj) => { - setPagingController((prevState) => { - return prevState.map((item, index) => { - if (index === updatedObj?.index) { - return { - ...item, - pageNum: item.pageNum, - pageSize: item.pageSize, - totalCount: item.totalCount, - }; - } - else - return item - }); - }); - }; + const [pagingController, setPagingController] = useState([ + { + pageNum: 1, + pageSize: 10, + totalCount: 0, + }, + { + pageNum: 1, + pageSize: 10, + totalCount: 0, + }, + { + pageNum: 1, + pageSize: 10, + totalCount: 0, + }, + { + pageNum: 1, + pageSize: 10, + totalCount: 0, + }, + { + pageNum: 1, + pageSize: 10, + totalCount: 0, + }, + { + pageNum: 1, + pageSize: 10, + totalCount: 0, + }, + { + pageNum: 1, + pageSize: 10, + totalCount: 0, + }, + { + pageNum: 1, + pageSize: 10, + totalCount: 0, + }, + ]); - const columns = useMemo[]>( - () => [ - { - field: "jobNo", - label: t("Job No."), - type: 'read-only', - // editable: true, - }, - { - field: "code", - label: t("code"), - type: 'read-only', - // editable: true, - }, - { - field: "name", - label: t("name"), - type: 'read-only', - }, - { - field: "type", - label: t("type"), - type: 'read-only', - // editable: true, - }, - // { - // field: "inStockQty", - // label: "Available Qty", - // type: 'read-only', - // style: { - // textAlign: "right", - // }, - // // editable: true, - // renderCell: (row: FGRecord) => { - // if (typeof (row.inStockQty) == "number") { - // return decimalFormatter.format(row.inStockQty) - // } - // return row.inStockQty - // } - // }, - { - field: "productionQty", - label: t("Demand Qty"), - type: 'input', - style: { - textAlign: "right", - }, - renderCell: (row: FGRecord) => { - if (typeof (row.productionQty) == "number") { - return decimalFormatter.format(row.productionQty ?? 0) - } - return row.productionQty - } - }, - { - field: "estimatedProductionTime", - label: t("Estimated Production Time"), - type: "read-only", - style: { - textAlign: "right", - } - }, - { - field: "priority", - label: t("Production Priority"), - type: 'read-only', - style: { - textAlign: "right", - }, - // editable: true, - }, - ], - [] - ); + const updatePagingController = (updatedObj) => { + setPagingController((prevState) => { + return prevState.map((item, index) => { + if (index === updatedObj?.index) { + return { + ...item, + pageNum: item.pageNum, + pageSize: item.pageSize, + totalCount: item.totalCount, + }; + } else return item; + }); + }); + }; - const overallColumns = useMemo[]>( - () => [ - { - field: "code", - label: t("code"), - type: 'read-only', - // editable: true, - }, - { - field: "name", - label: t("name"), - type: 'read-only', - }, - { - field: "type", - label: t("type"), - type: 'read-only', - // editable: true, - }, - { - field: "lastMonthAvgStock", - label: t("Last Month Average Stock"), - type: 'read-only', - style: { - textAlign: "right", - }, - renderCell: (row: FGRecord) => { - if (typeof (row.lastMonthAvgStock) == "number") { - return decimalFormatter.format(row.lastMonthAvgStock) - } - return row.lastMonthAvgStock - } - // editable: true, - }, - { - field: "safetyStock", - label: t("Safety Stock"), - type: 'read-only', - style: { - textAlign: "right", - }, - renderCell: (row: FGRecord) => { - if (typeof (row.safetyStock) == "number") { - return decimalFormatter.format(row.safetyStock) - } - return row.safetyStock - } - // editable: true, - }, - { - field: "inStockQty", - label: t("Available Qty"), - type: 'read-only', - style: { - textAlign: "right", - }, - renderCell: (row: FGRecord) => { - if (typeof (row.inStockQty) == "number") { - return decimalFormatter.format(row.inStockQty) - } - return row.inStockQty - } - // editable: true, - }, - { - field: "productionQty", - label: t("Demand Qty (7 Days)"), - type: 'read-only', - style: { - textAlign: "right", - }, - renderCell: (row: FGRecord) => { - if (typeof (row.productionQty) == "number") { - return decimalFormatter.format(row.productionQty) - } - return row.productionQty - } - }, - ], - [] - ); + const columns = useMemo[]>( + () => [ + { + field: "jobNo", + label: t("Job No."), + type: "read-only", + // editable: true, + }, + { + field: "code", + label: t("code"), + type: "read-only", + // editable: true, + }, + { + field: "name", + label: t("name"), + type: "read-only", + }, + { + field: "type", + label: t("type"), + type: "read-only", + // editable: true, + }, + // { + // field: "inStockQty", + // label: "Available Qty", + // type: 'read-only', + // style: { + // textAlign: "right", + // }, + // // editable: true, + // renderCell: (row: FGRecord) => { + // if (typeof (row.inStockQty) == "number") { + // return decimalFormatter.format(row.inStockQty) + // } + // return row.inStockQty + // } + // }, + { + field: "productionQty", + label: t("Demand Qty"), + type: "input", + style: { + textAlign: "right", + }, + renderCell: (row: FGRecord) => { + if (typeof row.productionQty == "number") { + return decimalFormatter.format(row.productionQty ?? 0); + } + return row.productionQty; + }, + }, + { + field: "estimatedProductionTime", + label: t("Estimated Production Time"), + type: "read-only", + style: { + textAlign: "right", + }, + }, + { + field: "priority", + label: t("Production Priority"), + type: "read-only", + style: { + textAlign: "right", + }, + // editable: true, + }, + ], + [], + ); - const fakeOverallRecords = useMemo( - () => [ - { - id: 1, jobNo: "JO20250507001", priority: 20, code: "PP1193", type: "FG", name: "蔥油(1磅) ", lastMonthAvgStock: 1320, safetyStock: 1322, inStockQty: 1322, productionQty: 4627, - lines: [ - { id: 2, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 20 * 7 }, - { id: 3, code: "FA0161", type: "Material", name: "洋蔥粒", inStockQty: 0, purchaseQty: 10 * 7 } - ] - }, - { - id: 2, jobNo: "JO20250507002", priority: 25, code: " PP1096", type: "FG", name: "白麵撈", lastMonthAvgStock: 1040, safetyStock: 1040, inStockQty: 1040, productionQty: 3640, - lines: [ - { id: 1, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 190.00 * 7 }, - { id: 1, code: "MH0040", type: "Material", name: "星加坡綠富貴花牌幼白麵粉 (50磅/包)", inStockQty: 0, purchaseQty: 250.00 * 7 }, - { id: 2, code: "FA0161", type: "Material", name: "蔥油", inStockQty: 1322, purchaseQty: 0 }, - ] - }, - { - id: 3, jobNo: "JO20250507003", priority: 70, code: "PP1080", type: "FG", name: "咖哩汁", lastMonthAvgStock: 2400, safetyStock: 2400, inStockQty: 2400, productionQty: 8400.0 * 7, - lines: [ - { id: 1, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 54.44, purchaseQty: 544.4 * 7 }, - { id: 2, code: "GI3236", type: "Material", name: "清水(煮過牛腩)", inStockQty: 317.52, purchaseQty: 3175.2 * 7 }, - { id: 3, code: "MG1700", type: "Material", name: "STERILTOM 意大利茄粒", inStockQty: 9.00, purchaseQty: 90 * 7 }, - { id: 4, code: "FA0533", type: "Material", name: "乾蔥茸", inStockQty: 6.04, purchaseQty: 60.4 * 7 }, - { id: 5, code: "FA0210", type: "Material", name: "薑茸", inStockQty: 6.04, purchaseQty: 60.4 * 7 }, - { id: 6, code: "FA0608", type: "Material", name: "粗蒜茸", inStockQty: 6.04, purchaseQty: 60.4 * 7 }, - { id: 7, code: "FA0056", type: "Material", name: "洋蔥肉", inStockQty: 241.98, purchaseQty: 2419.8 * 7 }, - { id: 8, code: "PP1188", type: "Material", name: "咖喱膽", inStockQty: 36.00, purchaseQty: 360 * 7 }, - { id: 9, code: "PP8001", type: "Material", name: "咖哩汁箱料粉", inStockQty: 77.42, purchaseQty: 774.2 * 7 }, - { id: 10, code: "PP1096", type: "Material", name: "白麵撈", inStockQty: 60.00, purchaseQty: 600 * 7 }, - { id: 10, code: "NA0476", type: "Material", name: "2磅份量三邊覆合袋 (0.1x225x260mm)個計", inStockQty: 600.00, purchaseQty: 6000 * 7 }, - ] - }, - { - id: 4, jobNo: "JO20250507004", priority: 80, code: " PP1188", type: "FG", name: "咖喱膽", lastMonthAvgStock: 1017, safetyStock: 1017, inStockQty: 1016.2, productionQty: 3556.7, - lines: [ - { id: 1, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 217.72 * 7 }, - { id: 2, code: "FA0161", type: "Material", name: "洋蔥粒", inStockQty: 0, purchaseQty: 18.15 * 7 }, - { id: 3, code: "FA0608", type: "Material", name: "粗蒜茸", inStockQty: 0, purchaseQty: 18.15 * 7 }, - { id: 4, code: "MG1288", type: "Material", name: "炸紅蔥頭", inStockQty: 0, purchaseQty: 6.05 * 7 }, - { id: 5, code: "FA0210", type: "Material", name: "薑茸", inStockQty: 0, purchaseQty: 6.05 * 7 }, - { id: 6, code: "MG0066", type: "Material", name: "咖哩料(5斤x16包+2斤/包)", inStockQty: 0, purchaseQty: 241.98 * 7 }, - ] - }, + const overallColumns = useMemo[]>( + () => [ + { + field: "code", + label: t("code"), + type: "read-only", + // editable: true, + }, + { + field: "name", + label: t("name"), + type: "read-only", + }, + { + field: "type", + label: t("type"), + type: "read-only", + // editable: true, + }, + { + field: "lastMonthAvgStock", + label: t("Last Month Average Stock"), + type: "read-only", + style: { + textAlign: "right", + }, + renderCell: (row: FGRecord) => { + if (typeof row.lastMonthAvgStock == "number") { + return decimalFormatter.format(row.lastMonthAvgStock); + } + return row.lastMonthAvgStock; + }, + // editable: true, + }, + { + field: "safetyStock", + label: t("Safety Stock"), + type: "read-only", + style: { + textAlign: "right", + }, + renderCell: (row: FGRecord) => { + if (typeof row.safetyStock == "number") { + return decimalFormatter.format(row.safetyStock); + } + return row.safetyStock; + }, + // editable: true, + }, + { + field: "inStockQty", + label: t("Available Qty"), + type: "read-only", + style: { + textAlign: "right", + }, + renderCell: (row: FGRecord) => { + if (typeof row.inStockQty == "number") { + return decimalFormatter.format(row.inStockQty); + } + return row.inStockQty; + }, + // editable: true, + }, + { + field: "productionQty", + label: t("Demand Qty (7 Days)"), + type: "read-only", + style: { + textAlign: "right", + }, + renderCell: (row: FGRecord) => { + if (typeof row.productionQty == "number") { + return decimalFormatter.format(row.productionQty); + } + return row.productionQty; + }, + }, + ], + [], + ); + + const fakeOverallRecords = useMemo( + () => [ + { + id: 1, + jobNo: "JO20250507001", + priority: 20, + code: "PP1193", + type: "FG", + name: "蔥油(1磅) ", + lastMonthAvgStock: 1320, + safetyStock: 1322, + inStockQty: 1322, + productionQty: 4627, + lines: [ + { + id: 2, + code: "MH0040", + type: "Material", + name: "大豆油(1噸/桶)", + inStockQty: 0, + purchaseQty: 20 * 7, + }, + { + id: 3, + code: "FA0161", + type: "Material", + name: "洋蔥粒", + inStockQty: 0, + purchaseQty: 10 * 7, + }, + ], + }, + { + id: 2, + jobNo: "JO20250507002", + priority: 25, + code: " PP1096", + type: "FG", + name: "白麵撈", + lastMonthAvgStock: 1040, + safetyStock: 1040, + inStockQty: 1040, + productionQty: 3640, + lines: [ + { + id: 1, + code: "MH0040", + type: "Material", + name: "大豆油(1噸/桶)", + inStockQty: 0, + purchaseQty: 190.0 * 7, + }, + { + id: 1, + code: "MH0040", + type: "Material", + name: "星加坡綠富貴花牌幼白麵粉 (50磅/包)", + inStockQty: 0, + purchaseQty: 250.0 * 7, + }, + { + id: 2, + code: "FA0161", + type: "Material", + name: "蔥油", + inStockQty: 1322, + purchaseQty: 0, + }, + ], + }, + { + id: 3, + jobNo: "JO20250507003", + priority: 70, + code: "PP1080", + type: "FG", + name: "咖哩汁", + lastMonthAvgStock: 2400, + safetyStock: 2400, + inStockQty: 2400, + productionQty: 8400.0 * 7, + lines: [ + { + id: 1, + code: "MH0040", + type: "Material", + name: "大豆油(1噸/桶)", + inStockQty: 54.44, + purchaseQty: 544.4 * 7, + }, + { + id: 2, + code: "GI3236", + type: "Material", + name: "清水(煮過牛腩)", + inStockQty: 317.52, + purchaseQty: 3175.2 * 7, + }, + { + id: 3, + code: "MG1700", + type: "Material", + name: "STERILTOM 意大利茄粒", + inStockQty: 9.0, + purchaseQty: 90 * 7, + }, + { + id: 4, + code: "FA0533", + type: "Material", + name: "乾蔥茸", + inStockQty: 6.04, + purchaseQty: 60.4 * 7, + }, + { + id: 5, + code: "FA0210", + type: "Material", + name: "薑茸", + inStockQty: 6.04, + purchaseQty: 60.4 * 7, + }, + { + id: 6, + code: "FA0608", + type: "Material", + name: "粗蒜茸", + inStockQty: 6.04, + purchaseQty: 60.4 * 7, + }, + { + id: 7, + code: "FA0056", + type: "Material", + name: "洋蔥肉", + inStockQty: 241.98, + purchaseQty: 2419.8 * 7, + }, + { + id: 8, + code: "PP1188", + type: "Material", + name: "咖喱膽", + inStockQty: 36.0, + purchaseQty: 360 * 7, + }, + { + id: 9, + code: "PP8001", + type: "Material", + name: "咖哩汁箱料粉", + inStockQty: 77.42, + purchaseQty: 774.2 * 7, + }, + { + id: 10, + code: "PP1096", + type: "Material", + name: "白麵撈", + inStockQty: 60.0, + purchaseQty: 600 * 7, + }, + { + id: 10, + code: "NA0476", + type: "Material", + name: "2磅份量三邊覆合袋 (0.1x225x260mm)個計", + inStockQty: 600.0, + purchaseQty: 6000 * 7, + }, + ], + }, + { + id: 4, + jobNo: "JO20250507004", + priority: 80, + code: " PP1188", + type: "FG", + name: "咖喱膽", + lastMonthAvgStock: 1017, + safetyStock: 1017, + inStockQty: 1016.2, + productionQty: 3556.7, + lines: [ + { + id: 1, + code: "MH0040", + type: "Material", + name: "大豆油(1噸/桶)", + inStockQty: 0, + purchaseQty: 217.72 * 7, + }, + { + id: 2, + code: "FA0161", + type: "Material", + name: "洋蔥粒", + inStockQty: 0, + purchaseQty: 18.15 * 7, + }, + { + id: 3, + code: "FA0608", + type: "Material", + name: "粗蒜茸", + inStockQty: 0, + purchaseQty: 18.15 * 7, + }, + { + id: 4, + code: "MG1288", + type: "Material", + name: "炸紅蔥頭", + inStockQty: 0, + purchaseQty: 6.05 * 7, + }, + { + id: 5, + code: "FA0210", + type: "Material", + name: "薑茸", + inStockQty: 0, + purchaseQty: 6.05 * 7, + }, + { + id: 6, + code: "MG0066", + type: "Material", + name: "咖哩料(5斤x16包+2斤/包)", + inStockQty: 0, + purchaseQty: 241.98 * 7, + }, ], - [] - ); + }, + ], + [], + ); - return ( - - {/* + return ( + + {/* {t("FG Demand List (7 Days)")} @@ -694,24 +2170,24 @@ const ViewByFGDetails: React.FC = ({ apiRef, isEdit }) => { hasCollapse={true} /> */} - {dayPeriod.map((date, index) => ( - - {/* + {dayPeriod.map((date, index) => ( + + {/* {`${t("FG Demand Date")}: ${date}`} */} - - items={fakeRecords[index]} // Use the corresponding records for the day - columns={columns} - setPagingController={updatePagingController} - pagingController={pagingController[index]} - isAutoPaging={false} - isEditable={true} - isEdit={isEdit} - hasCollapse={true} - /> - - ))} + + items={fakeRecords[index]} // Use the corresponding records for the day + columns={columns} + setPagingController={updatePagingController} + pagingController={pagingController[index]} + isAutoPaging={false} + isEditable={true} + isEdit={isEdit} + hasCollapse={true} + /> - ); + ))} + + ); }; export default ViewByFGDetails; diff --git a/src/components/DetailScheduleDetail/index.ts b/src/components/DetailScheduleDetail/index.ts index 3769580..e8e5b2f 100644 --- a/src/components/DetailScheduleDetail/index.ts +++ b/src/components/DetailScheduleDetail/index.ts @@ -1 +1 @@ -export { default } from "./DetailScheduleDetailWrapper"; \ No newline at end of file +export { default } from "./DetailScheduleDetailWrapper"; diff --git a/src/components/DoDetail/DoDetail.tsx b/src/components/DoDetail/DoDetail.tsx index 7ea87e2..b994b1a 100644 --- a/src/components/DoDetail/DoDetail.tsx +++ b/src/components/DoDetail/DoDetail.tsx @@ -1,3 +1,3 @@ -"use client" +"use client"; -// const doDetail = \ No newline at end of file +// const doDetail = diff --git a/src/components/DoSearch/DoSearch.tsx b/src/components/DoSearch/DoSearch.tsx index 3b2a802..f01c3e0 100644 --- a/src/components/DoSearch/DoSearch.tsx +++ b/src/components/DoSearch/DoSearch.tsx @@ -14,7 +14,13 @@ import { EditNote } from "@mui/icons-material"; import InputDataGrid from "../InputDataGrid"; import { CreateConsoDoInput } from "@/app/api/do/actions"; import { TableRow } from "../InputDataGrid/InputDataGrid"; -import { FooterPropsOverrides, GridColDef, GridRowModel, GridToolbarContainer, useGridApiRef } from "@mui/x-data-grid"; +import { + FooterPropsOverrides, + GridColDef, + GridRowModel, + GridToolbarContainer, + useGridApiRef, +} from "@mui/x-data-grid"; import { FormProvider, SubmitErrorHandler, @@ -50,35 +56,36 @@ const DoSearch: React.FC = ({ dos }) => { const tttt = [ { - id: 1, - code: "string", - orderDate: "2025-01-01", - estimatedArrivalDate: "2025-01-01", - status: "string", - shopName: "string", + id: 1, + code: "string", + orderDate: "2025-01-01", + estimatedArrivalDate: "2025-01-01", + status: "string", + shopName: "string", }, { - id: 2, - code: "string1", - orderDate: "2025-01-01", - estimatedArrivalDate: "2025-01-01", - status: "string", - shopName: "string", + id: 2, + code: "string1", + orderDate: "2025-01-01", + estimatedArrivalDate: "2025-01-01", + status: "string", + shopName: "string", }, { - id: 3, - code: "string2", - orderDate: "2025-01-01", - estimatedArrivalDate: "2025-01-01", - status: "string", - shopName: "string", + id: 3, + code: "string2", + orderDate: "2025-01-01", + estimatedArrivalDate: "2025-01-01", + status: "string", + shopName: "string", }, - ] -// const [filteredDos, setFilteredDos] = useState(dos); + ]; + // const [filteredDos, setFilteredDos] = useState(dos); const [filteredDos, setFilteredDos] = useState(tttt); const { t } = useTranslation("do"); const router = useRouter(); - const [rowSelectionModel, setRowSelectionModel] = useState([]) + const [rowSelectionModel, setRowSelectionModel] = + useState([]); const searchCriteria: Criterion[] = useMemo( () => [ @@ -101,13 +108,13 @@ const DoSearch: React.FC = ({ dos }) => { value: _do.status, label: t(upperFirst(_do.status)), })), - "value" + "value", ), - "label" + "label", ), }, ], - [t, dos] + [t, dos], ); const onReset = useCallback(() => { @@ -118,12 +125,12 @@ const DoSearch: React.FC = ({ dos }) => { (doResult: DoResult) => { router.push(`/do/edit?id=${doResult.id}`); }, - [router] + [router], ); const validationTest = useCallback( ( - newRow: GridRowModel + newRow: GridRowModel, // rowModel: GridRowSelectionModel ): EntryError => { const error: EntryError = {}; @@ -137,7 +144,7 @@ const DoSearch: React.FC = ({ dos }) => { // } return Object.keys(error).length > 0 ? error : undefined; }, - [] + [], ); const columns = useMemo( @@ -187,20 +194,20 @@ const DoSearch: React.FC = ({ dos }) => { }, }, ], - [t, arrayToDateString] + [t, arrayToDateString], ); const onSubmit = useCallback>( async (data, event) => { - let hasErrors = false; + const hasErrors = false; console.log(errors); console.log(data); }, - [] + [], ); const onSubmitError = useCallback>( (errors) => {}, - [] + [], ); return ( <> @@ -255,7 +262,7 @@ const DoSearch: React.FC = ({ dos }) => { doOrderDateStr.isSame(query.orderDateTo) || doOrderDateStr.isBefore(query.orderDateTo)) ); - }) + }), ); }} onReset={onReset} @@ -267,7 +274,7 @@ const DoSearch: React.FC = ({ dos }) => { rowSelectionModel={rowSelectionModel} onRowSelectionModelChange={(newRowSelectionModel) => { setRowSelectionModel(newRowSelectionModel); - formProps.setValue("ids", newRowSelectionModel) + formProps.setValue("ids", newRowSelectionModel); }} slots={{ footer: FooterToolbar, diff --git a/src/components/DoSearch/DoSearchWrapper.tsx b/src/components/DoSearch/DoSearchWrapper.tsx index 4cf3631..93934b7 100644 --- a/src/components/DoSearch/DoSearchWrapper.tsx +++ b/src/components/DoSearch/DoSearchWrapper.tsx @@ -1,22 +1,17 @@ import React from "react"; -import GeneralLoading from "../General/GeneralLoading" +import GeneralLoading from "../General/GeneralLoading"; import { fetchDoList } from "@/app/api/do"; import DoSearch from "./DoSearch"; interface SubComponents { - Loading: typeof GeneralLoading; + Loading: typeof GeneralLoading; } const DoSearchWrapper: React.FC & SubComponents = async () => { - - const [ - dos - ] = await Promise.all([ - fetchDoList() - ]); - return -} + const [dos] = await Promise.all([fetchDoList()]); + return ; +}; DoSearchWrapper.Loading = GeneralLoading; -export default DoSearchWrapper; \ No newline at end of file +export default DoSearchWrapper; diff --git a/src/components/DoSearch/index.ts b/src/components/DoSearch/index.ts index 4cb8a1d..0da216c 100644 --- a/src/components/DoSearch/index.ts +++ b/src/components/DoSearch/index.ts @@ -1 +1 @@ -export { default } from "./DoSearchWrapper" \ No newline at end of file +export { default } from "./DoSearchWrapper"; diff --git a/src/components/EditUser/AuthAllocation.tsx b/src/components/EditUser/AuthAllocation.tsx index fe6c5a9..574fc11 100644 --- a/src/components/EditUser/AuthAllocation.tsx +++ b/src/components/EditUser/AuthAllocation.tsx @@ -57,9 +57,9 @@ const AuthAllocation: React.FC = ({ auths }) => { const [selectedAuths, setSelectedAuths] = useState( () => { return filteredAuths.filter( - (s) => getValues("addAuthIds")?.includes(s.id) + (s) => getValues("addAuthIds")?.includes(s.id), ); - } + }, ); const [removeAuthIds, setRemoveAuthIds] = useState([]); @@ -77,8 +77,8 @@ const AuthAllocation: React.FC = ({ auths }) => { resetField("addAuthIds"); setSelectedAuths( initialAuths.filter( - (auth) => defaultValues.addAuthIds?.includes(auth.id) - ) + (auth) => defaultValues.addAuthIds?.includes(auth.id), + ), ); } }, [defaultValues]); @@ -87,7 +87,7 @@ const AuthAllocation: React.FC = ({ auths }) => { useEffect(() => { setValue( "addAuthIds", - selectedAuths.map((a) => a.id) + selectedAuths.map((a) => a.id), ); setValue("removeAuthIds", removeAuthIds); }, [selectedAuths, removeAuthIds, setValue]); @@ -103,7 +103,7 @@ const AuthAllocation: React.FC = ({ auths }) => { { label: t("authority"), name: "authority" }, { label: t("description"), name: "name" }, ], - [addAuth, t] + [addAuth, t], ); const allocatedAuthColumns = useMemo[]>( @@ -117,7 +117,7 @@ const AuthAllocation: React.FC = ({ auths }) => { { label: t("authority"), name: "authority" }, { label: t("description"), name: "name" }, ], - [removeAuth, selectedAuths, t] + [removeAuth, selectedAuths, t], ); const [query, setQuery] = React.useState(""); @@ -132,12 +132,11 @@ const AuthAllocation: React.FC = ({ auths }) => { React.useEffect(() => { setFilteredAuths( - initialAuths.filter((a) => - ( - a.authority.toLowerCase().includes(query.toLowerCase()) || - a.name?.toLowerCase().includes(query.toLowerCase()) - ) - ) + initialAuths.filter( + (a) => + a.authority.toLowerCase().includes(query.toLowerCase()) || + a.name?.toLowerCase().includes(query.toLowerCase()), + ), ); }, [auths, query]); @@ -154,7 +153,7 @@ const AuthAllocation: React.FC = ({ auths }) => { (_e, newValue) => { setTabIndex(newValue); }, - [] + [], ); return ( @@ -177,7 +176,7 @@ const AuthAllocation: React.FC = ({ auths }) => { onChange={onQueryInputChange} value={query} placeholder={t( - "Search by Authority or description or position." + "Search by Authority or description or position.", )} InputProps={{ endAdornment: query && ( diff --git a/src/components/EditUser/EditUser.tsx b/src/components/EditUser/EditUser.tsx index 27f6609..23a7ffd 100644 --- a/src/components/EditUser/EditUser.tsx +++ b/src/components/EditUser/EditUser.tsx @@ -48,7 +48,7 @@ interface Props { } const EditUser: React.FC = async ({ user, rules, auths }) => { - console.log(user) + console.log(user); const { t } = useTranslation("user"); const formProps = useForm(); const searchParams = useSearchParams(); @@ -68,7 +68,7 @@ const EditUser: React.FC = async ({ user, rules, auths }) => { (_e, newValue) => { setTabIndex(newValue); }, - [] + [], ); const errors = formProps.formState.errors; @@ -98,7 +98,7 @@ const EditUser: React.FC = async ({ user, rules, auths }) => { const hasErrorsInTab = ( tabIndex: number, - errors: FieldErrors + errors: FieldErrors, ) => { switch (tabIndex) { case 0: @@ -116,7 +116,7 @@ const EditUser: React.FC = async ({ user, rules, auths }) => { async (data) => { try { let haveError = false; - let regex_pw = + const regex_pw = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*])[A-Za-z\d!@#$%^&*]{8,20}$/; let pw = ""; if (data.password && data.password.length > 0) { @@ -170,13 +170,13 @@ const EditUser: React.FC = async ({ user, rules, auths }) => { setServerError(t("An error has occurred. Please try again later.")); } }, - [router] + [router], ); const onSubmitError = useCallback>( (errors) => { console.log(errors); }, - [] + [], ); return ( diff --git a/src/components/EditUser/EditUserLoading.tsx b/src/components/EditUser/EditUserLoading.tsx index 971c9e4..f7e66a8 100644 --- a/src/components/EditUser/EditUserLoading.tsx +++ b/src/components/EditUser/EditUserLoading.tsx @@ -16,14 +16,15 @@ export const EditUserLoading: React.FC = () => { - EditUser + + EditUser diff --git a/src/components/EditUser/EditUserWrapper.tsx b/src/components/EditUser/EditUserWrapper.tsx index dc0743b..19ea8d8 100644 --- a/src/components/EditUser/EditUserWrapper.tsx +++ b/src/components/EditUser/EditUserWrapper.tsx @@ -21,8 +21,8 @@ const EditUserWrapper: React.FC & SubComponents = async ({ fetchUserDetails(id), fetchAuth("user", id), ]); - console.log(user.data) - console.log(auths.records) + console.log(user.data); + console.log(auths.records); return ; }; diff --git a/src/components/EditUser/UserDetail.tsx b/src/components/EditUser/UserDetail.tsx index 42719e5..42d1754 100644 --- a/src/components/EditUser/UserDetail.tsx +++ b/src/components/EditUser/UserDetail.tsx @@ -15,7 +15,6 @@ import { useFormContext } from "react-hook-form"; import { useTranslation } from "react-i18next"; const UserDetail: React.FC = () => { - const { t } = useTranslation("user"); const { register, @@ -46,10 +45,10 @@ const UserDetail: React.FC = () => { fullWidth {...register("password")} // helperText={ - // Boolean(errors.password) && + // Boolean(errors.password) && // (errors.password?.message // ? t(errors.password.message) - // : + // : // (<> // - 8-20 characters //
@@ -59,7 +58,7 @@ const UserDetail: React.FC = () => { //
// - Numbers //
- // - Symbols + // - Symbols // ) // ) // } @@ -90,8 +89,8 @@ const UserDetail: React.FC = () => { export default UserDetail; - -{/* <> +{ + /* <> - 8-20 characters
- Uppercase letters @@ -101,4 +100,5 @@ export default UserDetail; - Numbers
- Symbols - */} \ No newline at end of file + */ +} diff --git a/src/components/EnterLeave/EnterLeaveModal.tsx b/src/components/EnterLeave/EnterLeaveModal.tsx index 95a0a12..0d8f8c0 100644 --- a/src/components/EnterLeave/EnterLeaveModal.tsx +++ b/src/components/EnterLeave/EnterLeaveModal.tsx @@ -49,7 +49,6 @@ const EnterTimesheetModal: React.FC = ({ // method: "GET", // mode: 'no-cors', // }); - // console.log(res.json); }; @@ -62,7 +61,8 @@ const EnterTimesheetModal: React.FC = ({
*/} - = ({ top: "50%", left: "50%", transform: "translate(-50%, -50%)", - }}> - + }} + > +
= ({ // method: "GET", // mode: 'no-cors', // }); - // console.log(res.json); }; @@ -67,7 +66,8 @@ const EnterTimesheetModal: React.FC = ({
*/} - = ({ top: "50%", left: "50%", transform: "translate(-50%, -50%)", - }}> - + }} + > +
>; type SearchParamNames = keyof SearchQuery; const EquipmentSearch: React.FC = ({ equipments }) => { - const [filteredEquipments, setFilteredEquipments] = useState(equipments); + const [filteredEquipments, setFilteredEquipments] = + useState(equipments); const { t } = useTranslation("common"); const router = useRouter(); const [filterObj, setFilterObj] = useState({}); @@ -29,9 +30,9 @@ const EquipmentSearch: React.FC = ({ equipments }) => { pageSize: 10, // totalCount: 0, }); - const [totalCount, setTotalCount] = useState(0) + const [totalCount, setTotalCount] = useState(0); const searchCriteria: Criterion[] = useMemo(() => { - var searchCriteria: Criterion[] = [ + const searchCriteria: Criterion[] = [ { label: t("Code"), paramName: "code", type: "text" }, { label: t("Description"), paramName: "description", type: "text" }, ]; @@ -42,10 +43,13 @@ const EquipmentSearch: React.FC = ({ equipments }) => { (equipment: EquipmentResult) => { router.push(`/settings/equipment/edit?id=${equipment.id}`); }, - [router] + [router], ); - const onDeleteClick = useCallback((equipment: EquipmentResult) => {}, [router]); + const onDeleteClick = useCallback( + (equipment: EquipmentResult) => {}, + [router], + ); const columns = useMemo[]>( () => [ @@ -74,7 +78,7 @@ const EquipmentSearch: React.FC = ({ equipments }) => { onClick: onDeleteClick, }, ], - [filteredEquipments] + [filteredEquipments], ); const refetchData = useCallback( @@ -91,12 +95,12 @@ const EquipmentSearch: React.FC = ({ equipments }) => { try { const response = await axiosInstance.get( `${NEXT_PUBLIC_API_URL}/Equipment/getRecordByPage`, - { params } + { params }, ); console.log(response); if (response.status == 200) { setFilteredEquipments(response.data.records); - setTotalCount(response.data.total) + setTotalCount(response.data.total); return response; // Return the data from the response } else { throw "400"; @@ -106,7 +110,7 @@ const EquipmentSearch: React.FC = ({ equipments }) => { throw error; // Rethrow the error for further handling } }, - [axiosInstance, pagingController.pageNum, pagingController.pageSize] + [axiosInstance, pagingController.pageNum, pagingController.pageSize], ); useEffect(() => { diff --git a/src/components/EquipmentSearch/EquipmentSearchWrapper.tsx b/src/components/EquipmentSearch/EquipmentSearchWrapper.tsx index 36da541..0efe9a7 100644 --- a/src/components/EquipmentSearch/EquipmentSearchWrapper.tsx +++ b/src/components/EquipmentSearch/EquipmentSearchWrapper.tsx @@ -1,4 +1,4 @@ -import { fetchAllEquipments, } from "@/app/api/settings/equipment"; +import { fetchAllEquipments } from "@/app/api/settings/equipment"; import EquipmentSearchLoading from "./EquipmentSearchLoading"; import { SearchParams } from "@/app/utils/fetchUtil"; import { TypeEnum } from "@/app/utils/typeEnum"; @@ -13,9 +13,11 @@ type Props = { // type: TypeEnum; }; -const EquipmentSearchWrapper: React.FC & SubComponents = async ({ - // type, -}) => { +const EquipmentSearchWrapper: React.FC & SubComponents = async ( + { + // type, + }, +) => { // console.log(type) // var result = await fetchAllEquipmentTypes() return ; diff --git a/src/components/EquipmentTypeSearch/EquipmentTypeSearch.tsx b/src/components/EquipmentTypeSearch/EquipmentTypeSearch.tsx index 5edd672..25605c0 100644 --- a/src/components/EquipmentTypeSearch/EquipmentTypeSearch.tsx +++ b/src/components/EquipmentTypeSearch/EquipmentTypeSearch.tsx @@ -20,7 +20,8 @@ type SearchQuery = Partial>; type SearchParamNames = keyof SearchQuery; const EquipmentTypeSearch: React.FC = ({ equipmentTypes }) => { - const [filteredEquipmentTypes, setFilteredEquipmentTypes] = useState(equipmentTypes); + const [filteredEquipmentTypes, setFilteredEquipmentTypes] = + useState(equipmentTypes); const { t } = useTranslation("common"); const router = useRouter(); const [filterObj, setFilterObj] = useState({}); @@ -29,9 +30,9 @@ const EquipmentTypeSearch: React.FC = ({ equipmentTypes }) => { pageSize: 10, // totalCount: 0, }); - const [totalCount, setTotalCount] = useState(0) + const [totalCount, setTotalCount] = useState(0); const searchCriteria: Criterion[] = useMemo(() => { - var searchCriteria: Criterion[] = [ + const searchCriteria: Criterion[] = [ { label: t("Code"), paramName: "code", type: "text" }, { label: t("Description"), paramName: "description", type: "text" }, ]; @@ -42,10 +43,13 @@ const EquipmentTypeSearch: React.FC = ({ equipmentTypes }) => { (equipmentType: EquipmentTypeResult) => { router.push(`/settings/equipmentType/edit?id=${equipmentType.id}`); }, - [router] + [router], ); - const onDeleteClick = useCallback((equipmentType: EquipmentTypeResult) => {}, [router]); + const onDeleteClick = useCallback( + (equipmentType: EquipmentTypeResult) => {}, + [router], + ); const columns = useMemo[]>( () => [ @@ -70,7 +74,7 @@ const EquipmentTypeSearch: React.FC = ({ equipmentTypes }) => { onClick: onDeleteClick, }, ], - [filteredEquipmentTypes] + [filteredEquipmentTypes], ); const refetchData = useCallback( @@ -87,12 +91,12 @@ const EquipmentTypeSearch: React.FC = ({ equipmentTypes }) => { try { const response = await axiosInstance.get( `${NEXT_PUBLIC_API_URL}/EquipmentType/getRecordByPage`, - { params } + { params }, ); console.log(response); if (response.status == 200) { setFilteredEquipmentTypes(response.data.records); - setTotalCount(response.data.total) + setTotalCount(response.data.total); return response; // Return the data from the response } else { throw "400"; @@ -102,7 +106,7 @@ const EquipmentTypeSearch: React.FC = ({ equipmentTypes }) => { throw error; // Rethrow the error for further handling } }, - [axiosInstance, pagingController.pageNum, pagingController.pageSize] + [axiosInstance, pagingController.pageNum, pagingController.pageSize], ); useEffect(() => { diff --git a/src/components/EquipmentTypeSearch/EquipmentTypeSearchWrapper.tsx b/src/components/EquipmentTypeSearch/EquipmentTypeSearchWrapper.tsx index b911219..7a747a8 100644 --- a/src/components/EquipmentTypeSearch/EquipmentTypeSearchWrapper.tsx +++ b/src/components/EquipmentTypeSearch/EquipmentTypeSearchWrapper.tsx @@ -1,4 +1,4 @@ -import { fetchAllEquipmentTypes, } from "@/app/api/settings/equipmentType"; +import { fetchAllEquipmentTypes } from "@/app/api/settings/equipmentType"; import EquipmentTypeSearchLoading from "./EquipmentTypeSearchLoading"; import { SearchParams } from "@/app/utils/fetchUtil"; import { TypeEnum } from "@/app/utils/typeEnum"; @@ -13,9 +13,11 @@ type Props = { // type: TypeEnum; }; -const EquipmentTypeSearchWrapper: React.FC & SubComponents = async ({ - // type, -}) => { +const EquipmentTypeSearchWrapper: React.FC & SubComponents = async ( + { + // type, + }, +) => { // console.log(type) // var result = await fetchAllEquipmentTypes() return ; diff --git a/src/components/General/GeneralLoading.tsx b/src/components/General/GeneralLoading.tsx index 14031b5..3df3ba6 100644 --- a/src/components/General/GeneralLoading.tsx +++ b/src/components/General/GeneralLoading.tsx @@ -5,35 +5,36 @@ import Stack from "@mui/material/Stack"; import React from "react"; export const GeneralLoading: React.FC = () => { - return ( - <> - - - - - - - - - - - CreateMaterial - - - - - - - - - - - ); + return ( + <> + + + + + + + + + + + + CreateMaterial + + + + + + + + + + + ); }; export default GeneralLoading; diff --git a/src/components/InputDataGrid/InputDataGrid.tsx b/src/components/InputDataGrid/InputDataGrid.tsx index effcdf0..c8a3c83 100644 --- a/src/components/InputDataGrid/InputDataGrid.tsx +++ b/src/components/InputDataGrid/InputDataGrid.tsx @@ -1,4 +1,4 @@ -"use client" +"use client"; import { Dispatch, MutableRefObject, @@ -33,7 +33,10 @@ import CancelIcon from "@mui/icons-material/Cancel"; import { Add } from "@mui/icons-material"; import { Box, Button, Typography } from "@mui/material"; import { useTranslation } from "react-i18next"; -import { GridApiCommunity, GridSlotsComponentsProps } from "@mui/x-data-grid/internals"; +import { + GridApiCommunity, + GridSlotsComponentsProps, +} from "@mui/x-data-grid/internals"; interface ResultWithId { id: string | number; @@ -51,7 +54,7 @@ interface SelectionResult { _isNew: boolean; _error: E; } -type Result = DefaultResult | SelectionResult +type Result = DefaultResult | SelectionResult; export type TableRow = Partial< V & { @@ -62,24 +65,27 @@ export type TableRow = Partial< >; export interface InputDataGridProps { - apiRef: MutableRefObject + apiRef: MutableRefObject; checkboxSelection: false | undefined; _formKey: keyof T; columns: GridColDef[]; validateRow: (newRow: GridRowModel>) => E; - needAdd?: Boolean -}; + needAdd?: boolean; +} -export interface SelectionInputDataGridProps { // thinking how do - apiRef: MutableRefObject +export interface SelectionInputDataGridProps { + // thinking how do + apiRef: MutableRefObject; checkboxSelection: true; _formKey: keyof T; columns: GridColDef[]; validateRow: (newRow: GridRowModel>) => E; - needAdd?: Boolean + needAdd?: boolean; } -export type Props = InputDataGridProps | SelectionInputDataGridProps +export type Props = + | InputDataGridProps + | SelectionInputDataGridProps; export class ProcessRowUpdateError extends Error { public readonly row: T; public readonly errors: E | undefined; @@ -106,14 +112,13 @@ function InputDataGrid({ t, // i18n: { language }, } = useTranslation("common"); - const formKey = _formKey.toString() + const formKey = _formKey.toString(); const { setValue, getValues } = useFormContext(); - const [rowModesModel, setRowModesModel] = - useState({}); + const [rowModesModel, setRowModesModel] = useState({}); // const apiRef = useGridApiRef(); const getRowId = useCallback>>( - (row) => row.id!! as number, - [] + (row) => row.id! as number, + [], ); const list: TableRow[] = getValues(formKey); // console.log(list) @@ -122,13 +127,16 @@ function InputDataGrid({ return list && list.length > 0 ? list : []; }); const originalRows = list && list.length > 0 ? list : []; - // const originalRowModel = originalRows.filter((li) => li.isActive).map(i => i.id) as GridRowSelectionModel - const [rowSelectionModel, setRowSelectionModel] = useState(() => { - // const rowModel = list.filter((li) => li.isActive).map(i => i.id) as GridRowSelectionModel - const rowModel: GridRowSelectionModel = getValues(`${formKey}_active`) as GridRowSelectionModel - console.log(rowModel) - return rowModel - }); + // const originalRowModel = originalRows.filter((li) => li.isActive).map(i => i.id) as GridRowSelectionModel + const [rowSelectionModel, setRowSelectionModel] = + useState(() => { + // const rowModel = list.filter((li) => li.isActive).map(i => i.id) as GridRowSelectionModel + const rowModel: GridRowSelectionModel = getValues( + `${formKey}_active`, + ) as GridRowSelectionModel; + console.log(rowModel); + return rowModel; + }); const handleSave = useCallback( (id: GridRowId) => () => { @@ -137,7 +145,7 @@ function InputDataGrid({ [id]: { mode: GridRowModes.View }, })); }, - [] + [], ); const onProcessRowUpdateError = useCallback( (updateError: ProcessRowUpdateError) => { @@ -146,18 +154,18 @@ function InputDataGrid({ console.log(errors); apiRef.current.updateRows([{ ...row, _error: errors }]); }, - [apiRef, rowModesModel] + [apiRef, rowModesModel], ); const processRowUpdate = useCallback( ( newRow: GridRowModel>, - originalRow: GridRowModel> + originalRow: GridRowModel>, ) => { ///////////////// // validation here const errors = validateRow(newRow); - console.log(newRow) + console.log(newRow); if (errors) { throw new ProcessRowUpdateError( originalRow, @@ -170,13 +178,13 @@ function InputDataGrid({ const rowToSave = { ...updatedRow, } as TableRow; /// test - console.log(rowToSave) + console.log(rowToSave); setRows((rw) => - rw.map((r) => (getRowId(r) === getRowId(originalRow) ? rowToSave : r)) + rw.map((r) => (getRowId(r) === getRowId(originalRow) ? rowToSave : r)), ); return rowToSave; }, - [validateRow, getRowId] + [validateRow, getRowId], ); const addRow = useCallback(() => { @@ -192,8 +200,8 @@ function InputDataGrid({ }, [getRowId]); const reset = useCallback(() => { - setRowModesModel({}) - setRows(originalRows) + setRowModesModel({}); + setRows(originalRows); }, []); const handleCancel = useCallback( @@ -204,22 +212,21 @@ function InputDataGrid({ })); const editedRow = rows.find((row) => getRowId(row) === id); if (editedRow?._isNew) { - setRows((rw) => rw.filter((r) => getRowId(r) !== id - )); + setRows((rw) => rw.filter((r) => getRowId(r) !== id)); } else { setRows((rw) => - rw.map((r) => (getRowId(r) === id ? { ...r, _error: undefined } : r)) + rw.map((r) => (getRowId(r) === id ? { ...r, _error: undefined } : r)), ); } }, - [setRowModesModel, rows] + [setRowModesModel, rows], ); - + const handleDelete = useCallback( (id: GridRowId) => () => { setRows((prevRows) => prevRows.filter((row) => getRowId(row) !== id)); }, - [] + [], ); const _columns = useMemo( @@ -267,7 +274,7 @@ function InputDataGrid({ }, }, ], - [columns, rowModesModel, handleSave, handleCancel, handleDelete] + [columns, rowModesModel, handleSave, handleCancel, handleDelete], ); // sync useForm useEffect(() => { @@ -298,11 +305,11 @@ function InputDataGrid({ ); -// const handleRowEditStop: GridEventListener<'rowEditStop'> = (params, event) => { -// if (params.reason === GridRowEditStopReasons.rowFocusOut) { -// event.defaultMuiPrevented = true; -// } -// }; + // const handleRowEditStop: GridEventListener<'rowEditStop'> = (params, event) => { + // if (params.reason === GridRowEditStopReasons.rowFocusOut) { + // event.defaultMuiPrevented = true; + // } + // }; return ( ({ onRowSelectionModelChange={(newRowSelectionModel) => { if (checkboxSelection) { setRowSelectionModel(newRowSelectionModel); - setValue("qcChecks_active", newRowSelectionModel) + setValue("qcChecks_active", newRowSelectionModel); } }} rowSelectionModel={rowSelectionModel} - apiRef={apiRef} rows={rows} columns={!checkboxSelection ? _columns : columns} @@ -337,7 +343,7 @@ function InputDataGrid({ }} disableColumnMenu processRowUpdate={processRowUpdate as any} - // onRowEditStop={handleRowEditStop} + // onRowEditStop={handleRowEditStop} rowModesModel={rowModesModel} onRowModesModelChange={setRowModesModel} onProcessRowUpdateError={onProcessRowUpdateError} @@ -348,19 +354,26 @@ function InputDataGrid({ } return classname; }} - slots={!checkboxSelection ? { - footer: FooterToolbar, - noRowsOverlay: NoRowsOverlay, - } : undefined} - slotProps={!checkboxSelection && Boolean(needAdd) ? { - footer: { child: footer }, - }: undefined - // slotProps={renderFooter ? { - // footer: { child: footer }, - // }: undefined - } + slots={ + !checkboxSelection + ? { + footer: FooterToolbar, + noRowsOverlay: NoRowsOverlay, + } + : undefined + } + slotProps={ + !checkboxSelection && Boolean(needAdd) + ? { + footer: { child: footer }, + } + : undefined + // slotProps={renderFooter ? { + // footer: { child: footer }, + // }: undefined + } /> - ) + ); } const FooterToolbar: React.FC = ({ child }) => { return {child}; diff --git a/src/components/InventorySearch/InventorySearch.tsx b/src/components/InventorySearch/InventorySearch.tsx index 97eec7e..4b2d52d 100644 --- a/src/components/InventorySearch/InventorySearch.tsx +++ b/src/components/InventorySearch/InventorySearch.tsx @@ -1,4 +1,4 @@ -"use client" +"use client"; import { InventoryResult } from "@/app/api/inventory"; import { useTranslation } from "react-i18next"; import SearchBox, { Criterion } from "../SearchBox"; @@ -8,10 +8,12 @@ import SearchResults, { Column } from "../SearchResults"; import { CheckCircleOutline, DoDisturb } from "@mui/icons-material"; interface Props { - inventories: InventoryResult[]; + inventories: InventoryResult[]; } -type SearchQuery = Partial>; + | "category" + > +>; type SearchParamNames = keyof SearchQuery; -const InventorySearch: React.FC = ({ - inventories, -}) => { - const { t } = useTranslation(["inventory", "common"]); +const InventorySearch: React.FC = ({ inventories }) => { + const { t } = useTranslation(["inventory", "common"]); - const [filteredInventories, setFilteredInventories] = useState(inventories) + const [filteredInventories, setFilteredInventories] = useState(inventories); - const searchCriteria: Criterion[] = useMemo(() => [ - { label: t("Code"), paramName: "code", type: "text" }, - { label: t("Name"), paramName: "name", type: "text" }, - { label: t("Type"), paramName: "type", type: "select", options: uniq(inventories.map(i => i.type)) }, - { label: t("Status"), paramName: "status", type: "select", options: uniq(inventories.map(i => i.status)) }, - ], [t] - ); + const searchCriteria: Criterion[] = useMemo( + () => [ + { label: t("Code"), paramName: "code", type: "text" }, + { label: t("Name"), paramName: "name", type: "text" }, + { + label: t("Type"), + paramName: "type", + type: "select", + options: uniq(inventories.map((i) => i.type)), + }, + { + label: t("Status"), + paramName: "status", + type: "select", + options: uniq(inventories.map((i) => i.status)), + }, + ], + [t], + ); - const onReset = useCallback(() => { - setFilteredInventories(inventories) - }, [inventories]) + const onReset = useCallback(() => { + setFilteredInventories(inventories); + }, [inventories]); - const columns = useMemo[]>( - () => [ - { - name: "code", - label: t("Code"), - }, - { - name: "name", - label: t("Name"), - }, - { - name: "type", - label: t("Type"), - renderCell: (params) => { - return t(params.type) - } - }, - { - name: "qty", - label: t("Qty"), - align: "right", - headerAlign: "right", - type: "integer" - }, - { - name: "uomUdfudesc", - label: t("UoM"), - }, - // { - // name: "qtyPerSmallestUnit", - // label: t("Qty Per Smallest Unit"), - // align: "right", - // headerAlign: "right", - // type: "decimal" - // }, - // { - // name: "smallestUnit", - // label: t("Smallest Unit"), - // }, - // { - // name: "price", - // label: t("Price"), - // align: "right", - // sx: { - // alignItems: "right", - // justifyContent: "end", - // } - // }, - // { - // name: "currencyName", - // label: t("Currency"), - // }, - // { - // name: "status", - // label: t("Status"), - // type: "icon", - // icons: { - // available: , - // unavailable: , - // }, - // colors: { - // available: "success", - // unavailable: "error", - // } - // }, - ], [t] - ) + const columns = useMemo[]>( + () => [ + { + name: "code", + label: t("Code"), + }, + { + name: "name", + label: t("Name"), + }, + { + name: "type", + label: t("Type"), + renderCell: (params) => { + return t(params.type); + }, + }, + { + name: "qty", + label: t("Qty"), + align: "right", + headerAlign: "right", + type: "integer", + }, + { + name: "uomUdfudesc", + label: t("UoM"), + }, + // { + // name: "qtyPerSmallestUnit", + // label: t("Qty Per Smallest Unit"), + // align: "right", + // headerAlign: "right", + // type: "decimal" + // }, + // { + // name: "smallestUnit", + // label: t("Smallest Unit"), + // }, + // { + // name: "price", + // label: t("Price"), + // align: "right", + // sx: { + // alignItems: "right", + // justifyContent: "end", + // } + // }, + // { + // name: "currencyName", + // label: t("Currency"), + // }, + // { + // name: "status", + // label: t("Status"), + // type: "icon", + // icons: { + // available: , + // unavailable: , + // }, + // colors: { + // available: "success", + // unavailable: "error", + // } + // }, + ], + [t], + ); - return ( - <> - { - // console.log(query) - // console.log(inventories) - setFilteredInventories( - inventories.filter( - (i) => - i.code.toLowerCase().includes(query.code.toLowerCase()) && - i.name.toLowerCase().includes(query.name.toLowerCase()) && - (query.type == "All" || i.type.toLowerCase().includes(query.type.toLowerCase())) && - (query.status == "All" || i.status.toLowerCase().includes(query.status.toLowerCase())) - ) - ) - }} - onReset={onReset} - /> - items={filteredInventories} columns={columns} pagingController={{ - pageNum: 0, - pageSize: 0, - totalCount: 0, - }} /> - - ) -} + return ( + <> + { + // console.log(query) + // console.log(inventories) + setFilteredInventories( + inventories.filter( + (i) => + i.code.toLowerCase().includes(query.code.toLowerCase()) && + i.name.toLowerCase().includes(query.name.toLowerCase()) && + (query.type == "All" || + i.type.toLowerCase().includes(query.type.toLowerCase())) && + (query.status == "All" || + i.status.toLowerCase().includes(query.status.toLowerCase())), + ), + ); + }} + onReset={onReset} + /> + + items={filteredInventories} + columns={columns} + pagingController={{ + pageNum: 0, + pageSize: 0, + totalCount: 0, + }} + /> + + ); +}; -export default InventorySearch \ No newline at end of file +export default InventorySearch; diff --git a/src/components/InventorySearch/InventorySearchWrapper.tsx b/src/components/InventorySearch/InventorySearchWrapper.tsx index f207c7f..63dd5ca 100644 --- a/src/components/InventorySearch/InventorySearchWrapper.tsx +++ b/src/components/InventorySearch/InventorySearchWrapper.tsx @@ -1,24 +1,18 @@ import React from "react"; -import GeneralLoading from "../General/GeneralLoading" +import GeneralLoading from "../General/GeneralLoading"; import { fetchInventories } from "@/app/api/inventory"; import InventorySearch from "./InventorySearch"; interface SubComponents { - Loading: typeof GeneralLoading; + Loading: typeof GeneralLoading; } const InventorySearchWrapper: React.FC & SubComponents = async () => { - - const [ - inventories - ] = await Promise.all([ - fetchInventories() - ]) - - return -} + const [inventories] = await Promise.all([fetchInventories()]); + return ; +}; InventorySearchWrapper.Loading = GeneralLoading; -export default InventorySearchWrapper \ No newline at end of file +export default InventorySearchWrapper; diff --git a/src/components/InventorySearch/index.ts b/src/components/InventorySearch/index.ts index 3d6573b..9de9ed4 100644 --- a/src/components/InventorySearch/index.ts +++ b/src/components/InventorySearch/index.ts @@ -1 +1 @@ -export { default } from "./InventorySearchWrapper" \ No newline at end of file +export { default } from "./InventorySearchWrapper"; diff --git a/src/components/ItemsSearch/ItemsSearch.tsx b/src/components/ItemsSearch/ItemsSearch.tsx index f6efdc0..0e50fe5 100644 --- a/src/components/ItemsSearch/ItemsSearch.tsx +++ b/src/components/ItemsSearch/ItemsSearch.tsx @@ -29,9 +29,9 @@ const ItemsSearch: React.FC = ({ items }) => { pageSize: 10, // totalCount: 0, }); - const [totalCount, setTotalCount] = useState(0) + const [totalCount, setTotalCount] = useState(0); const searchCriteria: Criterion[] = useMemo(() => { - var searchCriteria: Criterion[] = [ + const searchCriteria: Criterion[] = [ { label: t("Code"), paramName: "code", type: "text" }, { label: t("Name"), paramName: "name", type: "text" }, ]; @@ -42,7 +42,7 @@ const ItemsSearch: React.FC = ({ items }) => { (item: ItemsResult) => { router.push(`/settings/items/edit?id=${item.id}`); }, - [router] + [router], ); const onDeleteClick = useCallback((item: ItemsResult) => {}, [router]); @@ -70,7 +70,7 @@ const ItemsSearch: React.FC = ({ items }) => { onClick: onDeleteClick, }, ], - [filteredItems] + [filteredItems], ); const refetchData = useCallback( @@ -87,12 +87,12 @@ const ItemsSearch: React.FC = ({ items }) => { try { const response = await axiosInstance.get( `${NEXT_PUBLIC_API_URL}/items/getRecordByPage`, - { params } + { params }, ); console.log(response); if (response.status == 200) { setFilteredItems(response.data.records); - setTotalCount(response.data.total) + setTotalCount(response.data.total); return response; // Return the data from the response } else { throw "400"; @@ -102,7 +102,7 @@ const ItemsSearch: React.FC = ({ items }) => { throw error; // Rethrow the error for further handling } }, - [axiosInstance, pagingController.pageNum, pagingController.pageSize] + [axiosInstance, pagingController.pageNum, pagingController.pageSize], ); useEffect(() => { diff --git a/src/components/ItemsSearch/ItemsSearchWrapper.tsx b/src/components/ItemsSearch/ItemsSearchWrapper.tsx index fbfd01b..84faa57 100644 --- a/src/components/ItemsSearch/ItemsSearchWrapper.tsx +++ b/src/components/ItemsSearch/ItemsSearchWrapper.tsx @@ -1,4 +1,4 @@ -import { fetchAllItems, } from "@/app/api/settings/item"; +import { fetchAllItems } from "@/app/api/settings/item"; import ItemsSearch from "./ItemsSearch"; import ItemsSearchLoading from "./ItemsSearchLoading"; import { SearchParams } from "@/app/utils/fetchUtil"; @@ -13,9 +13,11 @@ type Props = { // type: TypeEnum; }; -const ItemsSearchWrapper: React.FC & SubComponents = async ({ - // type, -}) => { +const ItemsSearchWrapper: React.FC & SubComponents = async ( + { + // type, + }, +) => { // console.log(type) // var result = await fetchAllItems() return ; diff --git a/src/components/LoginPage/LoginForm.tsx b/src/components/LoginPage/LoginForm.tsx index a402d3c..4ff916f 100644 --- a/src/components/LoginPage/LoginForm.tsx +++ b/src/components/LoginPage/LoginForm.tsx @@ -12,8 +12,8 @@ import { useRouter } from "next/navigation"; import { useEffect, useState } from "react"; import { SubmitHandler, useForm } from "react-hook-form"; import { useTranslation } from "react-i18next"; -import {SetupAxiosInterceptors} from "@/app/(main)/axios/axiosInstance"; -import {useToken} from "@/app/(main)/axios/AxiosProvider"; +import { SetupAxiosInterceptors } from "@/app/(main)/axios/axiosInstance"; +import { useToken } from "@/app/(main)/axios/AxiosProvider"; import { Visibility, VisibilityOff } from "@mui/icons-material"; type LoginFields = { @@ -21,9 +21,11 @@ type LoginFields = { password: string; }; -type SessionWithAbilities = { - abilities: string[] -} & Session | null +type SessionWithAbilities = + | ({ + abilities: string[]; + } & Session) + | null; // Error codes in https://next-auth.js.org/configuration/pages#sign-in-page const getHumanFriendlyErrorMessage = ( @@ -57,7 +59,7 @@ const LoginForm: React.FC = () => { const handleMouseDownPassword = () => setShowPassword(!showPassword); const onSubmit: SubmitHandler = async (data) => { - console.log(data) + console.log(data); const res = await signIn("credentials", { redirect: false, ...data, @@ -68,27 +70,29 @@ const LoginForm: React.FC = () => { return; } - // set auth to local storage - const session = await getSession() as SessionWithAbilities + const session = (await getSession()) as SessionWithAbilities; // @ts-ignore - window.localStorage.setItem("accessToken", session?.accessToken) + window.localStorage.setItem("accessToken", session?.accessToken); setAccessToken(session?.accessToken); SetupAxiosInterceptors(session?.accessToken); // console.log(session) - window.localStorage.setItem("abilities", JSON.stringify(session?.abilities)) + window.localStorage.setItem( + "abilities", + JSON.stringify(session?.abilities), + ); const callbackUrl = - new URLSearchParams(window.location.search).get("callbackUrl") || "/"; + new URLSearchParams(window.location.search).get("callbackUrl") || "/"; router.push(callbackUrl); }; - useEffect(()=> { - // clean abilities before login - window.localStorage.removeItem("abilities") - }, []) - + useEffect(() => { + // clean abilities before login + window.localStorage.removeItem("abilities"); + }, []); + return ( { diff --git a/src/components/LoginPage/LoginPage.tsx b/src/components/LoginPage/LoginPage.tsx index eb65647..59fce6e 100644 --- a/src/components/LoginPage/LoginPage.tsx +++ b/src/components/LoginPage/LoginPage.tsx @@ -7,10 +7,19 @@ import { Box } from "@mui/material"; const LoginPage = () => { return ( - - + - + diff --git a/src/components/Logo/Logo.tsx b/src/components/Logo/Logo.tsx index 28b00fd..4750e72 100644 --- a/src/components/Logo/Logo.tsx +++ b/src/components/Logo/Logo.tsx @@ -21,8 +21,10 @@ const Logo: React.FC = ({ width, height }) => { fill="#000" // style="stroke:#000;stroke-width:0.25mm;fill:#000" > - + ); diff --git a/src/components/M18ImportTesting/M18ImportDo.tsx b/src/components/M18ImportTesting/M18ImportDo.tsx index 26423b3..ac00212 100644 --- a/src/components/M18ImportTesting/M18ImportDo.tsx +++ b/src/components/M18ImportTesting/M18ImportDo.tsx @@ -1,126 +1,153 @@ -"use client" -import { M18ImportTestingForm, M18ImportDoForm } from "@/app/api/settings/m18ImportTesting/actions"; -import { INPUT_DATE_FORMAT, OUTPUT_DATE_FORMAT, OUTPUT_TIME_FORMAT, dateTimeStringToDayjs } from "@/app/utils/formatUtil"; +"use client"; +import { + M18ImportTestingForm, + M18ImportDoForm, +} from "@/app/api/settings/m18ImportTesting/actions"; +import { + INPUT_DATE_FORMAT, + OUTPUT_DATE_FORMAT, + OUTPUT_TIME_FORMAT, + dateTimeStringToDayjs, +} from "@/app/utils/formatUtil"; import { Check } from "@mui/icons-material"; -import { Box, Button, Card, CardContent, FormControl, Grid, Stack, Typography } from "@mui/material"; -import { DatePicker, DateTimePicker, LocalizationProvider } from "@mui/x-date-pickers"; +import { + Box, + Button, + Card, + CardContent, + FormControl, + Grid, + Stack, + Typography, +} from "@mui/material"; +import { + DatePicker, + DateTimePicker, + LocalizationProvider, +} from "@mui/x-date-pickers"; import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs"; import dayjs, { Dayjs } from "dayjs"; import React, { useCallback, useState } from "react"; import { Controller, useFormContext } from "react-hook-form"; import { useTranslation } from "react-i18next"; -interface Props { -} +interface Props {} -const M18ImportDo: React.FC = ({ -}) => { +const M18ImportDo: React.FC = ({}) => { + const { t } = useTranslation("m18ImportTesting"); + const [isLoading, setIsLoading] = useState(false); + const { + control, + formState: { errors }, + watch, + } = useFormContext(); - const { t } = useTranslation("m18ImportTesting") - const [isLoading, setIsLoading] = useState(false) - const { - control, - formState: { errors }, - watch - } = useFormContext() + const handleDateTimePickerOnChange = useCallback( + (value: Dayjs | null, onChange: (value: any) => void) => { + const formattedValue = value + ? value.format(`${INPUT_DATE_FORMAT} ${OUTPUT_TIME_FORMAT}`) + : null; + onChange(formattedValue); + }, + [], + ); - const handleDateTimePickerOnChange = useCallback((value: Dayjs | null, onChange: (value: any) => void) => { - const formattedValue = value ? value.format(`${INPUT_DATE_FORMAT} ${OUTPUT_TIME_FORMAT}`) : null - onChange(formattedValue) - }, []) + return ( + + + + + + {t("Import Delivery Order")} + + + + + + + // value && dateTimeStringToDayjs(value).isValid() ? true : "Invalid date-time" + // }, + // }} + render={({ field, fieldState: { error } }) => ( + + handleDateTimePickerOnChange(newValue, field.onChange) + } + slotProps={{ + textField: { + error: !!error, + helperText: error ? error.message : null, + }, + }} + /> + )} + /> + + {"-"} + + + // value && dateTimeStringToDayjs(value).isValid() ? true : "Invalid date-time", + // isFuture: (value) => + // dateTimeStringToDayjs(value).isAfter(watch("do.dateFrom")) || "Date must be in the future", + // }, + // }} + render={({ field, fieldState: { error } }) => ( + + handleDateTimePickerOnChange(newValue, field.onChange) + } + slotProps={{ + textField: { + error: !!error, + helperText: error ? error.message : null, + }, + }} + /> + )} + /> + + + + + + + + + + ); +}; - - - return ( - - - - - {t("Import Delivery Order")} - - - - - - // value && dateTimeStringToDayjs(value).isValid() ? true : "Invalid date-time" - // }, - // }} - render={({ field, fieldState: { error } }) => ( - (handleDateTimePickerOnChange(newValue, field.onChange))} - slotProps={{ - textField: { - error: !!error, - helperText: error ? error.message : null - } - }} - /> - )} - /> - - {"-"} - - - // value && dateTimeStringToDayjs(value).isValid() ? true : "Invalid date-time", - // isFuture: (value) => - // dateTimeStringToDayjs(value).isAfter(watch("do.dateFrom")) || "Date must be in the future", - // }, - // }} - render={({ field, fieldState: { error } }) => ( - (handleDateTimePickerOnChange(newValue, field.onChange))} - slotProps={{ - textField: { - error: !!error, - helperText: error ? error.message : null - } - }} - /> - )} - /> - - - - - - - - - - ) -} - -export default M18ImportDo; \ No newline at end of file +export default M18ImportDo; diff --git a/src/components/M18ImportTesting/M18ImportMasterData.tsx b/src/components/M18ImportTesting/M18ImportMasterData.tsx index 774cf4b..bc12917 100644 --- a/src/components/M18ImportTesting/M18ImportMasterData.tsx +++ b/src/components/M18ImportTesting/M18ImportMasterData.tsx @@ -1,125 +1,153 @@ -"use client" -import { M18ImportTestingForm, M18ImportMasterDataForm } from "@/app/api/settings/m18ImportTesting/actions"; -import { INPUT_DATE_FORMAT, OUTPUT_DATE_FORMAT, OUTPUT_TIME_FORMAT, dateTimeStringToDayjs } from "@/app/utils/formatUtil"; +"use client"; +import { + M18ImportTestingForm, + M18ImportMasterDataForm, +} from "@/app/api/settings/m18ImportTesting/actions"; +import { + INPUT_DATE_FORMAT, + OUTPUT_DATE_FORMAT, + OUTPUT_TIME_FORMAT, + dateTimeStringToDayjs, +} from "@/app/utils/formatUtil"; import { Check } from "@mui/icons-material"; -import { Box, Button, Card, CardContent, FormControl, Grid, Stack, Typography } from "@mui/material"; -import { DatePicker, DateTimePicker, LocalizationProvider } from "@mui/x-date-pickers"; +import { + Box, + Button, + Card, + CardContent, + FormControl, + Grid, + Stack, + Typography, +} from "@mui/material"; +import { + DatePicker, + DateTimePicker, + LocalizationProvider, +} from "@mui/x-date-pickers"; import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs"; import dayjs, { Dayjs } from "dayjs"; import React, { useCallback, useState } from "react"; import { Controller, useFormContext } from "react-hook-form"; import { useTranslation } from "react-i18next"; -interface Props { -} +interface Props {} -const M18ImportMasterData: React.FC = ({ -}) => { - const { t } = useTranslation("m18ImportTesting") - const [isLoading, setIsLoading] = useState(false) - const { - control, - formState: { errors }, - watch - } = useFormContext() +const M18ImportMasterData: React.FC = ({}) => { + const { t } = useTranslation("m18ImportTesting"); + const [isLoading, setIsLoading] = useState(false); + const { + control, + formState: { errors }, + watch, + } = useFormContext(); - const handleDateTimePickerOnChange = useCallback((value: Dayjs | null, onChange: (value: any) => void) => { - const formattedValue = value ? value.format(`${INPUT_DATE_FORMAT} ${OUTPUT_TIME_FORMAT}`) : null - onChange(formattedValue) - }, []) + const handleDateTimePickerOnChange = useCallback( + (value: Dayjs | null, onChange: (value: any) => void) => { + const formattedValue = value + ? value.format(`${INPUT_DATE_FORMAT} ${OUTPUT_TIME_FORMAT}`) + : null; + onChange(formattedValue); + }, + [], + ); + return ( + + + + + + {t("Import Master Data")} + + + + + + + // value && dateTimeStringToDayjs(value).isValid() ? true : "Invalid date-time" + // }, + // }} + render={({ field, fieldState: { error } }) => ( + + handleDateTimePickerOnChange(newValue, field.onChange) + } + slotProps={{ + textField: { + error: !!error, + helperText: error ? error.message : null, + }, + }} + /> + )} + /> + + {"-"} + + + // value && dateTimeStringToDayjs(value).isValid() ? true : "Invalid date-time", + // isFuture: (value) => + // dateTimeStringToDayjs(value).isAfter(watch("po.dateFrom")) || "Date must be in the future", + // }, + // }} + render={({ field, fieldState: { error } }) => ( + + handleDateTimePickerOnChange(newValue, field.onChange) + } + slotProps={{ + textField: { + error: !!error, + helperText: error ? error.message : null, + }, + }} + /> + )} + /> + + + + + + + + + + ); +}; - - return ( - - - - - {t("Import Master Data")} - - - - - - // value && dateTimeStringToDayjs(value).isValid() ? true : "Invalid date-time" - // }, - // }} - render={({ field, fieldState: { error } }) => ( - (handleDateTimePickerOnChange(newValue, field.onChange))} - slotProps={{ - textField: { - error: !!error, - helperText: error ? error.message : null - } - }} - /> - )} - /> - - {"-"} - - - // value && dateTimeStringToDayjs(value).isValid() ? true : "Invalid date-time", - // isFuture: (value) => - // dateTimeStringToDayjs(value).isAfter(watch("po.dateFrom")) || "Date must be in the future", - // }, - // }} - render={({ field, fieldState: { error } }) => ( - (handleDateTimePickerOnChange(newValue, field.onChange))} - slotProps={{ - textField: { - error: !!error, - helperText: error ? error.message : null - } - }} - /> - )} - /> - - - - - - - - - - ) -} - -export default M18ImportMasterData; \ No newline at end of file +export default M18ImportMasterData; diff --git a/src/components/M18ImportTesting/M18ImportPo.tsx b/src/components/M18ImportTesting/M18ImportPo.tsx index 5892d21..463dc4e 100644 --- a/src/components/M18ImportTesting/M18ImportPo.tsx +++ b/src/components/M18ImportTesting/M18ImportPo.tsx @@ -1,126 +1,153 @@ -"use client" -import { M18ImportTestingForm, M18ImportPoForm } from "@/app/api/settings/m18ImportTesting/actions"; -import { INPUT_DATE_FORMAT, OUTPUT_DATE_FORMAT, OUTPUT_TIME_FORMAT, dateTimeStringToDayjs } from "@/app/utils/formatUtil"; +"use client"; +import { + M18ImportTestingForm, + M18ImportPoForm, +} from "@/app/api/settings/m18ImportTesting/actions"; +import { + INPUT_DATE_FORMAT, + OUTPUT_DATE_FORMAT, + OUTPUT_TIME_FORMAT, + dateTimeStringToDayjs, +} from "@/app/utils/formatUtil"; import { Check } from "@mui/icons-material"; -import { Box, Button, Card, CardContent, FormControl, Grid, Stack, Typography } from "@mui/material"; -import { DatePicker, DateTimePicker, LocalizationProvider } from "@mui/x-date-pickers"; +import { + Box, + Button, + Card, + CardContent, + FormControl, + Grid, + Stack, + Typography, +} from "@mui/material"; +import { + DatePicker, + DateTimePicker, + LocalizationProvider, +} from "@mui/x-date-pickers"; import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs"; import dayjs, { Dayjs } from "dayjs"; import React, { useCallback, useState } from "react"; import { Controller, useFormContext } from "react-hook-form"; import { useTranslation } from "react-i18next"; -interface Props { -} +interface Props {} -const M18ImportPo: React.FC = ({ -}) => { +const M18ImportPo: React.FC = ({}) => { + const { t } = useTranslation("m18ImportTesting"); + const [isLoading, setIsLoading] = useState(false); + const { + control, + formState: { errors }, + watch, + } = useFormContext(); - const { t } = useTranslation("m18ImportTesting") - const [isLoading, setIsLoading] = useState(false) - const { - control, - formState: { errors }, - watch - } = useFormContext() + const handleDateTimePickerOnChange = useCallback( + (value: Dayjs | null, onChange: (value: any) => void) => { + const formattedValue = value + ? value.format(`${INPUT_DATE_FORMAT} ${OUTPUT_TIME_FORMAT}`) + : null; + onChange(formattedValue); + }, + [], + ); - const handleDateTimePickerOnChange = useCallback((value: Dayjs | null, onChange: (value: any) => void) => { - const formattedValue = value ? value.format(`${INPUT_DATE_FORMAT} ${OUTPUT_TIME_FORMAT}`) : null - onChange(formattedValue) - }, []) + return ( + + + + + + {t("Import Purchase Order")} + + + + + + + // value && dateTimeStringToDayjs(value).isValid() ? true : "Invalid date-time" + // }, + // }} + render={({ field, fieldState: { error } }) => ( + + handleDateTimePickerOnChange(newValue, field.onChange) + } + slotProps={{ + textField: { + error: !!error, + helperText: error ? error.message : null, + }, + }} + /> + )} + /> + + {"-"} + + + // value && dateTimeStringToDayjs(value).isValid() ? true : "Invalid date-time", + // isFuture: (value) => + // dateTimeStringToDayjs(value).isAfter(watch("po.dateFrom")) || "Date must be in the future", + // }, + // }} + render={({ field, fieldState: { error } }) => ( + + handleDateTimePickerOnChange(newValue, field.onChange) + } + slotProps={{ + textField: { + error: !!error, + helperText: error ? error.message : null, + }, + }} + /> + )} + /> + + + + + + + + + + ); +}; - - - return ( - - - - - {t("Import Purchase Order")} - - - - - - // value && dateTimeStringToDayjs(value).isValid() ? true : "Invalid date-time" - // }, - // }} - render={({ field, fieldState: { error } }) => ( - (handleDateTimePickerOnChange(newValue, field.onChange))} - slotProps={{ - textField: { - error: !!error, - helperText: error ? error.message : null - } - }} - /> - )} - /> - - {"-"} - - - // value && dateTimeStringToDayjs(value).isValid() ? true : "Invalid date-time", - // isFuture: (value) => - // dateTimeStringToDayjs(value).isAfter(watch("po.dateFrom")) || "Date must be in the future", - // }, - // }} - render={({ field, fieldState: { error } }) => ( - (handleDateTimePickerOnChange(newValue, field.onChange))} - slotProps={{ - textField: { - error: !!error, - helperText: error ? error.message : null - } - }} - /> - )} - /> - - - - - - - - - - ) -} - -export default M18ImportPo; \ No newline at end of file +export default M18ImportPo; diff --git a/src/components/M18ImportTesting/M18ImportPq.tsx b/src/components/M18ImportTesting/M18ImportPq.tsx index 9a11fc4..7cd9cc9 100644 --- a/src/components/M18ImportTesting/M18ImportPq.tsx +++ b/src/components/M18ImportTesting/M18ImportPq.tsx @@ -1,126 +1,153 @@ -"use client" -import { M18ImportTestingForm, M18ImportPqForm } from "@/app/api/settings/m18ImportTesting/actions"; -import { INPUT_DATE_FORMAT, OUTPUT_DATE_FORMAT, OUTPUT_TIME_FORMAT, dateTimeStringToDayjs } from "@/app/utils/formatUtil"; +"use client"; +import { + M18ImportTestingForm, + M18ImportPqForm, +} from "@/app/api/settings/m18ImportTesting/actions"; +import { + INPUT_DATE_FORMAT, + OUTPUT_DATE_FORMAT, + OUTPUT_TIME_FORMAT, + dateTimeStringToDayjs, +} from "@/app/utils/formatUtil"; import { Check } from "@mui/icons-material"; -import { Box, Button, Card, CardContent, FormControl, Grid, Stack, Typography } from "@mui/material"; -import { DatePicker, DateTimePicker, LocalizationProvider } from "@mui/x-date-pickers"; +import { + Box, + Button, + Card, + CardContent, + FormControl, + Grid, + Stack, + Typography, +} from "@mui/material"; +import { + DatePicker, + DateTimePicker, + LocalizationProvider, +} from "@mui/x-date-pickers"; import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs"; import dayjs, { Dayjs } from "dayjs"; import React, { useCallback, useState } from "react"; import { Controller, useFormContext } from "react-hook-form"; import { useTranslation } from "react-i18next"; -interface Props { -} +interface Props {} -const M18ImportPq: React.FC = ({ -}) => { +const M18ImportPq: React.FC = ({}) => { + const { t } = useTranslation("m18ImportTesting"); + const [isLoading, setIsLoading] = useState(false); + const { + control, + formState: { errors }, + watch, + } = useFormContext(); - const { t } = useTranslation("m18ImportTesting") - const [isLoading, setIsLoading] = useState(false) - const { - control, - formState: { errors }, - watch - } = useFormContext() + const handleDateTimePickerOnChange = useCallback( + (value: Dayjs | null, onChange: (value: any) => void) => { + const formattedValue = value + ? value.format(`${INPUT_DATE_FORMAT} ${OUTPUT_TIME_FORMAT}`) + : null; + onChange(formattedValue); + }, + [], + ); - const handleDateTimePickerOnChange = useCallback((value: Dayjs | null, onChange: (value: any) => void) => { - const formattedValue = value ? value.format(`${INPUT_DATE_FORMAT} ${OUTPUT_TIME_FORMAT}`) : null - onChange(formattedValue) - }, []) + return ( + + + + + + {t("Import Purchase Quotation")} + + + + + + + // value && dateTimeStringToDayjs(value).isValid() ? true : "Invalid date-time" + // }, + // }} + render={({ field, fieldState: { error } }) => ( + + handleDateTimePickerOnChange(newValue, field.onChange) + } + slotProps={{ + textField: { + error: !!error, + helperText: error ? error.message : null, + }, + }} + /> + )} + /> + + {"-"} + + + // value && dateTimeStringToDayjs(value).isValid() ? true : "Invalid date-time", + // isFuture: (value) => + // dateTimeStringToDayjs(value).isAfter(watch("po.dateFrom")) || "Date must be in the future", + // }, + // }} + render={({ field, fieldState: { error } }) => ( + + handleDateTimePickerOnChange(newValue, field.onChange) + } + slotProps={{ + textField: { + error: !!error, + helperText: error ? error.message : null, + }, + }} + /> + )} + /> + + + + + + + + + + ); +}; - - - return ( - - - - - {t("Import Purchase Quotation")} - - - - - - // value && dateTimeStringToDayjs(value).isValid() ? true : "Invalid date-time" - // }, - // }} - render={({ field, fieldState: { error } }) => ( - (handleDateTimePickerOnChange(newValue, field.onChange))} - slotProps={{ - textField: { - error: !!error, - helperText: error ? error.message : null - } - }} - /> - )} - /> - - {"-"} - - - // value && dateTimeStringToDayjs(value).isValid() ? true : "Invalid date-time", - // isFuture: (value) => - // dateTimeStringToDayjs(value).isAfter(watch("po.dateFrom")) || "Date must be in the future", - // }, - // }} - render={({ field, fieldState: { error } }) => ( - (handleDateTimePickerOnChange(newValue, field.onChange))} - slotProps={{ - textField: { - error: !!error, - helperText: error ? error.message : null - } - }} - /> - )} - /> - - - - - - - - - - ) -} - -export default M18ImportPq; \ No newline at end of file +export default M18ImportPq; diff --git a/src/components/M18ImportTesting/M18ImportTesting.tsx b/src/components/M18ImportTesting/M18ImportTesting.tsx index 6e1120b..d4b0038 100644 --- a/src/components/M18ImportTesting/M18ImportTesting.tsx +++ b/src/components/M18ImportTesting/M18ImportTesting.tsx @@ -1,8 +1,20 @@ -"use client" - -import { M18ImportTestingForm, testM18ImportPo, M18ImportPoForm, testM18ImportPq, testM18ImportMasterData, testM18ImportDo } from "@/app/api/settings/m18ImportTesting/actions"; +"use client"; + +import { + M18ImportTestingForm, + testM18ImportPo, + M18ImportPoForm, + testM18ImportPq, + testM18ImportMasterData, + testM18ImportDo, +} from "@/app/api/settings/m18ImportTesting/actions"; import { Card, CardContent, Grid, Stack, Typography } from "@mui/material"; -import React, { BaseSyntheticEvent, FormEvent, useCallback, useState } from "react"; +import React, { + BaseSyntheticEvent, + FormEvent, + useCallback, + useState, +} from "react"; import { FormProvider, SubmitErrorHandler, useForm } from "react-hook-form"; import { useTranslation } from "react-i18next"; import M18ImportPo from "./M18ImportPo"; @@ -11,164 +23,181 @@ import { dateTimeStringToDayjs } from "@/app/utils/formatUtil"; import M18ImportMasterData from "./M18ImportMasterData"; import M18ImportDo from "./M18ImportDo"; -interface Props { - -} - -const M18ImportTesting: React.FC = ({ - -}) => { - - const { t } = useTranslation("m18ImportTesting") - const [isLoading, setIsLoading] = useState(false) - const [loadingType, setLoadingType] = useState(null) - const formProps = useForm() - - const onSubmit = useCallback(async (data: M18ImportTestingForm, event?: BaseSyntheticEvent) => { - console.log(isLoading) - - if (isLoading) { +interface Props {} + +const M18ImportTesting: React.FC = ({}) => { + const { t } = useTranslation("m18ImportTesting"); + const [isLoading, setIsLoading] = useState(false); + const [loadingType, setLoadingType] = useState(null); + const formProps = useForm(); + + const onSubmit = useCallback( + async (data: M18ImportTestingForm, event?: BaseSyntheticEvent) => { + console.log(isLoading); + + if (isLoading) { + return; + } + + const buttonId = (event?.nativeEvent as SubmitEvent).submitter?.id; + console.log(data); + console.log(buttonId); + + switch (buttonId) { + case "m18ImportMasterData": + const mdDateFrom = data.masterData.modifiedDateFrom; + const mdDateTo = data.masterData.modifiedDateTo; + if (!(!mdDateFrom || dateTimeStringToDayjs(mdDateFrom).isValid())) { + formProps.setError("masterData.modifiedDateFrom", { + message: "Invalid DateTime Format", + }); + } + + if (!(!mdDateTo || dateTimeStringToDayjs(mdDateTo).isValid())) { + formProps.setError("masterData.modifiedDateTo", { + message: "Invalid DateTime Format", + }); + } + + if (formProps.formState.errors.masterData) { + return; + } + + setIsLoading(() => true); + setLoadingType(() => "Master Data"); + const mdResponse = await testM18ImportMasterData(data.masterData); + console.log(mdResponse); + if (mdResponse) { + setIsLoading(() => false); + } + break; + case "m18ImportPo": + const poDateFrom = data.po.modifiedDateFrom; + const poDateTo = data.po.modifiedDateTo; + if (!(poDateFrom && dateTimeStringToDayjs(poDateFrom).isValid())) { + formProps.setError("po.modifiedDateFrom", { + message: "Invalid DateTime Format", + }); + } + + if (!(poDateTo && dateTimeStringToDayjs(poDateTo).isValid())) { + formProps.setError("po.modifiedDateTo", { + message: "Invalid DateTime Format", + }); + } + + if (formProps.formState.errors.po) { + return; + } + + setIsLoading(() => true); + setLoadingType(() => "Purchase Order"); + const poResponse = await testM18ImportPo(data.po); + console.log(poResponse); + if (poResponse) { + setIsLoading(() => false); + } + break; + case "m18ImportDo": + const doDateFrom = data.do.modifiedDateFrom; + const doDateTo = data.do.modifiedDateTo; + if (!(doDateFrom && dateTimeStringToDayjs(doDateFrom).isValid())) { + formProps.setError("do.modifiedDateFrom", { + message: "Invalid DateTime Format", + }); + } + + if (!(doDateTo && dateTimeStringToDayjs(doDateTo).isValid())) { + formProps.setError("do.modifiedDateTo", { + message: "Invalid DateTime Format", + }); + } + + if (formProps.formState.errors.do) { + return; + } + + setIsLoading(() => true); + setLoadingType(() => "Delivery Order"); + const doResponse = await testM18ImportDo(data.po); + console.log(doResponse); + if (doResponse) { + setIsLoading(() => false); + } + break; + case "m18ImportPq": + const pqDateFrom = data.pq.modifiedDateFrom; + const pqDateTo = data.pq.modifiedDateTo; + if (!(pqDateFrom || dateTimeStringToDayjs(pqDateFrom).isValid())) { + formProps.setError("pq.modifiedDateFrom", { + message: "Invalid DateTime Format", + }); + } + + if (!(pqDateTo || dateTimeStringToDayjs(pqDateTo).isValid())) { + formProps.setError("pq.modifiedDateTo", { + message: "Invalid DateTime Format", + }); + } + + if (formProps.formState.errors.pq) { return; - } - - const buttonId = (event?.nativeEvent as SubmitEvent).submitter?.id - console.log(data) - console.log(buttonId) - - switch (buttonId) { - case "m18ImportMasterData": - const mdDateFrom = data.masterData.modifiedDateFrom - const mdDateTo = data.masterData.modifiedDateTo - if (!(!mdDateFrom || dateTimeStringToDayjs(mdDateFrom).isValid())) { - formProps.setError("masterData.modifiedDateFrom", { message: "Invalid DateTime Format" }) - } - - if (!(!mdDateTo || dateTimeStringToDayjs(mdDateTo).isValid())) { - formProps.setError("masterData.modifiedDateTo", { message: "Invalid DateTime Format" }) - } - - if (formProps.formState.errors.masterData) { - return; - } - - setIsLoading(() => true) - setLoadingType(() => "Master Data") - const mdResponse = await testM18ImportMasterData(data.masterData) - console.log(mdResponse) - if (mdResponse) { - setIsLoading(() => false) - } - break; - case "m18ImportPo": - const poDateFrom = data.po.modifiedDateFrom - const poDateTo = data.po.modifiedDateTo - if (!(poDateFrom && dateTimeStringToDayjs(poDateFrom).isValid())) { - formProps.setError("po.modifiedDateFrom", { message: "Invalid DateTime Format" }) - } - - if (!(poDateTo && dateTimeStringToDayjs(poDateTo).isValid())) { - formProps.setError("po.modifiedDateTo", { message: "Invalid DateTime Format" }) - } - - if (formProps.formState.errors.po) { - return; - } - - setIsLoading(() => true) - setLoadingType(() => "Purchase Order") - const poResponse = await testM18ImportPo(data.po) - console.log(poResponse) - if (poResponse) { - setIsLoading(() => false) - } - break; - case "m18ImportDo": - const doDateFrom = data.do.modifiedDateFrom - const doDateTo = data.do.modifiedDateTo - if (!(doDateFrom && dateTimeStringToDayjs(doDateFrom).isValid())) { - formProps.setError("do.modifiedDateFrom", { message: "Invalid DateTime Format" }) - } - - if (!(doDateTo && dateTimeStringToDayjs(doDateTo).isValid())) { - formProps.setError("do.modifiedDateTo", { message: "Invalid DateTime Format" }) - } - - if (formProps.formState.errors.do) { - return; - } - - setIsLoading(() => true) - setLoadingType(() => "Delivery Order") - const doResponse = await testM18ImportDo(data.po) - console.log(doResponse) - if (doResponse) { - setIsLoading(() => false) - } - break; - case "m18ImportPq": - const pqDateFrom = data.pq.modifiedDateFrom - const pqDateTo = data.pq.modifiedDateTo - if (!(pqDateFrom || dateTimeStringToDayjs(pqDateFrom).isValid())) { - formProps.setError("pq.modifiedDateFrom", { message: "Invalid DateTime Format" }) - } - - if (!(pqDateTo || dateTimeStringToDayjs(pqDateTo).isValid())) { - formProps.setError("pq.modifiedDateTo", { message: "Invalid DateTime Format" }) - } - - if (formProps.formState.errors.pq) { - return; - } - - setIsLoading(() => true) - setLoadingType(() => "Purchase Quotation") - const pqResponse = await testM18ImportPq(data.pq) - console.log(pqResponse) - if (pqResponse) { - setIsLoading(() => false) - } - break; - default: - break; - } - }, []) - - // const onSubmitError = useCallback>( - // (errors) => { - // console.log(errors) - // }, - // [], - // ); - - return ( - - - {t("Status: ")}{isLoading ? t(`Importing ${loadingType}...`) : t("Ready to import")} - - - - - - - - - - - - - - - - - - - - - ) -} - -export default M18ImportTesting; \ No newline at end of file + } + + setIsLoading(() => true); + setLoadingType(() => "Purchase Quotation"); + const pqResponse = await testM18ImportPq(data.pq); + console.log(pqResponse); + if (pqResponse) { + setIsLoading(() => false); + } + break; + default: + break; + } + }, + [], + ); + + // const onSubmitError = useCallback>( + // (errors) => { + // console.log(errors) + // }, + // [], + // ); + + return ( + + + + {t("Status: ")} + {isLoading ? t(`Importing ${loadingType}...`) : t("Ready to import")} + + + + + + + + + + + + + + + + + + + + + + ); +}; + +export default M18ImportTesting; diff --git a/src/components/M18ImportTesting/M18ImportTestingWrapper.tsx b/src/components/M18ImportTesting/M18ImportTestingWrapper.tsx index 6f0ee60..fce2b18 100644 --- a/src/components/M18ImportTesting/M18ImportTestingWrapper.tsx +++ b/src/components/M18ImportTesting/M18ImportTestingWrapper.tsx @@ -1,17 +1,15 @@ import React from "react"; -import GeneralLoading from "../General/GeneralLoading" +import GeneralLoading from "../General/GeneralLoading"; import M18ImportTesting from "./M18ImportTesting"; interface SubComponents { - Loading: typeof GeneralLoading; + Loading: typeof GeneralLoading; } const M18ImportTestingWrapper: React.FC & SubComponents = async () => { - - return -} - + return ; +}; M18ImportTestingWrapper.Loading = GeneralLoading; -export default M18ImportTestingWrapper \ No newline at end of file +export default M18ImportTestingWrapper; diff --git a/src/components/M18ImportTesting/index.ts b/src/components/M18ImportTesting/index.ts index f3489f0..0e9ce28 100644 --- a/src/components/M18ImportTesting/index.ts +++ b/src/components/M18ImportTesting/index.ts @@ -1 +1 @@ -export { default } from './M18ImportTestingWrapper' \ No newline at end of file +export { default } from "./M18ImportTestingWrapper"; diff --git a/src/components/MailField/MailField.tsx b/src/components/MailField/MailField.tsx index 9d80956..456e0f8 100644 --- a/src/components/MailField/MailField.tsx +++ b/src/components/MailField/MailField.tsx @@ -1,102 +1,104 @@ "use client"; -import "./MailField.css" -import Document from '@tiptap/extension-document' -import Paragraph from '@tiptap/extension-paragraph' -import Text from '@tiptap/extension-text' -import Underline from '@tiptap/extension-underline' -import { useEditor, EditorContent, Extension } from "@tiptap/react" -import StarterKit from "@tiptap/starter-kit" +import "./MailField.css"; +import Document from "@tiptap/extension-document"; +import Paragraph from "@tiptap/extension-paragraph"; +import Text from "@tiptap/extension-text"; +import Underline from "@tiptap/extension-underline"; +import { useEditor, EditorContent, Extension } from "@tiptap/react"; +import StarterKit from "@tiptap/starter-kit"; import MailToolbar from "./MailToolbar"; import { Grid } from "@mui/material"; -import Highlight from '@tiptap/extension-highlight' -import { Color } from '@tiptap/extension-color' +import Highlight from "@tiptap/extension-highlight"; +import { Color } from "@tiptap/extension-color"; import ListItem from "@tiptap/extension-list-item"; import TextStyle from "@tiptap/extension-text-style"; -import TextAlign from '@tiptap/extension-text-align' -import Table from '@tiptap/extension-table' -import TableCell from '@tiptap/extension-table-cell' -import TableHeader from '@tiptap/extension-table-header' -import TableRow from '@tiptap/extension-table-row' -import Gapcursor from '@tiptap/extension-gapcursor' +import TextAlign from "@tiptap/extension-text-align"; +import Table from "@tiptap/extension-table"; +import TableCell from "@tiptap/extension-table-cell"; +import TableHeader from "@tiptap/extension-table-header"; +import TableRow from "@tiptap/extension-table-row"; +import Gapcursor from "@tiptap/extension-gapcursor"; interface Props { - content?: string, - onChange?: (richText: string) => void, - error?: boolean, + content?: string; + onChange?: (richText: string) => void; + error?: boolean; } -const MailField: React.FC = ({ - content, - onChange, - error -}) => { +const MailField: React.FC = ({ content, onChange, error }) => { + const TAB_CHAR = "\u0009"; - const TAB_CHAR = '\u0009'; - - const TabHandler = Extension.create({ - name: 'tabHandler', - addKeyboardShortcuts() { - return { - Tab: ({ editor }) => { - // Sinks a list item / inserts a tab character - editor - .chain() - .sinkListItem('listItem') - .command(({ tr }) => { - tr.insertText(TAB_CHAR); - return true; - }) - .run(); - // Prevent default behavior (losing focus) - return true; - }, - }; + const TabHandler = Extension.create({ + name: "tabHandler", + addKeyboardShortcuts() { + return { + Tab: ({ editor }) => { + // Sinks a list item / inserts a tab character + editor + .chain() + .sinkListItem("listItem") + .command(({ tr }) => { + tr.insertText(TAB_CHAR); + return true; + }) + .run(); + // Prevent default behavior (losing focus) + return true; }, - }); + }; + }, + }); - const editor = useEditor({ - extensions: [ - StarterKit.configure(), - Document, - Paragraph, - Text, - TextStyle, - TextAlign.configure({ - types: ['heading', 'paragraph'] - }), - Underline, - Highlight.configure({ multicolor: true }), - Color, - ListItem, - TabHandler, - Gapcursor, - Table.configure({ - resizable: true, - }), - TableRow, - TableHeader, - TableCell, - ], - content: content, - onUpdate({ editor }) { - if (onChange) { - onChange(editor.getHTML()) - } - console.log(editor.getHTML()) - }, - }, []) + const editor = useEditor( + { + extensions: [ + StarterKit.configure(), + Document, + Paragraph, + Text, + TextStyle, + TextAlign.configure({ + types: ["heading", "paragraph"], + }), + Underline, + Highlight.configure({ multicolor: true }), + Color, + ListItem, + TabHandler, + Gapcursor, + Table.configure({ + resizable: true, + }), + TableRow, + TableHeader, + TableCell, + ], + content: content, + onUpdate({ editor }) { + if (onChange) { + onChange(editor.getHTML()); + } + console.log(editor.getHTML()); + }, + }, + [], + ); - return ( - - {/* + return ( + + {/* {editor && } */} - - - - - ); + + + + + ); }; -export default MailField; \ No newline at end of file +export default MailField; diff --git a/src/components/MailField/MailFieldWrapper.tsx b/src/components/MailField/MailFieldWrapper.tsx index e5d2bf3..7d22420 100644 --- a/src/components/MailField/MailFieldWrapper.tsx +++ b/src/components/MailField/MailFieldWrapper.tsx @@ -4,18 +4,13 @@ import React from "react"; import MailField from "./MailField"; export interface Props { - content?: string, - onChange?: (richText: string) => void, - error?: boolean, + content?: string; + onChange?: (richText: string) => void; + error?: boolean; } -const TransferListWrapper: React.FC = ({ - content, - onChange, - error -}) => { - - return ; +const TransferListWrapper: React.FC = ({ content, onChange, error }) => { + return ; }; export default TransferListWrapper; diff --git a/src/components/MailField/MailToolbar.tsx b/src/components/MailField/MailToolbar.tsx index a79951b..5b27148 100644 --- a/src/components/MailField/MailToolbar.tsx +++ b/src/components/MailField/MailToolbar.tsx @@ -1,367 +1,549 @@ "use client"; -import { Button, ButtonGroup, Grid, IconButton, ToggleButton, ToggleButtonGroup } from "@mui/material"; -import "./MailField.css" -import { useEditor, EditorContent, Editor } from "@tiptap/react" -import FormatBoldIcon from '@mui/icons-material/FormatBold'; +import { + Button, + ButtonGroup, + Grid, + IconButton, + ToggleButton, + ToggleButtonGroup, +} from "@mui/material"; +import "./MailField.css"; +import { useEditor, EditorContent, Editor } from "@tiptap/react"; +import FormatBoldIcon from "@mui/icons-material/FormatBold"; import React, { useCallback } from "react"; import { FormatItalic, FormatUnderlined } from "@mui/icons-material"; -import { MuiColorInput, MuiColorInputColors, MuiColorInputValue } from 'mui-color-input' -import BorderColorIcon from '@mui/icons-material/BorderColor'; -import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; -import FormatColorTextIcon from '@mui/icons-material/FormatColorText'; -import FormatAlignLeftIcon from '@mui/icons-material/FormatAlignLeft'; -import FormatAlignJustifyIcon from '@mui/icons-material/FormatAlignJustify'; -import FormatAlignRightIcon from '@mui/icons-material/FormatAlignRight'; +import { + MuiColorInput, + MuiColorInputColors, + MuiColorInputValue, +} from "mui-color-input"; +import BorderColorIcon from "@mui/icons-material/BorderColor"; +import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; +import FormatColorTextIcon from "@mui/icons-material/FormatColorText"; +import FormatAlignLeftIcon from "@mui/icons-material/FormatAlignLeft"; +import FormatAlignJustifyIcon from "@mui/icons-material/FormatAlignJustify"; +import FormatAlignRightIcon from "@mui/icons-material/FormatAlignRight"; import { useTranslation } from "react-i18next"; -import GridOnIcon from '@mui/icons-material/GridOn'; +import GridOnIcon from "@mui/icons-material/GridOn"; interface Props { - editor: Editor | null; + editor: Editor | null; } const colorInputSx = { - width: 150, - height: 25, - ".MuiInputBase-colorPrimary": { - margin: -1, - borderRadius: "0px 5px 5px 0px", - borderColor: "rgba(0, 0, 0, 0)", - backgroundColor: "rgba(0, 0, 0, 0)", + width: 150, + height: 25, + ".MuiInputBase-colorPrimary": { + margin: -1, + borderRadius: "0px 5px 5px 0px", + borderColor: "rgba(0, 0, 0, 0)", + backgroundColor: "rgba(0, 0, 0, 0)", + }, + ".Mui-focused": { + borderColor: "rgba(0, 0, 0, 0)", + }, + ".MuiColorInput-Button": { + marginBottom: 2, + borderColor: "rgba(0, 0, 0, 0)", + backgroundColor: "rgba(0, 0, 0, 0)", + }, + ".MuiInputBase-input": { + marginBottom: 1.5, + }, +}; + +const fontFamily = [ + { + label: "Arial", + value: "Arial", + }, + { + label: "Times New Roman", + value: "Times New Roman", + }, + { + label: "Courier New", + value: "Courier New", + }, + { + label: "Georgia", + value: "Georgia", + }, + {}, +]; + +const MailToolbar: React.FC = ({ editor }) => { + const { t } = useTranslation(); + if (editor == null) { + return null; + } + + const [fontStyle, setFontStyle] = React.useState(["alignLeft"]); + const [colorHighlightValue, setColorHighlightValue] = + React.useState("red"); + const [colorTextValue, setColorTextValue] = + React.useState("black"); + const colorHighlightValueInputRef = React.useRef(null); + const colorTextValueInputRef = React.useRef(null); + + const handleFontStyle = useCallback( + (event: React.MouseEvent, newFontStyles: string[]) => { + setFontStyle((prev) => { + const id = event.currentTarget?.id; + const include = prev.includes(id); + + if (include) { + return prev.filter((ele) => ele !== id); + } else { + prev = prev.filter((ele) => !ele.includes("align")); + prev.push(id); + return prev; + } + }); }, - ".Mui-focused": { - borderColor: "rgba(0, 0, 0, 0)", + [], + ); + + const handleColorHighlightValue = useCallback( + (value: string, colors: MuiColorInputColors) => { + // console.log(colors) + setColorHighlightValue(() => value); + // editor.chain().focus().toggleHighlight({ color: value }).run() }, - ".MuiColorInput-Button": { - marginBottom: 2, - borderColor: "rgba(0, 0, 0, 0)", - backgroundColor: "rgba(0, 0, 0, 0)", + [], + ); + + const handleColorHighlightValueClick = useCallback( + (event: React.MouseEvent) => { + editor + .chain() + .focus() + .toggleHighlight({ color: colorHighlightValue.toString() }) + .run(); }, - ".MuiInputBase-input": { - marginBottom: 1.5, + [colorHighlightValue], + ); + + const handleColorHighlightValueClose = useCallback( + (event: {}, reason: "backdropClick" | "escapeKeyDown") => { + // console.log(event) + editor + .chain() + .focus() + .toggleHighlight({ color: colorHighlightValue.toString() }) + .run(); }, -} - -const fontFamily = [ - { - label: 'Arial', - value: 'Arial', + [colorHighlightValue], + ); + + const handleColorHighlightValueBlur = useCallback( + (event: React.FocusEvent) => { + editor + .chain() + .focus() + .toggleHighlight({ color: colorHighlightValue.toString() }) + .run(); }, - { - label: 'Times New Roman', - value: 'Times New Roman', + [colorHighlightValue], + ); + + const handleColorTextValue = useCallback( + (value: string, colors: MuiColorInputColors) => { + // console.log(colors) + setColorTextValue(() => value); + // if (editor.isActive("textStyle")) { + // editor.chain().focus().unsetColor().run() + // } else { + // editor.chain().focus().setColor(value).run() + // } }, - { - label: 'Courier New', - value: 'Courier New', + [], + ); + + const handleColorTextValueClick = useCallback( + (event: React.MouseEvent) => { + if (editor.isActive("textStyle", { color: colorTextValue.toString() })) { + editor.chain().focus().unsetColor().run(); + } else { + editor.chain().focus().setColor(colorTextValue.toString()).run(); + } }, - { - label: 'Georgia', - value: 'Georgia', + [colorTextValue], + ); + + const handleColorTextValueClose = useCallback( + (event: {}, reason: "backdropClick" | "escapeKeyDown") => { + if (editor.isActive("textStyle", { color: colorTextValue.toString() })) { + editor.chain().focus().unsetColor().run(); + } else { + editor.chain().focus().setColor(colorTextValue.toString()).run(); + } }, - { - + [colorTextValue], + ); + + const handleColorTextValueBlur = useCallback( + (event: React.FocusEvent) => { + if (editor.isActive("textStyle", { color: colorTextValue.toString() })) { + editor.chain().focus().unsetColor().run(); + } else { + editor.chain().focus().setColor(colorTextValue.toString()).run(); + } + }, + [colorTextValue], + ); + + const handleKeyDown = (event: React.KeyboardEvent) => { + if (event.key === "Enter") { + if (colorHighlightValueInputRef.current !== null) { + colorHighlightValueInputRef.current.blur(); + } + + if (colorTextValueInputRef.current !== null) { + colorTextValueInputRef.current.blur(); + } } -] + }; + + const handleTextAlign = useCallback( + (event: React.MouseEvent, value: any) => { + console.log(value); + switch (value) { + case "alignLeft": + if (editor.isActive({ textAlign: "left" })) { + editor.chain().focus().unsetTextAlign().run(); + } else { + editor.chain().focus().setTextAlign("left").run(); + } + break; + case "alignCenter": + if (editor.isActive({ textAlign: "center" })) { + editor.chain().focus().unsetTextAlign().run(); + } else { + editor.chain().focus().setTextAlign("center").run(); + } + break; + case "alignRight": + if (editor.isActive({ textAlign: "right" })) { + editor.chain().focus().unsetTextAlign().run(); + } else { + editor.chain().focus().setTextAlign("right").run(); + } + break; + default: + break; + } + }, + [], + ); -const MailToolbar: React.FC = ({ + const handleInsertTable = useCallback(() => { editor -}) => { - - const { t } = useTranslation() - if (editor == null) { - return null - } - - const [fontStyle, setFontStyle] = React.useState(["alignLeft"]); - const [colorHighlightValue, setColorHighlightValue] = React.useState("red"); - const [colorTextValue, setColorTextValue] = React.useState("black"); - const colorHighlightValueInputRef = React.useRef(null); - const colorTextValueInputRef = React.useRef(null); - - const handleFontStyle = useCallback(( - event: React.MouseEvent, - newFontStyles: string[], - ) => { - - setFontStyle((prev) => { - const id = event.currentTarget?.id - const include = prev.includes(id) - - if (include) { - return prev.filter(ele => ele !== id) - } else { - prev = prev.filter(ele => !ele.includes("align")) - prev.push(id) - return prev - } - }); - }, []); - - const handleColorHighlightValue = useCallback((value: string, colors: MuiColorInputColors) => { - // console.log(colors) - setColorHighlightValue(() => value) - // editor.chain().focus().toggleHighlight({ color: value }).run() - }, []) - - const handleColorHighlightValueClick = useCallback((event: React.MouseEvent) => { - editor.chain().focus().toggleHighlight({ color: colorHighlightValue.toString() }).run() - }, [colorHighlightValue]) - - const handleColorHighlightValueClose = useCallback((event: {}, reason: "backdropClick" | "escapeKeyDown") => { - // console.log(event) - editor.chain().focus().toggleHighlight({ color: colorHighlightValue.toString() }).run() - }, [colorHighlightValue]) - - const handleColorHighlightValueBlur = useCallback((event: React.FocusEvent) => { - editor.chain().focus().toggleHighlight({ color: colorHighlightValue.toString() }).run() - }, [colorHighlightValue]) - - const handleColorTextValue = useCallback((value: string, colors: MuiColorInputColors) => { - // console.log(colors) - setColorTextValue(() => value) - // if (editor.isActive("textStyle")) { - // editor.chain().focus().unsetColor().run() - // } else { - // editor.chain().focus().setColor(value).run() - // } - }, []) - - const handleColorTextValueClick = useCallback((event: React.MouseEvent) => { - if (editor.isActive("textStyle", { color: colorTextValue.toString() })) { - editor.chain().focus().unsetColor().run() - } else { - editor.chain().focus().setColor(colorTextValue.toString()).run() - } - }, [colorTextValue]) - - const handleColorTextValueClose = useCallback((event: {}, reason: "backdropClick" | "escapeKeyDown") => { - if (editor.isActive("textStyle", { color: colorTextValue.toString() })) { - editor.chain().focus().unsetColor().run() - } else { - editor.chain().focus().setColor(colorTextValue.toString()).run() - } - }, [colorTextValue]) - - const handleColorTextValueBlur = useCallback((event: React.FocusEvent) => { - if (editor.isActive("textStyle", { color: colorTextValue.toString() })) { - editor.chain().focus().unsetColor().run() - } else { - editor.chain().focus().setColor(colorTextValue.toString()).run() - } - }, [colorTextValue]) - - const handleKeyDown = (event: React.KeyboardEvent) => { - if (event.key === 'Enter') { - if (colorHighlightValueInputRef.current !== null) { - colorHighlightValueInputRef.current.blur(); - } - - if (colorTextValueInputRef.current !== null) { - colorTextValueInputRef.current.blur(); - } - } - } - - const handleTextAlign = useCallback((event: React.MouseEvent, value: any) => { - console.log(value) - switch (value) { - case "alignLeft": - if (editor.isActive({ textAlign: 'left' })) { - editor.chain().focus().unsetTextAlign().run() - } else { - editor.chain().focus().setTextAlign('left').run() - } - break; - case "alignCenter": - if (editor.isActive({ textAlign: 'center' })) { - editor.chain().focus().unsetTextAlign().run() - } else { - editor.chain().focus().setTextAlign('center').run() - } - break; - case "alignRight": - if (editor.isActive({ textAlign: 'right' })) { - editor.chain().focus().unsetTextAlign().run() - } else { - editor.chain().focus().setTextAlign('right').run() - } - break; - default: - break; - } - }, []) - - const handleInsertTable = useCallback(() => { - editor.chain().focus().insertTable({ rows: 3, cols: 3, withHeaderRow: true }).run() - }, []) - - React.useEffect(() => { - editor.on('selectionUpdate', ({ editor }) => { - const currentFormatList: string[] = [] - if (editor.isActive("bold")) { - currentFormatList.push("bold") - } - - if (editor.isActive("italic")) { - currentFormatList.push("italic") - } - - if (editor.isActive("underline")) { - currentFormatList.push("underline") - } - - if (editor.isActive("highlight", { color: colorHighlightValue.toString() })) { - currentFormatList.push("highlight") - } - - if (editor.isActive("textStyle", { color: colorTextValue.toString() })) { - currentFormatList.push("textStyle") - } - - if (editor.isActive({ textAlign: 'left' })) { - currentFormatList.push("alignLeft") - } - - if (editor.isActive({ textAlign: 'center' })) { - currentFormatList.push("alignCenter") - } - - if (editor.isActive({ textAlign: 'right' })) { - currentFormatList.push("alignRight") - } - - console.log(currentFormatList) - setFontStyle(() => currentFormatList) - }) - }, [editor]) - - return ( - - - editor.chain().focus().toggleBold().run()}> - - - editor.chain().focus().toggleItalic().run()}> - - - editor.chain().focus().toggleUnderline().run()}> - - - - - - - - - {/* console.log("Expand more")}> + .chain() + .focus() + .insertTable({ rows: 3, cols: 3, withHeaderRow: true }) + .run(); + }, []); + + React.useEffect(() => { + editor.on("selectionUpdate", ({ editor }) => { + const currentFormatList: string[] = []; + if (editor.isActive("bold")) { + currentFormatList.push("bold"); + } + + if (editor.isActive("italic")) { + currentFormatList.push("italic"); + } + + if (editor.isActive("underline")) { + currentFormatList.push("underline"); + } + + if ( + editor.isActive("highlight", { color: colorHighlightValue.toString() }) + ) { + currentFormatList.push("highlight"); + } + + if (editor.isActive("textStyle", { color: colorTextValue.toString() })) { + currentFormatList.push("textStyle"); + } + + if (editor.isActive({ textAlign: "left" })) { + currentFormatList.push("alignLeft"); + } + + if (editor.isActive({ textAlign: "center" })) { + currentFormatList.push("alignCenter"); + } + + if (editor.isActive({ textAlign: "right" })) { + currentFormatList.push("alignRight"); + } + + console.log(currentFormatList); + setFontStyle(() => currentFormatList); + }); + }, [editor]); + + return ( + + + editor.chain().focus().toggleBold().run()} + > + + + editor.chain().focus().toggleItalic().run()} + > + + + editor.chain().focus().toggleUnderline().run()} + > + + + + + + + + + {/* console.log("Expand more")}> */} - - - - - - - - - - - - - - - - - - - - - - - - - - - - editor.chain().focus().insertTable({ rows: 3, cols: 3, withHeaderRow: true }).run()}> - {t("Insert Table")} - - editor.chain().focus().deleteTable().run()}>{t("Delete table")} - editor.chain().focus().addColumnBefore().run()}> - {t("Add column before")} - - editor.chain().focus().addColumnAfter().run()}>{t("Add column after")} - editor.chain().focus().deleteColumn().run()}>{t("Delete column")} - editor.chain().focus().addRowBefore().run()}>{t("Add row before")} - editor.chain().focus().addRowAfter().run()}>{t("Add row after")} - editor.chain().focus().deleteRow().run()}>{t("Delete row")} - editor.chain().focus().mergeCells().run()}>{t("Merge cells")} - editor.chain().focus().splitCell().run()}>{t("Split cell")} - - - editor.chain().focus().toggleHeaderColumn().run()}> - {t("Toggle header column")} - - editor.chain().focus().toggleHeaderRow().run()}> - {t("Toggle header row")} - - editor.chain().focus().toggleHeaderCell().run()}> - {t("Toggle header cell")} - - editor.chain().focus().mergeOrSplit().run()}>{t("Merge or split")} - editor.chain().focus().setCellAttribute('colspan', 2).run()}> - {t("Set cell attribute")} - - editor.chain().focus().fixTables().run()}>{t("Fix tables")} - editor.chain().focus().goToNextCell().run()}>{t("Go to next cell")} - editor.chain().focus().goToPreviousCell().run()}> - {t("Go to previous cell")} - - - - ); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + editor + .chain() + .focus() + .insertTable({ rows: 3, cols: 3, withHeaderRow: true }) + .run() + } + > + + {t("Insert Table")} + + editor.chain().focus().deleteTable().run()} + > + {t("Delete table")} + + editor.chain().focus().addColumnBefore().run()} + > + {t("Add column before")} + + editor.chain().focus().addColumnAfter().run()} + > + {t("Add column after")} + + editor.chain().focus().deleteColumn().run()} + > + {t("Delete column")} + + editor.chain().focus().addRowBefore().run()} + > + {t("Add row before")} + + editor.chain().focus().addRowAfter().run()} + > + {t("Add row after")} + + editor.chain().focus().deleteRow().run()} + > + {t("Delete row")} + + editor.chain().focus().mergeCells().run()} + > + {t("Merge cells")} + + editor.chain().focus().splitCell().run()} + > + {t("Split cell")} + + + + editor.chain().focus().toggleHeaderColumn().run()} + > + {t("Toggle header column")} + + editor.chain().focus().toggleHeaderRow().run()} + > + {t("Toggle header row")} + + editor.chain().focus().toggleHeaderCell().run()} + > + {t("Toggle header cell")} + + editor.chain().focus().mergeOrSplit().run()} + > + {t("Merge or split")} + + + editor.chain().focus().setCellAttribute("colspan", 2).run() + } + > + {t("Set cell attribute")} + + editor.chain().focus().fixTables().run()} + > + {t("Fix tables")} + + editor.chain().focus().goToNextCell().run()} + > + {t("Go to next cell")} + + editor.chain().focus().goToPreviousCell().run()} + > + {t("Go to previous cell")} + + + + ); }; -export default MailToolbar; \ No newline at end of file +export default MailToolbar; diff --git a/src/components/MailField/index.ts b/src/components/MailField/index.ts index ab7f59d..3bff435 100644 --- a/src/components/MailField/index.ts +++ b/src/components/MailField/index.ts @@ -1 +1 @@ -export { default } from "./MailFieldWrapper"; \ No newline at end of file +export { default } from "./MailFieldWrapper"; diff --git a/src/components/MailSetting/MailSetting.tsx b/src/components/MailSetting/MailSetting.tsx index 6302769..5b62292 100644 --- a/src/components/MailSetting/MailSetting.tsx +++ b/src/components/MailSetting/MailSetting.tsx @@ -8,195 +8,203 @@ import { useRouter } from "next/navigation"; import React, { useCallback, useContext, useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import { - FieldErrors, - FormProvider, - SubmitErrorHandler, - SubmitHandler, - useForm, + FieldErrors, + FormProvider, + SubmitErrorHandler, + SubmitHandler, + useForm, } from "react-hook-form"; import { Tab, Tabs, TabsProps, Typography } from "@mui/material"; import TimesheetMailDetails from "./TimesheetMailDetails"; import { Error } from "@mui/icons-material"; -import { MailSave, saveMail, testEveryone, test7th, test15th, testSendMail } from "@/app/api/mail/actions"; +import { + MailSave, + saveMail, + testEveryone, + test7th, + test15th, + testSendMail, +} from "@/app/api/mail/actions"; import SettingDetails from "./SettingDetails"; import { errorDialog, submitDialog, successDialog } from "../Swal/CustomAlerts"; import { MailTemplate } from "@/app/api/mail"; import TemplateDetails from "./TemplateDetails"; import QrCodeScanner from "../QrCodeScanner/QrCodeScanner"; -import { QcCodeScannerContext, useQcCodeScanner } from "../QrCodeScannerProvider/QrCodeScannerProvider"; +import { + QcCodeScannerContext, + useQcCodeScanner, +} from "../QrCodeScannerProvider/QrCodeScannerProvider"; export interface Props { - defaultInputs?: MailSave, + defaultInputs?: MailSave; } -const hasErrorsInTab = ( - tabIndex: number, - errors: FieldErrors, -) => { - switch (tabIndex) { - case 0: - return ( - errors.settings - ); - case 1: - return ( - errors.templates - ); - default: - false; - } +const hasErrorsInTab = (tabIndex: number, errors: FieldErrors) => { + switch (tabIndex) { + case 0: + return errors.settings; + case 1: + return errors.templates; + default: + false; + } }; -const MailSetting: React.FC = ({ - defaultInputs, -}) => { - const [serverError, setServerError] = useState(""); - const { t } = useTranslation(); - const router = useRouter(); - const [tabIndex, setTabIndex] = useState(0); - const [test, setTest] = useState(false) - - const handleTabChange = useCallback>( - (_e, newValue) => { - setTabIndex(newValue); - }, - [], - ); - - const formProps = useForm({ - defaultValues: defaultInputs - }); - - const handleCancel = () => { - router.back(); - }; - - const onSubmit = useCallback>( - async (data) => { - try { - console.log(data); - - // let haveError = false - // if (data.name.length === 0) { - // haveError = true - // formProps.setError("name", { message: "Name is empty", type: "required" }) - // } - - // if (haveError) { - // return false - // } - - - setServerError(""); - - submitDialog(async () => { - const response = await saveMail(data); - - console.log(response) - if (response !== null) { - if (test) { - await testSendMail() - } - // if (test) { - // let msg = "" - // try { - // msg = "testEveryone" - // await testEveryone() - // msg = "test7th" - // await test7th() - // msg = "test15th" - // await test15th() - // } catch (error) { - // console.log(error) - // console.log(msg) - // } - // } - - successDialog(t("Save Success"), t) - } else { - errorDialog(t("Save Fail"), t).then(() => { - // formProps.setError("code", { message: response.message, type: "custom" }) - // setTabIndex(0) - return false - }) - } - }, t) - } catch (e) { - console.log(e) - setServerError(t("An error has occurred. Please try again later.")); +const MailSetting: React.FC = ({ defaultInputs }) => { + const [serverError, setServerError] = useState(""); + const { t } = useTranslation(); + const router = useRouter(); + const [tabIndex, setTabIndex] = useState(0); + const [test, setTest] = useState(false); + + const handleTabChange = useCallback>( + (_e, newValue) => { + setTabIndex(newValue); + }, + [], + ); + + const formProps = useForm({ + defaultValues: defaultInputs, + }); + + const handleCancel = () => { + router.back(); + }; + + const onSubmit = useCallback>( + async (data) => { + try { + console.log(data); + + // let haveError = false + // if (data.name.length === 0) { + // haveError = true + // formProps.setError("name", { message: "Name is empty", type: "required" }) + // } + + // if (haveError) { + // return false + // } + + setServerError(""); + + submitDialog(async () => { + const response = await saveMail(data); + + console.log(response); + if (response !== null) { + if (test) { + await testSendMail(); + } + // if (test) { + // let msg = "" + // try { + // msg = "testEveryone" + // await testEveryone() + // msg = "test7th" + // await test7th() + // msg = "test15th" + // await test15th() + // } catch (error) { + // console.log(error) + // console.log(msg) + // } + // } + + successDialog(t("Save Success"), t); + } else { + errorDialog(t("Save Fail"), t).then(() => { + // formProps.setError("code", { message: response.message, type: "custom" }) + // setTabIndex(0) + return false; + }); + } + }, t); + } catch (e) { + console.log(e); + setServerError(t("An error has occurred. Please try again later.")); + } + }, + [router, t, test], + ); + + const onSubmitError = useCallback>((errors) => { + console.log(errors); + }, []); + + const errors = formProps.formState.errors; + + return ( + + + {serverError && ( + + {serverError} + + )} + + + ) : undefined + } + iconPosition="end" + /> + + ) : undefined } - }, - [router, t, test], - ); - - const onSubmitError = useCallback>( - (errors) => { - console.log(errors) - }, - [], - ); - - const errors = formProps.formState.errors; - - return ( - - - {serverError && ( - - {serverError} - - )} - - - ) : undefined - } - iconPosition="end" - /> - - ) : undefined - } - iconPosition="end" - /> - - - - {/* */} - - - - - - - - - ); + iconPosition="end" + /> + + + + {/* */} + + + + + + + + + ); }; -export default MailSetting; \ No newline at end of file +export default MailSetting; diff --git a/src/components/MailSetting/MailSettingLoading.tsx b/src/components/MailSetting/MailSettingLoading.tsx index 9cd157b..43a82c7 100644 --- a/src/components/MailSetting/MailSettingLoading.tsx +++ b/src/components/MailSetting/MailSettingLoading.tsx @@ -6,33 +6,33 @@ import React from "react"; // Can make this nicer export const MailSettingLoading: React.FC = () => { - return ( - <> - - - - - - - - - - - - - - - - - - - - ); + return ( + <> + + + + + + + + + + + + + + + + + + + + ); }; -export default MailSettingLoading; \ No newline at end of file +export default MailSettingLoading; diff --git a/src/components/MailSetting/MailSettingWrapper.tsx b/src/components/MailSetting/MailSettingWrapper.tsx index 7774b8d..021ff78 100644 --- a/src/components/MailSetting/MailSettingWrapper.tsx +++ b/src/components/MailSetting/MailSettingWrapper.tsx @@ -4,40 +4,39 @@ import MailSettingLoading from "./MailSettingLoading"; import { fetchMailSetting, fetchMailTemplates } from "@/app/api/mail"; interface SubComponents { - Loading: typeof MailSettingLoading; + Loading: typeof MailSettingLoading; } const MailSettingWrapper: React.FC & SubComponents = async () => { - const [ - // abilities, - settings, - templates, - // timesheetTemplate, - ] = await Promise.all([ - // fetchUserAbilities(), - fetchMailSetting(), - fetchMailTemplates(), - // fetchMailTimesheetTemplate() - ]); + const [ + // abilities, + settings, + templates, + // timesheetTemplate, + ] = await Promise.all([ + // fetchUserAbilities(), + fetchMailSetting(), + fetchMailTemplates(), + // fetchMailTimesheetTemplate() + ]); - // const tempTimesheetTemplate: MailTemplate = { - // cc: timesheetTemplate.find(template => template.name.includes(".cc"))?.value, - // bcc: timesheetTemplate.find(template => template.name.includes(".bcc"))?.value, - // subject: timesheetTemplate.find(template => template.name.includes(".subject"))?.value, - // template: timesheetTemplate.find(template => template.name.includes(".template"))?.value, - // } - return ( - - ); + // const tempTimesheetTemplate: MailTemplate = { + // cc: timesheetTemplate.find(template => template.name.includes(".cc"))?.value, + // bcc: timesheetTemplate.find(template => template.name.includes(".bcc"))?.value, + // subject: timesheetTemplate.find(template => template.name.includes(".subject"))?.value, + // template: timesheetTemplate.find(template => template.name.includes(".template"))?.value, + // } + return ( + + ); }; MailSettingWrapper.Loading = MailSettingLoading; - export default MailSettingWrapper; diff --git a/src/components/MailSetting/SettingDetails.tsx b/src/components/MailSetting/SettingDetails.tsx index b1cca0c..c064dcd 100644 --- a/src/components/MailSetting/SettingDetails.tsx +++ b/src/components/MailSetting/SettingDetails.tsx @@ -18,126 +18,143 @@ import { Checkbox, IconButton, InputAdornment } from "@mui/material"; import { Visibility, VisibilityOff } from "@mui/icons-material"; interface Props { - isActive: boolean; + isActive: boolean; } const SettingDetails: React.FC = ({ isActive }) => { - const requiredFields = ["host", "port", "username"] - const { t } = useTranslation(); - const { - register, - formState: { errors }, - control, - watch - } = useFormContext(); + const requiredFields = ["host", "port", "username"]; + const { t } = useTranslation(); + const { + register, + formState: { errors }, + control, + watch, + } = useFormContext(); - const { fields } = useFieldArray({ - control, - name: "settings" - }) + const { fields } = useFieldArray({ + control, + name: "settings", + }); - const [showSMTPPassword, setShowSMTPPassword] = React.useState(false) + const [showSMTPPassword, setShowSMTPPassword] = React.useState(false); - const handleClickShowPassword = () => setShowSMTPPassword((show) => !show); + const handleClickShowPassword = () => setShowSMTPPassword((show) => !show); - const handleMouseDownPassword = (event: React.MouseEvent) => { - event.preventDefault(); - }; + const handleMouseDownPassword = ( + event: React.MouseEvent, + ) => { + event.preventDefault(); + }; - return ( - - - - - {t("Settings")} - - { - fields.map((field, index) => ( - - - {`${t(field.name)}${requiredFields.some(name => field.name.toLowerCase().includes(name)) ? "*" : ""}`} - - { - field.name.toLowerCase().includes("password") === true ? - - - - {showSMTPPassword ? : } - - - ), - }} - fullWidth - {...register(`settings.${index}.value`)} - /> - - : - field.type.toLowerCase() === "boolean" ? - - - - : - field.type.toLowerCase() === "integer" ? - - field.name.toLowerCase().includes(name)) - })} - error={Boolean( - errors.settings - && errors.settings.length - && errors.settings.length > index - && errors.settings[index]?.value - )} - /> - - : - - field.name.toLowerCase().includes(name)) - })} - error={Boolean( - errors.settings - && errors.settings.length - && errors.settings.length > index - && errors.settings[index]?.value - )} - /> - - } - - )) - } - - - - ); + return ( + + + + + {t("Settings")} + + {fields.map((field, index) => ( + + + {`${t(field.name)}${ + requiredFields.some((name) => + field.name.toLowerCase().includes(name), + ) + ? "*" + : "" + }`} + + {field.name.toLowerCase().includes("password") === true ? ( + + + + {showSMTPPassword ? ( + + ) : ( + + )} + + + ), + }} + fullWidth + {...register(`settings.${index}.value`)} + /> + + ) : field.type.toLowerCase() === "boolean" ? ( + + + + ) : field.type.toLowerCase() === "integer" ? ( + + + field.name.toLowerCase().includes(name), + ), + })} + error={Boolean( + errors.settings && + errors.settings.length && + errors.settings.length > index && + errors.settings[index]?.value, + )} + /> + + ) : ( + + + field.name.toLowerCase().includes(name), + ), + })} + error={Boolean( + errors.settings && + errors.settings.length && + errors.settings.length > index && + errors.settings[index]?.value, + )} + /> + + )} + + ))} + + + + ); }; -export default SettingDetails; \ No newline at end of file +export default SettingDetails; diff --git a/src/components/MailSetting/TemplateDetails.tsx b/src/components/MailSetting/TemplateDetails.tsx index f878c12..8e795f8 100644 --- a/src/components/MailSetting/TemplateDetails.tsx +++ b/src/components/MailSetting/TemplateDetails.tsx @@ -15,168 +15,179 @@ import MailField from "../MailField/MailField"; import { MailSave } from "@/app/api/mail/actions"; import { MailTemplate } from "@/app/api/mail"; import { isEmpty, keys } from "lodash"; -import { Autocomplete, ListSubheader, MenuItem, UseAutocompleteProps } from "@mui/material"; +import { + Autocomplete, + ListSubheader, + MenuItem, + UseAutocompleteProps, +} from "@mui/material"; interface Props { - isActive: boolean; + isActive: boolean; } interface OptionType { - value: number, - label: string, - group: string, + value: number; + label: string; + group: string; } -type fieldKeys = keyof MailTemplate +type fieldKeys = keyof MailTemplate; const TemplateDetails: React.FC = ({ isActive }) => { - const { t } = useTranslation(); + const { t } = useTranslation(); - // const disabledFields: fieldKeys[] = [] - // const requiredFields: fieldKeys[] = [] - // const skipFields: fieldKeys[] = ["code", "subjectEng", "contentEng"] - const [selectedIndex, setSelectedIndex] = useState(0) + // const disabledFields: fieldKeys[] = [] + // const requiredFields: fieldKeys[] = [] + // const skipFields: fieldKeys[] = ["code", "subjectEng", "contentEng"] + const [selectedIndex, setSelectedIndex] = useState(0); - const { - register, - formState: { errors }, - control, - watch, - getValues - } = useFormContext(); + const { + register, + formState: { errors }, + control, + watch, + getValues, + } = useFormContext(); - const { - fields, - } = useFieldArray({ - control, - name: "templates" - }) + const { fields } = useFieldArray({ + control, + name: "templates", + }); - const options: OptionType[] = useMemo(() => ( - fields.map((field, index) => { - return { - value: index, - label: `${field.code} - ${field.description}`, - group: field.type - } as OptionType - }) - ), [fields]) + const options: OptionType[] = useMemo( + () => + fields.map((field, index) => { + return { + value: index, + label: `${field.code} - ${field.description}`, + group: field.type, + } as OptionType; + }), + [fields], + ); - const makeAutocompleteChangeHandler = useCallback(() => { - return (e: SyntheticEvent, newValue: OptionType) => { - setSelectedIndex(() => newValue.value); - }; - }, []); + const makeAutocompleteChangeHandler = useCallback(() => { + return (e: SyntheticEvent, newValue: OptionType) => { + setSelectedIndex(() => newValue.value); + }; + }, []); - // const renderFieldsBySwitchCases = useCallback(() => { - // const fieldNames = keys(fields[0]) as fieldKeys[]; + // const renderFieldsBySwitchCases = useCallback(() => { + // const fieldNames = keys(fields[0]) as fieldKeys[]; - // return fieldNames - // .filter((name) => !skipFields.includes(name)) - // .map((name: fieldKeys, index: number) => { - // switch (name) { - // case "contentCht": - // return ( - // - // ( - // - // )} - // rules={{ - // required: requiredFields.includes(name), - // }} - // /> - // - // ) - // default: - // return ( - // - // - // - // ) - // } - // }) - // }, [fields]) + // return fieldNames + // .filter((name) => !skipFields.includes(name)) + // .map((name: fieldKeys, index: number) => { + // switch (name) { + // case "contentCht": + // return ( + // + // ( + // + // )} + // rules={{ + // required: requiredFields.includes(name), + // }} + // /> + // + // ) + // default: + // return ( + // + // + // + // ) + // } + // }) + // }, [fields]) - return ( - - - - - {t("Template")} - - - - ( - option.group && option.group.trim() !== '' ? option.group : 'Ungrouped' - )} - renderGroup={(params) => ( - - {params.group} - {params.children} - - )} - renderOption={( - params: React.HTMLAttributes & { key?: React.Key }, - option, - { selected }, - ) => { - // eslint-disable-next-line @typescript-eslint/no-unused-vars - const { key, ...rest } = params; - return ( - - {option.label} - - ); - }} - renderInput={(params) => } - /> - - - - - - - - {/* + return ( + + + + + {t("Template")} + + + + + option.group && option.group.trim() !== "" + ? option.group + : "Ungrouped" + } + renderGroup={(params) => ( + + {params.group} + {params.children} + + )} + renderOption={( + params: React.HTMLAttributes & { + key?: React.Key; + }, + option, + { selected }, + ) => { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const { key, ...rest } = params; + return ( + + {option.label} + + ); + }} + renderInput={(params) => ( + + )} + /> + + + + + + + + {/* = ({ isActive }) => { {...register(`templates.${selectedIndex}.params`)} /> */} - - - - - ( - - )} - rules={{ - required: "Mail Content is required!", - }} - /> - - - - - - ); + + + + + ( + + )} + rules={{ + required: "Mail Content is required!", + }} + /> + + + + + + ); }; export default TemplateDetails; diff --git a/src/components/MailSetting/TimesheetMailDetails.tsx b/src/components/MailSetting/TimesheetMailDetails.tsx index c38f8c7..d2c79b0 100644 --- a/src/components/MailSetting/TimesheetMailDetails.tsx +++ b/src/components/MailSetting/TimesheetMailDetails.tsx @@ -15,82 +15,80 @@ import MailField from "../MailField/MailField"; import { MailSave } from "@/app/api/mail/actions"; interface Props { - isActive: boolean; + isActive: boolean; } const TimesheetMailDetails: React.FC = ({ isActive }) => { - const { t } = useTranslation(); - const { - register, - formState: { errors }, - control - } = useFormContext(); + const { t } = useTranslation(); + const { + register, + formState: { errors }, + control, + } = useFormContext(); - return ( - - - - - {t("Timesheet Template")} - - - - - - - - - - - - - - - - ( - - )} - rules={{ - required: true, - validate: value => value?.includes("${date}") - }} - /> - - - - - - ); + return ( + + + + + {t("Timesheet Template")} + + + + + + + + + + + + + + + + ( + + )} + rules={{ + required: true, + validate: (value) => value?.includes("${date}"), + }} + /> + + + + + + ); }; export default TimesheetMailDetails; diff --git a/src/components/MailSetting/index.ts b/src/components/MailSetting/index.ts index fadb1d2..a126af0 100644 --- a/src/components/MailSetting/index.ts +++ b/src/components/MailSetting/index.ts @@ -1 +1 @@ -export { default } from "./MailSettingWrapper"; \ No newline at end of file +export { default } from "./MailSettingWrapper"; diff --git a/src/components/NavigationContent/NavigationContent.tsx b/src/components/NavigationContent/NavigationContent.tsx index 3fc03a1..f6b123a 100644 --- a/src/components/NavigationContent/NavigationContent.tsx +++ b/src/components/NavigationContent/NavigationContent.tsx @@ -29,14 +29,14 @@ interface NavigationItem { label: string; path: string; children?: NavigationItem[]; - isHidden?: true | undefined + isHidden?: true | undefined; } const NavigationContent: React.FC = () => { const navigationItems: NavigationItem[] = [ { icon: , - label: ("Dashboard"), + label: "Dashboard", path: "/dashboard", }, { @@ -181,6 +181,11 @@ const NavigationContent: React.FC = () => { label: "Detail Scheduling", path: "/scheduling/detail", }, + { + icon: , + label: "Production", + path: "/production", + }, ], }, { @@ -302,7 +307,9 @@ const NavigationContent: React.FC = () => { {item.children && isOpen && ( - {item.children.map((child) => (!child.isHidden && renderNavigationItem(child)))} + {item.children.map( + (child) => !child.isHidden && renderNavigationItem(child), + )} )} diff --git a/src/components/Orderstatus/PoSearch.tsx b/src/components/Orderstatus/PoSearch.tsx index c50ac0e..3742893 100644 --- a/src/components/Orderstatus/PoSearch.tsx +++ b/src/components/Orderstatus/PoSearch.tsx @@ -39,21 +39,21 @@ const PoSearch: React.FC = ({ const { t } = useTranslation("purchaseOrder"); const router = useRouter(); const [pagingController, setPagingController] = useState( - defaultPagingController + defaultPagingController, ); const [totalCount, setTotalCount] = useState(initTotalCount); const searchCriteria: Criterion[] = useMemo(() => { - var searchCriteria: Criterion[] = [ + const searchCriteria: Criterion[] = [ { label: t("Code"), paramName: "code", type: "text" }, { label: t("Status"), paramName: "status", type: "select-labelled", options: [ - {label: t(`pending`), value: `pending`}, - {label: t(`receiving`), value: `receiving`}, - {label: t(`completed`), value: `completed`}, - ] + { label: t(`pending`), value: `pending` }, + { label: t(`receiving`), value: `receiving` }, + { label: t(`completed`), value: `completed` }, + ], }, { label: t("Escalated"), @@ -69,7 +69,7 @@ const PoSearch: React.FC = ({ (po: PoResult) => { router.push(`/po/edit?id=${po.id}`); }, - [router] + [router], ); const onDeleteClick = useCallback((po: PoResult) => {}, [router]); @@ -90,9 +90,11 @@ const PoSearch: React.FC = ({ name: "orderDate", label: t("OrderDate"), renderCell: (params) => { - return dayjs(params.orderDate) - // .add(-1, "month") - .format(OUTPUT_DATE_FORMAT); + return ( + dayjs(params.orderDate) + // .add(-1, "month") + .format(OUTPUT_DATE_FORMAT) + ); }, }, { @@ -110,14 +112,14 @@ const PoSearch: React.FC = ({ name: "escalated", label: t("Escalated"), renderCell: (params) => { - console.log(params.escalated) + console.log(params.escalated); return params.escalated ? ( ) : undefined; }, }, ], - [filteredPo] + [filteredPo], ); const onReset = useCallback(() => { @@ -136,7 +138,7 @@ const PoSearch: React.FC = ({ const newPageFetch = useCallback( async ( pagingController: Record, - filterArgs: Record + filterArgs: Record, ) => { console.log(pagingController); console.log(filterArgs); @@ -152,7 +154,7 @@ const PoSearch: React.FC = ({ setTotalCount(res.total); } }, - [fetchPoListClient] + [fetchPoListClient], ); useEffect(() => { @@ -179,11 +181,14 @@ const PoSearch: React.FC = ({ { - console.log(query) - setFilterArgs({ + console.log(query); + setFilterArgs({ code: query.code, status: query.status === "All" ? "" : query.status, - escalated: query.escalated === 'All' ? undefined : query.escalated === t("Escalated") + escalated: + query.escalated === "All" + ? undefined + : query.escalated === t("Escalated"), }); // setFilteredPo((prev) => // po.filter((p) => { diff --git a/src/components/Orderstatus/PoSearchWrapper.tsx b/src/components/Orderstatus/PoSearchWrapper.tsx index 4505f2d..4abe5c6 100644 --- a/src/components/Orderstatus/PoSearchWrapper.tsx +++ b/src/components/Orderstatus/PoSearchWrapper.tsx @@ -25,27 +25,26 @@ type Props = { const PoSearchWrapper: React.FC & SubComponents = async ( { // type, - } + }, ) => { // console.log(defaultPagingController) - const [ - po, - warehouse, - ] = await Promise.all([ + const [po, warehouse] = await Promise.all([ fetchPoList({ - "pageNum": 1, - "pageSize": 10, - }), + pageNum: 1, + pageSize: 10, + }), // fetchPoList(), fetchWarehouseList(), ]); const fixPoDate = po.records.map((p) => { - return ({ + return { ...p, - orderDate: dayjs(p.orderDate).add(-1, "month").format(OUTPUT_DATE_FORMAT) - }) - }) - return ; + orderDate: dayjs(p.orderDate).add(-1, "month").format(OUTPUT_DATE_FORMAT), + }; + }); + return ( + + ); }; PoSearchWrapper.Loading = PoSearchLoading; diff --git a/src/components/PickOrderDetail/ApprovalContent.tsx b/src/components/PickOrderDetail/ApprovalContent.tsx index 18a5e9f..c492c71 100644 --- a/src/components/PickOrderDetail/ApprovalContent.tsx +++ b/src/components/PickOrderDetail/ApprovalContent.tsx @@ -33,18 +33,18 @@ import { PickOrderApprovalInput } from "@/app/api/pickorder/actions"; import { StockOutLine } from "@/app/api/pickorder"; interface Props { -// approvalDefaultValues: StockInLine; -// qc: QcItemWithChecks[]; + // approvalDefaultValues: StockInLine; + // qc: QcItemWithChecks[]; approvalDefaultValues: StockOutLine & PickOrderApprovalInput; - disabled: boolean + disabled: boolean; } -const ApprovalContent: React.FC = ({ -// qc, +const ApprovalContent: React.FC = ({ + // qc, approvalDefaultValues, - disabled - }) => { + disabled, +}) => { const { t } = useTranslation("purchaseOrder"); const apiRef = useGridApiRef(); const { @@ -59,10 +59,10 @@ const ApprovalContent: React.FC = ({ setError, clearErrors, } = useFormContext(); - console.log(approvalDefaultValues) + console.log(approvalDefaultValues); -// const status = "rejected" - const totalQty = approvalDefaultValues.qty + // const status = "rejected" + const totalQty = approvalDefaultValues.qty; const allowQty = watch("allowQty"); const rejectQty = watch("rejectQty"); @@ -93,7 +93,7 @@ const ApprovalContent: React.FC = ({ required: "allowQty required!", min: 0, valueAsNumber: true, - max: approvalDefaultValues.allowQty + max: approvalDefaultValues.allowQty, })} disabled={disabled} defaultValue={approvalDefaultValues.allowQty} @@ -109,7 +109,7 @@ const ApprovalContent: React.FC = ({ required: "rejectQty required!", min: 0, valueAsNumber: true, - max: approvalDefaultValues.rejectQty + max: approvalDefaultValues.rejectQty, })} disabled={disabled} defaultValue={approvalDefaultValues.rejectQty} @@ -124,8 +124,7 @@ const ApprovalContent: React.FC = ({ alignItems="flex-start" spacing={2} sx={{ mt: 0.5 }} - > - + > ); }; diff --git a/src/components/PickOrderDetail/ApprovalForm.tsx b/src/components/PickOrderDetail/ApprovalForm.tsx index 5eabaea..19fb7ba 100644 --- a/src/components/PickOrderDetail/ApprovalForm.tsx +++ b/src/components/PickOrderDetail/ApprovalForm.tsx @@ -60,7 +60,7 @@ const ApprovalForm: React.FC = ({ onClose?.(...args); // reset(); }, - [onClose] + [onClose], ); const onSubmit = useCallback>( @@ -68,7 +68,7 @@ const ApprovalForm: React.FC = ({ console.log(data); // checking later // post - let hasError = false; + const hasError = false; if (data.allowQty + data.rejectQty != approvalDefaultValues.qty) { formProps.setError("allowQty", { message: "illegal qty", @@ -80,7 +80,7 @@ const ApprovalForm: React.FC = ({ }); } if (hasError) { - return + return; } const postData: UpdateStockOutLine = { id: approvalDefaultValues.id, @@ -101,7 +101,7 @@ const ApprovalForm: React.FC = ({ console.log("bug la"); } }, - [t] + [t], ); return ( <> diff --git a/src/components/PickOrderDetail/PickOrderDetail.tsx b/src/components/PickOrderDetail/PickOrderDetail.tsx index 9e7a814..4aec851 100644 --- a/src/components/PickOrderDetail/PickOrderDetail.tsx +++ b/src/components/PickOrderDetail/PickOrderDetail.tsx @@ -92,7 +92,7 @@ class ProcessRowUpdateError extends Error { constructor( row: StockOutLineRow, message?: string, - errors?: StockOutLineEntryError + errors?: StockOutLineEntryError, ) { super(message); this.row = row; @@ -112,7 +112,7 @@ const PickOrderDetail: React.FC = ({ consoCode, qc }) => { const [selectedRow, setSelectedRow] = useState([]); const [currPol, setCurrPol] = useState(); const [isChangeLotSolId, setIsChangeLotSolId] = useState( - undefined + undefined, ); const [formDefaultValues, setFormDefaultValues] = @@ -183,7 +183,7 @@ const PickOrderDetail: React.FC = ({ consoCode, qc }) => { renderCell: (params) => { if (!params.row.suggestedLotNo) return <>; const suggestedLotNoList = JSON.parse( - params.row.suggestedLotNo + params.row.suggestedLotNo, ) as string[]; return FitAllCell(suggestedLotNoList); }, @@ -197,7 +197,7 @@ const PickOrderDetail: React.FC = ({ consoCode, qc }) => { }, }, ], - [] + [], ); const [isCompletedOrder, setIsCompletedOrder] = useState(false); @@ -216,7 +216,7 @@ const PickOrderDetail: React.FC = ({ consoCode, qc }) => { console.log(res); console.log(res.records.every((line) => line.status == "completed")); setIsCompletedOrder(() => - res.records.every((line) => line.status == "completed") + res.records.every((line) => line.status == "completed"), ); setPickOrderLine(res.records); @@ -230,7 +230,7 @@ const PickOrderDetail: React.FC = ({ consoCode, qc }) => { pickOrderLineTable: false, })); }, - [fetchPickOrderLineClient, consoCode] + [fetchPickOrderLineClient, consoCode], ); const buttonData = useMemo( @@ -245,14 +245,14 @@ const PickOrderDetail: React.FC = ({ consoCode, qc }) => { buttonColor: "info", disabled: true, }), - [] + [], ); const [stockOutLine, setStockOutLine] = useState([]); const getRowId = useCallback>( (row) => row.id as number, - [] + [], ); const [qcOpen, setQcOpen] = useState(false); const [approvalOpen, setApprovalOpen] = useState(false); @@ -279,7 +279,7 @@ const PickOrderDetail: React.FC = ({ consoCode, qc }) => { (id: GridRowId) => () => { setStockOutLine((prev) => prev.filter((e) => getRowId(e) !== id)); }, - [getRowId] + [getRowId], ); const handleStart = useCallback( @@ -307,7 +307,9 @@ const PickOrderDetail: React.FC = ({ consoCode, qc }) => { if (res) { console.log(res); setStockOutLine((prev) => - prev.map((p) => (p.id === oldId ? (res.entity as StockOutLine) : p)) + prev.map((p) => + p.id === oldId ? (res.entity as StockOutLine) : p, + ), ); } setBtnIsLoading(false); @@ -315,7 +317,7 @@ const PickOrderDetail: React.FC = ({ consoCode, qc }) => { // openStartModal(); }, 500); }, - [createStockOutLine] + [createStockOutLine], ); useEffect(() => { @@ -338,7 +340,7 @@ const PickOrderDetail: React.FC = ({ consoCode, qc }) => { setBtnIsLoading(false); }, 200); }, - [] + [], ); const handleLotChange = useCallback( @@ -350,7 +352,7 @@ const PickOrderDetail: React.FC = ({ consoCode, qc }) => { return id as number; }); }, - [] + [], ); useEffect(() => { @@ -381,7 +383,7 @@ const PickOrderDetail: React.FC = ({ consoCode, qc }) => { setBtnIsLoading(false); }, 200); }, - [] + [], ); const stockOutLineColumns = useMemo( @@ -523,7 +525,7 @@ const PickOrderDetail: React.FC = ({ consoCode, qc }) => { }, }, ], - [stockOutLineStatusMap, handleStart, handleDelete] + [stockOutLineStatusMap, handleStart, handleDelete], ); const fetchStockOutLine = useCallback( @@ -537,7 +539,7 @@ const PickOrderDetail: React.FC = ({ consoCode, qc }) => { // set state setStockOutLine(res); }, - [] + [], ); const addRow = useCallback( @@ -562,7 +564,7 @@ const PickOrderDetail: React.FC = ({ consoCode, qc }) => { }, })); }, - [getRowId, selectedRow] + [getRowId, selectedRow], ); // need modify this later @@ -580,11 +582,11 @@ const PickOrderDetail: React.FC = ({ consoCode, qc }) => { }; console.log(rowToSave); const newEntries = stockOutLine.map((e) => - getRowId(e) === id ? rowToSave : e + getRowId(e) === id ? rowToSave : e, ); setStockOutLine(newEntries as StockOutLine[]); }, - [stockOutLine, getRowId] + [stockOutLine, getRowId], ); /// handle refetch all data @@ -610,7 +612,7 @@ const PickOrderDetail: React.FC = ({ consoCode, qc }) => { console.log(res); return res; }, - [fetchLotDetail] + [fetchLotDetail], ); const getQcResult = useCallback( @@ -620,7 +622,7 @@ const PickOrderDetail: React.FC = ({ consoCode, qc }) => { console.log(res); return res; }, - [fetchPickOrderQcResult] + [fetchPickOrderQcResult], ); const [isOpenScanner, setOpenScanner] = useState(false); @@ -681,7 +683,7 @@ const PickOrderDetail: React.FC = ({ consoCode, qc }) => { const validation = useCallback( ( - newRow: GridRowModel + newRow: GridRowModel, // rowModel: GridRowSelectionModel ): StockOutLineEntryError | undefined => { const error: StockOutLineEntryError = {}; @@ -692,13 +694,13 @@ const PickOrderDetail: React.FC = ({ consoCode, qc }) => { } return Object.keys(error).length > 0 ? error : undefined; }, - [currPol] + [currPol], ); const processRowUpdate = useCallback( ( newRow: GridRowModel, - originalRow: GridRowModel + originalRow: GridRowModel, ) => { const errors = validation(newRow); // change to validation console.log(newRow); @@ -706,7 +708,7 @@ const PickOrderDetail: React.FC = ({ consoCode, qc }) => { throw new ProcessRowUpdateError( originalRow, "validation error", - errors + errors, ); } const { _isNew, _error, ...updatedRow } = newRow; @@ -715,14 +717,14 @@ const PickOrderDetail: React.FC = ({ consoCode, qc }) => { } satisfies StockOutLineRow; console.log(rowToSave); const newEntries = stockOutLine.map((e) => - getRowId(e) === getRowId(originalRow) ? rowToSave : e + getRowId(e) === getRowId(originalRow) ? rowToSave : e, ); console.log(newEntries); setStockOutLine(newEntries as StockOutLine[]); return rowToSave; }, - [stockOutLine, validation] + [stockOutLine, validation], ); const onProcessRowUpdateError = useCallback( @@ -732,19 +734,19 @@ const PickOrderDetail: React.FC = ({ consoCode, qc }) => { apiRef.current.updateRows([{ ...oldRow, _error: errors }]); }, - [apiRef] + [apiRef], ); const handleCompleteOrder = useCallback(async () => { - const res = await completeConsoPickOrder(consoCode) + const res = await completeConsoPickOrder(consoCode); if (res) { // completed - triggerRefetch() + triggerRefetch(); } else { // not completed - triggerRefetch() + triggerRefetch(); } - }, [consoCode, triggerRefetch]) + }, [consoCode, triggerRefetch]); return ( <> @@ -810,7 +812,7 @@ const PickOrderDetail: React.FC = ({ consoCode, qc }) => { setSelectedRow(newRowSelectionModel); if (newRowSelectionModel && newRowSelectionModel.length > 0) { const pol = pickOrderLine.find( - (item) => item.id === newRowSelectionModel[0] + (item) => item.id === newRowSelectionModel[0], ); console.log(pol); setCurrPol(pol); diff --git a/src/components/PickOrderDetail/PickOrderDetailWrapper.tsx b/src/components/PickOrderDetail/PickOrderDetailWrapper.tsx index a4bc31a..030e3f3 100644 --- a/src/components/PickOrderDetail/PickOrderDetailWrapper.tsx +++ b/src/components/PickOrderDetail/PickOrderDetailWrapper.tsx @@ -19,15 +19,13 @@ type Props = { consoCode: string; }; -const PoDetailWrapper: React.FC & SubComponents = async ({ consoCode }) => { - const [ - qc - ] = await Promise.all([ - fetchQcItemCheck(), - ]); +const PoDetailWrapper: React.FC & SubComponents = async ({ + consoCode, +}) => { + const [qc] = await Promise.all([fetchQcItemCheck()]); // const poWithStockInLine = await fetchPoWithStockInLines(id) - return ; + return ; }; PoDetailWrapper.Loading = PickOrderDetailLoading; diff --git a/src/components/PickOrderDetail/QcContent.tsx b/src/components/PickOrderDetail/QcContent.tsx index 7c24a1f..f45bb46 100644 --- a/src/components/PickOrderDetail/QcContent.tsx +++ b/src/components/PickOrderDetail/QcContent.tsx @@ -39,9 +39,9 @@ import QcSelect from "../PoDetail/QcSelect"; import { PickOrderQcInput } from "@/app/api/pickorder/actions"; interface Props { - qcDefaultValues: PickOrderQcInput + qcDefaultValues: PickOrderQcInput; qc: QcItemWithChecks[]; - disabled: boolean + disabled: boolean; } type EntryError = | { @@ -172,7 +172,7 @@ const QcContent: React.FC = ({ qc, qcDefaultValues, disabled }) => { }, }, ], - [qc] + [qc], ); /// validate datagrid const validation = useCallback( @@ -190,7 +190,7 @@ const QcContent: React.FC = ({ qc, qcDefaultValues, disabled }) => { } return Object.keys(error).length > 0 ? error : undefined; }, - [] + [], ); return ( diff --git a/src/components/PickOrderDetail/QcForm.tsx b/src/components/PickOrderDetail/QcForm.tsx index d3b53ad..9a74dc1 100644 --- a/src/components/PickOrderDetail/QcForm.tsx +++ b/src/components/PickOrderDetail/QcForm.tsx @@ -1,6 +1,10 @@ import { QcItemWithChecks } from "@/app/api/qc"; import useUploadContext from "../UploadProvider/useUploadContext"; -import { PickOrderQcInput, updateStockOutLine, UpdateStockOutLine } from "@/app/api/pickorder/actions"; +import { + PickOrderQcInput, + updateStockOutLine, + UpdateStockOutLine, +} from "@/app/api/pickorder/actions"; import { FormProvider, SubmitHandler, useForm } from "react-hook-form"; import QcContent from "./QcContent"; import { Box, Button, Modal, ModalProps, Stack } from "@mui/material"; @@ -43,7 +47,7 @@ const QcForm: React.FC = ({ const formProps = useForm({ defaultValues: { qty: qcDefaultValues.qty, - status: qcDefaultValues.status + status: qcDefaultValues.status, }, }); @@ -53,7 +57,7 @@ const QcForm: React.FC = ({ onClose?.(...args); // reset(); }, - [onClose] + [onClose], ); const onSubmit = useCallback>( @@ -70,19 +74,19 @@ const QcForm: React.FC = ({ qty: data.qty, status: data.status, // pickTime: dayjs().format(`${INPUT_DATE_FORMAT} ${OUTPUT_TIME_FORMAT}`), - } - console.log(postData) + }; + console.log(postData); // return - const res = await updateStockOutLine(postData) + const res = await updateStockOutLine(postData); if (res) { - console.log(res) + console.log(res); closeHandler({}, "backdropClick"); - } else { - console.log(res) - console.log("bug la") + } else { + console.log(res); + console.log("bug la"); } }, - [updateStockOutLine] + [updateStockOutLine], ); return ( <> diff --git a/src/components/PickOrderDetail/index.ts b/src/components/PickOrderDetail/index.ts index 47ec0ac..6e275c8 100644 --- a/src/components/PickOrderDetail/index.ts +++ b/src/components/PickOrderDetail/index.ts @@ -1 +1 @@ -export { default } from "./PickOrderDetailWrapper" \ No newline at end of file +export { default } from "./PickOrderDetailWrapper"; diff --git a/src/components/PickOrderSearch/ConsolidatePickOrderItemSum.tsx b/src/components/PickOrderSearch/ConsolidatePickOrderItemSum.tsx index 7e30b64..bfb2ff2 100644 --- a/src/components/PickOrderSearch/ConsolidatePickOrderItemSum.tsx +++ b/src/components/PickOrderSearch/ConsolidatePickOrderItemSum.tsx @@ -58,7 +58,7 @@ const ConsolidatePickOrderItemSum: React.FC = ({ rows, setRows }) => { }, }, ], - [] + [], ); return ( = ({ }} > {pickOrderLine.map((item, index) => ( - {`${item.itemName} x ${item.requiredQty} ${item.uomDesc}`} // Render each name in a span ))} @@ -73,7 +74,7 @@ const ConsolidatePickOrderSum: React.FC = ({ }, }, ], - [] + [], ); return ( @@ -101,7 +102,7 @@ const ConsolidatePickOrderSum: React.FC = ({ setRevertIds(newRowSelectionModel); }} getRowHeight={(params) => { - return 100 + return 100; }} rows={rows} columns={columns} diff --git a/src/components/PickOrderSearch/ConsolidatedPickOrders.tsx b/src/components/PickOrderSearch/ConsolidatedPickOrders.tsx index 1dfa165..2b0057e 100644 --- a/src/components/PickOrderSearch/ConsolidatedPickOrders.tsx +++ b/src/components/PickOrderSearch/ConsolidatedPickOrders.tsx @@ -76,7 +76,7 @@ const ConsolidatedPickOrders: React.FC = ({ filterArgs }) => { const router = useRouter(); const apiRef = useGridApiRef(); const [filteredPickOrders, setFilteredPickOrders] = useState( - [] as ConsoPickOrderResult[] + [] as ConsoPickOrderResult[], ); const [isLoading, setIsLoading] = useState(false); const [modalOpen, setModalOpen] = useState(false); //change back to false @@ -89,7 +89,7 @@ const ConsolidatedPickOrders: React.FC = ({ filterArgs }) => { Omit[] | undefined >(undefined); const [byItemsRows, setByItemsRows] = useState( - undefined + undefined, ); const [disableRelease, setDisableRelease] = useState(true); @@ -116,7 +116,7 @@ const ConsolidatedPickOrders: React.FC = ({ filterArgs }) => { openDetailModal(pickOrder.consoCode); } }, - [router, openDetailModal] + [router, openDetailModal], ); const columns = useMemo[]>( () => [ @@ -135,10 +135,10 @@ const ConsolidatedPickOrders: React.FC = ({ filterArgs }) => { label: t("status"), }, ], - [] + [], ); const [pagingController, setPagingController] = useState( - defaultPagingController + defaultPagingController, ); // pass conso code back to assign @@ -146,7 +146,7 @@ const ConsolidatedPickOrders: React.FC = ({ filterArgs }) => { const fetchNewPageConsoPickOrder = useCallback( async ( pagingController: Record, - filterArgs: Record + filterArgs: Record, ) => { setIsLoading(true); const params = { @@ -161,7 +161,7 @@ const ConsolidatedPickOrders: React.FC = ({ filterArgs }) => { } setIsLoading(false); }, - [] + [], ); useEffect(() => { @@ -169,7 +169,7 @@ const ConsolidatedPickOrders: React.FC = ({ filterArgs }) => { }, [fetchNewPageConsoPickOrder, pagingController, filterArgs]); const isReleasable = useCallback((itemList: ByItemsSummary[]): boolean => { - var isReleasable = true; + let isReleasable = true; for (const item of itemList) { isReleasable = item.requiredQty >= item.availableQty; if (!isReleasable) return isReleasable; @@ -199,7 +199,7 @@ const ConsolidatedPickOrders: React.FC = ({ filterArgs }) => { setUsernameList(nameListRes); } }, - [isReleasable] + [isReleasable], ); const closeHandler = useCallback>( @@ -207,7 +207,7 @@ const ConsolidatedPickOrders: React.FC = ({ filterArgs }) => { closeDetailModal(); // reset(); }, - [closeDetailModal] + [closeDetailModal], ); const onChange = useCallback( @@ -215,7 +215,7 @@ const ConsolidatedPickOrders: React.FC = ({ filterArgs }) => { console.log(newValue); formProps.setValue("assignTo", newValue.id); }, - [] + [], ); const onSubmit = useCallback>( @@ -225,7 +225,7 @@ const ConsolidatedPickOrders: React.FC = ({ filterArgs }) => { const res = await releasePickOrder(data); console.log(res); console.log(res.status); - if ((res.status === 200)) { + if (res.status === 200) { router.push(`/pickorder/detail?consoCode=${data.consoCode}`); } else { console.log(res); @@ -234,11 +234,11 @@ const ConsolidatedPickOrders: React.FC = ({ filterArgs }) => { console.log(error); } }, - [releasePickOrder] + [releasePickOrder], ); const onSubmitError = useCallback>( (errors) => {}, - [] + [], ); const handleConsolidate_revert = useCallback(() => { diff --git a/src/components/PickOrderSearch/PickOrderSearch.tsx b/src/components/PickOrderSearch/PickOrderSearch.tsx index 4090fc3..aa4065d 100644 --- a/src/components/PickOrderSearch/PickOrderSearch.tsx +++ b/src/components/PickOrderSearch/PickOrderSearch.tsx @@ -38,10 +38,8 @@ type SearchQuery = Partial< type SearchParamNames = keyof SearchQuery; -const PickOrderSearch: React.FC = ({ - pickOrders, -}) => { - const { t } = useTranslation("pickOrder"); +const PickOrderSearch: React.FC = ({ pickOrders }) => { + const { t } = useTranslation("pickOrder"); const [filteredPickOrders, setFilteredPickOrders] = useState(pickOrders); const [filterArgs, setFilterArgs] = useState>({}); @@ -50,7 +48,7 @@ const PickOrderSearch: React.FC = ({ (_e, newValue) => { setTabIndex(newValue); }, - [] + [], ); const searchCriteria: Criterion[] = useMemo( @@ -72,9 +70,9 @@ const PickOrderSearch: React.FC = ({ value: po.type, label: t(upperCase(po.type)), })), - "value" + "value", ), - "label" + "label", ), }, { @@ -87,9 +85,9 @@ const PickOrderSearch: React.FC = ({ value: po.status, label: t(upperFirst(po.status)), })), - "value" + "value", ), - "label" + "label", ), }, { @@ -106,16 +104,16 @@ const PickOrderSearch: React.FC = ({ label: item.name, // group: item.type })) - : [] + : [], ), - "label" - ) + "label", + ), ), - "value" + "value", ), }, ], - [t] + [t], ); const onReset = useCallback(() => { @@ -144,7 +142,7 @@ const PickOrderSearch: React.FC = ({ (intersectionWith(["All"], query.items).length > 0 || intersectionWith( po.items?.map((item) => item.name), - query.items + query.items, ).length > 0) && (query.status.toLowerCase() == "all" || po.status @@ -153,7 +151,7 @@ const PickOrderSearch: React.FC = ({ (query.type.toLowerCase() == "all" || po.type.toLowerCase().includes(query.type.toLowerCase())) ); - }) + }), ); }} onReset={onReset} diff --git a/src/components/PickOrderSearch/PickOrderSearchWrapper.tsx b/src/components/PickOrderSearch/PickOrderSearchWrapper.tsx index a06ae97..5868197 100644 --- a/src/components/PickOrderSearch/PickOrderSearchWrapper.tsx +++ b/src/components/PickOrderSearch/PickOrderSearchWrapper.tsx @@ -3,26 +3,24 @@ import GeneralLoading from "../General/GeneralLoading"; import PickOrderSearch from "./PickOrderSearch"; interface SubComponents { - Loading: typeof GeneralLoading; + Loading: typeof GeneralLoading; } const PickOrderSearchWrapper: React.FC & SubComponents = async () => { - const [ - pickOrders - ] = await Promise.all([ - fetchPickOrders({ - code: undefined, - targetDateFrom: undefined, - targetDateTo: undefined, - type: undefined, - status: undefined, - itemName: undefined, - }) - ]) + const [pickOrders] = await Promise.all([ + fetchPickOrders({ + code: undefined, + targetDateFrom: undefined, + targetDateTo: undefined, + type: undefined, + status: undefined, + itemName: undefined, + }), + ]); - return -} + return ; +}; PickOrderSearchWrapper.Loading = GeneralLoading; -export default PickOrderSearchWrapper; \ No newline at end of file +export default PickOrderSearchWrapper; diff --git a/src/components/PickOrderSearch/PickOrders.tsx b/src/components/PickOrderSearch/PickOrders.tsx index 910962e..6d798dc 100644 --- a/src/components/PickOrderSearch/PickOrders.tsx +++ b/src/components/PickOrderSearch/PickOrders.tsx @@ -5,7 +5,10 @@ import { useTranslation } from "react-i18next"; import { useCallback, useEffect, useMemo, useState } from "react"; import { isEmpty, upperCase, upperFirst } from "lodash"; import { arrayToDateString } from "@/app/utils/formatUtil"; -import { consolidatePickOrder, fetchPickOrderClient } from "@/app/api/pickorder/actions"; +import { + consolidatePickOrder, + fetchPickOrderClient, +} from "@/app/api/pickorder/actions"; import useUploadContext from "../UploadProvider/useUploadContext"; interface Props { @@ -17,7 +20,7 @@ const PickOrders: React.FC = ({ filteredPickOrders, filterArgs }) => { const { t } = useTranslation("pickOrder"); const [selectedRows, setSelectedRows] = useState<(string | number)[]>([]); const [filteredPickOrder, setFilteredPickOrder] = useState( - [] as PickOrderResult[] + [] as PickOrderResult[], ); const { setIsUploading } = useUploadContext(); const [isLoading, setIsLoading] = useState(false); @@ -45,14 +48,14 @@ const PickOrders: React.FC = ({ filteredPickOrders, filterArgs }) => { const fetchNewPagePickOrder = useCallback( async ( pagingController: Record, - filterArgs: Record + filterArgs: Record, ) => { setIsLoading(true); const params = { ...pagingController, ...filterArgs, }; - const res = await fetchPickOrderClient(params) + const res = await fetchPickOrderClient(params); if (res) { console.log(res); setFilteredPickOrder(res.records); @@ -60,7 +63,7 @@ const PickOrders: React.FC = ({ filteredPickOrders, filterArgs }) => { } setIsLoading(false); }, - [] + [], ); useEffect(() => { @@ -121,7 +124,7 @@ const PickOrders: React.FC = ({ filteredPickOrders, filterArgs }) => { }, }, ], - [t] + [t], ); return ( @@ -145,7 +148,7 @@ const PickOrders: React.FC = ({ filteredPickOrders, filterArgs }) => { pagingController={pagingController} setPagingController={setPagingController} totalCount={totalCount} - checkboxIds={selectedRows!!} + checkboxIds={selectedRows!} setCheckboxIds={setSelectedRows} /> )} diff --git a/src/components/PickOrderSearch/index.ts b/src/components/PickOrderSearch/index.ts index 3eb7e16..95fab4c 100644 --- a/src/components/PickOrderSearch/index.ts +++ b/src/components/PickOrderSearch/index.ts @@ -1 +1 @@ -export { default } from './PickOrderSearchWrapper' \ No newline at end of file +export { default } from "./PickOrderSearchWrapper"; diff --git a/src/components/PoDetail/EscalationForm.tsx b/src/components/PoDetail/EscalationForm.tsx index 29c5434..dbce837 100644 --- a/src/components/PoDetail/EscalationForm.tsx +++ b/src/components/PoDetail/EscalationForm.tsx @@ -35,8 +35,8 @@ import { stockInLineStatusMap } from "@/app/utils/formatUtil"; interface Props { itemDetail: StockInLine; -// qc: QcItemWithChecks[]; - disabled: boolean + // qc: QcItemWithChecks[]; + disabled: boolean; } type EntryError = | { @@ -44,11 +44,11 @@ type EntryError = } | undefined; -const EscalationForm: React.FC = ({ -// qc, +const EscalationForm: React.FC = ({ + // qc, itemDetail, - disabled - }) => { + disabled, +}) => { const { t } = useTranslation("purchaseOrder"); const apiRef = useGridApiRef(); const { @@ -63,31 +63,31 @@ const EscalationForm: React.FC = ({ setError, clearErrors, } = useFormContext(); - console.log(itemDetail) + console.log(itemDetail); const [status, determineCount] = useMemo(() => { switch (itemDetail.status) { - case "pending": - return ["determine1", 1]; - case "determine1": - return ["determine2", 2]; - case "determine2": - return ["determine3", 3]; - default: - return ["receiving", "receive or reject" ]; + case "pending": + return ["determine1", 1]; + case "determine1": + return ["determine2", 2]; + case "determine2": + return ["determine3", 3]; + default: + return ["receiving", "receive or reject"]; } - }, [itemDetail]) + }, [itemDetail]); // const acceptedQty = watch("acceptedQty") || 0 - const acceptedQty = watch("acceptedQty") || 0 + const acceptedQty = watch("acceptedQty") || 0; // console.log(acceptedQty) - console.log(acceptedQty) - console.log(itemDetail.acceptedQty) + console.log(acceptedQty); + console.log(itemDetail.acceptedQty); useEffect(() => { - console.log("triggered") - setValue("status", status) - }, []) + console.log("triggered"); + setValue("status", status); + }, []); return ( @@ -116,7 +116,7 @@ const EscalationForm: React.FC = ({ required: "acceptedQty required!", min: 0, valueAsNumber: true, - max: itemDetail.acceptedQty + max: itemDetail.acceptedQty, })} disabled={disabled} defaultValue={itemDetail.acceptedQty} @@ -131,8 +131,7 @@ const EscalationForm: React.FC = ({ alignItems="flex-start" spacing={2} sx={{ mt: 0.5 }} - > - + > ); }; diff --git a/src/components/PoDetail/PoDetail.tsx b/src/components/PoDetail/PoDetail.tsx index 4c4ce19..4965729 100644 --- a/src/components/PoDetail/PoDetail.tsx +++ b/src/components/PoDetail/PoDetail.tsx @@ -96,7 +96,7 @@ const PoDetail: React.FC = ({ po, qc, warehouse }) => { const apiRef = useGridApiRef(); const [purchaseOrder, setPurchaseOrder] = useState({ ...po }); const [rows, setRows] = useState( - purchaseOrder.pol || [] + purchaseOrder.pol || [], ); const params = useSearchParams(); // const [currPoStatus, setCurrPoStatus] = useState(purchaseOrder.status); @@ -127,11 +127,11 @@ const PoDetail: React.FC = ({ po, qc, warehouse }) => { const [stockInLine, setStockInLine] = useState(row.stockInLine); const totalWeight = useMemo( () => calculateWeight(row.qty, row.uom), - [calculateWeight] + [calculateWeight], ); const weightUnit = useMemo( () => returnWeightUnit(row.uom), - [returnWeightUnit] + [returnWeightUnit], ); useEffect(() => { @@ -204,7 +204,7 @@ const PoDetail: React.FC = ({ po, qc, warehouse }) => { (_e, newValue) => { setTabIndex(newValue); }, - [] + [], ); const [isOpenScanner, setOpenScanner] = useState(false); diff --git a/src/components/PoDetail/PoInfoCard.tsx b/src/components/PoDetail/PoInfoCard.tsx index 92c71ac..0b5688e 100644 --- a/src/components/PoDetail/PoInfoCard.tsx +++ b/src/components/PoDetail/PoInfoCard.tsx @@ -17,14 +17,12 @@ type Props = { const PoInfoCard: React.FC = async ( { // id - } + }, ) => { return ( <> - - - + ); diff --git a/src/components/PoDetail/PoInputGrid.tsx b/src/components/PoDetail/PoInputGrid.tsx index 77c4944..4c3c282 100644 --- a/src/components/PoDetail/PoInputGrid.tsx +++ b/src/components/PoDetail/PoInputGrid.tsx @@ -54,7 +54,7 @@ import QrCodeIcon from "@mui/icons-material/QrCode"; import { downloadFile } from "@/app/utils/commonUtil"; import { fetchPoQrcode } from "@/app/api/pdf/actions"; import { fetchQcResult } from "@/app/api/qc/actions"; -import PoQcStockInModal from "./PoQcStockInModal" +import PoQcStockInModal from "./PoQcStockInModal"; import DoDisturbIcon from "@mui/icons-material/DoDisturb"; import { useSession } from "next-auth/react"; @@ -90,7 +90,7 @@ class ProcessRowUpdateError extends Error { constructor( row: StockInLineRow, message?: string, - errors?: StockInLineEntryError + errors?: StockInLineEntryError, ) { super(message); this.row = row; @@ -115,7 +115,7 @@ function PoInputGrid({ const [rowModesModel, setRowModesModel] = useState({}); const getRowId = useCallback>( (row) => row.id as number, - [] + [], ); console.log(stockInLine); const [entries, setEntries] = useState(stockInLine || []); @@ -131,7 +131,7 @@ function PoInputGrid({ const [currQty, setCurrQty] = useState(() => { const total = entries.reduce( (acc, curr) => acc + (curr.acceptedQty || 0), - 0 + 0, ); return total; }); @@ -139,10 +139,12 @@ function PoInputGrid({ const { data: session } = useSession(); useEffect(() => { - const completedList = entries.filter((e) => stockInLineStatusMap[e.status!!] >= 8); + const completedList = entries.filter( + (e) => stockInLineStatusMap[e.status!] >= 8, + ); const processedQty = completedList.reduce( (acc, curr) => acc + (curr.acceptedQty || 0), - 0 + 0, ); setProcessedQty(processedQty); }, [entries]); @@ -151,7 +153,7 @@ function PoInputGrid({ (id: GridRowId) => () => { setEntries((es) => es.filter((e) => getRowId(e) !== id)); }, - [getRowId] + [getRowId], ); const handleStart = useCallback( (id: GridRowId, params: any) => () => { @@ -174,20 +176,20 @@ function PoInputGrid({ const res = await createStockInLine(postData); console.log(res); setEntries((prev) => - prev.map((p) => (p.id === oldId ? (res.entity as StockInLine) : p)) + prev.map((p) => (p.id === oldId ? (res.entity as StockInLine) : p)), ); setStockInLine( (prev) => prev.map((p) => - p.id === oldId ? (res.entity as StockInLine) : p - ) as StockInLine[] + p.id === oldId ? (res.entity as StockInLine) : p, + ) as StockInLine[], ); setBtnIsLoading(false); // do post directly to test // openStartModal(); }, 200); }, - [createStockInLine] + [createStockInLine], ); const fetchQcDefaultValue = useCallback(async (stockInLineId: GridRowId) => { return await fetchQcResult(stockInLineId as number); @@ -215,7 +217,7 @@ function PoInputGrid({ setBtnIsLoading(false); }, 200); }, - [fetchQcDefaultValue] + [fetchQcDefaultValue], ); const handleEscalation = useCallback( (id: GridRowId, params: any) => () => { @@ -232,7 +234,7 @@ function PoInputGrid({ // setBtnIsLoading(false); }, 200); }, - [] + [], ); const handleReject = useCallback( @@ -252,7 +254,7 @@ function PoInputGrid({ // printQrcode(params.row); }, 200); }, - [] + [], ); const handleStockIn = useCallback( @@ -272,7 +274,7 @@ function PoInputGrid({ // setBtnIsLoading(false); }, 200); }, - [] + [], ); const handlePutAway = useCallback( @@ -292,7 +294,7 @@ function PoInputGrid({ // setBtnIsLoading(false); }, 200); }, - [] + [], ); const printQrcode = useCallback( @@ -304,11 +306,11 @@ function PoInputGrid({ const response = await fetchPoQrcode(postData); if (response) { console.log(response); - downloadFile(new Uint8Array(response.blobValue), response.filename!!); + downloadFile(new Uint8Array(response.blobValue), response.filename!); } setBtnIsLoading(false); }, - [fetchPoQrcode, downloadFile] + [fetchPoQrcode, downloadFile], ); const handleQrCode = useCallback( @@ -327,7 +329,7 @@ function PoInputGrid({ printQrcode(params.row); }, 200); }, - [] + [], ); const closeQcModal = useCallback(() => { @@ -400,7 +402,7 @@ function PoInputGrid({ renderCell: (params) => { const weight = calculateWeight( params.row.acceptedQty, - params.row.uom + params.row.uom, ); const weightUnit = returnWeightUnit(params.row.uom); return `${weight} ${weightUnit}`; @@ -411,13 +413,15 @@ function PoInputGrid({ headerName: t("status"), flex: 0.5, renderCell: (params) => { - return t(`${params.row.status}`) - } + return t(`${params.row.status}`); + }, }, { field: "actions", type: "actions", - headerName: `${t("start")} | ${t("qc")} | ${t("escalation")} | ${t("stock in")} | ${t("putaway")} | ${t("delete")}`, + headerName: `${t("start")} | ${t("qc")} | ${t("escalation")} | ${t( + "stock in", + )} | ${t("putaway")} | ${t("delete")}`, // headerName: "start | qc | escalation | stock in | putaway | delete", flex: 1.5, cellClassName: "actions", @@ -487,7 +491,9 @@ function PoInputGrid({ stockInLineStatusMap[status] === 9 || stockInLineStatusMap[status] <= 2 || stockInLineStatusMap[status] >= 7 || - ((stockInLineStatusMap[status] >= 3 && stockInLineStatusMap[status] <= 5) && !session?.user?.abilities?.includes("APPROVAL")) + (stockInLineStatusMap[status] >= 3 && + stockInLineStatusMap[status] <= 5 && + !session?.user?.abilities?.includes("APPROVAL")) } // set _isNew to false after posting // or check status @@ -502,7 +508,10 @@ function PoInputGrid({ color: "primary.main", // marginRight: 1, }} - disabled={stockInLineStatusMap[status] === 9 || stockInLineStatusMap[status] < 7} + disabled={ + stockInLineStatusMap[status] === 9 || + stockInLineStatusMap[status] < 7 + } // set _isNew to false after posting // or check status onClick={handlePutAway(params.row.id, params)} @@ -551,7 +560,7 @@ function PoInputGrid({ }, }, ], - [stockInLineStatusMap, btnIsLoading, handleQrCode, handleReject] + [stockInLineStatusMap, btnIsLoading, handleQrCode, handleReject], ); const addRow = useCallback(() => { @@ -579,7 +588,7 @@ function PoInputGrid({ }, [currQty, getRowId]); const validation = useCallback( ( - newRow: GridRowModel + newRow: GridRowModel, // rowModel: GridRowSelectionModel ): StockInLineEntryError | undefined => { const error: StockInLineEntryError = {}; @@ -590,19 +599,19 @@ function PoInputGrid({ } return Object.keys(error).length > 0 ? error : undefined; }, - [currQty] + [currQty], ); const processRowUpdate = useCallback( ( newRow: GridRowModel, - originalRow: GridRowModel + originalRow: GridRowModel, ) => { const errors = validation(newRow); // change to validation if (errors) { throw new ProcessRowUpdateError( originalRow, "validation error", - errors + errors, ); } const { _isNew, _error, ...updatedRow } = newRow; @@ -610,7 +619,7 @@ function PoInputGrid({ ...updatedRow, } satisfies StockInLineRow; const newEntries = entries.map((e) => - getRowId(e) === getRowId(originalRow) ? rowToSave : e + getRowId(e) === getRowId(originalRow) ? rowToSave : e, ); setStockInLine(newEntries as StockInLine[]); console.log("triggered"); @@ -618,12 +627,12 @@ function PoInputGrid({ //update remaining qty const total = newEntries.reduce( (acc, curr) => acc + (curr.acceptedQty || 0), - 0 + 0, ); setCurrQty(total); return rowToSave; }, - [getRowId, entries] + [getRowId, entries], ); const onProcessRowUpdateError = useCallback( @@ -633,7 +642,7 @@ function PoInputGrid({ apiRef.current.updateRows([{ ...oldRow, _error: errors }]); }, - [apiRef] + [apiRef], ); const footer = ( diff --git a/src/components/PoDetail/PoQcStockInModal.tsx b/src/components/PoDetail/PoQcStockInModal.tsx index 804b609..f55e4a8 100644 --- a/src/components/PoDetail/PoQcStockInModal.tsx +++ b/src/components/PoDetail/PoQcStockInModal.tsx @@ -136,7 +136,7 @@ const PoQcStockInModal: React.FC = ({ onClose?.(...args); // reset(); }, - [onClose] + [onClose], ); useEffect(() => { @@ -175,7 +175,7 @@ const PoQcStockInModal: React.FC = ({ hasErrors = true; } - if (data.expiryDate && data.expiryDate < data.receiptDate!!) { + if (data.expiryDate && data.expiryDate < data.receiptDate!) { formProps.setError("expiryDate", { message: "Expired", type: "invalid", @@ -184,7 +184,7 @@ const PoQcStockInModal: React.FC = ({ } return hasErrors; }, - [itemDetail, formProps] + [itemDetail, formProps], ); const checkPutaway = useCallback( @@ -200,7 +200,7 @@ const PoQcStockInModal: React.FC = ({ } return hasErrors; }, - [itemDetail, formProps] + [itemDetail, formProps], ); const onSubmit = useCallback>( @@ -224,10 +224,10 @@ const PoQcStockInModal: React.FC = ({ console.log(hasErrors); } //////////////////////// modify this mess later ////////////////////// - var productionDate = null; - var expiryDate = null; - var receiptDate = null; - var acceptedQty = null; + let productionDate = null; + let expiryDate = null; + let receiptDate = null; + let acceptedQty = null; if (data.productionDate) { productionDate = dayjs(data.productionDate).format(INPUT_DATE_FORMAT); } @@ -245,7 +245,7 @@ const PoQcStockInModal: React.FC = ({ } const args = { id: itemDetail.id, - purchaseOrderId: parseInt(params.get("id")!!), + purchaseOrderId: parseInt(params.get("id")!), purchaseOrderLineId: itemDetail.purchaseOrderLineId, itemId: itemDetail.itemId, ...data, @@ -320,7 +320,7 @@ const PoQcStockInModal: React.FC = ({ console.log(e); } }, - [t, itemDetail, checkStockIn, checkPutaway] + [t, itemDetail, checkStockIn, checkPutaway], ); const printQrcode = useCallback(async () => { @@ -331,7 +331,7 @@ const PoQcStockInModal: React.FC = ({ const response = await fetchPoQrcode(postData); if (response) { console.log(response); - downloadFile(new Uint8Array(response.blobValue), response.filename!!); + downloadFile(new Uint8Array(response.blobValue), response.filename!); } setBtnIsLoading(false); setIsUploading(false); @@ -385,7 +385,7 @@ const PoQcStockInModal: React.FC = ({ > {itemDetail !== undefined && type === "qc" && ( @@ -405,7 +405,7 @@ const PoQcStockInModal: React.FC = ({ {itemDetail !== undefined && type === "putaway" && ( )} diff --git a/src/components/PoDetail/PutawayForm.tsx b/src/components/PoDetail/PutawayForm.tsx index ed509f5..b0d3b94 100644 --- a/src/components/PoDetail/PutawayForm.tsx +++ b/src/components/PoDetail/PutawayForm.tsx @@ -37,7 +37,10 @@ import { QcItemWithChecks } from "@/app/api/qc"; import { GridEditInputCell } from "@mui/x-data-grid"; import { StockInLine } from "@/app/api/po"; import { WarehouseResult } from "@/app/api/warehouse"; -import { OUTPUT_DATE_FORMAT, stockInLineStatusMap } from "@/app/utils/formatUtil"; +import { + OUTPUT_DATE_FORMAT, + stockInLineStatusMap, +} from "@/app/utils/formatUtil"; import { QRCodeSVG } from "qrcode.react"; import { QrCode } from "../QrCode"; import ReactQrCodeScanner, { @@ -52,7 +55,7 @@ dayjs.extend(arraySupport); interface Props { itemDetail: StockInLine; warehouse: WarehouseResult[]; - disabled: boolean + disabled: boolean; // qc: QcItemWithChecks[]; } type EntryError = @@ -101,7 +104,7 @@ const PutawayForm: React.FC = ({ itemDetail, warehouse, disabled }) => { value: 0, // think think sin label: t("Select warehouse"), group: "default", - } + }; const options = useMemo(() => { return [ // { @@ -119,12 +122,13 @@ const PutawayForm: React.FC = ({ itemDetail, warehouse, disabled }) => { const currentValue = warehouseId > 0 ? options.find((o) => o.value === warehouseId) - : options.find((o) => o.value === getValues("warehouseId")) || defaultOption; - + : options.find((o) => o.value === getValues("warehouseId")) || + defaultOption; + const onChange = useCallback( ( event: React.SyntheticEvent, - newValue: { value: number; group: string } | { value: number }[] + newValue: { value: number; group: string } | { value: number }[], ) => { const singleNewVal = newValue as { value: number; @@ -135,7 +139,7 @@ const PutawayForm: React.FC = ({ itemDetail, warehouse, disabled }) => { // setValue("warehouseId", singleNewVal.value); setWarehouseId(singleNewVal.value); }, - [] + [], ); // const accQty = watch("acceptedQty"); @@ -177,7 +181,7 @@ const PutawayForm: React.FC = ({ itemDetail, warehouse, disabled }) => { // supplier: itemDetail.supplier, // poCode: itemDetail.poCode, }), - [itemDetail] + [itemDetail], ); const [isOpenScanner, setOpenScanner] = useState(false); @@ -185,7 +189,7 @@ const PutawayForm: React.FC = ({ itemDetail, warehouse, disabled }) => { (...args) => { setOpenScanner(false); }, - [] + [], ); const onOpenScanner = useCallback(() => { @@ -211,22 +215,22 @@ const PutawayForm: React.FC = ({ itemDetail, warehouse, disabled }) => { } else return; }, }), - [onCloseScanner] + [onCloseScanner], ); - // QR Code Scanner - const scanner = useQcCodeScanner() + // QR Code Scanner + const scanner = useQcCodeScanner(); useEffect(() => { if (isOpenScanner) { - scanner.startScan() + scanner.startScan(); } else if (!isOpenScanner) { - scanner.stopScan() + scanner.stopScan(); } - }, [isOpenScanner]) + }, [isOpenScanner]); useEffect(() => { if (scanner.values.length > 0) { - console.log(scanner.values[0]) + console.log(scanner.values[0]); const data: QrCodeInfo = JSON.parse(scanner.values[0]); console.log(data); if (data.warehouseId) { @@ -234,9 +238,9 @@ const PutawayForm: React.FC = ({ itemDetail, warehouse, disabled }) => { setWarehouseId(data.warehouseId); onCloseScanner(); } - scanner.resetScan() + scanner.resetScan(); } - }, [scanner.values]) + }, [scanner.values]); useEffect(() => { setValue("status", "completed"); @@ -246,19 +250,19 @@ const PutawayForm: React.FC = ({ itemDetail, warehouse, disabled }) => { useEffect(() => { if (warehouseId > 0) { setValue("warehouseId", warehouseId); - clearErrors("warehouseId") + clearErrors("warehouseId"); } }, [warehouseId]); - + const getWarningTextHardcode = useCallback((): string | undefined => { - const defaultWarehouseId = options[0].value - const currWarehouseId = watch("warehouseId") + const defaultWarehouseId = options[0].value; + const currWarehouseId = watch("warehouseId"); if (defaultWarehouseId !== currWarehouseId) { - return t("not default warehosue") + return t("not default warehosue"); } - return undefined - }, [options]) - + return undefined; + }, [options]); + return ( @@ -325,7 +329,9 @@ const PutawayForm: React.FC = ({ itemDetail, warehouse, disabled }) => { @@ -333,7 +339,9 @@ const PutawayForm: React.FC = ({ itemDetail, warehouse, disabled }) => { @@ -371,7 +379,9 @@ const PutawayForm: React.FC = ({ itemDetail, warehouse, disabled }) => { /> - + {/* = ({ itemDetail, warehouse, disabled }) => { getOptionLabel={(option) => option.label} options={options} renderInput={(params) => ( - )} /> @@ -450,7 +460,9 @@ const PutawayForm: React.FC = ({ itemDetail, warehouse, disabled }) => { - {t("Please scan warehouse qr code.")} + + {t("Please scan warehouse qr code.")} + {/* */} diff --git a/src/components/PoDetail/QcForm.tsx b/src/components/PoDetail/QcForm.tsx index 4184745..9b19e53 100644 --- a/src/components/PoDetail/QcForm.tsx +++ b/src/components/PoDetail/QcForm.tsx @@ -40,7 +40,7 @@ import axiosInstance from "@/app/(main)/axios/axiosInstance"; interface Props { itemDetail: StockInLine; qc: QcItemWithChecks[]; - disabled: boolean + disabled: boolean; } type EntryError = | { @@ -74,7 +74,9 @@ const QcForm: React.FC = ({ qc, itemDetail, disabled }) => { console.log(accQty); if (accQty > itemDetail.acceptedQty) { setError("acceptedQty", { - message: `${t("acceptedQty must not greater than")} ${itemDetail.acceptedQty}`, + message: `${t("acceptedQty must not greater than")} ${ + itemDetail.acceptedQty + }`, type: "required", }); } @@ -96,7 +98,7 @@ const QcForm: React.FC = ({ qc, itemDetail, disabled }) => { clearErrors(); validateForm(); }, [validateForm]); - + const columns = useMemo( () => [ { @@ -171,7 +173,7 @@ const QcForm: React.FC = ({ qc, itemDetail, disabled }) => { }, }, ], - [qc] + [qc], ); /// validate datagrid const validation = useCallback( @@ -189,12 +191,12 @@ const QcForm: React.FC = ({ qc, itemDetail, disabled }) => { } return Object.keys(error).length > 0 ? error : undefined; }, - [] + [], ); useEffect(() => { console.log(itemDetail); - var status = "receiving"; + const status = "receiving"; // switch (itemDetail.status) { // case 'pending': // status = "receiving" diff --git a/src/components/PoDetail/QcSelect.tsx b/src/components/PoDetail/QcSelect.tsx index e365f8a..4ceebea 100644 --- a/src/components/PoDetail/QcSelect.tsx +++ b/src/components/PoDetail/QcSelect.tsx @@ -51,7 +51,7 @@ const QcSelect: React.FC = ({ allQcs, value, error, onQcSelect }) => { const onChange = useCallback( ( event: React.SyntheticEvent, - newValue: { value: number; group: string } | { value: number }[] + newValue: { value: number; group: string } | { value: number }[], ) => { const singleNewVal = newValue as { value: number; @@ -59,7 +59,7 @@ const QcSelect: React.FC = ({ allQcs, value, error, onQcSelect }) => { }; onQcSelect(singleNewVal.value); }, - [onQcSelect] + [onQcSelect], ); return ( diff --git a/src/components/PoDetail/QrCoderScanner.tsx b/src/components/PoDetail/QrCoderScanner.tsx index 0bd8ba6..2d49c7e 100644 --- a/src/components/PoDetail/QrCoderScanner.tsx +++ b/src/components/PoDetail/QrCoderScanner.tsx @@ -1,42 +1,37 @@ -"use client" +"use client"; -import { Box, Modal, ModalProps } from "@mui/material" +import { Box, Modal, ModalProps } from "@mui/material"; import { useCallback } from "react"; -interface Props extends Omit { - -}; +interface Props extends Omit {} const style = { - position: "absolute", - top: "50%", - left: "50%", - transform: "translate(-50%, -50%)", - bgcolor: "background.paper", - pt: 5, - px: 5, - pb: 10, - width: { xs: "80%", sm: "80%", md: "80%" }, - }; - -const QrCodeScanner: React.FC = ({ - open, -}) => { + position: "absolute", + top: "50%", + left: "50%", + transform: "translate(-50%, -50%)", + bgcolor: "background.paper", + pt: 5, + px: 5, + pb: 10, + width: { xs: "80%", sm: "80%", md: "80%" }, +}; - const closeHandler = useCallback>( - (...args) => { - // onClose?.(...args); - // reset(); - }, - [] - ); +const QrCodeScanner: React.FC = ({ open }) => { + const closeHandler = useCallback>( + (...args) => { + // onClose?.(...args); + // reset(); + }, + [], + ); - return ( + return ( - - - - - ) -} -export default QrCodeScanner \ No newline at end of file + + + + + ); +}; +export default QrCodeScanner; diff --git a/src/components/PoDetail/QrModal.tsx b/src/components/PoDetail/QrModal.tsx index c15f391..e64b6cd 100644 --- a/src/components/PoDetail/QrModal.tsx +++ b/src/components/PoDetail/QrModal.tsx @@ -49,7 +49,7 @@ const QrModal: React.FC = ({ open, onClose, warehouse }) => { const params = useSearchParams(); const formProps = useForm({ defaultValues: { - status: "received" + status: "received", // acceptedQty // ...itemDetail, }, @@ -62,7 +62,7 @@ const QrModal: React.FC = ({ open, onClose, warehouse }) => { setStockInLineId(undefined); // reset(); }, - [onClose] + [onClose], ); const [stockInLineId, setStockInLineId] = useState(); const scannerConfig = useMemo( @@ -79,7 +79,7 @@ const QrModal: React.FC = ({ open, onClose, warehouse }) => { } else return; }, }), - [] + [], ); // QR Code Scanner @@ -108,8 +108,10 @@ const QrModal: React.FC = ({ open, onClose, warehouse }) => { const [itemDetail, setItemDetail] = useState(); const [disabledSubmit, setDisabledSubmit] = useState(false); - const [unavailableText, setUnavailableText] = useState(undefined); - + const [unavailableText, setUnavailableText] = useState( + undefined, + ); + const fetchStockInLine = useCallback( async (stockInLineId: number) => { setUnavailableText(undefined); @@ -127,7 +129,7 @@ const QrModal: React.FC = ({ open, onClose, warehouse }) => { setDisabledSubmit(true); } }, - [formProps, itemDetail, fetchStockInLineInfo] + [formProps, itemDetail, fetchStockInLineInfo], ); useEffect(() => { @@ -136,7 +138,7 @@ const QrModal: React.FC = ({ open, onClose, warehouse }) => { const onSubmit = useCallback>( async (data, event) => { - let hasErrors = false; + const hasErrors = false; console.log("errors"); console.log(errors); console.log("data"); @@ -150,12 +152,12 @@ const QrModal: React.FC = ({ open, onClose, warehouse }) => { //////////////////////// modify this mess later ////////////////////// const args = { id: itemDetail?.id, - purchaseOrderId: parseInt(params.get("id")!!), + purchaseOrderId: parseInt(params.get("id")!), purchaseOrderLineId: itemDetail?.purchaseOrderLineId, itemId: itemDetail?.itemId, acceptedQty: data.acceptedQty, warehouseId: data.warehouseId, - status: data.status + status: data.status, // ...data, // productionDate: productionDate, } as StockInLineEntry & ModalFormInput; @@ -182,7 +184,7 @@ const QrModal: React.FC = ({ open, onClose, warehouse }) => { console.log(e); } }, - [t, itemDetail] + [t, itemDetail], ); return ( @@ -224,7 +226,7 @@ const QrModal: React.FC = ({ open, onClose, warehouse }) => { // {t( - "Will start binding procedure after scanning item qr code." + "Will start binding procedure after scanning item qr code.", )} )} diff --git a/src/components/PoDetail/RejectForm.tsx b/src/components/PoDetail/RejectForm.tsx index bae792b..9c80855 100644 --- a/src/components/PoDetail/RejectForm.tsx +++ b/src/components/PoDetail/RejectForm.tsx @@ -35,8 +35,8 @@ import { stockInLineStatusMap } from "@/app/utils/formatUtil"; interface Props { itemDetail: StockInLine; -// qc: QcItemWithChecks[]; - disabled: boolean + // qc: QcItemWithChecks[]; + disabled: boolean; } type EntryError = | { @@ -44,11 +44,11 @@ type EntryError = } | undefined; -const RejectForm: React.FC = ({ -// qc, +const RejectForm: React.FC = ({ + // qc, itemDetail, - disabled - }) => { + disabled, +}) => { const { t } = useTranslation("purchaseOrder"); const apiRef = useGridApiRef(); const { @@ -63,17 +63,17 @@ const RejectForm: React.FC = ({ setError, clearErrors, } = useFormContext(); - console.log(itemDetail) + console.log(itemDetail); -// const status = "rejected" + // const status = "rejected" - const acceptedQty = watch("acceptedQty") || 0 + const acceptedQty = watch("acceptedQty") || 0; - console.log(disabled) + console.log(disabled); useEffect(() => { - console.log("triggered") - setValue("status", "rejected") - }, []) + console.log("triggered"); + setValue("status", "rejected"); + }, []); return ( @@ -102,7 +102,7 @@ const RejectForm: React.FC = ({ required: "acceptedQty required!", min: 0, valueAsNumber: true, - max: itemDetail.acceptedQty + max: itemDetail.acceptedQty, })} disabled={disabled} defaultValue={itemDetail.acceptedQty} @@ -117,8 +117,7 @@ const RejectForm: React.FC = ({ alignItems="flex-start" spacing={2} sx={{ mt: 0.5 }} - > - + > ); }; diff --git a/src/components/PoDetail/StockInForm.tsx b/src/components/PoDetail/StockInForm.tsx index 6e07284..e8fc3e1 100644 --- a/src/components/PoDetail/StockInForm.tsx +++ b/src/components/PoDetail/StockInForm.tsx @@ -43,7 +43,7 @@ import dayjs from "dayjs"; interface Props { itemDetail: StockInLine; // qc: QcItemWithChecks[]; - disabled: boolean + disabled: boolean; } type EntryError = | { @@ -56,7 +56,7 @@ type EntryError = const StockInForm: React.FC = ({ // qc, itemDetail, - disabled + disabled, }) => { const { t, @@ -92,11 +92,11 @@ const StockInForm: React.FC = ({ const expiryDate = watch("expiryDate"); useEffect(() => { - console.log(productionDate) - console.log(expiryDate) - if (expiryDate) clearErrors() - if (productionDate) clearErrors() - }, [productionDate, expiryDate]) + console.log(productionDate); + console.log(expiryDate); + if (expiryDate) clearErrors(); + if (productionDate) clearErrors(); + }, [productionDate, expiryDate]); return ( @@ -141,7 +141,7 @@ const StockInForm: React.FC = ({ value={dayjs(watch("receiptDate"))} disabled={disabled} onChange={(date) => { - if (!date) return + if (!date) return; // setValue("receiptDate", date.format(INPUT_DATE_FORMAT)); field.onChange(date); }} @@ -201,8 +201,11 @@ const StockInForm: React.FC = ({ value={productionDate ? dayjs(productionDate) : undefined} disabled={disabled} onChange={(date) => { - if (!date) return - setValue("productionDate", date.format(INPUT_DATE_FORMAT)); + if (!date) return; + setValue( + "productionDate", + date.format(INPUT_DATE_FORMAT), + ); // field.onChange(date); }} inputRef={field.ref} @@ -237,9 +240,9 @@ const StockInForm: React.FC = ({ value={expiryDate ? dayjs(expiryDate) : undefined} disabled={disabled} onChange={(date) => { - console.log(date) - if (!date) return - console.log(date.format(INPUT_DATE_FORMAT)) + console.log(date); + if (!date) return; + console.log(date.format(INPUT_DATE_FORMAT)); setValue("expiryDate", date.format(INPUT_DATE_FORMAT)); // field.onChange(date); }} diff --git a/src/components/PoSearch/PoSearch.tsx b/src/components/PoSearch/PoSearch.tsx index c50ac0e..3742893 100644 --- a/src/components/PoSearch/PoSearch.tsx +++ b/src/components/PoSearch/PoSearch.tsx @@ -39,21 +39,21 @@ const PoSearch: React.FC = ({ const { t } = useTranslation("purchaseOrder"); const router = useRouter(); const [pagingController, setPagingController] = useState( - defaultPagingController + defaultPagingController, ); const [totalCount, setTotalCount] = useState(initTotalCount); const searchCriteria: Criterion[] = useMemo(() => { - var searchCriteria: Criterion[] = [ + const searchCriteria: Criterion[] = [ { label: t("Code"), paramName: "code", type: "text" }, { label: t("Status"), paramName: "status", type: "select-labelled", options: [ - {label: t(`pending`), value: `pending`}, - {label: t(`receiving`), value: `receiving`}, - {label: t(`completed`), value: `completed`}, - ] + { label: t(`pending`), value: `pending` }, + { label: t(`receiving`), value: `receiving` }, + { label: t(`completed`), value: `completed` }, + ], }, { label: t("Escalated"), @@ -69,7 +69,7 @@ const PoSearch: React.FC = ({ (po: PoResult) => { router.push(`/po/edit?id=${po.id}`); }, - [router] + [router], ); const onDeleteClick = useCallback((po: PoResult) => {}, [router]); @@ -90,9 +90,11 @@ const PoSearch: React.FC = ({ name: "orderDate", label: t("OrderDate"), renderCell: (params) => { - return dayjs(params.orderDate) - // .add(-1, "month") - .format(OUTPUT_DATE_FORMAT); + return ( + dayjs(params.orderDate) + // .add(-1, "month") + .format(OUTPUT_DATE_FORMAT) + ); }, }, { @@ -110,14 +112,14 @@ const PoSearch: React.FC = ({ name: "escalated", label: t("Escalated"), renderCell: (params) => { - console.log(params.escalated) + console.log(params.escalated); return params.escalated ? ( ) : undefined; }, }, ], - [filteredPo] + [filteredPo], ); const onReset = useCallback(() => { @@ -136,7 +138,7 @@ const PoSearch: React.FC = ({ const newPageFetch = useCallback( async ( pagingController: Record, - filterArgs: Record + filterArgs: Record, ) => { console.log(pagingController); console.log(filterArgs); @@ -152,7 +154,7 @@ const PoSearch: React.FC = ({ setTotalCount(res.total); } }, - [fetchPoListClient] + [fetchPoListClient], ); useEffect(() => { @@ -179,11 +181,14 @@ const PoSearch: React.FC = ({ { - console.log(query) - setFilterArgs({ + console.log(query); + setFilterArgs({ code: query.code, status: query.status === "All" ? "" : query.status, - escalated: query.escalated === 'All' ? undefined : query.escalated === t("Escalated") + escalated: + query.escalated === "All" + ? undefined + : query.escalated === t("Escalated"), }); // setFilteredPo((prev) => // po.filter((p) => { diff --git a/src/components/PoSearch/PoSearchWrapper.tsx b/src/components/PoSearch/PoSearchWrapper.tsx index 4505f2d..4abe5c6 100644 --- a/src/components/PoSearch/PoSearchWrapper.tsx +++ b/src/components/PoSearch/PoSearchWrapper.tsx @@ -25,27 +25,26 @@ type Props = { const PoSearchWrapper: React.FC & SubComponents = async ( { // type, - } + }, ) => { // console.log(defaultPagingController) - const [ - po, - warehouse, - ] = await Promise.all([ + const [po, warehouse] = await Promise.all([ fetchPoList({ - "pageNum": 1, - "pageSize": 10, - }), + pageNum: 1, + pageSize: 10, + }), // fetchPoList(), fetchWarehouseList(), ]); const fixPoDate = po.records.map((p) => { - return ({ + return { ...p, - orderDate: dayjs(p.orderDate).add(-1, "month").format(OUTPUT_DATE_FORMAT) - }) - }) - return ; + orderDate: dayjs(p.orderDate).add(-1, "month").format(OUTPUT_DATE_FORMAT), + }; + }); + return ( + + ); }; PoSearchWrapper.Loading = PoSearchLoading; diff --git a/src/components/ProductionProcess/DefectsSection.tsx b/src/components/ProductionProcess/DefectsSection.tsx index 6470e29..3179c4e 100644 --- a/src/components/ProductionProcess/DefectsSection.tsx +++ b/src/components/ProductionProcess/DefectsSection.tsx @@ -1,40 +1,49 @@ -import React, { useState } from 'react'; -import { X } from '@mui/icons-material'; -import { DefectsSectionProps, QualityCheckItem } from './types'; -import { Autocomplete, TextField, Button, Typography, Box, Stack, Paper, IconButton } from '@mui/material'; -import { defectOptions } from './dummyData'; +import React, { useState } from "react"; +import { X } from "@mui/icons-material"; +import { DefectsSectionProps, QualityCheckItem } from "./types"; +import { + Autocomplete, + TextField, + Button, + Typography, + Box, + Stack, + Paper, + IconButton, +} from "@mui/material"; +import { defectOptions } from "./dummyData"; - -const DefectsSection: React.FC = ({ +const DefectsSection: React.FC = ({ defects, onDefectsChange, - error + error, }) => { const [newDefect, setNewDefect] = useState(null); - const [inputValue, setInputValue] = useState(''); + const [inputValue, setInputValue] = useState(""); const handleAddDefect = (): void => { let defectToAdd: QualityCheckItem | null = null; - + if (newDefect) { // If user selected from options defectToAdd = { id: newDefect.id, code: newDefect.code, name: newDefect.name, - description: newDefect.description + description: newDefect.description, }; - } - + } + if (defectToAdd) { // Check for duplicate code (skip if code is empty) - const isDuplicate = defectToAdd.code && defects.some(d => d.code === defectToAdd.code); + const isDuplicate = + defectToAdd.code && defects.some((d) => d.code === defectToAdd.code); if (!isDuplicate) { const updatedDefects = [...defects, defectToAdd]; onDefectsChange(updatedDefects); } setNewDefect(null); - setInputValue(''); + setInputValue(""); } }; @@ -44,7 +53,7 @@ const DefectsSection: React.FC = ({ }; const handleKeyPress = (e: React.KeyboardEvent): void => { - if (e.key === 'Enter') { + if (e.key === "Enter") { e.preventDefault(); handleAddDefect(); } @@ -59,8 +68,8 @@ const DefectsSection: React.FC = ({ { - if (typeof value === 'string') { - setNewDefect({ id: 0, code: '', name: value, description: '' }); + if (typeof value === "string") { + setNewDefect({ id: 0, code: "", name: value, description: "" }); } else { setNewDefect(value); } @@ -70,7 +79,11 @@ const DefectsSection: React.FC = ({ setInputValue(newInputValue); }} options={defectOptions} - getOptionLabel={(option) => typeof option === 'string' ? option : `${option.code} - ${option.name}`} + getOptionLabel={(option) => + typeof option === "string" + ? option + : `${option.code} - ${option.name}` + } isOptionEqualToValue={(option, value) => option.id === value.id} fullWidth renderOption={(props, option) => ( @@ -96,17 +109,17 @@ const DefectsSection: React.FC = ({ /> )} /> - - + {error && ( - + {error} )} @@ -120,22 +133,30 @@ const DefectsSection: React.FC = ({ - - {defect.code && `${defect.code} - `}{defect.name} + + {defect.code && `${defect.code} - `} + {defect.name} {defect.description && ( - + {defect.description} )} @@ -155,4 +176,4 @@ const DefectsSection: React.FC = ({ ); }; -export default DefectsSection; \ No newline at end of file +export default DefectsSection; diff --git a/src/components/ProductionProcess/MachineScanner.tsx b/src/components/ProductionProcess/MachineScanner.tsx index 4316fae..8e082e9 100644 --- a/src/components/ProductionProcess/MachineScanner.tsx +++ b/src/components/ProductionProcess/MachineScanner.tsx @@ -1,11 +1,19 @@ "use client"; -import React, { useState, useRef } from 'react'; -import { MachineQrCode } from './types'; -import { Button, TextField, Typography, Paper, Box, IconButton, Stack } from '@mui/material'; -import CloseIcon from '@mui/icons-material/Close'; -import { isCorrectMachineUsed } from '@/app/api/jo/actions'; -import { Machine } from '@/app/api/jo'; -import { useTranslation } from 'react-i18next'; +import React, { useState, useRef } from "react"; +import { MachineQrCode } from "./types"; +import { + Button, + TextField, + Typography, + Paper, + Box, + IconButton, + Stack, +} from "@mui/material"; +import CloseIcon from "@mui/icons-material/Close"; +import { isCorrectMachineUsed } from "@/app/api/jo/actions"; +import { Machine } from "@/app/api/jo"; +import { useTranslation } from "react-i18next"; interface MachineScannerProps { machines: Machine[]; @@ -14,22 +22,22 @@ interface MachineScannerProps { } const machineDatabase: Machine[] = [ - { id: 1, name: 'CNC Mill #1', code: 'CNC001', qrCode: 'QR-CNC001' }, - { id: 2, name: 'Lathe #2', code: 'LAT002', qrCode: 'QR-LAT002' }, - { id: 3, name: 'Press #3', code: 'PRS003', qrCode: 'QR-PRS003' }, - { id: 4, name: 'Welder #4', code: 'WLD004', qrCode: 'QR-WLD004' }, - { id: 5, name: 'Drill Press #5', code: 'DRL005', qrCode: 'QR-DRL005' } + { id: 1, name: "CNC Mill #1", code: "CNC001", qrCode: "QR-CNC001" }, + { id: 2, name: "Lathe #2", code: "LAT002", qrCode: "QR-LAT002" }, + { id: 3, name: "Press #3", code: "PRS003", qrCode: "QR-PRS003" }, + { id: 4, name: "Welder #4", code: "WLD004", qrCode: "QR-WLD004" }, + { id: 5, name: "Drill Press #5", code: "DRL005", qrCode: "QR-DRL005" }, ]; -const MachineScanner: React.FC = ({ - machines, - onMachinesChange, - error +const MachineScanner: React.FC = ({ + machines, + onMachinesChange, + error, }) => { const [scanningMode, setScanningMode] = useState(false); const [scanError, setScanError] = useState(null); const machineScanRef = useRef(null); - const { t } = useTranslation() + const { t } = useTranslation(); const startScanning = (): void => { setScanningMode(true); @@ -44,53 +52,73 @@ const MachineScanner: React.FC = ({ setScanningMode(false); }; - const handleMachineScan = async (e: React.KeyboardEvent): Promise => { + const handleMachineScan = async ( + e: React.KeyboardEvent, + ): Promise => { const target = e.target as HTMLInputElement; const scannedCodeJSON = target.value.trim(); - if (e.key === 'Enter' || scannedCodeJSON.endsWith('}') ) { - const scannedObj: MachineQrCode = JSON.parse(scannedCodeJSON) - - const response = await isCorrectMachineUsed(scannedObj?.code) - + if (e.key === "Enter" || scannedCodeJSON.endsWith("}")) { + const scannedObj: MachineQrCode = JSON.parse(scannedCodeJSON); + + const response = await isCorrectMachineUsed(scannedObj?.code); + if (response.message === "Success") { - const isAlreadyAdded = machines.some(m => m.code === response.entity.code); - + const isAlreadyAdded = machines.some( + (m) => m.code === response.entity.code, + ); + if (!isAlreadyAdded) { onMachinesChange([...machines, response.entity]); } - - target.value = ''; + + target.value = ""; // stopScanning(); } else { - alert('Machine not found. Please check the code and try again.'); - setScanError('An error occurred while checking the operator. Please try again.'); - target.value = ''; + alert("Machine not found. Please check the code and try again."); + setScanError( + "An error occurred while checking the operator. Please try again.", + ); + target.value = ""; } } }; const removeMachine = (machineId: number): void => { - onMachinesChange(machines.filter(m => m.id !== machineId)); + onMachinesChange(machines.filter((m) => m.id !== machineId)); }; return ( - + Machines * {scanningMode && ( - + = ({ label="Scan machine QR code or enter manually..." variant="outlined" size="small" - sx={{ bgcolor: 'white' }} + sx={{ bgcolor: "white" }} /> - {scanError ? ( - {scanError} + + {scanError} + ) : ( - {t("Position the QR code scanner and scan, or type the machine code manually")} + {t( + "Position the QR code scanner and scan, or type the machine code manually", + )} )} )} - {error && {error}} + {error && ( + + {error} + + )} {machines.map((machine) => ( - + - {machine.name} - {machine.code} + + {machine.name} + + + {machine.code} + removeMachine(machine.id)} color="error"> @@ -135,8 +182,19 @@ const MachineScanner: React.FC = ({ ))} {machines.length === 0 && ( - - + + No machines added yet. Use the scan button to add machines. @@ -146,4 +204,4 @@ const MachineScanner: React.FC = ({ ); }; -export default MachineScanner; \ No newline at end of file +export default MachineScanner; diff --git a/src/components/ProductionProcess/MaterialLotScanner.tsx b/src/components/ProductionProcess/MaterialLotScanner.tsx index 40c2693..e06469e 100644 --- a/src/components/ProductionProcess/MaterialLotScanner.tsx +++ b/src/components/ProductionProcess/MaterialLotScanner.tsx @@ -1,9 +1,18 @@ "use client"; -import React, { useState, useRef, useEffect } from 'react'; -import { Material, MaterialDatabase } from './types'; -import { Box, Typography, TextField, Paper, Stack, Button, IconButton, Chip } from '@mui/material'; -import CheckIcon from '@mui/icons-material/Check'; -import CloseIcon from '@mui/icons-material/Close'; +import React, { useState, useRef, useEffect } from "react"; +import { Material, MaterialDatabase } from "./types"; +import { + Box, + Typography, + TextField, + Paper, + Stack, + Button, + IconButton, + Chip, +} from "@mui/material"; +import CheckIcon from "@mui/icons-material/Check"; +import CloseIcon from "@mui/icons-material/Close"; interface MaterialLotScannerProps { materials: Material[]; @@ -11,13 +20,12 @@ interface MaterialLotScannerProps { error?: string; } - -const MaterialLotScanner: React.FC = ({ - materials, - onMaterialsChange, - error +const MaterialLotScanner: React.FC = ({ + materials, + onMaterialsChange, + error, }) => { - const [materialScanInput, setMaterialScanInput] = useState(''); + const [materialScanInput, setMaterialScanInput] = useState(""); const materialScanRef = useRef(null); useEffect(() => { @@ -26,56 +34,73 @@ const MaterialLotScanner: React.FC = ({ } }, []); - const handleMaterialInputChange = (e: React.ChangeEvent) => { + const handleMaterialInputChange = ( + e: React.ChangeEvent, + ) => { setMaterialScanInput(e.target.value.trim()); }; - const handleMaterialInputKeyPress = async (e: React.KeyboardEvent) => { - if (e.key === 'Enter') { + const handleMaterialInputKeyPress = async ( + e: React.KeyboardEvent, + ) => { + if (e.key === "Enter") { const target = e.target as HTMLInputElement; const scannedLot = target.value.trim(); if (scannedLot) { - const response = await fetch('http://your-backend-url.com/validateLot', { - method: 'POST', - headers: { - 'Content-Type': 'application/json' + const response = await fetch( + "http://your-backend-url.com/validateLot", + { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ lot: scannedLot }), }, - body: JSON.stringify({ lot: scannedLot }) - }); + ); const data = await response.json(); if (data.suggestedLot) { - const updatedMaterials = materials.map(material => { + const updatedMaterials = materials.map((material) => { if (material.name === data.matchedMaterial.name) { const isAlreadyAdded = material.lotNumbers.includes(scannedLot); if (!isAlreadyAdded) { return { ...material, isUsed: true, - lotNumbers: [...material.lotNumbers, scannedLot] + lotNumbers: [...material.lotNumbers, scannedLot], }; } } return material; }); onMaterialsChange(updatedMaterials); - setMaterialScanInput(''); + setMaterialScanInput(""); } else if (data.matchedMaterial) { - setMaterialScanInput(scannedLot + ' (Invalid lot number format. Suggested lot number: ' + data.suggestedLot + ')'); + setMaterialScanInput( + scannedLot + + " (Invalid lot number format. Suggested lot number: " + + data.suggestedLot + + ")", + ); } else { - setMaterialScanInput(scannedLot + ' (Invalid lot number format or material not recognized.)'); + setMaterialScanInput( + scannedLot + + " (Invalid lot number format or material not recognized.)", + ); } } } }; const removeLotNumber = (materialName: string, lotNumber: string): void => { - const updatedMaterials = materials.map(material => { + const updatedMaterials = materials.map((material) => { if (material.name === materialName) { - const updatedLotNumbers = material.lotNumbers.filter(lot => lot !== lotNumber); + const updatedLotNumbers = material.lotNumbers.filter( + (lot) => lot !== lotNumber, + ); return { ...material, lotNumbers: updatedLotNumbers, - isUsed: updatedLotNumbers.length > 0 + isUsed: updatedLotNumbers.length > 0, }; } return material; @@ -83,15 +108,24 @@ const MaterialLotScanner: React.FC = ({ onMaterialsChange(updatedMaterials); }; - const requiredMaterials = materials.filter(m => m.required); - const optionalMaterials = materials.filter(m => !m.required); + const requiredMaterials = materials.filter((m) => m.required); + const optionalMaterials = materials.filter((m) => !m.required); return ( Material Lot Numbers - + = ({ label="Scan or enter material lot number (e.g., SS-240616-001)" variant="outlined" size="small" - sx={{ bgcolor: 'white' }} + sx={{ bgcolor: "white" }} /> Lot Number Formats: - Steel Sheet: SS-YYMMDD-XXX | Aluminum: AL-YYMMDD-XXX | Plastic: PP-YYMMDD-XXX + Steel Sheet: SS-YYMMDD-XXX | Aluminum: AL-YYMMDD-XXX | Plastic: + PP-YYMMDD-XXX - Copper Wire: CW-YYMMDD-XXX | Rubber: RG-YYMMDD-XXX | Glass: GP-YYMMDD-XXX + Copper Wire: CW-YYMMDD-XXX | Rubber: RG-YYMMDD-XXX | Glass: + GP-YYMMDD-XXX - {error && {error}} + {error && ( + + {error} + + )} {/* Required Materials */} @@ -128,10 +168,25 @@ const MaterialLotScanner: React.FC = ({ {requiredMaterials.map((material) => ( - - + + - {material.isUsed && } + {material.isUsed && ( + + )} {material.name} @@ -141,9 +196,28 @@ const MaterialLotScanner: React.FC = ({ {material.lotNumbers.length > 0 && ( {material.lotNumbers.map((lotNumber, index) => ( - - {lotNumber} - removeLotNumber(material.name, lotNumber)} color="error" size="small"> + + + {lotNumber} + + + removeLotNumber(material.name, lotNumber) + } + color="error" + size="small" + > @@ -157,17 +231,40 @@ const MaterialLotScanner: React.FC = ({ {/* Optional Materials */} - + Optional Materials - + {optionalMaterials.map((material) => ( - - + + - {material.isUsed && } + {material.isUsed && ( + + )} {material.name} @@ -177,9 +274,28 @@ const MaterialLotScanner: React.FC = ({ {material.lotNumbers.length > 0 && ( {material.lotNumbers.map((lotNumber, index) => ( - - {lotNumber} - removeLotNumber(material.name, lotNumber)} color="error" size="small"> + + + {lotNumber} + + + removeLotNumber(material.name, lotNumber) + } + color="error" + size="small" + > @@ -195,4 +311,4 @@ const MaterialLotScanner: React.FC = ({ ); }; -export default MaterialLotScanner; \ No newline at end of file +export default MaterialLotScanner; diff --git a/src/components/ProductionProcess/OperatorScanner.tsx b/src/components/ProductionProcess/OperatorScanner.tsx index 5894067..298a571 100644 --- a/src/components/ProductionProcess/OperatorScanner.tsx +++ b/src/components/ProductionProcess/OperatorScanner.tsx @@ -1,10 +1,18 @@ "use client"; -import React, { useState, useRef, useEffect } from 'react'; +import React, { useState, useRef, useEffect } from "react"; import { Operator } from "@/app/api/jo"; -import { Button, TextField, Typography, Paper, Box, IconButton, Stack } from '@mui/material'; -import CloseIcon from '@mui/icons-material/Close'; -import { isOperatorExist } from '@/app/api/jo/actions'; -import { OperatorQrCode } from './types'; +import { + Button, + TextField, + Typography, + Paper, + Box, + IconButton, + Stack, +} from "@mui/material"; +import CloseIcon from "@mui/icons-material/Close"; +import { isOperatorExist } from "@/app/api/jo/actions"; +import { OperatorQrCode } from "./types"; interface OperatorScannerProps { operators: Operator[]; @@ -12,16 +20,15 @@ interface OperatorScannerProps { error?: string; } -const OperatorScanner: React.FC = ({ - operators, - onOperatorsChange, - error +const OperatorScanner: React.FC = ({ + operators, + onOperatorsChange, + error, }) => { const [scanningMode, setScanningMode] = useState(false); const [scanError, setScanError] = useState(null); const operatorScanRef = useRef(null); - const startScanning = (): void => { setScanningMode(true); setScanError(null); @@ -37,58 +44,80 @@ const OperatorScanner: React.FC = ({ setScanError(null); }; - const handleOperatorScan = async (e: React.KeyboardEvent): Promise => { + const handleOperatorScan = async ( + e: React.KeyboardEvent, + ): Promise => { const target = e.target as HTMLInputElement; const usernameJSON: string = target.value.trim(); - - if (e.key === 'Enter' || usernameJSON.endsWith('}') ) { - console.log(usernameJSON) + + if (e.key === "Enter" || usernameJSON.endsWith("}")) { + console.log(usernameJSON); try { - const usernameObj: OperatorQrCode = JSON.parse(usernameJSON) + const usernameObj: OperatorQrCode = JSON.parse(usernameJSON); + + const response = await isOperatorExist(usernameObj.username); - const response = await isOperatorExist(usernameObj.username) - if (response.message === "Success") { - const isAlreadyAdded = operators.some(op => op.username === response.entity.username); + const isAlreadyAdded = operators.some( + (op) => op.username === response.entity.username, + ); if (!isAlreadyAdded) { onOperatorsChange([...operators, response.entity]); } - target.value = ''; + target.value = ""; setScanError(null); // stopScanning(); } else { - setScanError('Operator not found. Please check the ID and try again.'); - target.value = ''; + setScanError( + "Operator not found. Please check the ID and try again.", + ); + target.value = ""; } } catch (error) { - console.error('Error checking operator:', error); - setScanError('An error occurred while checking the operator. Please try again.'); - target.value = ''; + console.error("Error checking operator:", error); + setScanError( + "An error occurred while checking the operator. Please try again.", + ); + target.value = ""; } } }; const removeOperator = (operatorId: number): void => { - onOperatorsChange(operators.filter(op => op.id !== operatorId)); + onOperatorsChange(operators.filter((op) => op.id !== operatorId)); }; return ( - + Operators * {scanningMode && ( - + = ({ label="Scan operator ID card or enter manually..." variant="outlined" size="small" - sx={{ bgcolor: 'white' }} + sx={{ bgcolor: "white" }} onInput={handleOperatorScan} /> - {scanError ? ( - {scanError} + + {scanError} + ) : ( - Position the ID card scanner and scan, or type the employee ID manually + Position the ID card scanner and scan, or type the employee ID + manually )} )} - {error && {error}} + {error && ( + + {error} + + )} {operators.map((operator) => ( - + - {operator.name} - {operator.username} + + {operator.name} + + + {operator.username} + - removeOperator(operator.id)} color="error"> + removeOperator(operator.id)} + color="error" + > ))} {operators.length === 0 && ( - - + + No operators added yet. Use the scan button to add operators. @@ -145,4 +206,4 @@ const OperatorScanner: React.FC = ({ ); }; -export default OperatorScanner; \ No newline at end of file +export default OperatorScanner; diff --git a/src/components/ProductionProcess/ProductionProcess.tsx b/src/components/ProductionProcess/ProductionProcess.tsx index 0b3c86e..f55610f 100644 --- a/src/components/ProductionProcess/ProductionProcess.tsx +++ b/src/components/ProductionProcess/ProductionProcess.tsx @@ -1,30 +1,30 @@ "use client"; -import React, { useTransition } from 'react'; -import ProductionRecordingModal from './ProductionRecordingModal'; -import { - Box, - Button, - Table, - TableBody, - TableCell, - TableContainer, - TableHead, - TableRow, +import React, { useTransition } from "react"; +import ProductionRecordingModal from "./ProductionRecordingModal"; +import { + Box, + Button, + Table, + TableBody, + TableCell, + TableContainer, + TableHead, + TableRow, Paper, Typography, - Chip -} from '@mui/material'; -import { Material } from './types'; -import { useTranslation } from 'react-i18next'; -import QualityCheckModal from './QualityCheckModal'; -import { sampleItem } from './dummyData'; + Chip, +} from "@mui/material"; +import { Material } from "./types"; +import { useTranslation } from "react-i18next"; +import QualityCheckModal from "./QualityCheckModal"; +import { sampleItem } from "./dummyData"; interface ProcessData { id: string; processName: string; - status: 'Not Started' | 'In Progress' | 'Completed'; + status: "Not Started" | "In Progress" | "Completed"; recordedData?: any; // You can type this based on your actual data structure - materials: Material[] + materials: Material[]; } interface ProductionProcessProps { @@ -40,11 +40,12 @@ interface ProductionRecordingModalProps { const ProductionProcess: React.FC = ({ processes }) => { const [isModalOpen, setIsModalOpen] = React.useState(false); - const [selectedProcess, setSelectedProcess] = React.useState(null); + const [selectedProcess, setSelectedProcess] = + React.useState(null); const [isQCModalOpen, setIsQCModalOpen] = React.useState(false); - const { t } = useTranslation() + const { t } = useTranslation(); console.log("production process"); @@ -61,7 +62,7 @@ const ProductionProcess: React.FC = ({ processes }) => { const handleQCOpenModal = (process: ProcessData) => { setSelectedProcess(process); setIsQCModalOpen(true); - } + }; const handleQCCloseModal = () => { setIsQCModalOpen(false); @@ -69,24 +70,24 @@ const ProductionProcess: React.FC = ({ processes }) => { }; const handleDataRecorded = (processId: string, data: any) => { - const updated = processes.map(process => + const updated = processes.map((process) => process.id === processId - ? { ...process, status: 'Completed', recordedData: data } - : process + ? { ...process, status: "Completed", recordedData: data } + : process, ); - console.log(updated) + console.log(updated); }; - const getStatusColor = (status: ProcessData['status']) => { + const getStatusColor = (status: ProcessData["status"]) => { switch (status) { - case 'Not Started': - return 'default'; - case 'In Progress': - return 'warning'; - case 'Completed': - return 'success'; + case "Not Started": + return "default"; + case "In Progress": + return "warning"; + case "Completed": + return "success"; default: - return 'default'; + return "default"; } }; @@ -99,20 +100,20 @@ const ProductionProcess: React.FC = ({ processes }) => { - - Process ID - Process Name - Status - Action + + Process ID + Process Name + Status + Action {processes.map((process) => ( - @@ -120,7 +121,7 @@ const ProductionProcess: React.FC = ({ processes }) => { {process.processName} - = ({ processes }) => { color="primary" size="small" onClick={() => handleOpenModal(process)} - sx={{ - fontWeight: 500, - textTransform: 'none' + sx={{ + fontWeight: 500, + textTransform: "none", }} > - {process.status === 'Completed' ? 'View/Edit Data' : 'Record Data'} + {process.status === "Completed" + ? "View/Edit Data" + : "Record Data"} } - - - - - - - ) + }); + + const handleSubmit = useCallback(async (data: SaveQcItemInputs) => { + const response = await saveQcItem(data); + + const errors = response.errors; + if (errors) { + let errorContents = ""; + for (const [key, value] of Object.entries(errors)) { + formProps.setError(key as keyof SaveQcItemInputs, { + type: "custom", + message: value, + }); + errorContents = errorContents + t(value) + "
"; + } + + errorDialogWithContent(t("Submit Error"), errorContents, t); + } else { + await successDialog(t("Submit Success"), t, () => + router.push("/settings/qcItem"), + ); + } + }, []); + + const onSubmit = useCallback>( + async (data) => { + await submitDialog(() => handleSubmit(data), t); + }, + [], + ); + + const handleCancel = () => { + router.replace("/qcItem"); + }; + + const handleDelete = () => { + deleteDialog(async () => { + await deleteQcItem(formProps.getValues("id")!); + + await successDialog(t("Delete Success"), t, () => + router.replace("/settings/qcItem"), + ); + }, t); + }; + + return ( + <> + + + + + {defaultInputs?.id && ( + + )} + + + + + + + ); }; - -export default QcItemSave; \ No newline at end of file +export default QcItemSave; diff --git a/src/components/QcItemSave/QcItemSaveWrapper.tsx b/src/components/QcItemSave/QcItemSaveWrapper.tsx index 6c7a261..25b106f 100644 --- a/src/components/QcItemSave/QcItemSaveWrapper.tsx +++ b/src/components/QcItemSave/QcItemSaveWrapper.tsx @@ -1,26 +1,24 @@ -import React from "react" -import QcItemSaveLoading from "./QcItemSaveLoading" +import React from "react"; +import QcItemSaveLoading from "./QcItemSaveLoading"; import QcItemSave from "./QcItemSave"; import { fetchQcItemDetails } from "@/app/api/settings/qcItem"; interface SubComponents { - Loading: typeof QcItemSaveLoading; + Loading: typeof QcItemSaveLoading; } type SaveQcItemProps = { - id?: string -} + id?: string; +}; -type Props = SaveQcItemProps +type Props = SaveQcItemProps; -const QcItemSaveWrapper: React.FC & SubComponents = async ( - props -) => { - const qcItem = props.id ? await fetchQcItemDetails(props.id) : undefined; +const QcItemSaveWrapper: React.FC & SubComponents = async (props) => { + const qcItem = props.id ? await fetchQcItemDetails(props.id) : undefined; - return ; + return ; }; QcItemSaveWrapper.Loading = QcItemSaveLoading; -export default QcItemSaveWrapper; \ No newline at end of file +export default QcItemSaveWrapper; diff --git a/src/components/QcItemSave/index.ts b/src/components/QcItemSave/index.ts index 7c6812d..034c12e 100644 --- a/src/components/QcItemSave/index.ts +++ b/src/components/QcItemSave/index.ts @@ -1 +1 @@ -export { default } from "./QcItemSaveWrapper"; \ No newline at end of file +export { default } from "./QcItemSaveWrapper"; diff --git a/src/components/QcItemSearch/QcItemSearch.tsx b/src/components/QcItemSearch/QcItemSearch.tsx index 5f8ea29..1d70790 100644 --- a/src/components/QcItemSearch/QcItemSearch.tsx +++ b/src/components/QcItemSearch/QcItemSearch.tsx @@ -1,5 +1,10 @@ "use client"; -import { Html5QrcodeResult, Html5QrcodeScanner, QrcodeErrorCallback, QrcodeSuccessCallback } from "html5-qrcode"; +import { + Html5QrcodeResult, + Html5QrcodeScanner, + QrcodeErrorCallback, + QrcodeSuccessCallback, +} from "html5-qrcode"; import React, { useCallback, useEffect, useMemo, useState } from "react"; import SearchBox, { Criterion } from "../SearchBox"; import { useTranslation } from "react-i18next"; @@ -23,7 +28,7 @@ type SearchParamNames = keyof SearchQuery; const QcItemSearch: React.FC = ({ qcItems }) => { const { t } = useTranslation("qcItems"); const router = useRouter(); - const pathname = usePathname() + const pathname = usePathname(); // If qcItem searching is done on the server-side, then no need for this. const [filteredQcItems, setFilteredQcItems] = useState(qcItems); @@ -33,34 +38,28 @@ const QcItemSearch: React.FC = ({ qcItems }) => { { label: t("Code"), paramName: "code", type: "text" }, { label: t("Name"), paramName: "name", type: "text" }, ], - [t] + [t], ); - const onReset = useCallback( - () => { - setFilteredQcItems(qcItems); - }, [qcItems] - ); + const onReset = useCallback(() => { + setFilteredQcItems(qcItems); + }, [qcItems]); const onQcItemClick = useCallback( (qcItem: QcItemResult) => { router.push(`${pathname}/edit?id=${qcItem.id}`); }, - [router] + [router], ); - const handleDelete = useCallback( - (qcItem: QcItemResult) => { - deleteDialog(async () => { - qcItems = await deleteQcItem(qcItem.id); - setFilteredQcItems(qcItems) + const handleDelete = useCallback((qcItem: QcItemResult) => { + deleteDialog(async () => { + qcItems = await deleteQcItem(qcItem.id); + setFilteredQcItems(qcItems); - await successDialog( - t("Delete Success"), - t - ); - }, t); - }, []) + await successDialog(t("Delete Success"), t); + }, t); + }, []); const columns = useMemo[]>( () => [ @@ -77,10 +76,10 @@ const QcItemSearch: React.FC = ({ qcItems }) => { label: t("Delete"), onClick: handleDelete, buttonIcon: , - buttonColor: "error" - } + buttonColor: "error", + }, ], - [t, onQcItemClick] + [t, onQcItemClick], ); // const [isOpenScanner, setOpenScanner] = useState(false) @@ -107,15 +106,15 @@ const QcItemSearch: React.FC = ({ qcItems }) => { qcItems.filter( (qi) => qi.code.toLowerCase().includes(query.code.toLowerCase()) && - qi.name.toLowerCase().includes(query.name.toLowerCase()) - ) + qi.name.toLowerCase().includes(query.name.toLowerCase()), + ), ); }} onReset={onReset} /> items={filteredQcItems} columns={columns} /> - ) + ); }; export default QcItemSearch; diff --git a/src/components/QcItemSearch/QcItemSearchWrapper.tsx b/src/components/QcItemSearch/QcItemSearchWrapper.tsx index 1242174..dfb03dd 100644 --- a/src/components/QcItemSearch/QcItemSearchWrapper.tsx +++ b/src/components/QcItemSearch/QcItemSearchWrapper.tsx @@ -1,23 +1,18 @@ -import React from "react" -import QcItemSearchLoading from "./QcItemSearchLoading" +import React from "react"; +import QcItemSearchLoading from "./QcItemSearchLoading"; import QcItemSearch from "./QcItemSearch"; import { fetchQcItems } from "@/app/api/settings/qcItem"; interface SubComponents { - Loading: typeof QcItemSearchLoading; + Loading: typeof QcItemSearchLoading; } const QcItemSearchWrapper: React.FC & SubComponents = async () => { + const [qcItems] = await Promise.all([fetchQcItems()]); - const [ - qcItems - ] = await Promise.all([ - fetchQcItems() - ]); - - return ; + return ; }; QcItemSearchWrapper.Loading = QcItemSearchLoading; -export default QcItemSearchWrapper; \ No newline at end of file +export default QcItemSearchWrapper; diff --git a/src/components/QcItemSearch/index.ts b/src/components/QcItemSearch/index.ts index e4237cd..764633e 100644 --- a/src/components/QcItemSearch/index.ts +++ b/src/components/QcItemSearch/index.ts @@ -1 +1 @@ -export { default } from "./QcItemSearchWrapper"; \ No newline at end of file +export { default } from "./QcItemSearchWrapper"; diff --git a/src/components/QrCode/QrCode.tsx b/src/components/QrCode/QrCode.tsx index dd0189c..381c945 100644 --- a/src/components/QrCode/QrCode.tsx +++ b/src/components/QrCode/QrCode.tsx @@ -1,7 +1,7 @@ -"use client" +"use client"; -import { QRCodeSVG } from 'qrcode.react'; -import { CSSProperties } from 'react'; +import { QRCodeSVG } from "qrcode.react"; +import { CSSProperties } from "react"; interface Props { content: any; diff --git a/src/components/QrCode/index.ts b/src/components/QrCode/index.ts index 3833923..01904fb 100644 --- a/src/components/QrCode/index.ts +++ b/src/components/QrCode/index.ts @@ -1 +1 @@ -export {default as QrCode} from "./QrCode" \ No newline at end of file +export { default as QrCode } from "./QrCode"; diff --git a/src/components/QrCodeScanner/QrCodeScanner.tsx b/src/components/QrCodeScanner/QrCodeScanner.tsx index 409dfa1..2fdacab 100644 --- a/src/components/QrCodeScanner/QrCodeScanner.tsx +++ b/src/components/QrCodeScanner/QrCodeScanner.tsx @@ -108,7 +108,7 @@ const QrCodeScanner: React.FC = ({ selectedCameraId, cameraConfig, handleScanSuccess, - handleScanError + handleScanError, ); } }, [selectedCameraId, scanner]); @@ -152,7 +152,7 @@ const QrCodeScanner: React.FC = ({ onScanSuccess(parseData); } }, - [scanner, onScanSuccess] + [scanner, onScanSuccess], ); const handleScanError = useCallback( @@ -163,7 +163,7 @@ const QrCodeScanner: React.FC = ({ onScanError(errorMessage); } }, - [scanner, onScanError] + [scanner, onScanError], ); const handleScanCloseButton = useCallback(async () => { diff --git a/src/components/QrCodeScanner/QrCodeScannerModal.tsx b/src/components/QrCodeScanner/QrCodeScannerModal.tsx index 9169073..b4b09ed 100644 --- a/src/components/QrCodeScanner/QrCodeScannerModal.tsx +++ b/src/components/QrCodeScanner/QrCodeScannerModal.tsx @@ -53,7 +53,7 @@ const QrCodeScannerModal: React.FC = ({ setModalOpen(false); } }, - [] + [], ); return ( diff --git a/src/components/QrCodeScanner/index.ts b/src/components/QrCodeScanner/index.ts index c856b00..8eff789 100644 --- a/src/components/QrCodeScanner/index.ts +++ b/src/components/QrCodeScanner/index.ts @@ -1 +1 @@ -export { default } from "./QrCodeScannerModal" \ No newline at end of file +export { default } from "./QrCodeScannerModal"; diff --git a/src/components/QrCodeScannerProvider/QrCodeScannerProvider.tsx b/src/components/QrCodeScannerProvider/QrCodeScannerProvider.tsx index 8b613c2..47e8247 100644 --- a/src/components/QrCodeScannerProvider/QrCodeScannerProvider.tsx +++ b/src/components/QrCodeScannerProvider/QrCodeScannerProvider.tsx @@ -1,99 +1,119 @@ "use client"; -import { ReactNode, createContext, useCallback, useContext, useEffect, useState } from "react"; +import { + ReactNode, + createContext, + useCallback, + useContext, + useEffect, + useState, +} from "react"; interface QcCodeScanner { - values: string[]; - isScanning: boolean; - startScan: () => void; - stopScan: () => void; - resetScan: () => void; + values: string[]; + isScanning: boolean; + startScan: () => void; + stopScan: () => void; + resetScan: () => void; } interface QrCodeScannerProviderProps { - children: ReactNode; + children: ReactNode; } -export const QcCodeScannerContext = createContext(undefined) - -const QrCodeScannerProvider: React.FC = ({ children }) => { - const [qcCodeScannerValues, setQrCodeScannerValues] = useState([]); - const [isScanning, setIsScanning] = useState(false); - const [keys, setKeys] = useState([]); - const [leftCurlyBraceCount, setLeftCurlyBraceCount] = useState(0); - const [rightCurlyBraceCount, setRightCurlyBraceCount] = useState(0); - const resetQrCodeScanner = useCallback(() => { - setQrCodeScannerValues(() => []) - }, []) - - const startQrCodeScanner = useCallback(() => { - resetQrCodeScanner() - setIsScanning(() => true) - }, []) - - const endQrCodeScanner = useCallback(() => { - setIsScanning(() => false) - }, []) - - - // Check the KeyDown - useEffect(() => { - if (isScanning) { - - const handleKeyDown = (event: KeyboardEvent) => { - if (event.key.length === 1) { - setKeys((key) => [...key, event.key]) - } - - if (event.key === "{") { - setLeftCurlyBraceCount((count) => count + 1) - } else if (event.key === "}") { - setRightCurlyBraceCount((count) => count + 1) - } - } - - document.addEventListener('keydown', handleKeyDown); - - return () => { - document.removeEventListener('keydown', handleKeyDown); - }; - }; - }, [isScanning]) - - // Update Qr Code Scanner Values - useEffect(() => { - if (leftCurlyBraceCount !== 0 && rightCurlyBraceCount !== 0 && leftCurlyBraceCount === rightCurlyBraceCount) { - const startBrace = keys.indexOf('{'); - const endBrace = keys.lastIndexOf('}'); - setQrCodeScannerValues((value) => [...value, keys.join("").substring(startBrace, endBrace + 1)]) - console.log(keys) - console.log(qcCodeScannerValues) +export const QcCodeScannerContext = createContext( + undefined, +); + +const QrCodeScannerProvider: React.FC = ({ + children, +}) => { + const [qcCodeScannerValues, setQrCodeScannerValues] = useState([]); + const [isScanning, setIsScanning] = useState(false); + const [keys, setKeys] = useState([]); + const [leftCurlyBraceCount, setLeftCurlyBraceCount] = useState(0); + const [rightCurlyBraceCount, setRightCurlyBraceCount] = useState(0); + const resetQrCodeScanner = useCallback(() => { + setQrCodeScannerValues(() => []); + }, []); + + const startQrCodeScanner = useCallback(() => { + resetQrCodeScanner(); + setIsScanning(() => true); + }, []); + + const endQrCodeScanner = useCallback(() => { + setIsScanning(() => false); + }, []); + + // Check the KeyDown + useEffect(() => { + if (isScanning) { + const handleKeyDown = (event: KeyboardEvent) => { + if (event.key.length === 1) { + setKeys((key) => [...key, event.key]); + } - // reset - setKeys(() => []) - setLeftCurlyBraceCount(() => 0) - setRightCurlyBraceCount(() => 0) + if (event.key === "{") { + setLeftCurlyBraceCount((count) => count + 1); + } else if (event.key === "}") { + setRightCurlyBraceCount((count) => count + 1); } - }, [keys, leftCurlyBraceCount, rightCurlyBraceCount]) + }; - return ( - - {children} - - ) -} + document.addEventListener("keydown", handleKeyDown); -export const useQcCodeScanner = (): QcCodeScanner => { - const context = useContext(QcCodeScannerContext); - if (!context) { - throw new Error('useQcCodeScanner must be used within a QcCodeScannerProvider'); + return () => { + document.removeEventListener("keydown", handleKeyDown); + }; } - return context; + }, [isScanning]); + + // Update Qr Code Scanner Values + useEffect(() => { + if ( + leftCurlyBraceCount !== 0 && + rightCurlyBraceCount !== 0 && + leftCurlyBraceCount === rightCurlyBraceCount + ) { + const startBrace = keys.indexOf("{"); + const endBrace = keys.lastIndexOf("}"); + setQrCodeScannerValues((value) => [ + ...value, + keys.join("").substring(startBrace, endBrace + 1), + ]); + console.log(keys); + console.log(qcCodeScannerValues); + + // reset + setKeys(() => []); + setLeftCurlyBraceCount(() => 0); + setRightCurlyBraceCount(() => 0); + } + }, [keys, leftCurlyBraceCount, rightCurlyBraceCount]); + + return ( + + {children} + + ); +}; + +export const useQcCodeScanner = (): QcCodeScanner => { + const context = useContext(QcCodeScannerContext); + if (!context) { + throw new Error( + "useQcCodeScanner must be used within a QcCodeScannerProvider", + ); + } + return context; }; -export default QrCodeScannerProvider; \ No newline at end of file +export default QrCodeScannerProvider; diff --git a/src/components/ReactQrCodeScanner/ReactQrCodeScanner.tsx b/src/components/ReactQrCodeScanner/ReactQrCodeScanner.tsx index 3642b3d..7646e60 100644 --- a/src/components/ReactQrCodeScanner/ReactQrCodeScanner.tsx +++ b/src/components/ReactQrCodeScanner/ReactQrCodeScanner.tsx @@ -53,7 +53,7 @@ export interface ScannerConfig { const ReactQrCodeScanner: React.FC = ({ scannerConfig }) => { const [stopStream, setStopStream] = useState( - scannerConfig.stopStream || defaultScannerConfig.stopStream || false + scannerConfig.stopStream || defaultScannerConfig.stopStream || false, ); const [torchEnabled, setTorchEnabled] = useState(false); // const _scannerConfig = useMemo(() => ({ @@ -61,7 +61,7 @@ const ReactQrCodeScanner: React.FC = ({ scannerConfig }) => { // ...scannerConfig, // }),[]) const [_scannerConfig, setScannerConfig] = useState({ - ...defaultScannerConfig + ...defaultScannerConfig, }); useEffect(() => { setScannerConfig({ diff --git a/src/components/RoughSchedule/RoughSchedileSearchView.tsx b/src/components/RoughSchedule/RoughSchedileSearchView.tsx index bc3f778..43b14c8 100644 --- a/src/components/RoughSchedule/RoughSchedileSearchView.tsx +++ b/src/components/RoughSchedule/RoughSchedileSearchView.tsx @@ -12,9 +12,14 @@ import axios from "axios"; import { BASE_API_URL, NEXT_PUBLIC_API_URL } from "@/config/api"; import { useTranslation } from "react-i18next"; import axiosInstance from "@/app/(main)/axios/axiosInstance"; -import Qs from 'qs'; +import Qs from "qs"; import EditableSearchResults from "@/components/SearchResults/EditableSearchResults"; // Make sure to import Qs -import { ProdScheduleResult, ProdScheduleResultByPage, SearchProdSchedule, fetchProdSchedules } from "@/app/api/scheduling/actions"; +import { + ProdScheduleResult, + ProdScheduleResultByPage, + SearchProdSchedule, + fetchProdSchedules, +} from "@/app/api/scheduling/actions"; import { arrayToDateString, decimalFormatter } from "@/app/utils/formatUtil"; import { isEqual, uniqBy } from "lodash"; import dayjs from "dayjs"; @@ -28,222 +33,250 @@ import { ScheduleType } from "@/app/api/scheduling"; // }; type Props = { - type: ScheduleType; - // initProdSchedules: ProdScheduleResultByPage; - defaultInputs: SearchProdSchedule; + type: ScheduleType; + // initProdSchedules: ProdScheduleResultByPage; + defaultInputs: SearchProdSchedule; }; -type SearchQuery = Partial>; +type SearchQuery = Partial< + Omit +>; type SearchParamNames = keyof SearchQuery; const RSOverview: React.FC = ({ type, defaultInputs }) => { - const [filteredSchedules, setFilteredSchedules] = useState([]); - const { t } = useTranslation("schedule"); - const router = useRouter(); - // const [filterObj, setFilterObj] = useState({}); - // const [tempSelectedValue, setTempSelectedValue] = useState({}); - const [pagingController, setPagingController] = useState(defaultPagingController) - const [totalCount, setTotalCount] = useState(0) - const [inputs, setInputs] = useState(defaultInputs) - - const searchCriteria: Criterion[] = useMemo( - () => { - var searchCriteria: Criterion[] = [ - { label: t("Schedule Period"), label2: t("Schedule Period To"), paramName: "schedulePeriod", type: "dateRange" }, - { label: t("Scheduled At"), paramName: "scheduleAt", type: "date" }, - { label: t("Product Count"), paramName: "totalEstProdCount", type: "text" }, - ] - return searchCriteria + const [filteredSchedules, setFilteredSchedules] = useState< + ProdScheduleResult[] + >([]); + const { t } = useTranslation("schedule"); + const router = useRouter(); + // const [filterObj, setFilterObj] = useState({}); + // const [tempSelectedValue, setTempSelectedValue] = useState({}); + const [pagingController, setPagingController] = useState( + defaultPagingController, + ); + const [totalCount, setTotalCount] = useState(0); + const [inputs, setInputs] = useState(defaultInputs); + + const searchCriteria: Criterion[] = useMemo(() => { + const searchCriteria: Criterion[] = [ + { + label: t("Schedule Period"), + label2: t("Schedule Period To"), + paramName: "schedulePeriod", + type: "dateRange", + }, + { label: t("Scheduled At"), paramName: "scheduleAt", type: "date" }, + { + label: t("Product Count"), + paramName: "totalEstProdCount", + type: "text", + }, + ]; + return searchCriteria; + }, [t]); + + // const onDetailClick = useCallback( + // (item: ItemsResult) => { + // router.push(`/settings/items/edit?id=${item.id}`); + // }, + // [router] + // ); + + // const onDeleteClick = useCallback( + // (item: ItemsResult) => { }, + // [router] + // ); + + const onDetailClick = (record: ProdScheduleResult) => { + console.log("[debug] record", record); + router.push(`/scheduling/rough/edit?id=${record.id}`); + }; + + const columns = useMemo[]>( + () => [ + { + name: "id", + label: t("Details"), + onClick: (record) => onDetailClick(record), + buttonIcon: , + }, + { + name: "schedulePeriod", + label: t("Demand Forecast Period"), + renderCell: (params) => { + return `${arrayToDateString( + params.schedulePeriod, + )} - ${arrayToDateString(params.schedulePeriodTo)}`; }, - [t] - ); - - // const onDetailClick = useCallback( - // (item: ItemsResult) => { - // router.push(`/settings/items/edit?id=${item.id}`); - // }, - // [router] - // ); - - // const onDeleteClick = useCallback( - // (item: ItemsResult) => { }, - // [router] - // ); - - const onDetailClick = (record: ProdScheduleResult) => { - console.log("[debug] record", record); - router.push(`/scheduling/rough/edit?id=${record.id}`); - } - - const columns = useMemo[]>( - () => [ - { - name: "id", - label: t("Details"), - onClick: (record) => onDetailClick(record), - buttonIcon: , - }, - { - name: "schedulePeriod", - label: t("Demand Forecast Period"), - renderCell: (params) => { - return `${arrayToDateString(params.schedulePeriod)} - ${arrayToDateString(params.schedulePeriodTo)}` - } - }, - { - name: "scheduleAt", - label: t("Schedule At"), - renderCell: (params) => { - return arrayToDateString(params.scheduleAt) - } - }, - { - name: "totalEstProdCount", - label: t("Product Count(s)"), - headerAlign: "right", - align: "right", - renderCell: (params) => { - return decimalFormatter.format(params.totalEstProdCount) - } - }, - // { - // name: "action", - // label: t(""), - // buttonIcon: , - // onClick: onDeleteClick, - // }, - ], - [filteredSchedules] - ); - - // useEffect(() => { - // refetchData(filterObj); - - // }, [filterObj, pagingController.pageNum, pagingController.pageSize]); - - const refetchData = useCallback(async (query: Record | SearchProdSchedule, actionType: "reset" | "search" | "paging") => { - // console.log(query) - const params: SearchProdSchedule = { - scheduleAt: dayjs(query?.scheduleAt).isValid() ? query?.scheduleAt : undefined, - schedulePeriod: dayjs(query?.schedulePeriod).isValid() ? query?.schedulePeriod : undefined, - schedulePeriodTo: dayjs(query?.schedulePeriodTo).isValid() ? query?.schedulePeriodTo : undefined, - totalEstProdCount: query?.totalEstProdCount ? Number(query?.totalEstProdCount) : undefined, - types: ["rough"], - pageNum: pagingController.pageNum - 1, - pageSize: pagingController.pageSize - } - const response = await fetchProdSchedules(params) - - // console.log(response) - if (response) { - setTotalCount(response.total) - switch (actionType) { - case "reset": - case "search": - setFilteredSchedules(() => response.records) - break; - case "paging": - setFilteredSchedules((fs) => uniqBy([...fs, ...response.records], "id")) - break; - } + }, + { + name: "scheduleAt", + label: t("Schedule At"), + renderCell: (params) => { + return arrayToDateString(params.scheduleAt); + }, + }, + { + name: "totalEstProdCount", + label: t("Product Count(s)"), + headerAlign: "right", + align: "right", + renderCell: (params) => { + return decimalFormatter.format(params.totalEstProdCount); + }, + }, + // { + // name: "action", + // label: t(""), + // buttonIcon: , + // onClick: onDeleteClick, + // }, + ], + [filteredSchedules], + ); + + // useEffect(() => { + // refetchData(filterObj); + + // }, [filterObj, pagingController.pageNum, pagingController.pageSize]); + + const refetchData = useCallback( + async ( + query: Record | SearchProdSchedule, + actionType: "reset" | "search" | "paging", + ) => { + // console.log(query) + const params: SearchProdSchedule = { + scheduleAt: dayjs(query?.scheduleAt).isValid() + ? query?.scheduleAt + : undefined, + schedulePeriod: dayjs(query?.schedulePeriod).isValid() + ? query?.schedulePeriod + : undefined, + schedulePeriodTo: dayjs(query?.schedulePeriodTo).isValid() + ? query?.schedulePeriodTo + : undefined, + totalEstProdCount: query?.totalEstProdCount + ? Number(query?.totalEstProdCount) + : undefined, + types: ["rough"], + pageNum: pagingController.pageNum - 1, + pageSize: pagingController.pageSize, + }; + const response = await fetchProdSchedules(params); + + // console.log(response) + if (response) { + setTotalCount(response.total); + switch (actionType) { + case "reset": + case "search": + setFilteredSchedules(() => response.records); + break; + case "paging": + setFilteredSchedules((fs) => + uniqBy([...fs, ...response.records], "id"), + ); + break; } - }, [pagingController, setPagingController]) - - useEffect(() => { - refetchData(inputs, "paging") - }, [pagingController]) - - // const refetchData = async (filterObj: SearchQuery) => { - - // const authHeader = axiosInstance.defaults.headers['Authorization']; - // if (!authHeader) { - // return; // Exit the function if the token is not set - // } - - // const params ={ - // pageNum: pagingController.pageNum, - // pageSize: pagingController.pageSize, - // ...filterObj, - // ...tempSelectedValue, - // } - - // try { - // // const response = await axiosInstance.get(`${NEXT_PUBLIC_API_URL}/items/getRecordByPage`, { - // // params, - // // paramsSerializer: (params) => { - // // return Qs.stringify(params, { arrayFormat: 'repeat' }); - // // }, - // // }); - // //setFilteredSchedules(response.data.records); - // // setFilteredSchedules([ - // // { - // // id: 1, - // // scheduledPeriod: "2025-05-11 to 2025-05-17", - // // scheduledAt: "2025-05-07", - // // productCount: 13, - // // }, - // // { - // // id: 2, - // // scheduledPeriod: "2025-05-18 to 2025-05-24", - // // scheduledAt: "2025-05-14", - // // productCount: 15, - // // }, - // // { - // // id: 3, - // // scheduledPeriod: "2025-05-25 to 2025-05-31", - // // scheduledAt: "2025-05-21", - // // productCount: 13, - // // }, - // // ]) - // setPagingController({ - // ...pagingController, - // // totalCount: response.data.total - // }) - // // return response; // Return the data from the response - // } catch (error) { - // console.error('Error fetching items:', error); - // throw error; // Rethrow the error for further handling - // } - // }; - - const onReset = useCallback(() => { - // setFilteredSchedules(items ?? []); - // setFilterObj({}); - // setTempSelectedValue({}); - refetchData(inputs, "reset"); - }, []); - - return ( - <> - { - // resetPagingController() - setInputs(() => ( - { - scheduleAt: query?.scheduleAt, - schedulePeriod: query?.schedulePeriod, - schedulePeriodTo: query?.schedulePeriodTo, - totalEstProdCount: Number(query?.totalEstProdCount) - } - )) - refetchData(query, "search") - // setFilterObj({ - // ...query - // }) - }} - onReset={onReset} - /> - - items={filteredSchedules} - columns={columns} - setPagingController={setPagingController} - pagingController={pagingController} - totalCount={totalCount} - // isAutoPaging={false} - /> - - ); + } + }, + [pagingController, setPagingController], + ); + + useEffect(() => { + refetchData(inputs, "paging"); + }, [pagingController]); + + // const refetchData = async (filterObj: SearchQuery) => { + + // const authHeader = axiosInstance.defaults.headers['Authorization']; + // if (!authHeader) { + // return; // Exit the function if the token is not set + // } + + // const params ={ + // pageNum: pagingController.pageNum, + // pageSize: pagingController.pageSize, + // ...filterObj, + // ...tempSelectedValue, + // } + + // try { + // // const response = await axiosInstance.get(`${NEXT_PUBLIC_API_URL}/items/getRecordByPage`, { + // // params, + // // paramsSerializer: (params) => { + // // return Qs.stringify(params, { arrayFormat: 'repeat' }); + // // }, + // // }); + // //setFilteredSchedules(response.data.records); + // // setFilteredSchedules([ + // // { + // // id: 1, + // // scheduledPeriod: "2025-05-11 to 2025-05-17", + // // scheduledAt: "2025-05-07", + // // productCount: 13, + // // }, + // // { + // // id: 2, + // // scheduledPeriod: "2025-05-18 to 2025-05-24", + // // scheduledAt: "2025-05-14", + // // productCount: 15, + // // }, + // // { + // // id: 3, + // // scheduledPeriod: "2025-05-25 to 2025-05-31", + // // scheduledAt: "2025-05-21", + // // productCount: 13, + // // }, + // // ]) + // setPagingController({ + // ...pagingController, + // // totalCount: response.data.total + // }) + // // return response; // Return the data from the response + // } catch (error) { + // console.error('Error fetching items:', error); + // throw error; // Rethrow the error for further handling + // } + // }; + + const onReset = useCallback(() => { + // setFilteredSchedules(items ?? []); + // setFilterObj({}); + // setTempSelectedValue({}); + refetchData(inputs, "reset"); + }, []); + + return ( + <> + { + // resetPagingController() + setInputs(() => ({ + scheduleAt: query?.scheduleAt, + schedulePeriod: query?.schedulePeriod, + schedulePeriodTo: query?.schedulePeriodTo, + totalEstProdCount: Number(query?.totalEstProdCount), + })); + refetchData(query, "search"); + // setFilterObj({ + // ...query + // }) + }} + onReset={onReset} + /> + + items={filteredSchedules} + columns={columns} + setPagingController={setPagingController} + pagingController={pagingController} + totalCount={totalCount} + // isAutoPaging={false} + /> + + ); }; export default RSOverview; diff --git a/src/components/RoughSchedule/RoughScheduleWrapper.tsx b/src/components/RoughSchedule/RoughScheduleWrapper.tsx index 490e27c..6f04543 100644 --- a/src/components/RoughSchedule/RoughScheduleWrapper.tsx +++ b/src/components/RoughSchedule/RoughScheduleWrapper.tsx @@ -1,7 +1,10 @@ import { fetchAllItems } from "@/app/api/settings/item"; import { RoughScheduleLoading } from "./RoughScheduleLoading"; import RSOverview from "./RoughSchedileSearchView"; -import { SearchProdSchedule, fetchProdSchedules } from "@/app/api/scheduling/actions"; +import { + SearchProdSchedule, + fetchProdSchedules, +} from "@/app/api/scheduling/actions"; import { ScheduleType } from "@/app/api/scheduling"; interface SubComponents { @@ -9,28 +12,26 @@ interface SubComponents { } type Props = { - type: ScheduleType + type: ScheduleType; }; -const RoughScheduleWrapper: React.FC & SubComponents = async ( - { - type - } -) => { +const RoughScheduleWrapper: React.FC & SubComponents = async ({ + type, +}) => { // console.log(type) const defaultInputs: SearchProdSchedule = { - types: ["rough"] - } + types: ["rough"], + }; // const [ - // items, + // items, // prodSchedules // ] = await Promise.all([ - // fetchAllItems(), + // fetchAllItems(), // fetchProdSchedules(defaultInputs) // ]) - return ; + return ; }; RoughScheduleWrapper.Loading = RoughScheduleLoading; diff --git a/src/components/RoughSchedule/index.ts b/src/components/RoughSchedule/index.ts index d3f27f8..ea2abdb 100644 --- a/src/components/RoughSchedule/index.ts +++ b/src/components/RoughSchedule/index.ts @@ -1 +1 @@ -export { default } from "./RoughScheduleWrapper"; \ No newline at end of file +export { default } from "./RoughScheduleWrapper"; diff --git a/src/components/RoughScheduleDetail/DetailInfoCard.tsx b/src/components/RoughScheduleDetail/DetailInfoCard.tsx index 5cefcff..7ef40b6 100644 --- a/src/components/RoughScheduleDetail/DetailInfoCard.tsx +++ b/src/components/RoughScheduleDetail/DetailInfoCard.tsx @@ -43,13 +43,13 @@ const DetailInfoCard: React.FC = ({ isEditing }) => { // const [details, setDetails] = useState(null); useEffect(() => { - console.log("[debug] record details", getValues()) + console.log("[debug] record details", getValues()); // setDetails(recordDetails); - }, [getValues]) + }, [getValues]); useEffect(() => { - console.log("[debug] isEdit", isEditing) - }, [isEditing]) + console.log("[debug] isEdit", isEditing); + }, [isEditing]); return ( @@ -66,10 +66,12 @@ const DetailInfoCard: React.FC = ({ isEditing }) => { // {...register("scheduledPeriod", { // required: "name required!", // })} - defaultValue={`${arrayToDateString(getValues("schedulePeriod"))} - ${arrayToDateString(getValues("schedulePeriodTo"))}`} + defaultValue={`${arrayToDateString( + getValues("schedulePeriod"), + )} - ${arrayToDateString(getValues("schedulePeriodTo"))}`} disabled={!isEditing} - // error={Boolean(errors.name)} - // helperText={errors.name?.message} + // error={Boolean(errors.name)} + // helperText={errors.name?.message} /> @@ -79,7 +81,11 @@ const DetailInfoCard: React.FC = ({ isEditing }) => { // {...register("totalFGType", { // required: "Total FG Item required!", // })} - defaultValue={typeof (getValues("totalFGType")) == "number" ? integerFormatter.format(getValues("totalFGType")) : getValues("totalFGType")} + defaultValue={ + typeof getValues("totalFGType") == "number" + ? integerFormatter.format(getValues("totalFGType")) + : getValues("totalFGType") + } disabled={!isEditing} // error={Boolean(errors.code)} // helperText={errors.code?.message} @@ -93,7 +99,11 @@ const DetailInfoCard: React.FC = ({ isEditing }) => { // required: "Qty required!", // })} disabled={!isEditing} - defaultValue={typeof (getValues("totalFGType")) == "number" ? integerFormatter.format(getValues("totalEstProdCount")) : getValues("totalEstProdCount")} + defaultValue={ + typeof getValues("totalFGType") == "number" + ? integerFormatter.format(getValues("totalEstProdCount")) + : getValues("totalEstProdCount") + } // error={Boolean(errors.type)} // helperText={errors.type?.message} /> diff --git a/src/components/RoughScheduleDetail/RoughScheduleDetailWrapper.tsx b/src/components/RoughScheduleDetail/RoughScheduleDetailWrapper.tsx index 694a3c3..5dcc50d 100644 --- a/src/components/RoughScheduleDetail/RoughScheduleDetailWrapper.tsx +++ b/src/components/RoughScheduleDetail/RoughScheduleDetailWrapper.tsx @@ -9,13 +9,16 @@ interface SubComponents { } type Props = { - id?: number + id?: number; type: ScheduleType; }; -const RoughScheduleDetailWrapper: React.FC & SubComponents = async ({ id, type }) => { - const prodSchedule = id ? await fetchProdScheduleDetail(id) : undefined - +const RoughScheduleDetailWrapper: React.FC & SubComponents = async ({ + id, + type, +}) => { + const prodSchedule = id ? await fetchProdScheduleDetail(id) : undefined; + return ( = ({ }) => { // console.log(type) const apiRef = useGridApiRef(); - const params = useSearchParams() + const params = useSearchParams(); const [serverError, setServerError] = useState(""); const [tabIndex, setTabIndex] = useState(0); - const { t } = useTranslation("schedule") + const { t } = useTranslation("schedule"); const router = useRouter(); const [isEdit, setIsEdit] = useState(false); //const title = "Demand Forecast Detail" // console.log(typeId) const formProps = useForm({ - defaultValues: defaultValues ? defaultValues : { - }, + defaultValues: defaultValues ? defaultValues : {}, }); const errors = formProps.formState.errors; @@ -64,24 +70,23 @@ const RoughScheduleDetailView: React.FC = ({ ); const dayPeriod = useMemo(() => { - const from = arrayToDayjs(formProps.getValues("schedulePeriod")) - const to = arrayToDayjs(formProps.getValues("schedulePeriodTo")) + const from = arrayToDayjs(formProps.getValues("schedulePeriod")); + const to = arrayToDayjs(formProps.getValues("schedulePeriodTo")); - const diffDays = Math.abs(from.diff(to, "day")) - let result: string[] = [] + const diffDays = Math.abs(from.diff(to, "day")); + const result: string[] = []; for (let i = 0; i <= diffDays; i++) { - result.push(dayjsToDateString(from.add(i, "day"))) + result.push(dayjsToDateString(from.add(i, "day"))); } return result; - }, []) + }, []); const [pagingController, setPagingController] = useState({ pageNum: 1, pageSize: 10, totalCount: 0, - }) - + }); const handleCancel = () => { router.replace(`/scheduling/rough`); @@ -89,8 +94,8 @@ const RoughScheduleDetailView: React.FC = ({ const onSubmit = useCallback>( async (data, event) => { - let hasErrors = false; - console.log(errors) + const hasErrors = false; + console.log(errors); // console.log(apiRef.current.getCellValue(2, "lowerLimit")) // apiRef.current. try { @@ -104,18 +109,17 @@ const RoughScheduleDetailView: React.FC = ({ console.log(e); } }, - [apiRef, router, t] + [apiRef, router, t], ); // multiple tabs - const onSubmitError = useCallback>( - (errors) => { }, - [] - ); + const onSubmitError = useCallback< + SubmitErrorHandler + >((errors) => {}, []); const onClickEdit = () => { - setIsEdit(!isEdit) - } + setIsEdit(!isEdit); + }; return ( <> @@ -157,18 +161,43 @@ const RoughScheduleDetailView: React.FC = ({ */} - - - - + + + {serverError && ( {serverError} )} - {tabIndex === 0 && } - {tabIndex === 1 && } + {tabIndex === 0 && ( + + )} + {tabIndex === 1 && ( + + )} {/*
- - - - - - - -
- - + // case 'multi-select': + // //TODO: May need update if use + // return ( + // handleInputChange(row.id as number, columnName, selectedValues)} + // /> + // ); + case "read-only": + return {row[columnName] as string}; + default: + return null; // Handle any default case if needed } - - - ) - } - - const table = ( - <> - - - - - {isDetailedType(type) && {t("Release")}} - {(isEditable || hasCollapse) && {t("Actions")}} {/* Action Column Header */} - {columns.map((column, idx) => ( - - {column.label} - - ))} - - - - {/* {(isAutoPaging ? editedItems.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage) : editedItems).map((item) => ( */} - {(editedItems?.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage))?.map((item) => ( - - ))} - + })() + ) : column.renderCell ? ( +
{column.renderCell(row)}
+ ) : ( +
+ + isEdit && handleEditClick(row.id as number) + } + > + {row[columnName] as string} + +
+ )} + + ); + })} + + + {hasCollapse && ( + + +
+ + + + + + +
-
- - + + + )} + + ); + } + + const table = ( + <> + + + + + {isDetailedType(type) && {t("Release")}} + {(isEditable || hasCollapse) && ( + {t("Actions")} + )}{" "} + {/* Action Column Header */} + {columns.map((column, idx) => ( + + {column.label} + + ))} + + + + {/* {(isAutoPaging ? editedItems.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage) : editedItems).map((item) => ( */} + {editedItems + ?.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage) + ?.map((item) => )} + +
+
+ + + ); - return noWrapper ? table : {table}; + return noWrapper ? table : {table}; } -export default ScheduleTable; \ No newline at end of file +export default ScheduleTable; diff --git a/src/components/ScheduleTable/index.ts b/src/components/ScheduleTable/index.ts index c8a48ec..fb4310e 100644 --- a/src/components/ScheduleTable/index.ts +++ b/src/components/ScheduleTable/index.ts @@ -1 +1 @@ -export { default } from "./ScheduleTable" \ No newline at end of file +export { default } from "./ScheduleTable"; diff --git a/src/components/SearchBox/MultiSelect.tsx b/src/components/SearchBox/MultiSelect.tsx index ba71493..87bb957 100644 --- a/src/components/SearchBox/MultiSelect.tsx +++ b/src/components/SearchBox/MultiSelect.tsx @@ -1,67 +1,80 @@ -import React, {useEffect, useState} from 'react'; -import { FormControl, InputLabel, Select, MenuItem, Chip, Box } from '@mui/material'; +import React, { useEffect, useState } from "react"; +import { + FormControl, + InputLabel, + Select, + MenuItem, + Chip, + Box, +} from "@mui/material"; interface Option { - value: number; - label: string; + value: number; + label: string; } interface MultiSelectProps { - label: string; - options: Option[]; - selectedValues: number[]; - onChange: (values: number[]) => void; + label: string; + options: Option[]; + selectedValues: number[]; + onChange: (values: number[]) => void; } -const MultiSelect: React.FC = ({ label, options, selectedValues, onChange, isReset }) => { - const [displayValues, setDisplayValues] = useState(selectedValues); +const MultiSelect: React.FC = ({ + label, + options, + selectedValues, + onChange, + isReset, +}) => { + const [displayValues, setDisplayValues] = useState(selectedValues); - const handleChange = (event: React.ChangeEvent<{ value: unknown }>) => { - const value = event.target.value as number[]; - console.log("[debug] value", value); + const handleChange = (event: React.ChangeEvent<{ value: unknown }>) => { + const value = event.target.value as number[]; + console.log("[debug] value", value); - // Update display values state - setDisplayValues(value); - // Update selected values in parent component - onChange(value); - }; + // Update display values state + setDisplayValues(value); + // Update selected values in parent component + onChange(value); + }; - useEffect(()=>{ - setDisplayValues([]); - }, [isReset]) + useEffect(() => { + setDisplayValues([]); + }, [isReset]); - return ( - - {label} - -1} - readOnly - /> - {option.label} - - ))} - - - ); + return ( + + {label} + -1} + readOnly + /> + {option.label} + + ))} + + + ); }; -export default MultiSelect; \ No newline at end of file +export default MultiSelect; diff --git a/src/components/SearchBox/SearchBox.tsx b/src/components/SearchBox/SearchBox.tsx index cfa215c..5494e4a 100644 --- a/src/components/SearchBox/SearchBox.tsx +++ b/src/components/SearchBox/SearchBox.tsx @@ -20,7 +20,13 @@ import "dayjs/locale/zh-hk"; import { DatePicker } from "@mui/x-date-pickers/DatePicker"; import { LocalizationProvider } from "@mui/x-date-pickers/LocalizationProvider"; import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs"; -import { Autocomplete, Box, Checkbox, Chip, ListSubheader } from "@mui/material"; +import { + Autocomplete, + Box, + Checkbox, + Chip, + ListSubheader, +} from "@mui/material"; import MultiSelect from "@/components/SearchBox/MultiSelect"; import { intersectionWith } from "lodash"; @@ -35,8 +41,8 @@ interface BaseCriterion { } interface OptionWithLabel { - label: string, - value: any, + label: string; + value: any; } interface TextCriterion extends BaseCriterion { @@ -106,23 +112,33 @@ function SearchBox({ onReset, }: Props) { const { t } = useTranslation("common"); - const defaultAll: AutocompleteOptions = { value: "All", label: t("All"), group: t("All") } + const defaultAll: AutocompleteOptions = { + value: "All", + label: t("All"), + group: t("All"), + }; const defaultInputs = useMemo( () => criteria.reduce>( (acc, c) => { - var tempCriteria = { + let tempCriteria = { ...acc, - [c.paramName]: (c.type === "select" || c.type === "select-labelled" || (c.type === "autocomplete" && !Boolean(c.multiple)) ? "All" - : (c.type === "autocomplete" && Boolean(c.multiple)) ? [defaultAll.value]: "") - } - + [c.paramName]: + c.type === "select" || + c.type === "select-labelled" || + (c.type === "autocomplete" && !Boolean(c.multiple)) + ? "All" + : c.type === "autocomplete" && Boolean(c.multiple) + ? [defaultAll.value] + : "", + }; + if (c.type === "dateRange") { tempCriteria = { ...tempCriteria, [c.paramName]: "", - [`${c.paramName}To`]: "" - } + [`${c.paramName}To`]: "", + }; } return tempCriteria; @@ -149,17 +165,26 @@ function SearchBox({ }; }, []); - const makeAutocompleteChangeHandler = useCallback((paramName: T, multiple: boolean) => { - return (e: SyntheticEvent, newValue: AutocompleteOptions | AutocompleteOptions[]) => { - if (multiple) { - const multiNewValue = newValue as AutocompleteOptions[]; - setInputs((i) => ({ ...i, [paramName]: multiNewValue.map(({ value }) => value) })); - } else { - const singleNewValue = newValue as AutocompleteOptions; - setInputs((i) => ({ ...i, [paramName]: singleNewValue.value })); - } - }; - }, []); + const makeAutocompleteChangeHandler = useCallback( + (paramName: T, multiple: boolean) => { + return ( + e: SyntheticEvent, + newValue: AutocompleteOptions | AutocompleteOptions[], + ) => { + if (multiple) { + const multiNewValue = newValue as AutocompleteOptions[]; + setInputs((i) => ({ + ...i, + [paramName]: multiNewValue.map(({ value }) => value), + })); + } else { + const singleNewValue = newValue as AutocompleteOptions; + setInputs((i) => ({ ...i, [paramName]: singleNewValue.value })); + } + }; + }, + [], + ); const makeDateChangeHandler = useCallback((paramName: T) => { return (e: any) => { @@ -221,7 +246,7 @@ function SearchBox({ > {t("All")} {c.options.map((option) => ( - + {option} ))} @@ -248,46 +273,72 @@ function SearchBox({ {c.type === "autocomplete" && ( option.group !== "All").length > 0 && c.options.every((option) => option.group) - ? (option) => (option.group && option.group.trim() !== '' ? option.group : 'Ungrouped') + c.options.filter((option) => option.group !== "All") + .length > 0 && c.options.every((option) => option.group) + ? (option) => + option.group && option.group.trim() !== "" + ? option.group + : "Ungrouped" : undefined } multiple={Boolean(c.multiple)} noOptionsText={c.noOptionsText ?? t("No options")} disableClearable fullWidth - value={c.multiple ? intersectionWith([defaultAll, ...c.options], inputs[c.paramName], (option, v) => { - return option.value === (v ?? "") - }) - : c.options.find((option) => option.value === inputs[c.paramName]) ?? defaultAll} - onChange={makeAutocompleteChangeHandler(c.paramName, Boolean(c.multiple))} + value={ + c.multiple + ? intersectionWith( + [defaultAll, ...c.options], + inputs[c.paramName], + (option, v) => { + return option.value === (v ?? ""); + }, + ) + : c.options.find( + (option) => option.value === inputs[c.paramName], + ) ?? defaultAll + } + onChange={makeAutocompleteChangeHandler( + c.paramName, + Boolean(c.multiple), + )} getOptionLabel={(option) => option.label} options={[defaultAll, ...c.options]} disableCloseOnSelect={Boolean(c.multiple)} - renderGroup={c.options.every((option) => option.group) ? (params) => ( - - {params.group} - {params.children} - - ) : undefined} + renderGroup={ + c.options.every((option) => option.group) + ? (params) => ( + + {params.group} + {params.children} + + ) + : undefined + } renderTags={ c.multiple ? (value, getTagProps) => - value.map((option, index) => { - // eslint-disable-next-line @typescript-eslint/no-unused-vars - const { key, ...chipProps } = getTagProps({ index }); - return ( - - ); - }) + value.map((option, index) => { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const { key, ...chipProps } = getTagProps({ + index, + }); + return ( + + ); + }) : undefined } renderOption={( - params: React.HTMLAttributes & { key?: React.Key }, + params: React.HTMLAttributes & { + key?: React.Key; + }, option, { selected }, ) => { @@ -312,7 +363,13 @@ function SearchBox({ ); }} - renderInput={(params) => } + renderInput={(params) => ( + + )} /> )} {c.type === "dateRange" && ( @@ -326,7 +383,11 @@ function SearchBox({ ({ diff --git a/src/components/SearchResults/EditableSearchResults.tsx b/src/components/SearchResults/EditableSearchResults.tsx index 0f211a8..2639902 100644 --- a/src/components/SearchResults/EditableSearchResults.tsx +++ b/src/components/SearchResults/EditableSearchResults.tsx @@ -21,293 +21,348 @@ import TempInputGridForMockUp from "./TempInputGridForMockUp"; import KeyboardArrowDownIcon from "@mui/icons-material/KeyboardArrowDown"; import KeyboardArrowUpIcon from "@mui/icons-material/KeyboardArrowUp"; import { decimalFormatter, integerFormatter } from "@/app/utils/formatUtil"; -import PlayCircleOutlineIcon from '@mui/icons-material/PlayCircleOutline'; +import PlayCircleOutlineIcon from "@mui/icons-material/PlayCircleOutline"; import { useTranslation } from "react-i18next"; import { RoughProdScheduleLineResultByFg } from "@/app/api/scheduling"; export interface ResultWithId { - id: string | number; + id: string | number; } interface BaseColumn { - field: keyof T; - label: string; - type: string; - options?: T[]; - renderCell?: (params: T) => React.ReactNode; - style?: Partial & { [propName: string]: string } & CSSProperties; - // style?: Partial & { [propName: string]: string }; + field: keyof T; + label: string; + type: string; + options?: T[]; + renderCell?: (params: T) => React.ReactNode; + style?: Partial & { + [propName: string]: string; + } & CSSProperties; + // style?: Partial & { [propName: string]: string }; } interface ColumnWithAction extends BaseColumn { - onClick: (item: T) => void; - buttonIcon: React.ReactNode; - buttonColor?: "inherit" | "default" | "primary" | "secondary"; + onClick: (item: T) => void; + buttonIcon: React.ReactNode; + buttonColor?: "inherit" | "default" | "primary" | "secondary"; } export type Column = - | BaseColumn - | ColumnWithAction; + | BaseColumn + | ColumnWithAction; interface Props { - items: T[], - columns: Column[], - noWrapper?: boolean, - setPagingController: (value: { pageNum: number; pageSize: number; totalCount: number, index?: number }) => void, - pagingController: { pageNum: number; pageSize: number; totalCount: number }, - isAutoPaging: boolean, - index: any, - isEdit: any, - isEditable: any, - hasCollapse: any, + items: T[]; + columns: Column[]; + noWrapper?: boolean; + setPagingController: (value: { + pageNum: number; + pageSize: number; + totalCount: number; + index?: number; + }) => void; + pagingController: { pageNum: number; pageSize: number; totalCount: number }; + isAutoPaging: boolean; + index: any; + isEdit: any; + isEditable: any; + hasCollapse: any; } function EditableSearchResults({ - index, - items, - columns, - noWrapper, - pagingController, - setPagingController, - isAutoPaging = true, - isEdit = false, - isEditable = true, - hasCollapse = false, + index, + items, + columns, + noWrapper, + pagingController, + setPagingController, + isAutoPaging = true, + isEdit = false, + isEditable = true, + hasCollapse = false, }: Props) { - const [page, setPage] = useState(0); - const [rowsPerPage, setRowsPerPage] = useState(10); - const [editingRowId, setEditingRowId] = useState(null); - const [editedItems, setEditedItems] = useState(items); - const { t } = useTranslation("project"); - console.log(items) - useEffect(() => { - setEditedItems(items) - }, [items]) - const handleChangePage = (_event: unknown, newPage: number) => { - setPage(newPage); - // setPagingController({ ...pagingController, pageNum: newPage + 1 }, (index ?? -1)); - }; + const [page, setPage] = useState(0); + const [rowsPerPage, setRowsPerPage] = useState(10); + const [editingRowId, setEditingRowId] = useState(null); + const [editedItems, setEditedItems] = useState(items); + const { t } = useTranslation("project"); + console.log(items); + useEffect(() => { + setEditedItems(items); + }, [items]); + const handleChangePage = (_event: unknown, newPage: number) => { + setPage(newPage); + // setPagingController({ ...pagingController, pageNum: newPage + 1 }, (index ?? -1)); + }; - const handleChangeRowsPerPage = (event: React.ChangeEvent) => { - setRowsPerPage(+event.target.value); - setPage(0); - setPagingController({ ...pagingController, pageSize: +event.target.value, pageNum: 1, index: index }); - }; + const handleChangeRowsPerPage = ( + event: React.ChangeEvent, + ) => { + setRowsPerPage(+event.target.value); + setPage(0); + setPagingController({ + ...pagingController, + pageSize: +event.target.value, + pageNum: 1, + index: index, + }); + }; - const handleEditClick = (id: number) => { - setEditingRowId(id); - }; + const handleEditClick = (id: number) => { + setEditingRowId(id); + }; - const handleSaveClick = (item: T) => { - setEditingRowId(null); - // Call API or any save logic here - setEditedItems((prev) => - prev.map((row) => (row.id === item.id ? { ...row } : row)) - ); - }; + const handleSaveClick = (item: T) => { + setEditingRowId(null); + // Call API or any save logic here + setEditedItems((prev) => + prev.map((row) => (row.id === item.id ? { ...row } : row)), + ); + }; - const handleInputChange = (id: number, field: keyof T, value: string | number[]) => { - setEditedItems((prev) => - prev.map((item) => - item.id === id ? { ...item, [field]: value } : item - ) - ); - }; + const handleInputChange = ( + id: number, + field: keyof T, + value: string | number[], + ) => { + setEditedItems((prev) => + prev.map((item) => (item.id === id ? { ...item, [field]: value } : item)), + ); + }; - const handleDeleteClick = (id: number) => { - // Implement delete logic here - setEditedItems((prev) => prev.filter(item => item.id !== id)); - }; + const handleDeleteClick = (id: number) => { + // Implement delete logic here + setEditedItems((prev) => prev.filter((item) => item.id !== id)); + }; - useEffect(() => { - console.log("[debug] isEdit in table", isEdit) - //TODO: switch all record to not in edit mode and save the changes - if (!isEdit) { - editedItems.forEach(item => { - // Call save logic here - console.log("Saving item:", item); - // Reset editing state if needed - }); + useEffect(() => { + console.log("[debug] isEdit in table", isEdit); + //TODO: switch all record to not in edit mode and save the changes + if (!isEdit) { + editedItems.forEach((item) => { + // Call save logic here + console.log("Saving item:", item); + // Reset editing state if needed + }); - setEditingRowId(null); - } - }, [isEdit]) + setEditingRowId(null); + } + }, [isEdit]); - function Row(props: { row: T }) { - const { row } = props; - const [open, setOpen] = useState(false); - console.log(row) - return ( - <> - - - - - - - { - (isEditable || hasCollapse) && - {(editingRowId === row.id) ? ( - <> - { - isEditable && handleSaveClick(row)}> - - - } - { - isEditable && setEditingRowId(null)}> - - - } - { - hasCollapse && setOpen(!open)} - > - {open ? : } - {t("View BoM")} - - } - - ) : ( - <> - { - isEditable && handleEditClick(row.id as number)}> - - - } - { - isEditable && handleDeleteClick(row.id as number)}> - - - } - { - hasCollapse && setOpen(!open)} - > - {open ? : } - {t("View BoM")} - - } - - )} - - } - {columns.map((column, idx) => { - const columnName = column.field; + function Row(props: { row: T }) { + const { row } = props; + const [open, setOpen] = useState(false); + console.log(row); + return ( + <> + + + + + + + {(isEditable || hasCollapse) && ( + + {editingRowId === row.id ? ( + <> + {isEditable && ( + handleSaveClick(row)} + > + + + )} + {isEditable && ( + setEditingRowId(null)} + > + + + )} + {hasCollapse && ( + setOpen(!open)} + > + {open ? ( + + ) : ( + + )} + {t("View BoM")} + + )} + + ) : ( + <> + {isEditable && ( + handleEditClick(row.id as number)} + > + + + )} + {isEditable && ( + handleDeleteClick(row.id as number)} + > + + + )} + {hasCollapse && ( + setOpen(!open)} + > + {open ? ( + + ) : ( + + )} + {t("View BoM")} + + )} + + )} + + )} + {columns.map((column, idx) => { + const columnName = column.field; + return ( + + {editingRowId === row.id ? ( + (() => { + switch (column.type) { + case "input": + console.log(column.type); return ( - - {editingRowId === row.id ? ( - (() => { - switch (column.type) { - case 'input': - console.log(column.type) - return ( - handleInputChange(row.id as number, columnName, e.target.value)} - /> - ); - // case 'multi-select': - // return ( - // handleInputChange(row.id as number, columnName, selectedValues)} - // /> - // ); - case 'read-only': - return ( - - {row[columnName] as string} - - ); - default: - return null; // Handle any default case if needed - } - })() - ) : ( - column.renderCell ? -
- {column.renderCell(row)} -
- : -
- isEdit && handleEditClick(row.id as number)}> - {row[columnName] as String} - -
- )} -
+ + handleInputChange( + row.id as number, + columnName, + e.target.value, + ) + } + /> ); - })} -
- - { - hasCollapse && - - - - - - - - - - -
-
-
+ // case 'multi-select': + // return ( + // handleInputChange(row.id as number, columnName, selectedValues)} + // /> + // ); + case "read-only": + return {row[columnName] as string}; + default: + return null; // Handle any default case if needed } -
- - ) - } - - const table = ( - <> - - - - - {t("Release")} - {(isEditable || hasCollapse) && {t("Actions")}} {/* Action Column Header */} - {columns.map((column, idx) => ( - - {column.label} - - ))} - - - - {(isAutoPaging ? editedItems.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage) : editedItems).map((item) => ( - - ))} - + })() + ) : column.renderCell ? ( +
{column.renderCell(row)}
+ ) : ( +
+ + isEdit && handleEditClick(row.id as number) + } + > + {row[columnName] as string} + +
+ )} + + ); + })} + + + {hasCollapse && ( + + +
+ + + + + + +
-
- - + + + )} +
+ ); + } + + const table = ( + <> + + + + + {t("Release")} + {(isEditable || hasCollapse) && ( + {t("Actions")} + )}{" "} + {/* Action Column Header */} + {columns.map((column, idx) => ( + + {column.label} + + ))} + + + + {(isAutoPaging + ? editedItems.slice( + page * rowsPerPage, + page * rowsPerPage + rowsPerPage, + ) + : editedItems + ).map((item) => ( + + ))} + +
+
+ + + ); - return noWrapper ? table : {table}; + return noWrapper ? table : {table}; } -export default EditableSearchResults; \ No newline at end of file +export default EditableSearchResults; diff --git a/src/components/SearchResults/SearchResults.tsx b/src/components/SearchResults/SearchResults.tsx index 05f3d70..1130e0b 100644 --- a/src/components/SearchResults/SearchResults.tsx +++ b/src/components/SearchResults/SearchResults.tsx @@ -1,6 +1,13 @@ "use client"; -import React, { ChangeEvent, Dispatch, MouseEvent, SetStateAction, useCallback, useState } from "react"; +import React, { + ChangeEvent, + Dispatch, + MouseEvent, + SetStateAction, + useCallback, + useState, +} from "react"; import Paper from "@mui/material/Paper"; import Table from "@mui/material/Table"; import TableBody from "@mui/material/TableBody"; @@ -83,60 +90,62 @@ interface Props { items: T[]; columns: Column[]; noWrapper?: boolean; - setPagingController?: Dispatch> - pagingController: { pageNum: number; pageSize: number; }; + setPagingController?: Dispatch< + SetStateAction<{ + pageNum: number; + pageSize: number; + }> + >; + pagingController?: { pageNum: number; pageSize: number }; isAutoPaging?: boolean; checkboxIds?: (string | number)[]; setCheckboxIds?: Dispatch>; } function isActionColumn( - column: Column + column: Column, ): column is ColumnWithAction { return Boolean((column as ColumnWithAction).onClick); } function isIconColumn( - column: Column + column: Column, ): column is IconColumn { return column.type === "icon"; } function isDecimalColumn( - column: Column + column: Column, ): column is DecimalColumn { return column.type === "decimal"; } function isIntegerColumn( - column: Column + column: Column, ): column is IntegerColumn { return column.type === "integer"; } function isCheckboxColumn( - column: Column + column: Column, ): column is CheckboxColumn { return column.type === "checkbox"; } // Icon Component Functions function convertObjectKeysToLowercase( - obj: T + obj: T, ): object | undefined { return obj ? Object.fromEntries( - Object.entries(obj).map(([key, value]) => [key.toLowerCase(), value]) - ) + Object.entries(obj).map(([key, value]) => [key.toLowerCase(), value]), + ) : undefined; } function handleIconColors( column: IconColumn, - value: T[keyof T] + value: T[keyof T], ): IconOwnProps["color"] { const colors = convertObjectKeysToLowercase(column.colors ?? {}); const valueKey = String(value).toLowerCase() as keyof typeof colors; @@ -150,7 +159,7 @@ function handleIconColors( function handleIconIcons( column: IconColumn, - value: T[keyof T] + value: T[keyof T], ): React.ReactNode { const icons = convertObjectKeysToLowercase(column.icons ?? {}); const valueKey = String(value).toLowerCase() as keyof typeof icons; @@ -162,9 +171,9 @@ function handleIconIcons( return column.icon ?? ; } export const defaultPagingController: { pageNum: number; pageSize: number } = { - "pageNum": 1, - "pageSize": 10, -} + pageNum: 1, + pageSize: 10, +}; function SearchResults({ items, columns, @@ -182,70 +191,73 @@ function SearchResults({ /// this const handleChangePage: TablePaginationProps["onPageChange"] = ( _event, - newPage + newPage, ) => { console.log(_event); setPage(newPage); if (setPagingController) { setPagingController({ - ...pagingController, + ...(pagingController ?? defaultPagingController), pageNum: newPage + 1, }); } }; const handleChangeRowsPerPage: TablePaginationProps["onRowsPerPageChange"] = ( - event + event, ) => { console.log(event); setRowsPerPage(+event.target.value); setPage(0); if (setPagingController) { setPagingController({ - ...pagingController, + ...(pagingController ?? defaultPagingController), pageNum: 1, }); } }; // checkbox - const handleRowClick = useCallback((event: MouseEvent, item: T, columns: Column[]) => { - // check is disabled or not - var disabled = false - columns.forEach((col) => { - if (isCheckboxColumn(col) && col.disabled) { - disabled = col.disabled(item) - if (disabled) { - return; + const handleRowClick = useCallback( + (event: MouseEvent, item: T, columns: Column[]) => { + // check is disabled or not + let disabled = false; + columns.forEach((col) => { + if (isCheckboxColumn(col) && col.disabled) { + disabled = col.disabled(item); + if (disabled) { + return; + } } - } - }) + }); - if (disabled) { - return; - } + if (disabled) { + return; + } - // set id - const id = item.id - if (setCheckboxIds) { - const selectedIndex = checkboxIds.indexOf(id); - let newSelected: (string | number)[] = []; - - if (selectedIndex === -1) { - newSelected = newSelected.concat(checkboxIds, id); - } else if (selectedIndex === 0) { - newSelected = newSelected.concat(checkboxIds.slice(1)); - } else if (selectedIndex === checkboxIds.length - 1) { - newSelected = newSelected.concat(checkboxIds.slice(0, -1)); - } else if (selectedIndex > 0) { - newSelected = newSelected.concat( - checkboxIds.slice(0, selectedIndex), - checkboxIds.slice(selectedIndex + 1), - ); + // set id + const id = item.id; + if (setCheckboxIds) { + const selectedIndex = checkboxIds.indexOf(id); + let newSelected: (string | number)[] = []; + + if (selectedIndex === -1) { + newSelected = newSelected.concat(checkboxIds, id); + } else if (selectedIndex === 0) { + newSelected = newSelected.concat(checkboxIds.slice(1)); + } else if (selectedIndex === checkboxIds.length - 1) { + newSelected = newSelected.concat(checkboxIds.slice(0, -1)); + } else if (selectedIndex > 0) { + newSelected = newSelected.concat( + checkboxIds.slice(0, selectedIndex), + checkboxIds.slice(selectedIndex + 1), + ); + } + setCheckboxIds(newSelected); } - setCheckboxIds(newSelected); - } - }, [checkboxIds]) + }, + [checkboxIds], + ); const table = ( <> @@ -267,16 +279,40 @@ function SearchResults({ {isAutoPaging ? items - .slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage) - .map((item) => { + .slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage) + .map((item) => { + return ( + handleRowClick(event, item, columns) + : undefined + } + role={setCheckboxIds ? "checkbox" : undefined} + > + {columns.map((column, idx) => { + const columnName = column.name; + + return ( + + ); + })} + + ); + }) + : items.map((item) => { return ( - handleRowClick(event, item, columns) : undefined} - role={setCheckboxIds ? "checkbox" : undefined} - > + {columns.map((column, idx) => { const columnName = column.name; @@ -293,37 +329,14 @@ function SearchResults({ })} ); - }) - : items.map((item) => { - return ( - - {columns.map((column, idx) => { - const columnName = column.name; - - return ( - - ); - })} - - ); - })} + })}
({ ) : isIntegerColumn(column) ? ( <>{integerFormatter.format(Number(item[columnName]))} ) : isCheckboxColumn(column) ? ( - + ) : column.renderCell ? ( column.renderCell(item) ) : ( diff --git a/src/components/SearchResults/TempInputGridForMockUp.tsx b/src/components/SearchResults/TempInputGridForMockUp.tsx index dc53233..6c0843d 100644 --- a/src/components/SearchResults/TempInputGridForMockUp.tsx +++ b/src/components/SearchResults/TempInputGridForMockUp.tsx @@ -36,7 +36,7 @@ import PlayArrowIcon from "@mui/icons-material/PlayArrow"; import { createStockInLine, testFetch } from "@/app/api/po/actions"; import { useSearchParams } from "next/navigation"; import { decimalFormatter, stockInLineStatusMap } from "@/app/utils/formatUtil"; -import CheckCircleOutlineIcon from '@mui/icons-material/CheckCircleOutline'; +import CheckCircleOutlineIcon from "@mui/icons-material/CheckCircleOutline"; interface ResultWithId { id: number; @@ -64,7 +64,11 @@ export type StockInLineRow = Partial< class ProcessRowUpdateError extends Error { public readonly row: StockInLineRow; public readonly errors: StockInLineEntryError | undefined; - constructor(row: StockInLineRow, message?: string, errors?: StockInLineEntryError) { + constructor( + row: StockInLineRow, + message?: string, + errors?: StockInLineEntryError, + ) { super(message); this.row = row; this.errors = errors; @@ -79,24 +83,24 @@ function TempInputGridForMockUp({ stockInLine }: Props) { const [rowModesModel, setRowModesModel] = useState({}); const getRowId = useCallback>( (row) => row.id as number, - [] + [], ); console.log(stockInLine); const [entries, setEntries] = useState(stockInLine || []); - const [modalInfo, setModalInfo] = useState() + const [modalInfo, setModalInfo] = useState(); const [qcOpen, setQcOpen] = useState(false); // const [defaultQty, setDefaultQty] = useState(() => { // const total = entries.reduce((acc, curr) => acc + (curr.acceptedQty || 0), 0); // return itemDetail.qty - total; // }); - const params = useSearchParams() + const params = useSearchParams(); const handleDelete = useCallback( (id: GridRowId) => () => { setEntries((es) => es.filter((e) => getRowId(e) !== id)); }, - [getRowId] + [getRowId], ); const handleStart = useCallback( (id: GridRowId, params: any) => () => { @@ -108,8 +112,8 @@ function TempInputGridForMockUp({ stockInLine }: Props) { // post stock in line console.log("delayed"); console.log(params); - const oldId = params.row.id - console.log(oldId) + const oldId = params.row.id; + console.log(oldId); const postData = { itemId: params.row.itemId, itemNo: params.row.itemNo, @@ -117,15 +121,15 @@ function TempInputGridForMockUp({ stockInLine }: Props) { purchaseOrderId: params.row.purchaseOrderId, purchaseOrderLineId: params.row.purchaseOrderLineId, acceptedQty: params.row.acceptedQty, - } - const res = await createStockInLine(postData) - console.log(res) + }; + const res = await createStockInLine(postData); + console.log(res); // setEntries((prev) => prev.map((p) => p.id === oldId ? res.entity : p)) // do post directly to test // openStartModal(); }, 200); }, - [] + [], ); const handleQC = useCallback( (id: GridRowId, params: any) => () => { @@ -133,14 +137,14 @@ function TempInputGridForMockUp({ stockInLine }: Props) { ...prev, [id]: { mode: GridRowModes.View }, })); - setModalInfo(params.row) + setModalInfo(params.row); setTimeout(() => { // open qc modal console.log("delayed"); openQcModal(); }, 200); }, - [] + [], ); const handleStockIn = useCallback( (id: GridRowId) => () => { @@ -155,7 +159,7 @@ function TempInputGridForMockUp({ stockInLine }: Props) { console.log("delayed"); }, 200); }, - [] + [], ); const closeQcModal = useCallback(() => { @@ -191,8 +195,8 @@ function TempInputGridForMockUp({ stockInLine }: Props) { align: "right", headerAlign: "right", renderCell: (row) => { - return decimalFormatter.format(row.value) - } + return decimalFormatter.format(row.value); + }, // replace with tooltip + content }, { @@ -203,8 +207,8 @@ function TempInputGridForMockUp({ stockInLine }: Props) { align: "right", headerAlign: "right", renderCell: (row) => { - return decimalFormatter.format(row.value) - } + return decimalFormatter.format(row.value); + }, }, { field: "status", @@ -214,11 +218,8 @@ function TempInputGridForMockUp({ stockInLine }: Props) { align: "center", headerAlign: "center", renderCell: () => { - return - } + return ; + }, }, // { // field: "actions", @@ -295,7 +296,7 @@ function TempInputGridForMockUp({ stockInLine }: Props) { // }, // }, ], - [] + [], ); // const addRow = useCallback(() => { @@ -321,7 +322,7 @@ function TempInputGridForMockUp({ stockInLine }: Props) { // }, [getRowId]); const validation = useCallback( ( - newRow: GridRowModel + newRow: GridRowModel, // rowModel: GridRowSelectionModel ): StockInLineEntryError | undefined => { const error: StockInLineEntryError = {}; @@ -331,16 +332,19 @@ function TempInputGridForMockUp({ stockInLine }: Props) { // } return Object.keys(error).length > 0 ? error : undefined; }, - [] + [], ); const processRowUpdate = useCallback( - (newRow: GridRowModel, originalRow: GridRowModel) => { + ( + newRow: GridRowModel, + originalRow: GridRowModel, + ) => { const errors = validation(newRow); // change to validation if (errors) { throw new ProcessRowUpdateError( originalRow, "validation error", - errors + errors, ); } const { _isNew, _error, ...updatedRow } = newRow; @@ -348,15 +352,18 @@ function TempInputGridForMockUp({ stockInLine }: Props) { ...updatedRow, } satisfies StockInLineRow; const newEntries = entries.map((e) => - getRowId(e) === getRowId(originalRow) ? rowToSave : e + getRowId(e) === getRowId(originalRow) ? rowToSave : e, ); setEntries(newEntries); //update remaining qty - const total = newEntries.reduce((acc, curr) => acc + (curr.acceptedQty || 0), 0); + const total = newEntries.reduce( + (acc, curr) => acc + (curr.acceptedQty || 0), + 0, + ); // setDefaultQty(itemDetail.qty - total); return rowToSave; }, - [getRowId, entries] + [getRowId, entries], ); const onProcessRowUpdateError = useCallback( @@ -366,7 +373,7 @@ function TempInputGridForMockUp({ stockInLine }: Props) { apiRef.current.updateRows([{ ...oldRow, _error: errors }]); }, - [apiRef] + [apiRef], ); // useEffect(() => { @@ -420,13 +427,13 @@ function TempInputGridForMockUp({ stockInLine }: Props) { } return classname; }} - // slots={{ - // footer: FooterToolbar, - // noRowsOverlay: NoRowsOverlay, - // }} - // slotProps={{ - // footer: { child: footer }, - // }} + // slots={{ + // footer: FooterToolbar, + // noRowsOverlay: NoRowsOverlay, + // }} + // slotProps={{ + // footer: { child: footer }, + // }} /> ); diff --git a/src/components/SessionProviderWrapper/SessionProviderWrapper.tsx b/src/components/SessionProviderWrapper/SessionProviderWrapper.tsx index c6b92d6..20be3d7 100644 --- a/src/components/SessionProviderWrapper/SessionProviderWrapper.tsx +++ b/src/components/SessionProviderWrapper/SessionProviderWrapper.tsx @@ -3,6 +3,12 @@ import { SessionProvider } from "next-auth/react"; import { ReactNode } from "react"; -export default function SessionProviderWrapper({ children, session }: { children: ReactNode, session?: any }) { +export default function SessionProviderWrapper({ + children, + session, +}: { + children: ReactNode; + session?: any; +}) { return {children}; -} \ No newline at end of file +} diff --git a/src/components/Swal/CustomAlerts.tsx b/src/components/Swal/CustomAlerts.tsx index 1bffca8..8bf6c2e 100644 --- a/src/components/Swal/CustomAlerts.tsx +++ b/src/components/Swal/CustomAlerts.tsx @@ -2,11 +2,11 @@ import Swal, { SweetAlertOptions } from "sweetalert2"; import "./sweetalert2.css"; import { TFunction } from "i18next"; -export type SweetAlertTitle = string | HTMLElement | JQuery | undefined -export type SweetAlertHtml = string | HTMLElement | JQuery | undefined -export type SweetAlertConfirmButtonText = string | undefined +export type SweetAlertTitle = string | HTMLElement | JQuery | undefined; +export type SweetAlertHtml = string | HTMLElement | JQuery | undefined; +export type SweetAlertConfirmButtonText = string | undefined; -type Transaction = TFunction<["translation", ...string[]], undefined> +type Transaction = TFunction<["translation", ...string[]], undefined>; export const msg = (title: SweetAlertTitle) => { Swal.mixin({ @@ -29,7 +29,11 @@ export const popup = (options: SweetAlertOptions) => { Swal.fire(options); }; -export const successDialog = async (title: SweetAlertTitle, t: Transaction, confirmAction?: () => void) => { +export const successDialog = async ( + title: SweetAlertTitle, + t: Transaction, + confirmAction?: () => void, +) => { const result = await Swal.fire({ icon: "success", title: title, @@ -42,7 +46,11 @@ export const successDialog = async (title: SweetAlertTitle, t: Transaction, conf } }; -export const successDialogWithContent = (title: SweetAlertTitle, html: SweetAlertHtml, t: Transaction) => { +export const successDialogWithContent = ( + title: SweetAlertTitle, + html: SweetAlertHtml, + t: Transaction, +) => { return Swal.fire({ icon: "success", title: title, @@ -61,7 +69,11 @@ export const errorDialog = (title: SweetAlertTitle, t: Transaction) => { }); }; -export const errorDialogWithContent = (title: SweetAlertTitle, html: SweetAlertHtml, t: Transaction) => { +export const errorDialogWithContent = ( + title: SweetAlertTitle, + html: SweetAlertHtml, + t: Transaction, +) => { return Swal.fire({ icon: "error", title: title, @@ -86,7 +98,7 @@ export const submitDialog = async ( { ...props } = { title: t("Do you want to submit?") as SweetAlertTitle, confirmButtonText: t("Submit") as SweetAlertConfirmButtonText, - } + }, ) => { // console.log(props) // const { t } = useTranslation("common") @@ -114,7 +126,7 @@ export const submitDialogWithWarning = async ( title: t("Do you want to submit?") as SweetAlertTitle, html: t("Warning!") as SweetAlertHtml, confirmButtonText: t("Submit") as SweetAlertConfirmButtonText, - } + }, ) => { // console.log(props) // const { t } = useTranslation("common") @@ -136,7 +148,10 @@ export const submitDialogWithWarning = async ( } }; -export const deleteDialog = async (confirmAction: () => void, t: Transaction) => { +export const deleteDialog = async ( + confirmAction: () => void, + t: Transaction, +) => { // const { t } = useTranslation("common") const result = await Swal.fire({ icon: "question", diff --git a/src/components/UploadProvider/UploadProvider.tsx b/src/components/UploadProvider/UploadProvider.tsx index e34c520..b32884e 100644 --- a/src/components/UploadProvider/UploadProvider.tsx +++ b/src/components/UploadProvider/UploadProvider.tsx @@ -1,52 +1,55 @@ "use client"; -import React, { createContext, useState } from 'react'; -import {CircularProgress} from "@mui/material"; +import React, { createContext, useState } from "react"; +import { CircularProgress } from "@mui/material"; -const UploadContext = createContext<{ - isUploading: boolean, - setIsUploading: React.Dispatch> -} | undefined>(undefined); +const UploadContext = createContext< + | { + isUploading: boolean; + setIsUploading: React.Dispatch>; + } + | undefined +>(undefined); export const UploadProvider: React.FC<{ children: React.ReactNode }> = ({ - children, - }) => { - const [isUploading, setIsUploading] = useState(false); + children, +}) => { + const [isUploading, setIsUploading] = useState(false); - return ( - - {children} - {isUploading && ( -
-
- -
-
- )} -
- ); + return ( + + {children} + {isUploading && ( +
+
+ +
+
+ )} +
+ ); }; -export default UploadContext; \ No newline at end of file +export default UploadContext; diff --git a/src/components/UploadProvider/useUploadContext.tsx b/src/components/UploadProvider/useUploadContext.tsx index 508f3ca..53961e5 100644 --- a/src/components/UploadProvider/useUploadContext.tsx +++ b/src/components/UploadProvider/useUploadContext.tsx @@ -1,15 +1,13 @@ - -"use client" -import { useContext } from 'react'; -import UploadContext from './UploadProvider'; - +"use client"; +import { useContext } from "react"; +import UploadContext from "./UploadProvider"; const useUploadContext = () => { - const context = useContext(UploadContext); - if (!context) { - throw new Error('useUploadContext must be used within an UploadProvider'); - } - return context; + const context = useContext(UploadContext); + if (!context) { + throw new Error("useUploadContext must be used within an UploadProvider"); + } + return context; }; -export default useUploadContext; \ No newline at end of file +export default useUploadContext; diff --git a/src/components/UserSearch/UserSearch.tsx b/src/components/UserSearch/UserSearch.tsx index b437900..43cb6b0 100644 --- a/src/components/UserSearch/UserSearch.tsx +++ b/src/components/UserSearch/UserSearch.tsx @@ -32,15 +32,15 @@ const UserSearch: React.FC = ({ users }) => { type: "text", }, ], - [t] + [t], ); const onUserClick = useCallback( (users: UserResult) => { console.log(users); - router.push(`/settings/user/edit?id=${users.id}`) + router.push(`/settings/user/edit?id=${users.id}`); }, - [router, t] + [router, t], ); const onDeleteClick = useCallback((users: UserResult) => { @@ -64,10 +64,10 @@ const UserSearch: React.FC = ({ users }) => { label: t("Delete"), onClick: onDeleteClick, buttonIcon: , - color: "error" + color: "error", }, ], - [t] + [t], ); return ( @@ -75,17 +75,21 @@ const UserSearch: React.FC = ({ users }) => { { - // setFilteredUser( - // users.filter( - // (t) => - // t.name.toLowerCase().includes(query.name.toLowerCase()) && - // t.code.toLowerCase().includes(query.code.toLowerCase()) && - // t.description.toLowerCase().includes(query.description.toLowerCase()) - // ) - // ) + // setFilteredUser( + // users.filter( + // (t) => + // t.name.toLowerCase().includes(query.name.toLowerCase()) && + // t.code.toLowerCase().includes(query.code.toLowerCase()) && + // t.description.toLowerCase().includes(query.description.toLowerCase()) + // ) + // ) }} /> - items={filteredUser} columns={columns} pagingController={{ pageNum: 1, pageSize: 10, totalCount: 100 }}/> + + items={filteredUser} + columns={columns} + pagingController={{ pageNum: 1, pageSize: 10, totalCount: 100 }} + /> ); }; diff --git a/src/components/UserSearch/UserSearchWrapper.tsx b/src/components/UserSearch/UserSearchWrapper.tsx index beaef92..875f6e0 100644 --- a/src/components/UserSearch/UserSearchWrapper.tsx +++ b/src/components/UserSearch/UserSearchWrapper.tsx @@ -8,7 +8,7 @@ interface SubComponents { } const UserSearchWrapper: React.FC & SubComponents = async () => { -const users = await fetchUser() + const users = await fetchUser(); console.log(users); return ; diff --git a/src/config/api.ts b/src/config/api.ts index 7eb5caa..e9a8c27 100644 --- a/src/config/api.ts +++ b/src/config/api.ts @@ -1,3 +1,3 @@ export const BASE_API_URL = `${process.env.API_URL}`; export const LOGIN_API_PATH = `${BASE_API_URL}/login`; -export const NEXT_PUBLIC_API_URL= `${process.env.NEXT_PUBLIC_API_URL}`; \ No newline at end of file +export const NEXT_PUBLIC_API_URL = `${process.env.NEXT_PUBLIC_API_URL}`; diff --git a/src/config/authConfig.ts b/src/config/authConfig.ts index 90010d6..37912a1 100644 --- a/src/config/authConfig.ts +++ b/src/config/authConfig.ts @@ -6,10 +6,9 @@ export interface SessionWithTokens extends Session { accessToken: string | null; refreshToken?: string; abilities: string[]; - id?: string | null + id?: string | null; } - export const authOptions: AuthOptions = { debug: process.env.NODE_ENV === "development", providers: [ @@ -53,7 +52,7 @@ export const authOptions: AuthOptions = { id: token.id as string | undefined, accessToken: token.accessToken as string | null, refreshToken: token.refreshToken as string | undefined, - abilities: token.abilities as string[] + abilities: token.abilities as string[], }; if (sessionWithToken.user) { sessionWithToken.user.abilities = token.abilities as string[]; diff --git a/src/middleware.ts b/src/middleware.ts index c7a6f42..5bfb8cd 100644 --- a/src/middleware.ts +++ b/src/middleware.ts @@ -11,17 +11,17 @@ const authMiddleware = withAuth({ callbacks: { authorized: ({ req, token }) => { if (!Boolean(token)) { - return Boolean(token) + return Boolean(token); } - + // example // const abilities = token!.abilities as string[] // if (req.nextUrl.pathname.endsWith('/user') && 'abilities dont hv view/maintain user') { // return false // } - return true - } - } + return true; + }, + }, }); export default async function middleware( @@ -42,4 +42,4 @@ export default async function middleware( return PRIVATE_ROUTES.some((route) => req.nextUrl.pathname.startsWith(route)) ? await authMiddleware(req, event) // Let auth middleware handle response : NextResponse.next(); // Return normal response -} \ No newline at end of file +} diff --git a/src/routes.ts b/src/routes.ts index 4495441..0c58071 100644 --- a/src/routes.ts +++ b/src/routes.ts @@ -1,10 +1,10 @@ export const PRIVATE_ROUTES = [ - "/analytics", - "/dashboard", - "/dashboard", - "/invoice", - "/projects", - "/tasks", - "/settings", - "/material", - ]; \ No newline at end of file + "/analytics", + "/dashboard", + "/dashboard", + "/invoice", + "/projects", + "/tasks", + "/settings", + "/material", +]; diff --git a/src/theme/ThemeRegistry.tsx b/src/theme/ThemeRegistry.tsx index 081ca48..e2628bf 100644 --- a/src/theme/ThemeRegistry.tsx +++ b/src/theme/ThemeRegistry.tsx @@ -6,7 +6,6 @@ import NextAppDirEmotionCacheProvider from "./EmotionCache"; import theme from "./devias-material-kit"; import { zhHK, enUS } from "@mui/material/locale"; - const getLocalizationFromLang = (lang: string) => { switch (lang) { case "zh": diff --git a/tailwind.config.js b/tailwind.config.js index a73bb7e..d8b4566 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -4,7 +4,7 @@ module.exports = { "./app/**/*.{js,ts,jsx,tsx,mdx}", "./pages/**/*.{js,ts,jsx,tsx,mdx}", "./components/**/*.{js,ts,jsx,tsx,mdx}", - + // Or if using `src` directory: "./src/**/*.{js,ts,jsx,tsx,mdx}", ], @@ -12,5 +12,4 @@ module.exports = { extend: {}, }, plugins: [], -} - +}; diff --git a/tsconfig.json b/tsconfig.json index a0dd41e..9ca15fe 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -19,7 +19,7 @@ } ], "paths": { - "@/*": ["/src/*", "./src/*", ] + "@/*": ["/src/*", "./src/*", "./src/app/*"] }, "baseUrl": "." }, diff --git a/types/next-auth.d.ts b/types/next-auth.d.ts index c0d27ea..24982c9 100644 --- a/types/next-auth.d.ts +++ b/types/next-auth.d.ts @@ -11,4 +11,4 @@ declare module "next-auth" { }; expires: ISODateString; } -} \ No newline at end of file +}