| @@ -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 = { | |||
| @@ -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", | |||
| @@ -3,4 +3,4 @@ module.exports = { | |||
| tailwindcss: {}, | |||
| autoprefixer: {}, | |||
| }, | |||
| } | |||
| }; | |||
| @@ -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<string | null>(localStorage.getItem("accessToken")); | |||
| export const AxiosProvider: React.FC<{ children: React.ReactNode }> = ({ | |||
| children, | |||
| }) => { | |||
| const [accessToken, setAccessToken] = useState<string | null>( | |||
| 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 ( | |||
| <AxiosContext.Provider value={axiosInstance}> | |||
| <TokenContext.Provider value={{ setAccessToken }}> | |||
| {children} | |||
| </TokenContext.Provider> | |||
| </AxiosContext.Provider> | |||
| ); | |||
| return ( | |||
| <AxiosContext.Provider value={axiosInstance}> | |||
| <TokenContext.Provider value={{ setAccessToken }}> | |||
| {children} | |||
| </TokenContext.Provider> | |||
| </AxiosContext.Provider> | |||
| ); | |||
| }; | |||
| // 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); | |||
| }; | |||
| return useContext(TokenContext); | |||
| }; | |||
| @@ -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; | |||
| export default axiosInstance; | |||
| @@ -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<Props> = async ({ | |||
| searchParams | |||
| }) => { | |||
| const Dashboard: React.FC<Props> = async ({ searchParams }) => { | |||
| const { t } = await getServerI18n("dashboard"); | |||
| return ( | |||
| <I18nProvider namespaces={["dashboard", "common"]}> | |||
| <Suspense fallback={<DashboardPage.Loading />}> | |||
| <DashboardPage | |||
| searchParams={searchParams} | |||
| /> | |||
| <DashboardPage searchParams={searchParams} /> | |||
| </Suspense> | |||
| </I18nProvider> | |||
| ) | |||
| ); | |||
| }; | |||
| export default Dashboard; | |||
| @@ -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 ( | |||
| <> | |||
| <Stack | |||
| direction="row" | |||
| justifyContent={"space-between"} | |||
| flexWrap={"wrap"} | |||
| rowGap={2} | |||
| > | |||
| </Stack> | |||
| return ( | |||
| <> | |||
| <Stack | |||
| direction="row" | |||
| justifyContent={"space-between"} | |||
| flexWrap={"wrap"} | |||
| rowGap={2} | |||
| ></Stack> | |||
| <I18nProvider namespaces={["do", "common"]}> | |||
| <Suspense fallback={<DoSearch.Loading />}> | |||
| <DoSearch /> | |||
| </Suspense> | |||
| </I18nProvider> | |||
| </> | |||
| ) | |||
| } | |||
| <I18nProvider namespaces={["do", "common"]}> | |||
| <Suspense fallback={<DoSearch.Loading />}> | |||
| <DoSearch /> | |||
| </Suspense> | |||
| </I18nProvider> | |||
| </> | |||
| ); | |||
| }; | |||
| export default DeliveryOrder; | |||
| export default DeliveryOrder; | |||
| @@ -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 <> | |||
| <Stack | |||
| direction="row" | |||
| justifyContent={"space-between"} | |||
| flexWrap={"wrap"} | |||
| rowGap={2} | |||
| > | |||
| <Typography variant="h4" marginInlineEnd={2}> | |||
| {t("Inventory")} | |||
| </Typography> | |||
| </Stack> | |||
| <I18nProvider namespaces={["common", "inventory"]}> | |||
| <Suspense fallback={<InventorySearch.Loading />}> | |||
| <InventorySearch /> | |||
| </Suspense> | |||
| </I18nProvider> | |||
| </>; | |||
| } | |||
| return ( | |||
| <> | |||
| <Stack | |||
| direction="row" | |||
| justifyContent={"space-between"} | |||
| flexWrap={"wrap"} | |||
| rowGap={2} | |||
| > | |||
| <Typography variant="h4" marginInlineEnd={2}> | |||
| {t("Inventory")} | |||
| </Typography> | |||
| </Stack> | |||
| <I18nProvider namespaces={["common", "inventory"]}> | |||
| <Suspense fallback={<InventorySearch.Loading />}> | |||
| <InventorySearch /> | |||
| </Suspense> | |||
| </I18nProvider> | |||
| </> | |||
| ); | |||
| }; | |||
| export default Inventory; | |||
| export default Inventory; | |||
| @@ -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, SessionWithTokens>(authOptions); | |||
| const session = await getServerSession<AuthOptions, SessionWithTokens>( | |||
| authOptions, | |||
| ); | |||
| if (!session?.user) { | |||
| redirect("/login"); | |||
| @@ -36,33 +36,33 @@ export default async function MainLayout({ | |||
| return ( | |||
| <SessionProviderWrapper session={session}> | |||
| <UploadProvider> | |||
| <CameraProvider> | |||
| <AxiosProvider> | |||
| <QrCodeScannerProvider> | |||
| <> | |||
| <AppBar | |||
| profileName={session.user.name!} | |||
| avatarImageSrc={session.user.image || undefined} | |||
| /> | |||
| <Box | |||
| component="main" | |||
| sx={{ | |||
| marginInlineStart: { xs: 0, xl: NAVIGATION_CONTENT_WIDTH }, | |||
| padding: { xs: "1rem", sm: "1.5rem", lg: "3rem" }, | |||
| }} | |||
| > | |||
| <Stack spacing={2}> | |||
| <I18nProvider namespaces={["common"]}> | |||
| <Breadcrumb /> | |||
| {children} | |||
| </I18nProvider> | |||
| </Stack> | |||
| </Box> | |||
| </> | |||
| </QrCodeScannerProvider> | |||
| </AxiosProvider> | |||
| </CameraProvider> | |||
| <UploadProvider> | |||
| <CameraProvider> | |||
| <AxiosProvider> | |||
| <QrCodeScannerProvider> | |||
| <> | |||
| <AppBar | |||
| profileName={session.user.name!} | |||
| avatarImageSrc={session.user.image || undefined} | |||
| /> | |||
| <Box | |||
| component="main" | |||
| sx={{ | |||
| marginInlineStart: { xs: 0, xl: NAVIGATION_CONTENT_WIDTH }, | |||
| padding: { xs: "1rem", sm: "1.5rem", lg: "3rem" }, | |||
| }} | |||
| > | |||
| <Stack spacing={2}> | |||
| <I18nProvider namespaces={["common"]}> | |||
| <Breadcrumb /> | |||
| {children} | |||
| </I18nProvider> | |||
| </Stack> | |||
| </Box> | |||
| </> | |||
| </QrCodeScannerProvider> | |||
| </AxiosProvider> | |||
| </CameraProvider> | |||
| </UploadProvider> | |||
| </SessionProviderWrapper> | |||
| ); | |||
| @@ -11,13 +11,11 @@ export const metadata: Metadata = { | |||
| title: "Material Setting", | |||
| }; | |||
| type Props = { | |||
| } & SearchParams | |||
| type Props = {} & SearchParams; | |||
| const material: React.FC<Props> = async ({ searchParams }) => { | |||
| const { t } = await getServerI18n("material"); | |||
| console.log(searchParams) | |||
| console.log(searchParams); | |||
| return ( | |||
| <> | |||
| <Stack | |||
| @@ -37,7 +35,6 @@ const material: React.FC<Props> = async ({ searchParams }) => { | |||
| > | |||
| {t("Create Claim")} | |||
| </Button> | |||
| </Stack> | |||
| {/* <Suspense fallback={<MaterialSearch.Loading />}> | |||
| <MaterialSearch /> | |||
| @@ -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<Props> = async ({ searchParams }) => { | |||
| <> | |||
| <I18nProvider namespaces={["pickOrder"]}> | |||
| <Suspense fallback={<PickOrderDetail.Loading />}> | |||
| <PickOrderDetail consoCode={`${searchParams["consoCode"]}`}/> | |||
| <PickOrderDetail consoCode={`${searchParams["consoCode"]}`} /> | |||
| </Suspense> | |||
| </I18nProvider> | |||
| </> | |||
| @@ -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 ( | |||
| <> | |||
| <Stack | |||
| direction={"row"} | |||
| justifyContent={"space-between"} | |||
| flexWrap={"wrap"} | |||
| rowGap={2} | |||
| > | |||
| <Typography variant="h4" marginInlineEnd={2}> | |||
| {t("Pick Order")} | |||
| </Typography> | |||
| </Stack> | |||
| <I18nProvider namespaces={["pickOrder", "common"]}> | |||
| <Suspense fallback={<PickOrderSearch.Loading />}> | |||
| <PickOrderSearch /> | |||
| </Suspense> | |||
| </I18nProvider> | |||
| </> | |||
| ) | |||
| } | |||
| return ( | |||
| <> | |||
| <Stack | |||
| direction={"row"} | |||
| justifyContent={"space-between"} | |||
| flexWrap={"wrap"} | |||
| rowGap={2} | |||
| > | |||
| <Typography variant="h4" marginInlineEnd={2}> | |||
| {t("Pick Order")} | |||
| </Typography> | |||
| </Stack> | |||
| <I18nProvider namespaces={["pickOrder", "common"]}> | |||
| <Suspense fallback={<PickOrderSearch.Loading />}> | |||
| <PickOrderSearch /> | |||
| </Suspense> | |||
| </I18nProvider> | |||
| </> | |||
| ); | |||
| }; | |||
| export default PickOrder; | |||
| export default PickOrder; | |||
| @@ -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"; | |||
| @@ -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} | |||
| > | |||
| </Stack> | |||
| <Suspense fallback={<PoSearch.Loading />}> | |||
| <PoSearch /> | |||
| </Suspense> | |||
| ></Stack> | |||
| <Suspense fallback={<PoSearch.Loading />}> | |||
| <PoSearch /> | |||
| </Suspense> | |||
| </I18nProvider> | |||
| </> | |||
| ); | |||
| @@ -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")} | |||
| </Button> | |||
| </Stack> | |||
| <Suspense fallback={<ClaimSearch.Loading />}> | |||
| <ProductionProcess /> | |||
| </Suspense> | |||
| {/* <Suspense fallback={<ClaimSearch.Loading />}> */} | |||
| <ProductionProcess /> | |||
| {/* </Suspense> */} | |||
| </> | |||
| ); | |||
| }; | |||
| @@ -8,7 +8,9 @@ export default async function NotFound() { | |||
| return ( | |||
| <Stack spacing={2}> | |||
| <Typography variant="h4">{t("Not Found")}</Typography> | |||
| <Typography variant="body1">{t("The edit detail scheduling page was not found!")}</Typography> | |||
| <Typography variant="body1"> | |||
| {t("The edit detail scheduling page was not found!")} | |||
| </Typography> | |||
| <Link href="/scheduling/detail" component={NextLink} variant="body2"> | |||
| {t("Return to all detail scheduling")} | |||
| </Link> | |||
| @@ -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<Props> = 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 <> | |||
| <Typography variant="h4" marginInlineEnd={2}> | |||
| {t("FG Production Schedule")} | |||
| </Typography> | |||
| <I18nProvider namespaces={["schedule", "common", "project"]}> | |||
| <DetailScheduleDetail id={id}/> | |||
| </I18nProvider> | |||
| </>; | |||
| 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 ( | |||
| <> | |||
| <Typography variant="h4" marginInlineEnd={2}> | |||
| {t("FG Production Schedule")} | |||
| </Typography> | |||
| <I18nProvider namespaces={["schedule", "common", "project"]}> | |||
| <DetailScheduleDetail id={id} /> | |||
| </I18nProvider> | |||
| </> | |||
| ); | |||
| }; | |||
| export default DetailScheduling; | |||
| export default DetailScheduling; | |||
| @@ -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 ( | |||
| <> | |||
| <Stack | |||
| direction="row" | |||
| justifyContent="space-between" | |||
| flexWrap="wrap" | |||
| rowGap={2} | |||
| > | |||
| <Typography variant="h4" marginInlineEnd={2}> | |||
| {t("Detail Scheduling")} | |||
| </Typography> | |||
| </Stack> | |||
| <I18nProvider namespaces={["schedule", "common"]}> | |||
| <Suspense fallback={<DetailSchedule.Loading />}> | |||
| <DetailSchedule type={type}/> | |||
| </Suspense> | |||
| </I18nProvider> | |||
| </> | |||
| ); | |||
| return ( | |||
| <> | |||
| <Stack | |||
| direction="row" | |||
| justifyContent="space-between" | |||
| flexWrap="wrap" | |||
| rowGap={2} | |||
| > | |||
| <Typography variant="h4" marginInlineEnd={2}> | |||
| {t("Detail Scheduling")} | |||
| </Typography> | |||
| </Stack> | |||
| <I18nProvider namespaces={["schedule", "common"]}> | |||
| <Suspense fallback={<DetailSchedule.Loading />}> | |||
| <DetailSchedule type={type} /> | |||
| </Suspense> | |||
| </I18nProvider> | |||
| </> | |||
| ); | |||
| }; | |||
| export default DetailScheduling; | |||
| @@ -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; | |||
| @@ -8,7 +8,9 @@ export default async function NotFound() { | |||
| return ( | |||
| <Stack spacing={2}> | |||
| <Typography variant="h4">{t("Not Found")}</Typography> | |||
| <Typography variant="body1">{t("The production schedule detail page was not found!")}</Typography> | |||
| <Typography variant="body1"> | |||
| {t("The production schedule detail page was not found!")} | |||
| </Typography> | |||
| <Link href="/settings/scheduling" component={NextLink} variant="body2"> | |||
| {t("Return to all scheduling")} | |||
| </Link> | |||
| @@ -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<Props> = 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 ( | |||
| <> | |||
| <Stack | |||
| direction="row" | |||
| justifyContent="space-between" | |||
| flexWrap="wrap" | |||
| rowGap={2} | |||
| > | |||
| <Typography variant="h4" marginInlineEnd={2}> | |||
| {t("FG & Material Demand Forecast Detail")} | |||
| </Typography> | |||
| {/* <Button | |||
| return ( | |||
| <> | |||
| <Stack | |||
| direction="row" | |||
| justifyContent="space-between" | |||
| flexWrap="wrap" | |||
| rowGap={2} | |||
| > | |||
| <Typography variant="h4" marginInlineEnd={2}> | |||
| {t("FG & Material Demand Forecast Detail")} | |||
| </Typography> | |||
| {/* <Button | |||
| variant="contained" | |||
| startIcon={<Add />} | |||
| LinkComponent={Link} | |||
| @@ -58,14 +61,14 @@ const roughSchedulingDetail: React.FC<Props> = async ({ searchParams }) => { | |||
| > | |||
| {t("Create product")} | |||
| </Button> */} | |||
| </Stack> | |||
| <I18nProvider namespaces={["schedule","common"]}> | |||
| <Suspense fallback={<RoughScheduleDetailView.Loading />}> | |||
| <RoughScheduleDetailView type={type} id={parseInt(id)}/> | |||
| </Suspense> | |||
| </I18nProvider> | |||
| </> | |||
| ); | |||
| </Stack> | |||
| <I18nProvider namespaces={["schedule", "common"]}> | |||
| <Suspense fallback={<RoughScheduleDetailView.Loading />}> | |||
| <RoughScheduleDetailView type={type} id={parseInt(id)} /> | |||
| </Suspense> | |||
| </I18nProvider> | |||
| </> | |||
| ); | |||
| }; | |||
| export default roughSchedulingDetail; | |||
| @@ -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 ( | |||
| <> | |||
| <Stack | |||
| direction="row" | |||
| justifyContent="space-between" | |||
| flexWrap="wrap" | |||
| rowGap={2} | |||
| > | |||
| <Typography variant="h4" marginInlineEnd={2}> | |||
| {t("Demand Forecast")} | |||
| </Typography> | |||
| return ( | |||
| <> | |||
| <Stack | |||
| direction="row" | |||
| justifyContent="space-between" | |||
| flexWrap="wrap" | |||
| rowGap={2} | |||
| > | |||
| <Typography variant="h4" marginInlineEnd={2}> | |||
| {t("Demand Forecast")} | |||
| </Typography> | |||
| {/* <Button | |||
| {/* <Button | |||
| variant="contained" | |||
| startIcon={<Add />} | |||
| onClick={() => testingRoughSchedule} | |||
| > | |||
| {t("Test Rough Scheduling")} | |||
| </Button> */} | |||
| </Stack> | |||
| <I18nProvider namespaces={["schedule", "common"]}> | |||
| <Suspense fallback={<RoughSchedule.Loading />}> | |||
| <RoughSchedule type={type} /> | |||
| </Suspense> | |||
| </I18nProvider> | |||
| </> | |||
| ); | |||
| </Stack> | |||
| <I18nProvider namespaces={["schedule", "common"]}> | |||
| <Suspense fallback={<RoughSchedule.Loading />}> | |||
| <RoughSchedule type={type} /> | |||
| </Suspense> | |||
| </I18nProvider> | |||
| </> | |||
| ); | |||
| }; | |||
| export default roughScheduling; | |||
| @@ -41,8 +41,8 @@ const productSetting: React.FC = async () => { | |||
| </Button> */} | |||
| </Stack> | |||
| <Suspense fallback={<EquipmentSearch.Loading />}> | |||
| <I18nProvider namespaces={["common","project"]}> | |||
| <EquipmentSearch /> | |||
| <I18nProvider namespaces={["common", "project"]}> | |||
| <EquipmentSearch /> | |||
| </I18nProvider> | |||
| </Suspense> | |||
| </> | |||
| @@ -41,8 +41,8 @@ const productSetting: React.FC = async () => { | |||
| </Button> */} | |||
| </Stack> | |||
| <Suspense fallback={<EquipmentTypeSearch.Loading />}> | |||
| <I18nProvider namespaces={["common","project"]}> | |||
| <EquipmentTypeSearch /> | |||
| <I18nProvider namespaces={["common", "project"]}> | |||
| <EquipmentTypeSearch /> | |||
| </I18nProvider> | |||
| </Suspense> | |||
| </> | |||
| @@ -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(); | |||
| @@ -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 ( | |||
| <> | |||
| <Stack | |||
| direction="row" | |||
| justifyContent="space-between" | |||
| flexWrap="wrap" | |||
| rowGap={2} | |||
| > | |||
| </Stack> | |||
| <Suspense fallback={<M18ImportTesting.Loading />}> | |||
| <I18nProvider namespaces={["common", "m18ImportTesting"]}> | |||
| <M18ImportTesting /> | |||
| </I18nProvider> | |||
| </Suspense> | |||
| </> | |||
| ) | |||
| } | |||
| return ( | |||
| <> | |||
| <Stack | |||
| direction="row" | |||
| justifyContent="space-between" | |||
| flexWrap="wrap" | |||
| rowGap={2} | |||
| ></Stack> | |||
| <Suspense fallback={<M18ImportTesting.Loading />}> | |||
| <I18nProvider namespaces={["common", "m18ImportTesting"]}> | |||
| <M18ImportTesting /> | |||
| </I18nProvider> | |||
| </Suspense> | |||
| </> | |||
| ); | |||
| }; | |||
| export default M18ImportTestingPage; | |||
| export default M18ImportTestingPage; | |||
| @@ -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 ( | |||
| <> | |||
| <Stack | |||
| direction="row" | |||
| justifyContent="space-between" | |||
| flexWrap="wrap" | |||
| rowGap={2} | |||
| > | |||
| <Typography variant="h4" marginInlineEnd={2}> | |||
| {t("Mail")} | |||
| </Typography> | |||
| </Stack> | |||
| <I18nProvider namespaces={["mail", "common"]}> | |||
| <Suspense fallback={<MailSetting.Loading />}> | |||
| <MailSetting /> | |||
| </Suspense> | |||
| </I18nProvider> | |||
| </> | |||
| ); | |||
| return ( | |||
| <> | |||
| <Stack | |||
| direction="row" | |||
| justifyContent="space-between" | |||
| flexWrap="wrap" | |||
| rowGap={2} | |||
| > | |||
| <Typography variant="h4" marginInlineEnd={2}> | |||
| {t("Mail")} | |||
| </Typography> | |||
| </Stack> | |||
| <I18nProvider namespaces={["mail", "common"]}> | |||
| <Suspense fallback={<MailSetting.Loading />}> | |||
| <MailSetting /> | |||
| </Suspense> | |||
| </I18nProvider> | |||
| </> | |||
| ); | |||
| }; | |||
| export default Customer; | |||
| export default Customer; | |||
| @@ -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 <> | |||
| <Stack | |||
| direction="row" | |||
| justifyContent="space-between" | |||
| flexWrap="wrap" | |||
| rowGap={2} | |||
| return ( | |||
| <> | |||
| <Stack | |||
| direction="row" | |||
| justifyContent="space-between" | |||
| flexWrap="wrap" | |||
| rowGap={2} | |||
| > | |||
| <Typography variant="h4" marginInlineEnd={2}> | |||
| {t("Qc Category")} | |||
| </Typography> | |||
| <Button | |||
| variant="contained" | |||
| startIcon={<Add />} | |||
| LinkComponent={Link} | |||
| href="qcCategory/create" | |||
| > | |||
| <Typography variant="h4" marginInlineEnd={2}> | |||
| {t("Qc Category")} | |||
| </Typography> | |||
| <Button | |||
| variant="contained" | |||
| startIcon={<Add />} | |||
| LinkComponent={Link} | |||
| href="qcCategory/create" | |||
| > | |||
| {t("Create Qc Category")} | |||
| </Button> | |||
| </Stack> | |||
| <Suspense fallback={<QcCategorySearch.Loading />}> | |||
| <QcCategorySearch /> | |||
| </Suspense> | |||
| </>; | |||
| {t("Create Qc Category")} | |||
| </Button> | |||
| </Stack> | |||
| <Suspense fallback={<QcCategorySearch.Loading />}> | |||
| <QcCategorySearch /> | |||
| </Suspense> | |||
| </> | |||
| ); | |||
| }; | |||
| export default qcCategory; | |||
| export default qcCategory; | |||
| @@ -8,7 +8,9 @@ export default async function NotFound() { | |||
| return ( | |||
| <Stack spacing={2}> | |||
| <Typography variant="h4">{t("Not Found")}</Typography> | |||
| <Typography variant="body1">{t("The create qc item page was not found!")}</Typography> | |||
| <Typography variant="body1"> | |||
| {t("The create qc item page was not found!")} | |||
| </Typography> | |||
| <Link href="/qcItems" component={NextLink} variant="body2"> | |||
| {t("Return to all qc items")} | |||
| </Link> | |||
| @@ -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 <> | |||
| <Typography variant="h4" marginInlineEnd={2}> | |||
| {t("Create Qc Item")} | |||
| </Typography> | |||
| <I18nProvider namespaces={["qcItem"]}> | |||
| <QcItemSave /> | |||
| </I18nProvider> | |||
| </>; | |||
| return ( | |||
| <> | |||
| <Typography variant="h4" marginInlineEnd={2}> | |||
| {t("Create Qc Item")} | |||
| </Typography> | |||
| <I18nProvider namespaces={["qcItem"]}> | |||
| <QcItemSave /> | |||
| </I18nProvider> | |||
| </> | |||
| ); | |||
| }; | |||
| export default qcItem; | |||
| export default qcItem; | |||
| @@ -8,7 +8,9 @@ export default async function NotFound() { | |||
| return ( | |||
| <Stack spacing={2}> | |||
| <Typography variant="h4">{t("Not Found")}</Typography> | |||
| <Typography variant="body1">{t("The edit qc item page was not found!")}</Typography> | |||
| <Typography variant="body1"> | |||
| {t("The edit qc item page was not found!")} | |||
| </Typography> | |||
| <Link href="/settings/qcItems" component={NextLink} variant="body2"> | |||
| {t("Return to all qc items")} | |||
| </Link> | |||
| @@ -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<Props> = 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 <> | |||
| <Typography variant="h4" marginInlineEnd={2}> | |||
| {t("Edit Qc Item")} | |||
| </Typography> | |||
| <I18nProvider namespaces={["qcItem"]}> | |||
| <QcItemSave id={id}/> | |||
| </I18nProvider> | |||
| </>; | |||
| } | |||
| return ( | |||
| <> | |||
| <Typography variant="h4" marginInlineEnd={2}> | |||
| {t("Edit Qc Item")} | |||
| </Typography> | |||
| <I18nProvider namespaces={["qcItem"]}> | |||
| <QcItemSave id={id} /> | |||
| </I18nProvider> | |||
| </> | |||
| ); | |||
| }; | |||
| export default qcItem; | |||
| export default qcItem; | |||
| @@ -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 <> | |||
| <Stack | |||
| direction="row" | |||
| justifyContent="space-between" | |||
| flexWrap="wrap" | |||
| rowGap={2} | |||
| return ( | |||
| <> | |||
| <Stack | |||
| direction="row" | |||
| justifyContent="space-between" | |||
| flexWrap="wrap" | |||
| rowGap={2} | |||
| > | |||
| <Typography variant="h4" marginInlineEnd={2}> | |||
| {t("Qc Item")} | |||
| </Typography> | |||
| <Button | |||
| variant="contained" | |||
| startIcon={<Add />} | |||
| LinkComponent={Link} | |||
| href="qcItem/create" | |||
| > | |||
| <Typography variant="h4" marginInlineEnd={2}> | |||
| {t("Qc Item")} | |||
| </Typography> | |||
| <Button | |||
| variant="contained" | |||
| startIcon={<Add />} | |||
| LinkComponent={Link} | |||
| href="qcItem/create" | |||
| > | |||
| {t("Create Qc Item")} | |||
| </Button> | |||
| </Stack> | |||
| <Suspense fallback={<QcItemSearch.Loading />}> | |||
| <QcItemSearch /> | |||
| </Suspense> | |||
| </>; | |||
| {t("Create Qc Item")} | |||
| </Button> | |||
| </Stack> | |||
| <Suspense fallback={<QcItemSearch.Loading />}> | |||
| <QcItemSearch /> | |||
| </Suspense> | |||
| </> | |||
| ); | |||
| }; | |||
| export default qcItem; | |||
| export default qcItem; | |||
| @@ -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 ( | |||
| <> | |||
| <Stack | |||
| direction="row" | |||
| justifyContent="space-between" | |||
| flexWrap="wrap" | |||
| rowGap={2} | |||
| > | |||
| <Typography variant="h4" marginInlineEnd={2}> | |||
| {t("Demand Forecast Setting")} | |||
| </Typography> | |||
| {/* <Button | |||
| return ( | |||
| <> | |||
| <Stack | |||
| direction="row" | |||
| justifyContent="space-between" | |||
| flexWrap="wrap" | |||
| rowGap={2} | |||
| > | |||
| <Typography variant="h4" marginInlineEnd={2}> | |||
| {t("Demand Forecast Setting")} | |||
| </Typography> | |||
| {/* <Button | |||
| variant="contained" | |||
| startIcon={<Add />} | |||
| LinkComponent={Link} | |||
| @@ -39,14 +38,14 @@ const roughScheduleSetting: React.FC = async () => { | |||
| > | |||
| {t("Create product")} | |||
| </Button> */} | |||
| </Stack> | |||
| <I18nProvider namespaces={[ "common", "project"]}> | |||
| <Suspense fallback={<RoughScheduleLoading.Loading />}> | |||
| <RoughScheduleSetting /> | |||
| </Suspense> | |||
| </I18nProvider> | |||
| </> | |||
| ); | |||
| </Stack> | |||
| <I18nProvider namespaces={["common", "project"]}> | |||
| <Suspense fallback={<RoughScheduleSetting.Loading />}> | |||
| <RoughScheduleSetting /> | |||
| </Suspense> | |||
| </I18nProvider> | |||
| </> | |||
| ); | |||
| }; | |||
| export default roughScheduleSetting; | |||
| @@ -19,7 +19,7 @@ const CreateStaffPage: React.FC = async () => { | |||
| <Typography variant="h4">{t("Create User")}</Typography> | |||
| <I18nProvider namespaces={["user", "common"]}> | |||
| <Suspense fallback={<CreateUser.Loading />}> | |||
| <CreateUser/> | |||
| <CreateUser /> | |||
| </Suspense> | |||
| </I18nProvider> | |||
| </> | |||
| @@ -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 ( | |||
| <> | |||
| @@ -15,21 +15,21 @@ export interface PostStockInLiineResponse<T> { | |||
| 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<PurchaseQCInput & StockInInput & EscalationInput & PutawayInput> | |||
| export type ModalFormInput = Partial< | |||
| PurchaseQCInput & StockInInput & EscalationInput & PutawayInput | |||
| >; | |||
| export const testFetch = cache(async (id: number) => { | |||
| return serverFetchJson<PoResult>(`${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<StockInLine>(`${BASE_API_URL}/stockInLine/${stockInLineId}`, { | |||
| return serverFetchJson<StockInLine>( | |||
| `${BASE_API_URL}/stockInLine/${stockInLineId}`, | |||
| { | |||
| next: { tags: ["stockInLine"] }, | |||
| }); | |||
| }, | |||
| ); | |||
| }); | |||
| export const createStockInLine = async (data: StockInLineEntry) => { | |||
| const stockInLine = await serverFetchJson<PostStockInLiineResponse<StockInLineEntry>>(`${BASE_API_URL}/stockInLine/create`, { | |||
| const stockInLine = await serverFetchJson< | |||
| PostStockInLiineResponse<StockInLineEntry> | |||
| >(`${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<PostStockInLiineResponse<StockInLineEntry & ModalFormInput>>(`${BASE_API_URL}/stockInLine/update`, { | |||
| export const updateStockInLine = async ( | |||
| data: StockInLineEntry & ModalFormInput, | |||
| ) => { | |||
| const stockInLine = await serverFetchJson< | |||
| PostStockInLiineResponse<StockInLineEntry & ModalFormInput> | |||
| >(`${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<PostStockInLiineResponse<PoResult>>(`${BASE_API_URL}/po/start/${poId}`, { | |||
| method: "POST", | |||
| body: JSON.stringify({ poId }), | |||
| headers: { "Content-Type": "application/json" }, | |||
| }); | |||
| const po = await serverFetchJson<PostStockInLiineResponse<PoResult>>( | |||
| `${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<PostStockInLiineResponse<PoResult>>(`${BASE_API_URL}/po/check/${poId}`, { | |||
| method: "POST", | |||
| body: JSON.stringify({ poId }), | |||
| headers: { "Content-Type": "application/json" }, | |||
| }); | |||
| const po = await serverFetchJson<PostStockInLiineResponse<PoResult>>( | |||
| `${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<PoResult>(`${BASE_API_URL}/po/detail/${id}`, { | |||
| @@ -127,33 +144,46 @@ export const fetchPoInClient = cache(async (id: number) => { | |||
| }); | |||
| }); | |||
| export const fetchPoListClient = cache(async (queryParams?: Record<string, any>) => { | |||
| export const fetchPoListClient = cache( | |||
| async (queryParams?: Record<string, any>) => { | |||
| if (queryParams) { | |||
| const queryString = new URLSearchParams(queryParams).toString(); | |||
| return serverFetchJson<RecordsRes<PoResult[]>>(`${BASE_API_URL}/po/list?${queryString}`, { | |||
| method: 'GET', | |||
| next: { tags: ["po"] }, | |||
| }); | |||
| return serverFetchJson<RecordsRes<PoResult[]>>( | |||
| `${BASE_API_URL}/po/list?${queryString}`, | |||
| { | |||
| method: "GET", | |||
| next: { tags: ["po"] }, | |||
| }, | |||
| ); | |||
| } else { | |||
| return serverFetchJson<RecordsRes<PoResult[]>>(`${BASE_API_URL}/po/list`, { | |||
| method: 'GET', | |||
| next: { tags: ["po"] }, | |||
| }); | |||
| return serverFetchJson<RecordsRes<PoResult[]>>( | |||
| `${BASE_API_URL}/po/list`, | |||
| { | |||
| method: "GET", | |||
| next: { tags: ["po"] }, | |||
| }, | |||
| ); | |||
| } | |||
| }); | |||
| }, | |||
| ); | |||
| export const testing = cache(async (queryParams?: Record<string, any>) => { | |||
| if (queryParams) { | |||
| const queryString = new URLSearchParams(queryParams).toString(); | |||
| return serverFetchJson<RecordsRes<PoResult[]>>(`${BASE_API_URL}/po/testing?${queryString}`, { | |||
| method: 'GET', | |||
| export const testing = cache(async (queryParams?: Record<string, any>) => { | |||
| if (queryParams) { | |||
| const queryString = new URLSearchParams(queryParams).toString(); | |||
| return serverFetchJson<RecordsRes<PoResult[]>>( | |||
| `${BASE_API_URL}/po/testing?${queryString}`, | |||
| { | |||
| method: "GET", | |||
| next: { tags: ["po"] }, | |||
| }); | |||
| } else { | |||
| return serverFetchJson<RecordsRes<PoResult[]>>(`${BASE_API_URL}/po/testing`, { | |||
| method: 'GET', | |||
| }, | |||
| ); | |||
| } else { | |||
| return serverFetchJson<RecordsRes<PoResult[]>>( | |||
| `${BASE_API_URL}/po/testing`, | |||
| { | |||
| method: "GET", | |||
| next: { tags: ["po"] }, | |||
| }); | |||
| } | |||
| }); | |||
| }, | |||
| ); | |||
| } | |||
| }); | |||
| @@ -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<string, any>) => { | |||
| if (queryParams) { | |||
| const queryString = new URLSearchParams(queryParams).toString(); | |||
| return serverFetchJson<RecordsRes<PoResult[]>>(`${BASE_API_URL}/po/list?${queryString}`, { | |||
| method: 'GET', | |||
| export const fetchPoList = cache(async (queryParams?: Record<string, any>) => { | |||
| if (queryParams) { | |||
| const queryString = new URLSearchParams(queryParams).toString(); | |||
| return serverFetchJson<RecordsRes<PoResult[]>>( | |||
| `${BASE_API_URL}/po/list?${queryString}`, | |||
| { | |||
| method: "GET", | |||
| next: { tags: ["po"] }, | |||
| }); | |||
| } else { | |||
| return serverFetchJson<RecordsRes<PoResult[]>>(`${BASE_API_URL}/po/list`, { | |||
| method: 'GET', | |||
| next: { tags: ["po"] }, | |||
| }); | |||
| } | |||
| }); | |||
| export const fetchPoWithStockInLines = cache(async (id: number) => { | |||
| return serverFetchJson<PoResult>(`${BASE_API_URL}/po/detail/${id}`, { | |||
| }, | |||
| ); | |||
| } else { | |||
| return serverFetchJson<RecordsRes<PoResult[]>>(`${BASE_API_URL}/po/list`, { | |||
| method: "GET", | |||
| next: { tags: ["po"] }, | |||
| }); | |||
| }); | |||
| } | |||
| }); | |||
| export const fetchPoWithStockInLines = cache(async (id: number) => { | |||
| return serverFetchJson<PoResult>(`${BASE_API_URL}/po/detail/${id}`, { | |||
| next: { tags: ["po"] }, | |||
| }); | |||
| }); | |||
| @@ -10,5 +10,5 @@ import { DoResult } from "."; | |||
| import { GridRowId, GridRowSelectionModel } from "@mui/x-data-grid"; | |||
| export interface CreateConsoDoInput { | |||
| ids: GridRowSelectionModel | |||
| ids: GridRowSelectionModel; | |||
| } | |||
| @@ -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<DoResult[]>(`${BASE_API_URL}/do/list`, { | |||
| next: { tags: ["doList"] } | |||
| }) | |||
| }) | |||
| return serverFetchJson<DoResult[]>(`${BASE_API_URL}/do/list`, { | |||
| next: { tags: ["doList"] }, | |||
| }); | |||
| }); | |||
| @@ -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<record>(`${BASE_API_URL}/group/auth/${target}/${id ?? 0}`, { | |||
| export const fetchAuth = cache(async (target: string, id?: number) => { | |||
| return serverFetchJson<record>( | |||
| `${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 | |||
| }; | |||
| revalidateTag("group"); | |||
| return newGroup; | |||
| }; | |||
| @@ -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<Records>(`${BASE_API_URL}/group`, { | |||
| next: { tags: ["group"] }, | |||
| }); | |||
| return serverFetchJson<Records>(`${BASE_API_URL}/group`, { | |||
| next: { tags: ["group"] }, | |||
| }); | |||
| }); | |||
| export const fetchIndivGroup = cache(async (id: number) => { | |||
| return serverFetchJson<IndivUserGroup>(`${BASE_API_URL}/group/${id}`, { | |||
| next: { tags: ["group"] }, | |||
| }); | |||
| return serverFetchJson<IndivUserGroup>(`${BASE_API_URL}/group/${id}`, { | |||
| next: { tags: ["group"] }, | |||
| }); | |||
| }); | |||
| @@ -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<LotLineInfo>(`${BASE_API_URL}/inventoryLotLine/lot-detail/${stockInLineId}`, { | |||
| method: 'GET', | |||
| next: { tags: ["inventory"] }, | |||
| }); | |||
| }); | |||
| export const fetchLotDetail = cache(async (stockInLineId: number) => { | |||
| return serverFetchJson<LotLineInfo>( | |||
| `${BASE_API_URL}/inventoryLotLine/lot-detail/${stockInLineId}`, | |||
| { | |||
| method: "GET", | |||
| next: { tags: ["inventory"] }, | |||
| }, | |||
| ); | |||
| }); | |||
| @@ -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<InventoryResult[]>(`${BASE_API_URL}/inventory/list`, { | |||
| next: { tags: ["inventories"]} | |||
| }) | |||
| }) | |||
| export const fetchInventories = cache(async () => { | |||
| return serverFetchJson<InventoryResult[]>(`${BASE_API_URL}/inventory/list`, { | |||
| next: { tags: ["inventories"] }, | |||
| }); | |||
| }); | |||
| @@ -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<T> { | |||
| 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<T> { | |||
| 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<IsOperatorExistResponse<Operator>>(`${BASE_API_URL}/jop/isOperatorExist`, { | |||
| const isExist = await serverFetchJson<IsOperatorExistResponse<Operator>>( | |||
| `${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<isCorrectMachineUsedResponse<Machine>>(`${BASE_API_URL}/jop/isCorrectMachineUsed`, { | |||
| method: "POST", | |||
| body: JSON.stringify({ machineCode }), | |||
| headers: { "Content-Type": "application/json" }, | |||
| }); | |||
| revalidateTag("po"); | |||
| return isExist | |||
| } | |||
| const isExist = await serverFetchJson<isCorrectMachineUsedResponse<Machine>>( | |||
| `${BASE_API_URL}/jop/isCorrectMachineUsed`, | |||
| { | |||
| method: "POST", | |||
| body: JSON.stringify({ machineCode }), | |||
| headers: { "Content-Type": "application/json" }, | |||
| }, | |||
| ); | |||
| revalidateTag("po"); | |||
| return isExist; | |||
| }; | |||
| @@ -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; | |||
| } | |||
| id: number; | |||
| name: string; | |||
| code: string; | |||
| qrCode: string; | |||
| } | |||
| @@ -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<MailSetting[]>(`${BASE_API_URL}/mails/save`, { | |||
| method: "POST", | |||
| body: JSON.stringify(data), | |||
| headers: { "Content-Type": "application/json" }, | |||
| }); | |||
| return serverFetchJson<MailSetting[]>(`${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" }, | |||
| }); | |||
| }; | |||
| return serverFetchWithNoContent(`${BASE_API_URL}/mails/test15th`, { | |||
| method: "GET", | |||
| // body: JSON.stringify(data), | |||
| headers: { "Content-Type": "application/json" }, | |||
| }); | |||
| }; | |||
| @@ -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<MailSetting[]>(`${BASE_API_URL}/mails/setting`, { | |||
| next: { tags: ["mailSetting"] }, | |||
| }); | |||
| return serverFetchJson<MailSetting[]>(`${BASE_API_URL}/mails/setting`, { | |||
| next: { tags: ["mailSetting"] }, | |||
| }); | |||
| }); | |||
| export const fetchMailTemplates = cache(async () => { | |||
| return serverFetchJson<MailTemplate[]>(`${BASE_API_URL}/mailTemplates`, { | |||
| next: { tags: ["mailTemplates"] }, | |||
| }); | |||
| return serverFetchJson<MailTemplate[]>(`${BASE_API_URL}/mailTemplates`, { | |||
| next: { tags: ["mailTemplates"] }, | |||
| }); | |||
| }); | |||
| // export const fetchMailTimesheetTemplate = cache(async () => { | |||
| @@ -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<FileResponse>( | |||
| `${BASE_API_URL}/stockInLine/print-label`, | |||
| { | |||
| method: "POST", | |||
| body: JSON.stringify(data), | |||
| headers: { "Content-Type": "application/json" }, | |||
| }, | |||
| ); | |||
| const reportBlob = await serverFetchBlob<FileResponse>( | |||
| `${BASE_API_URL}/stockInLine/print-label`, | |||
| { | |||
| method: "POST", | |||
| body: JSON.stringify(data), | |||
| headers: { "Content-Type": "application/json" }, | |||
| }, | |||
| ); | |||
| return reportBlob | |||
| }; | |||
| return reportBlob; | |||
| }; | |||
| @@ -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<T> { | |||
| 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<any>(`${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<any>( | |||
| `${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<any>(`${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<string, any>) => { | |||
| const pickOrder = await serverFetchJson<any>( | |||
| `${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<string, any>) => { | |||
| if (queryParams) { | |||
| const queryString = new URLSearchParams(queryParams).toString(); | |||
| return serverFetchJson<RecordsRes<PickOrderResult[]>>(`${BASE_API_URL}/pickOrder/getRecordByPage?${queryString}`, { | |||
| method: 'GET', | |||
| next: { tags: ["pickorder"] }, | |||
| }); | |||
| return serverFetchJson<RecordsRes<PickOrderResult[]>>( | |||
| `${BASE_API_URL}/pickOrder/getRecordByPage?${queryString}`, | |||
| { | |||
| method: "GET", | |||
| next: { tags: ["pickorder"] }, | |||
| }, | |||
| ); | |||
| } else { | |||
| return serverFetchJson<RecordsRes<PickOrderResult[]>>(`${BASE_API_URL}/pickOrder/getRecordByPage`, { | |||
| method: 'GET', | |||
| next: { tags: ["pickorder"] }, | |||
| }); | |||
| return serverFetchJson<RecordsRes<PickOrderResult[]>>( | |||
| `${BASE_API_URL}/pickOrder/getRecordByPage`, | |||
| { | |||
| method: "GET", | |||
| next: { tags: ["pickorder"] }, | |||
| }, | |||
| ); | |||
| } | |||
| }); | |||
| }, | |||
| ); | |||
| export const fetchConsoPickOrderClient = cache(async (queryParams?: Record<string, any>) => { | |||
| export const fetchConsoPickOrderClient = cache( | |||
| async (queryParams?: Record<string, any>) => { | |||
| if (queryParams) { | |||
| const queryString = new URLSearchParams(queryParams).toString(); | |||
| return serverFetchJson<RecordsRes<ConsoPickOrderResult[]>>(`${BASE_API_URL}/pickOrder/getRecordByPage-conso?${queryString}`, { | |||
| method: 'GET', | |||
| next: { tags: ["pickorder"] }, | |||
| }); | |||
| return serverFetchJson<RecordsRes<ConsoPickOrderResult[]>>( | |||
| `${BASE_API_URL}/pickOrder/getRecordByPage-conso?${queryString}`, | |||
| { | |||
| method: "GET", | |||
| next: { tags: ["pickorder"] }, | |||
| }, | |||
| ); | |||
| } else { | |||
| return serverFetchJson<RecordsRes<ConsoPickOrderResult[]>>(`${BASE_API_URL}/pickOrder/getRecordByPage-conso`, { | |||
| method: 'GET', | |||
| next: { tags: ["pickorder"] }, | |||
| }); | |||
| return serverFetchJson<RecordsRes<ConsoPickOrderResult[]>>( | |||
| `${BASE_API_URL}/pickOrder/getRecordByPage-conso`, | |||
| { | |||
| method: "GET", | |||
| next: { tags: ["pickorder"] }, | |||
| }, | |||
| ); | |||
| } | |||
| }); | |||
| }, | |||
| ); | |||
| export const fetchPickOrderLineClient = cache(async (queryParams?: Record<string, any>) => { | |||
| export const fetchPickOrderLineClient = cache( | |||
| async (queryParams?: Record<string, any>) => { | |||
| if (queryParams) { | |||
| const queryString = new URLSearchParams(queryParams).toString(); | |||
| return serverFetchJson<RecordsRes<PickOrderLineWithSuggestedLot[]>>(`${BASE_API_URL}/pickOrder/get-pickorder-line-byPage?${queryString}`, { | |||
| method: 'GET', | |||
| next: { tags: ["pickorder"] }, | |||
| }); | |||
| return serverFetchJson<RecordsRes<PickOrderLineWithSuggestedLot[]>>( | |||
| `${BASE_API_URL}/pickOrder/get-pickorder-line-byPage?${queryString}`, | |||
| { | |||
| method: "GET", | |||
| next: { tags: ["pickorder"] }, | |||
| }, | |||
| ); | |||
| } else { | |||
| return serverFetchJson<RecordsRes<PickOrderLineWithSuggestedLot[]>>(`${BASE_API_URL}/pickOrder/get-pickorder-line-byPage`, { | |||
| method: 'GET', | |||
| next: { tags: ["pickorder"] }, | |||
| }); | |||
| return serverFetchJson<RecordsRes<PickOrderLineWithSuggestedLot[]>>( | |||
| `${BASE_API_URL}/pickOrder/get-pickorder-line-byPage`, | |||
| { | |||
| method: "GET", | |||
| next: { tags: ["pickorder"] }, | |||
| }, | |||
| ); | |||
| } | |||
| }); | |||
| export const fetchStockOutLineClient = cache(async (pickOrderLineId: number) => { | |||
| return serverFetchJson<StockOutLine[]>(`${BASE_API_URL}/stockOutLine/getByPickOrderLineId/${pickOrderLineId}`, { | |||
| method: 'GET', | |||
| next: { tags: ["pickorder"] }, | |||
| }); | |||
| }); | |||
| export const fetchConsoDetail = cache(async (consoCode: string) => { | |||
| return serverFetchJson<PreReleasePickOrderSummary>(`${BASE_API_URL}/pickOrder/pre-release-info/${consoCode}`, { | |||
| method: 'GET', | |||
| }, | |||
| ); | |||
| export const fetchStockOutLineClient = cache( | |||
| async (pickOrderLineId: number) => { | |||
| return serverFetchJson<StockOutLine[]>( | |||
| `${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<PreReleasePickOrderSummary>( | |||
| `${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<PostStockOutLiineResponse<StockOutLine>>(`${BASE_API_URL}/stockOutLine/create`, { | |||
| }, | |||
| ); | |||
| revalidateTag("pickorder"); | |||
| return po; | |||
| }; | |||
| export const createStockOutLine = async (data: CreateStockOutLine) => { | |||
| console.log("triggering"); | |||
| const po = await serverFetchJson<PostStockOutLiineResponse<StockOutLine>>( | |||
| `${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<PostStockOutLiineResponse<StockOutLine>> | |||
| (`${BASE_API_URL}/stockOutLine/update`, { | |||
| }, | |||
| ); | |||
| revalidateTag("pickorder"); | |||
| return po; | |||
| }; | |||
| export const updateStockOutLine = async (data: UpdateStockOutLine) => { | |||
| console.log(data); | |||
| const po = await serverFetchJson<PostStockOutLiineResponse<StockOutLine>>( | |||
| `${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<PostStockOutLiineResponse<StockOutLine>> | |||
| (`${BASE_API_URL}/pickOrder/consoPickOrder/complete/${consoCode}`, { | |||
| }, | |||
| ); | |||
| revalidateTag("pickorder"); | |||
| return po; | |||
| }; | |||
| export const completeConsoPickOrder = async (consoCode: string) => { | |||
| const po = await serverFetchJson<PostStockOutLiineResponse<StockOutLine>>( | |||
| `${BASE_API_URL}/pickOrder/consoPickOrder/complete/${consoCode}`, | |||
| { | |||
| method: "POST", | |||
| headers: { "Content-Type": "application/json" }, | |||
| }); | |||
| revalidateTag("pickorder"); | |||
| return po | |||
| } | |||
| }, | |||
| ); | |||
| revalidateTag("pickorder"); | |||
| return po; | |||
| }; | |||
| @@ -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<PickOrderResult, "items">[] | |||
| items: ByItemsSummary[] | |||
| consoCode: string; | |||
| pickOrders: Omit<PickOrderResult, "items">[]; | |||
| 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<string, any>).toString(); | |||
| return serverFetchJson<PickOrderResult[]>(`${BASE_API_URL}/pickOrder/list?${queryString}`, { | |||
| next: { | |||
| tags: ["pickOrders"] | |||
| } | |||
| }) | |||
| }) | |||
| const queryString = new URLSearchParams( | |||
| queryParams as Record<string, any>, | |||
| ).toString(); | |||
| return serverFetchJson<PickOrderResult[]>( | |||
| `${BASE_API_URL}/pickOrder/list?${queryString}`, | |||
| { | |||
| next: { | |||
| tags: ["pickOrders"], | |||
| }, | |||
| }, | |||
| ); | |||
| }); | |||
| @@ -15,21 +15,21 @@ export interface PostStockInLiineResponse<T> { | |||
| 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<PurchaseQCInput & StockInInput & EscalationInput & PutawayInput> | |||
| export type ModalFormInput = Partial< | |||
| PurchaseQCInput & StockInInput & EscalationInput & PutawayInput | |||
| >; | |||
| export const testFetch = cache(async (id: number) => { | |||
| return serverFetchJson<PoResult>(`${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<StockInLine>(`${BASE_API_URL}/stockInLine/${stockInLineId}`, { | |||
| return serverFetchJson<StockInLine>( | |||
| `${BASE_API_URL}/stockInLine/${stockInLineId}`, | |||
| { | |||
| next: { tags: ["stockInLine"] }, | |||
| }); | |||
| }, | |||
| ); | |||
| }); | |||
| export const createStockInLine = async (data: StockInLineEntry) => { | |||
| const stockInLine = await serverFetchJson<PostStockInLiineResponse<StockInLineEntry>>(`${BASE_API_URL}/stockInLine/create`, { | |||
| const stockInLine = await serverFetchJson< | |||
| PostStockInLiineResponse<StockInLineEntry> | |||
| >(`${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<PostStockInLiineResponse<StockInLineEntry & ModalFormInput>>(`${BASE_API_URL}/stockInLine/update`, { | |||
| export const updateStockInLine = async ( | |||
| data: StockInLineEntry & ModalFormInput, | |||
| ) => { | |||
| const stockInLine = await serverFetchJson< | |||
| PostStockInLiineResponse<StockInLineEntry & ModalFormInput> | |||
| >(`${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<PostStockInLiineResponse<PoResult>>(`${BASE_API_URL}/po/start/${poId}`, { | |||
| method: "POST", | |||
| body: JSON.stringify({ poId }), | |||
| headers: { "Content-Type": "application/json" }, | |||
| }); | |||
| const po = await serverFetchJson<PostStockInLiineResponse<PoResult>>( | |||
| `${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<PostStockInLiineResponse<PoResult>>(`${BASE_API_URL}/po/check/${poId}`, { | |||
| method: "POST", | |||
| body: JSON.stringify({ poId }), | |||
| headers: { "Content-Type": "application/json" }, | |||
| }); | |||
| const po = await serverFetchJson<PostStockInLiineResponse<PoResult>>( | |||
| `${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<PoResult>(`${BASE_API_URL}/po/detail/${id}`, { | |||
| @@ -127,33 +144,46 @@ export const fetchPoInClient = cache(async (id: number) => { | |||
| }); | |||
| }); | |||
| export const fetchPoListClient = cache(async (queryParams?: Record<string, any>) => { | |||
| export const fetchPoListClient = cache( | |||
| async (queryParams?: Record<string, any>) => { | |||
| if (queryParams) { | |||
| const queryString = new URLSearchParams(queryParams).toString(); | |||
| return serverFetchJson<RecordsRes<PoResult[]>>(`${BASE_API_URL}/po/list?${queryString}`, { | |||
| method: 'GET', | |||
| next: { tags: ["po"] }, | |||
| }); | |||
| return serverFetchJson<RecordsRes<PoResult[]>>( | |||
| `${BASE_API_URL}/po/list?${queryString}`, | |||
| { | |||
| method: "GET", | |||
| next: { tags: ["po"] }, | |||
| }, | |||
| ); | |||
| } else { | |||
| return serverFetchJson<RecordsRes<PoResult[]>>(`${BASE_API_URL}/po/list`, { | |||
| method: 'GET', | |||
| next: { tags: ["po"] }, | |||
| }); | |||
| return serverFetchJson<RecordsRes<PoResult[]>>( | |||
| `${BASE_API_URL}/po/list`, | |||
| { | |||
| method: "GET", | |||
| next: { tags: ["po"] }, | |||
| }, | |||
| ); | |||
| } | |||
| }); | |||
| }, | |||
| ); | |||
| export const testing = cache(async (queryParams?: Record<string, any>) => { | |||
| if (queryParams) { | |||
| const queryString = new URLSearchParams(queryParams).toString(); | |||
| return serverFetchJson<RecordsRes<PoResult[]>>(`${BASE_API_URL}/po/testing?${queryString}`, { | |||
| method: 'GET', | |||
| export const testing = cache(async (queryParams?: Record<string, any>) => { | |||
| if (queryParams) { | |||
| const queryString = new URLSearchParams(queryParams).toString(); | |||
| return serverFetchJson<RecordsRes<PoResult[]>>( | |||
| `${BASE_API_URL}/po/testing?${queryString}`, | |||
| { | |||
| method: "GET", | |||
| next: { tags: ["po"] }, | |||
| }); | |||
| } else { | |||
| return serverFetchJson<RecordsRes<PoResult[]>>(`${BASE_API_URL}/po/testing`, { | |||
| method: 'GET', | |||
| }, | |||
| ); | |||
| } else { | |||
| return serverFetchJson<RecordsRes<PoResult[]>>( | |||
| `${BASE_API_URL}/po/testing`, | |||
| { | |||
| method: "GET", | |||
| next: { tags: ["po"] }, | |||
| }); | |||
| } | |||
| }); | |||
| }, | |||
| ); | |||
| } | |||
| }); | |||
| @@ -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<string, any>) => { | |||
| if (queryParams) { | |||
| const queryString = new URLSearchParams(queryParams).toString(); | |||
| return serverFetchJson<RecordsRes<PoResult[]>>(`${BASE_API_URL}/po/list?${queryString}`, { | |||
| method: 'GET', | |||
| export const fetchPoList = cache(async (queryParams?: Record<string, any>) => { | |||
| if (queryParams) { | |||
| const queryString = new URLSearchParams(queryParams).toString(); | |||
| return serverFetchJson<RecordsRes<PoResult[]>>( | |||
| `${BASE_API_URL}/po/list?${queryString}`, | |||
| { | |||
| method: "GET", | |||
| next: { tags: ["po"] }, | |||
| }); | |||
| } else { | |||
| return serverFetchJson<RecordsRes<PoResult[]>>(`${BASE_API_URL}/po/list`, { | |||
| method: 'GET', | |||
| next: { tags: ["po"] }, | |||
| }); | |||
| } | |||
| }); | |||
| export const fetchPoWithStockInLines = cache(async (id: number) => { | |||
| return serverFetchJson<PoResult>(`${BASE_API_URL}/po/detail/${id}`, { | |||
| }, | |||
| ); | |||
| } else { | |||
| return serverFetchJson<RecordsRes<PoResult[]>>(`${BASE_API_URL}/po/list`, { | |||
| method: "GET", | |||
| next: { tags: ["po"] }, | |||
| }); | |||
| }); | |||
| } | |||
| }); | |||
| export const fetchPoWithStockInLines = cache(async (id: number) => { | |||
| return serverFetchJson<PoResult>(`${BASE_API_URL}/po/detail/${id}`, { | |||
| next: { tags: ["po"] }, | |||
| }); | |||
| }); | |||
| @@ -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<QcItemWithChecks[]>(url, { | |||
| next: { tags: ["qc"] }, | |||
| }); | |||
| let url = `${BASE_API_URL}/qcCheck`; | |||
| if (itemId) url += `/${itemId}`; | |||
| return serverFetchJson<QcItemWithChecks[]>(url, { | |||
| next: { tags: ["qc"] }, | |||
| }); | |||
| }); | |||
| export const fetchQcResult = cache(async (id: number) => { | |||
| return serverFetchJson<QcResult[]>(`${BASE_API_URL}/qcResult/${id}`, { | |||
| next: { tags: ["qc"] }, | |||
| }); | |||
| return serverFetchJson<QcResult[]>(`${BASE_API_URL}/qcResult/${id}`, { | |||
| next: { tags: ["qc"] }, | |||
| }); | |||
| }); | |||
| export const fetchPickOrderQcResult = cache(async (id: number) => { | |||
| return serverFetchJson<QcResult[]>(`${BASE_API_URL}/qcResult/pick-order/${id}`, { | |||
| next: { tags: ["qc"] }, | |||
| }); | |||
| }); | |||
| return serverFetchJson<QcResult[]>( | |||
| `${BASE_API_URL}/qcResult/pick-order/${id}`, | |||
| { | |||
| next: { tags: ["qc"] }, | |||
| }, | |||
| ); | |||
| }); | |||
| @@ -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<QcItemWithChecks[]>(`${BASE_API_URL}/qc/list`, { | |||
| next: { tags: ["qc"] }, | |||
| }); | |||
| export const fetchQcItemCheckList = cache(async () => { | |||
| return serverFetchJson<QcItemWithChecks[]>(`${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<QcItemWithChecks[]>(url, { | |||
| next: { tags: ["qc"] }, | |||
| }); | |||
| }); | |||
| }); | |||
| @@ -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 | |||
| } | |||
| itemId: number; | |||
| lotNo?: string; | |||
| } | |||
| @@ -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<SearchProdSchedule>(data) | |||
| export const fetchProdSchedules = cache( | |||
| async (data: SearchProdSchedule | null) => { | |||
| const params = convertObjToURLSearchParams<SearchProdSchedule>(data); | |||
| // console.log(params) | |||
| return serverFetchJson<ProdScheduleResultByPage>(`${BASE_API_URL}/productionSchedule/getRecordByPage?${params}`, { | |||
| return serverFetchJson<ProdScheduleResultByPage>( | |||
| `${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"] | |||
| } | |||
| }) | |||
| }) | |||
| return serverFetchJson( | |||
| `${BASE_API_URL}/productionSchedule/testDetailSchedule`, | |||
| { | |||
| method: "GET", | |||
| headers: { "Content-Type": "application/json" }, | |||
| next: { | |||
| tags: ["prodSchedules"], | |||
| }, | |||
| }, | |||
| ); | |||
| }); | |||
| @@ -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<RoughProdScheduleResult>(`${BASE_API_URL}/productionSchedule/detail/${id}`, { | |||
| method: "GET", | |||
| headers: { "Content-Type": "application/json" }, | |||
| next: { | |||
| tags: ["prodSchedule"] | |||
| } | |||
| }) | |||
| }) | |||
| return serverFetchJson<RoughProdScheduleResult>( | |||
| `${BASE_API_URL}/productionSchedule/detail/${id}`, | |||
| { | |||
| method: "GET", | |||
| headers: { "Content-Type": "application/json" }, | |||
| next: { | |||
| tags: ["prodSchedule"], | |||
| }, | |||
| }, | |||
| ); | |||
| }); | |||
| @@ -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<CreateEquipmentTypeResponse<CreateEquipmentInputs>>(`${BASE_API_URL}/Equipment/save`, { | |||
| method: "POST", | |||
| body: JSON.stringify(data), | |||
| headers: { "Content-Type": "application/json" }, | |||
| }); | |||
| revalidateTag("EquipmentType"); | |||
| return equipment | |||
| }; | |||
| // try { | |||
| const equipment = await serverFetchJson< | |||
| CreateEquipmentTypeResponse<CreateEquipmentInputs> | |||
| >(`${BASE_API_URL}/Equipment/save`, { | |||
| method: "POST", | |||
| body: JSON.stringify(data), | |||
| headers: { "Content-Type": "application/json" }, | |||
| }); | |||
| revalidateTag("EquipmentType"); | |||
| return equipment; | |||
| }; | |||
| @@ -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<EquipmentResult[]>(`${BASE_API_URL}/Equipment`, { | |||
| next: { tags: ["equipments"] }, | |||
| }); | |||
| return serverFetchJson<EquipmentResult[]>(`${BASE_API_URL}/Equipment`, { | |||
| next: { tags: ["equipments"] }, | |||
| }); | |||
| }); | |||
| export const fetchEquipment = cache(async (id: number) => { | |||
| return serverFetchJson<EquipmentResult>(`${BASE_API_URL}/Equipment/details/${id}`, { | |||
| next: { tags: ["equipments"] }, | |||
| }); | |||
| }); | |||
| return serverFetchJson<EquipmentResult>( | |||
| `${BASE_API_URL}/Equipment/details/${id}`, | |||
| { | |||
| next: { tags: ["equipments"] }, | |||
| }, | |||
| ); | |||
| }); | |||
| @@ -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<CreateEquipmentTypeResponse<CreateEquipmentTypeInputs>>(`${BASE_API_URL}/EquipmentType/save`, { | |||
| method: "POST", | |||
| body: JSON.stringify(data), | |||
| headers: { "Content-Type": "application/json" }, | |||
| }); | |||
| revalidateTag("EquipmentType"); | |||
| return equipmentType | |||
| }; | |||
| // try { | |||
| const equipmentType = await serverFetchJson< | |||
| CreateEquipmentTypeResponse<CreateEquipmentTypeInputs> | |||
| >(`${BASE_API_URL}/EquipmentType/save`, { | |||
| method: "POST", | |||
| body: JSON.stringify(data), | |||
| headers: { "Content-Type": "application/json" }, | |||
| }); | |||
| revalidateTag("EquipmentType"); | |||
| return equipmentType; | |||
| }; | |||
| @@ -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<EquipmentTypeResult[]>(`${BASE_API_URL}/EquipmentType`, { | |||
| return serverFetchJson<EquipmentTypeResult[]>( | |||
| `${BASE_API_URL}/EquipmentType`, | |||
| { | |||
| next: { tags: ["equipmentTypes"] }, | |||
| }); | |||
| }); | |||
| }, | |||
| ); | |||
| }); | |||
| export const fetchEquipmentType = cache(async (id: number) => { | |||
| return serverFetchJson<EquipmentTypeResult>(`${BASE_API_URL}/EquipmentType/details/${id}`, { | |||
| next: { tags: ["equipmentTypes"] }, | |||
| }); | |||
| }); | |||
| return serverFetchJson<EquipmentTypeResult>( | |||
| `${BASE_API_URL}/EquipmentType/details/${id}`, | |||
| { | |||
| next: { tags: ["equipmentTypes"] }, | |||
| }, | |||
| ); | |||
| }); | |||
| @@ -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<CreateItemResponse<CreateItemInputs>>(`${BASE_API_URL}/items/new`, { | |||
| method: "POST", | |||
| body: JSON.stringify(data), | |||
| headers: { "Content-Type": "application/json" }, | |||
| }); | |||
| revalidateTag("items"); | |||
| return item | |||
| }; | |||
| // try { | |||
| const item = await serverFetchJson<CreateItemResponse<CreateItemInputs>>( | |||
| `${BASE_API_URL}/items/new`, | |||
| { | |||
| method: "POST", | |||
| body: JSON.stringify(data), | |||
| headers: { "Content-Type": "application/json" }, | |||
| }, | |||
| ); | |||
| revalidateTag("items"); | |||
| return item; | |||
| }; | |||
| @@ -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<ItemsResult[]>(`${BASE_API_URL}/items`, { | |||
| next: { tags: ["items"] }, | |||
| }); | |||
| return serverFetchJson<ItemsResult[]>(`${BASE_API_URL}/items`, { | |||
| next: { tags: ["items"] }, | |||
| }); | |||
| }); | |||
| export const fetchItem = cache(async (id: number) => { | |||
| return serverFetchJson<Result>(`${BASE_API_URL}/items/details/${id}`, { | |||
| next: { tags: ["items"] }, | |||
| }); | |||
| }); | |||
| }); | |||
| @@ -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" }, | |||
| }) | |||
| } | |||
| 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" }, | |||
| }); | |||
| }; | |||
| @@ -1 +1 @@ | |||
| // "server only" | |||
| // "server only" | |||
| @@ -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" }, | |||
| }) | |||
| } | |||
| return serverFetchJson(`${BASE_API_URL}/qcCategories/save`, { | |||
| method: "POST", | |||
| body: JSON.stringify(data), | |||
| headers: { "Content-Type": "application/json" }, | |||
| }); | |||
| }; | |||
| @@ -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<QcCategoryResult[]>(`${BASE_API_URL}/qcCategories`, { | |||
| next: { tags: ["qcCategories"]} | |||
| }); | |||
| }); | |||
| return serverFetchJson<QcCategoryResult[]>(`${BASE_API_URL}/qcCategories`, { | |||
| next: { tags: ["qcCategories"] }, | |||
| }); | |||
| }); | |||
| @@ -7,18 +7,18 @@ import { BASE_API_URL } from "../../../../config/api"; | |||
| import { CreateItemResponse } from "../../utils"; | |||
| import { ItemQc } from "../item"; | |||
| export type QcChecksInputs = { | |||
| } & Partial<ItemQc> | |||
| export type QcChecksInputs = {} & Partial<ItemQc>; | |||
| export const saveItemQcChecks = async (data: QcChecksInputs[]) => { | |||
| // try { | |||
| const res = await serverFetchJson<CreateItemResponse<QcChecksInputs>>(`${BASE_API_URL}/qcCheck/new`, { | |||
| method: "POST", | |||
| body: JSON.stringify(data), | |||
| headers: { "Content-Type": "application/json" }, | |||
| }); | |||
| revalidateTag("items"); | |||
| return res | |||
| }; | |||
| // try { | |||
| const res = await serverFetchJson<CreateItemResponse<QcChecksInputs>>( | |||
| `${BASE_API_URL}/qcCheck/new`, | |||
| { | |||
| method: "POST", | |||
| body: JSON.stringify(data), | |||
| headers: { "Content-Type": "application/json" }, | |||
| }, | |||
| ); | |||
| revalidateTag("items"); | |||
| return res; | |||
| }; | |||
| @@ -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<keyof SaveQcItemInputs, string> | |||
| id?: number; | |||
| code: string; | |||
| name: string; | |||
| description?: string; | |||
| errors: Record<keyof SaveQcItemInputs, string>; | |||
| } | |||
| export const saveQcItem = async (data: SaveQcItemInputs) => { | |||
| const response = await serverFetchJson<SaveQcItemResponse>(`${BASE_API_URL}/qcItems/save`, { | |||
| method: "POST", | |||
| body: JSON.stringify(data), | |||
| headers: { "Content-Type": "application/json" }, | |||
| }) | |||
| const response = await serverFetchJson<SaveQcItemResponse>( | |||
| `${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<QcItemResult[]>(`${BASE_API_URL}/qcItems/${id}`, { | |||
| method: "DELETE", | |||
| headers: { "Content-Type": "application/json" }, | |||
| }) | |||
| revalidateTag("qcItems") | |||
| revalidatePath("/(main)/settings/qcItem") | |||
| return response | |||
| } | |||
| const response = await serverFetchJson<QcItemResult[]>( | |||
| `${BASE_API_URL}/qcItems/${id}`, | |||
| { | |||
| method: "DELETE", | |||
| headers: { "Content-Type": "application/json" }, | |||
| }, | |||
| ); | |||
| revalidateTag("qcItems"); | |||
| revalidatePath("/(main)/settings/qcItem"); | |||
| return response; | |||
| }; | |||
| @@ -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<QcItemResult[]>(`${BASE_API_URL}/qcItems`, { | |||
| next: { tags: ["qcItems"] } | |||
| }); | |||
| return serverFetchJson<QcItemResult[]>(`${BASE_API_URL}/qcItems`, { | |||
| next: { tags: ["qcItems"] }, | |||
| }); | |||
| }); | |||
| export const fetchQcItemDetails = cache(async (qcItemId: string) => { | |||
| return serverFetchJson<SaveQcItemInputs>( | |||
| `${BASE_API_URL}/qcItems/qcItemDetails/${qcItemId}`, | |||
| { | |||
| next: { tags: [`qcItemDetails_${qcItemId}`] } | |||
| } | |||
| ) | |||
| }) | |||
| return serverFetchJson<SaveQcItemInputs>( | |||
| `${BASE_API_URL}/qcItems/qcItemDetails/${qcItemId}`, | |||
| { | |||
| next: { tags: [`qcItemDetails_${qcItemId}`] }, | |||
| }, | |||
| ); | |||
| }); | |||
| @@ -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 | |||
| } | |||
| 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; | |||
| } | |||
| @@ -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<UserDetail>(`${BASE_API_URL}/user/${id}`, { | |||
| next: { tags: ["user"] }, | |||
| }); | |||
| return serverFetchJson<UserDetail>(`${BASE_API_URL}/user/${id}`, { | |||
| next: { tags: ["user"] }, | |||
| }); | |||
| }); | |||
| export const fetchNameList = cache(async () => { | |||
| return serverFetchJson<NameList[]>(`${BASE_API_URL}/user/name-list`, { | |||
| next: { tags: ["user"] }, | |||
| }); | |||
| return serverFetchJson<NameList[]>(`${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" }, | |||
| }); | |||
| }; | |||
| }, | |||
| ); | |||
| }; | |||
| @@ -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<UserResult[]>(`${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<UserResult[]>(`${BASE_API_URL}/user`, { | |||
| next: { tags: ["user"] }, | |||
| }); | |||
| }); | |||
| export const fetchUserDetail = cache(async (id: number) => { | |||
| return serverFetchJson<UserResult[]>(`${BASE_API_URL}/user/${id}`, { | |||
| next: { tags: ["user"] }, | |||
| }); | |||
| export const fetchUserDetail = cache(async (id: number) => { | |||
| return serverFetchJson<UserResult[]>(`${BASE_API_URL}/user/${id}`, { | |||
| next: { tags: ["user"] }, | |||
| }); | |||
| }); | |||
| export const fetchPwRules = cache(async () => { | |||
| return serverFetchJson<passwordRule>(`${BASE_API_URL}/user/password-rule`, { | |||
| next: { tags: ["pwRule"] }, | |||
| }); | |||
| }); | |||
| export const fetchPwRules = cache(async () => { | |||
| return serverFetchJson<passwordRule>(`${BASE_API_URL}/user/password-rule`, { | |||
| next: { tags: ["pwRule"] }, | |||
| }); | |||
| }); | |||
| @@ -19,7 +19,7 @@ export interface CreateEquipmentResponse<T> { | |||
| message: string | null; | |||
| errorPosition: string | keyof T; | |||
| } | |||
| export interface RecordsRes<T>{ | |||
| records: T | |||
| total: number | |||
| } | |||
| export interface RecordsRes<T> { | |||
| records: T; | |||
| total: number; | |||
| } | |||
| @@ -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<WarehouseResult[]>(`${BASE_API_URL}/warehouse`, { | |||
| next: { tags: ["warehouse"] }, | |||
| }); | |||
| }); | |||
| return serverFetchJson<WarehouseResult[]>(`${BASE_API_URL}/warehouse`, { | |||
| next: { tags: ["warehouse"] }, | |||
| }); | |||
| }); | |||
| @@ -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 = <T extends Object>(data: T | null): string => { | |||
| export const convertObjToURLSearchParams = <T extends Object>( | |||
| 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() | |||
| } | |||
| return params.toString(); | |||
| }; | |||
| @@ -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<typeof fetch>; | |||
| export async function serverFetchJson<T>(...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, | |||
| ); | |||
| } | |||
| } | |||
| } | |||
| @@ -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<number | undefined, boolean>): boolean => | |||
| typeof item === "number" && !isNaN(item) && isFinite(item) | |||
| const isValidNumber = ( | |||
| item: ListIterateeCustom<number | undefined, boolean>, | |||
| ): 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; | |||
| } | |||
| }; | |||
| @@ -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, | |||
| } | |||
| MATERIAL = "material", | |||
| MATERIAL_ID = 1, | |||
| PRODUCT = "product", | |||
| PRODUCT_ID = 2, | |||
| BYPRODUCT = "byProduct", | |||
| BYPRODUCT_ID = 3, | |||
| CONSUMABLE = "consumables", | |||
| CONSUMABLE_ID = 4, | |||
| } | |||
| @@ -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", | |||
| ] | |||
| ]; | |||
| @@ -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 ( | |||
| <Breadcrumbs> | |||
| @@ -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<Omit<ClaimResult, "id">>; | |||
| type SearchParamNames = keyof SearchQuery; | |||
| const ClaimSearch: React.FC<Props> = ({ 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<SearchParamNames>[] = 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<Column<ClaimResult>[]>( | |||
| () => [ | |||
| // { | |||
| // name: "action", | |||
| // label: t("Actions"), | |||
| // onClick: onClaimClick, | |||
| // buttonIcon: <EditNote />, | |||
| // }, | |||
| { 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 ( | |||
| <> | |||
| <SearchBox | |||
| criteria={searchCriteria} | |||
| onSearch={(query) => { | |||
| console.log(query); | |||
| }} | |||
| /> | |||
| <SearchResults<ClaimResult> items={filteredClaims} columns={columns} /> | |||
| </> | |||
| ); | |||
| }; | |||
| export default ClaimSearch; | |||
| @@ -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 ( | |||
| <> | |||
| <Card> | |||
| <CardContent> | |||
| <Stack spacing={2}> | |||
| <Skeleton variant="rounded" height={60} /> | |||
| <Skeleton variant="rounded" height={60} /> | |||
| <Skeleton variant="rounded" height={60} /> | |||
| <Skeleton | |||
| variant="rounded" | |||
| height={50} | |||
| width={100} | |||
| sx={{ alignSelf: "flex-end" }} | |||
| /> | |||
| </Stack> | |||
| </CardContent> | |||
| </Card> | |||
| <Card> | |||
| <CardContent> | |||
| <Stack spacing={2}> | |||
| <Skeleton variant="rounded" height={40} /> | |||
| <Skeleton variant="rounded" height={40} /> | |||
| <Skeleton variant="rounded" height={40} /> | |||
| <Skeleton variant="rounded" height={40} /> | |||
| </Stack> | |||
| </CardContent> | |||
| </Card> | |||
| </> | |||
| ); | |||
| }; | |||
| export default ClaimSearchLoading; | |||
| @@ -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 <ClaimSearch claims={claims} />; | |||
| }; | |||
| ClaimSearchWrapper.Loading = ClaimSearchLoading; | |||
| export default ClaimSearchWrapper; | |||
| @@ -1 +0,0 @@ | |||
| export { default } from "./ClaimSearchWrapper"; | |||
| @@ -1 +1 @@ | |||
| export { default } from "./ControlledAutoComplete"; | |||
| export { default } from "./ControlledAutoComplete"; | |||
| @@ -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<Props> = ({ | |||
| 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<Props> = ({ | |||
| }, [isEditMode]); | |||
| // console.log(typeId) | |||
| const formProps = useForm<CreateEquipmentInputs>({ | |||
| defaultValues: defaultValues ? defaultValues : { | |||
| }, | |||
| defaultValues: defaultValues ? defaultValues : {}, | |||
| }); | |||
| const errors = formProps.formState.errors; | |||
| @@ -90,8 +97,8 @@ const CreateItem: React.FC<Props> = ({ | |||
| }; | |||
| const onSubmit = useCallback<SubmitHandler<CreateEquipmentInputs & {}>>( | |||
| 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<Props> = ({ | |||
| 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<Props> = ({ | |||
| console.log(e); | |||
| } | |||
| }, | |||
| [apiRef, router, t] | |||
| [apiRef, router, t], | |||
| ); | |||
| // multiple tabs | |||
| const onSubmitError = useCallback<SubmitErrorHandler<CreateEquipmentInputs>>( | |||
| (errors) => {}, | |||
| [] | |||
| [], | |||
| ); | |||
| return ( | |||
| @@ -147,21 +155,25 @@ const CreateItem: React.FC<Props> = ({ | |||
| component="form" | |||
| onSubmit={formProps.handleSubmit(onSubmit, onSubmitError)} | |||
| > | |||
| <Grid> | |||
| <Typography mb={2} variant="h4"> | |||
| {t(`${mode} ${title}`)} | |||
| </Typography> | |||
| </Grid> | |||
| <Tabs value={tabIndex} onChange={handleTabChange} variant="scrollable"> | |||
| <Tab label={t("Equipment Details")} iconPosition="end"/> | |||
| {/* <Tab label={t("Qc items")} iconPosition="end" /> */} | |||
| </Tabs> | |||
| <Grid> | |||
| <Typography mb={2} variant="h4"> | |||
| {t(`${mode} ${title}`)} | |||
| </Typography> | |||
| </Grid> | |||
| <Tabs | |||
| value={tabIndex} | |||
| onChange={handleTabChange} | |||
| variant="scrollable" | |||
| > | |||
| <Tab label={t("Equipment Details")} iconPosition="end" /> | |||
| {/* <Tab label={t("Qc items")} iconPosition="end" /> */} | |||
| </Tabs> | |||
| {serverError && ( | |||
| <Typography variant="body2" color="error" alignSelf="flex-end"> | |||
| {serverError} | |||
| </Typography> | |||
| )} | |||
| {tabIndex === 0 && <EquipmentDetails isEditMode={isEditMode} />} | |||
| {tabIndex === 0 && <EquipmentDetails isEditMode={isEditMode} />} | |||
| {/* {tabIndex === 1 && <QcDetails apiRef={apiRef} />} */} | |||
| {/* {type === TypeEnum.MATERIAL && <MaterialDetails />} */} | |||
| {/* {type === TypeEnum.BYPRODUCT && <ByProductDetails />} */} | |||
| @@ -23,7 +23,8 @@ export const CreateItemLoading: React.FC = () => { | |||
| </Stack> | |||
| </CardContent> | |||
| </Card> | |||
| <Card>CreateMaterial | |||
| <Card> | |||
| CreateMaterial | |||
| <CardContent> | |||
| <Stack spacing={2}> | |||
| <Skeleton variant="rounded" height={40} /> | |||
| @@ -9,34 +9,32 @@ interface SubComponents { | |||
| } | |||
| type Props = { | |||
| id?: number | |||
| id?: number; | |||
| // type: TypeEnum; | |||
| }; | |||
| const CreateEquipmentWrapper: React.FC<Props> & | |||
| SubComponents = async ({ id }) => { | |||
| var result | |||
| var defaultValues: Partial<CreateEquipmentInputs> | undefined | |||
| const CreateEquipmentWrapper: React.FC<Props> & SubComponents = async ({ | |||
| id, | |||
| }) => { | |||
| let result; | |||
| let defaultValues: Partial<CreateEquipmentInputs> | 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 ( | |||
| <CreateEquipment | |||
| isEditMode={Boolean(id)} | |||
| defaultValues={defaultValues} | |||
| /> | |||
| <CreateEquipment isEditMode={Boolean(id)} defaultValues={defaultValues} /> | |||
| ); | |||
| }; | |||
| CreateEquipmentWrapper.Loading = CreateEquipmentLoading; | |||
| @@ -26,10 +26,10 @@ type Props = { | |||
| // type: TypeEnum; | |||
| isEditMode: boolean; | |||
| // type: TypeEnum; | |||
| defaultValues: Partial<CreateEquipmentInputs> | undefined; | |||
| defaultValues?: Partial<CreateEquipmentInputs> | undefined; | |||
| }; | |||
| const ProductDetails: React.FC<Props> = ({isEditMode}) => { | |||
| const ProductDetails: React.FC<Props> = ({ isEditMode }) => { | |||
| const { | |||
| t, | |||
| i18n: { language }, | |||
| @@ -99,7 +99,8 @@ const ProductDetails: React.FC<Props> = ({isEditMode}) => { | |||
| // [] | |||
| // ); | |||
| const handleCancel = () => { | |||
| router.replace(`/settings/equipment`); | |||
| // router.replace(`/settings/equipment`); | |||
| console.log("cancel"); | |||
| }; | |||
| return ( | |||
| <Card sx={{ display: "block" }}> | |||
| @@ -139,8 +140,7 @@ const ProductDetails: React.FC<Props> = ({isEditMode}) => { | |||
| helperText={errors.code?.message} | |||
| /> | |||
| </Grid> | |||
| */ | |||
| } | |||
| */} | |||
| <Grid item xs={6}> | |||
| <TextField | |||
| label={t("description")} | |||
| @@ -150,32 +150,37 @@ const ProductDetails: React.FC<Props> = ({isEditMode}) => { | |||
| </Grid> | |||
| <Grid item xs={12}> | |||
| <Stack direction="row" justifyContent="flex-start" spacing={2} sx={{ mt: 2 }}> | |||
| <Button | |||
| name="submit" | |||
| variant="contained" | |||
| startIcon={<Check />} | |||
| type="submit" | |||
| // disabled={submitDisabled} | |||
| > | |||
| {isEditMode ? t("Save") : t("Confirm")} | |||
| </Button> | |||
| <Button | |||
| variant="outlined" | |||
| startIcon={<Close />} | |||
| onClick={handleCancel} | |||
| > | |||
| {t("Cancel")} | |||
| </Button> | |||
| <Button | |||
| variant="outlined" | |||
| startIcon={<RestartAlt />} | |||
| onClick={() => reset()} | |||
| > | |||
| {t("Reset")} | |||
| </Button> | |||
| </Stack> | |||
| </Grid> | |||
| <Stack | |||
| direction="row" | |||
| justifyContent="flex-start" | |||
| spacing={2} | |||
| sx={{ mt: 2 }} | |||
| > | |||
| <Button | |||
| name="submit" | |||
| variant="contained" | |||
| startIcon={<Check />} | |||
| type="submit" | |||
| // disabled={submitDisabled} | |||
| > | |||
| {isEditMode ? t("Save") : t("Confirm")} | |||
| </Button> | |||
| <Button | |||
| variant="outlined" | |||
| startIcon={<Close />} | |||
| onClick={handleCancel} | |||
| > | |||
| {t("Cancel")} | |||
| </Button> | |||
| <Button | |||
| variant="outlined" | |||
| startIcon={<RestartAlt />} | |||
| onClick={() => reset()} | |||
| > | |||
| {t("Reset")} | |||
| </Button> | |||
| </Stack> | |||
| </Grid> | |||
| {/* <Grid item xs={6}> | |||
| <InputDataGrid<CreateItemInputs, EntryError> | |||
| _formKey={"type"} | |||
| @@ -1,5 +1,5 @@ | |||
| import { InputBaseComponentProps } from "@mui/material"; | |||
| export var NumberInputProps: InputBaseComponentProps = { | |||
| step: 0.01, | |||
| }; | |||
| step: 0.01, | |||
| }; | |||
| @@ -1 +1 @@ | |||
| export { default } from "./CreateEquipmentWrapper"; | |||
| export { default } from "./CreateEquipmentWrapper"; | |||
| @@ -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<Props> = ({ | |||
| 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<Props> = ({ | |||
| }, [isEditMode]); | |||
| // console.log(typeId) | |||
| const formProps = useForm<CreateEquipmentTypeInputs>({ | |||
| defaultValues: defaultValues ? defaultValues : { | |||
| }, | |||
| defaultValues: defaultValues ? defaultValues : {}, | |||
| }); | |||
| const errors = formProps.formState.errors; | |||
| @@ -90,8 +97,8 @@ const CreateItem: React.FC<Props> = ({ | |||
| }; | |||
| const onSubmit = useCallback<SubmitHandler<CreateEquipmentTypeInputs & {}>>( | |||
| 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<Props> = ({ | |||
| 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<Props> = ({ | |||
| console.log(e); | |||
| } | |||
| }, | |||
| [apiRef, router, t] | |||
| [apiRef, router, t], | |||
| ); | |||
| // multiple tabs | |||
| const onSubmitError = useCallback<SubmitErrorHandler<CreateEquipmentTypeInputs>>( | |||
| (errors) => {}, | |||
| [] | |||
| ); | |||
| const onSubmitError = useCallback< | |||
| SubmitErrorHandler<CreateEquipmentTypeInputs> | |||
| >((errors) => {}, []); | |||
| return ( | |||
| <> | |||
| @@ -147,21 +154,25 @@ const CreateItem: React.FC<Props> = ({ | |||
| component="form" | |||
| onSubmit={formProps.handleSubmit(onSubmit, onSubmitError)} | |||
| > | |||
| <Grid> | |||
| <Typography mb={2} variant="h4"> | |||
| {t(`${mode} ${title}`)} | |||
| </Typography> | |||
| </Grid> | |||
| <Tabs value={tabIndex} onChange={handleTabChange} variant="scrollable"> | |||
| <Tab label={t("Equipment Type Details")} iconPosition="end"/> | |||
| {/* <Tab label={t("Qc items")} iconPosition="end" /> */} | |||
| </Tabs> | |||
| <Grid> | |||
| <Typography mb={2} variant="h4"> | |||
| {t(`${mode} ${title}`)} | |||
| </Typography> | |||
| </Grid> | |||
| <Tabs | |||
| value={tabIndex} | |||
| onChange={handleTabChange} | |||
| variant="scrollable" | |||
| > | |||
| <Tab label={t("Equipment Type Details")} iconPosition="end" /> | |||
| {/* <Tab label={t("Qc items")} iconPosition="end" /> */} | |||
| </Tabs> | |||
| {serverError && ( | |||
| <Typography variant="body2" color="error" alignSelf="flex-end"> | |||
| {serverError} | |||
| </Typography> | |||
| )} | |||
| {tabIndex === 0 && <EquipmentTypeDetails isEditMode={isEditMode} />} | |||
| {tabIndex === 0 && <EquipmentTypeDetails isEditMode={isEditMode} />} | |||
| {/* {tabIndex === 1 && <QcDetails apiRef={apiRef} />} */} | |||
| {/* {type === TypeEnum.MATERIAL && <MaterialDetails />} */} | |||
| {/* {type === TypeEnum.BYPRODUCT && <ByProductDetails />} */} | |||
| @@ -23,7 +23,8 @@ export const CreateItemLoading: React.FC = () => { | |||
| </Stack> | |||
| </CardContent> | |||
| </Card> | |||
| <Card>CreateMaterial | |||
| <Card> | |||
| CreateMaterial | |||
| <CardContent> | |||
| <Stack spacing={2}> | |||
| <Skeleton variant="rounded" height={40} /> | |||
| @@ -9,20 +9,21 @@ interface SubComponents { | |||
| } | |||
| type Props = { | |||
| id?: number | |||
| id?: number; | |||
| // type: TypeEnum; | |||
| }; | |||
| const CreateEquipmentTypeWrapper: React.FC<Props> & | |||
| SubComponents = async ({ id }) => { | |||
| var result | |||
| var defaultValues: Partial<CreateEquipmentTypeInputs> | undefined | |||
| const CreateEquipmentTypeWrapper: React.FC<Props> & SubComponents = async ({ | |||
| id, | |||
| }) => { | |||
| let result; | |||
| let defaultValues: Partial<CreateEquipmentTypeInputs> | 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<Props> & | |||
| description: equipmentType?.description, | |||
| }; | |||
| } | |||
| return ( | |||
| <CreateEquipmentType | |||
| isEditMode={Boolean(id)} | |||
| @@ -26,10 +26,10 @@ type Props = { | |||
| // type: TypeEnum; | |||
| isEditMode: boolean; | |||
| // type: TypeEnum; | |||
| defaultValues: Partial<CreateEquipmentTypeInputs> | undefined; | |||
| defaultValues?: Partial<CreateEquipmentTypeInputs> | undefined; | |||
| }; | |||
| const ProductDetails: React.FC<Props> = ({isEditMode}) => { | |||
| const ProductDetails: React.FC<Props> = ({ isEditMode }) => { | |||
| const { | |||
| t, | |||
| i18n: { language }, | |||
| @@ -99,7 +99,8 @@ const ProductDetails: React.FC<Props> = ({isEditMode}) => { | |||
| // [] | |||
| // ); | |||
| const handleCancel = () => { | |||
| router.replace(`/settings/equipmentType`); | |||
| // router.replace(`/settings/equipmentType`); | |||
| console.log("cancel"); | |||
| }; | |||
| return ( | |||
| <Card sx={{ display: "block" }}> | |||
| @@ -132,8 +133,7 @@ const ProductDetails: React.FC<Props> = ({isEditMode}) => { | |||
| helperText={errors.code?.message} | |||
| /> | |||
| </Grid> | |||
| */ | |||
| } | |||
| */} | |||
| <Grid item xs={6}> | |||
| <TextField | |||
| label={t("description")} | |||
| @@ -143,32 +143,37 @@ const ProductDetails: React.FC<Props> = ({isEditMode}) => { | |||
| </Grid> | |||
| <Grid item xs={12}> | |||
| <Stack direction="row" justifyContent="flex-start" spacing={2} sx={{ mt: 2 }}> | |||
| <Button | |||
| name="submit" | |||
| variant="contained" | |||
| startIcon={<Check />} | |||
| type="submit" | |||
| // disabled={submitDisabled} | |||
| > | |||
| {isEditMode ? t("Save") : t("Confirm")} | |||
| </Button> | |||
| <Button | |||
| variant="outlined" | |||
| startIcon={<Close />} | |||
| onClick={handleCancel} | |||
| > | |||
| {t("Cancel")} | |||
| </Button> | |||
| <Button | |||
| variant="outlined" | |||
| startIcon={<RestartAlt />} | |||
| onClick={() => reset()} | |||
| > | |||
| {t("Reset")} | |||
| </Button> | |||
| </Stack> | |||
| </Grid> | |||
| <Stack | |||
| direction="row" | |||
| justifyContent="flex-start" | |||
| spacing={2} | |||
| sx={{ mt: 2 }} | |||
| > | |||
| <Button | |||
| name="submit" | |||
| variant="contained" | |||
| startIcon={<Check />} | |||
| type="submit" | |||
| // disabled={submitDisabled} | |||
| > | |||
| {isEditMode ? t("Save") : t("Confirm")} | |||
| </Button> | |||
| <Button | |||
| variant="outlined" | |||
| startIcon={<Close />} | |||
| onClick={handleCancel} | |||
| > | |||
| {t("Cancel")} | |||
| </Button> | |||
| <Button | |||
| variant="outlined" | |||
| startIcon={<RestartAlt />} | |||
| onClick={() => reset()} | |||
| > | |||
| {t("Reset")} | |||
| </Button> | |||
| </Stack> | |||
| </Grid> | |||
| {/* <Grid item xs={6}> | |||
| <InputDataGrid<CreateItemInputs, EntryError> | |||
| _formKey={"type"} | |||
| @@ -1,5 +1,5 @@ | |||
| import { InputBaseComponentProps } from "@mui/material"; | |||
| export var NumberInputProps: InputBaseComponentProps = { | |||
| step: 0.01, | |||
| }; | |||
| step: 0.01, | |||
| }; | |||
| @@ -1 +1 @@ | |||
| export { default } from "./CreateEquipmentTypeWrapper"; | |||
| export { default } from "./CreateEquipmentTypeWrapper"; | |||