2 Commit

Autore SHA1 Messaggio Data
  MSI\2Fi 5c6e25f78f Merge branch 'master' of https://git.2fi-solutions.com/derek/FPSMS-frontend 1 mese fa
  MSI\2Fi 3c5cb3f8b2 eslint suggested spacing 1 mese fa
100 ha cambiato i file con 2086 aggiunte e 2011 eliminazioni
  1. +1
    -1
      next.config.js
  2. +2
    -1
      package.json
  3. +1
    -1
      postcss.config.js
  4. +26
    -22
      src/app/(main)/axios/AxiosProvider.tsx
  5. +43
    -43
      src/app/(main)/axios/axiosInstance.ts
  6. +4
    -11
      src/app/(main)/dashboard/page.tsx
  7. +0
    -0
      src/app/(main)/do/edit/page.tsx
  8. +21
    -22
      src/app/(main)/do/page.tsx
  9. +25
    -23
      src/app/(main)/inventory/page.tsx
  10. +30
    -30
      src/app/(main)/layout.tsx
  11. +2
    -5
      src/app/(main)/material/page.tsx
  12. +2
    -2
      src/app/(main)/pickOrder/detail/page.tsx
  13. +26
    -26
      src/app/(main)/pickOrder/page.tsx
  14. +0
    -2
      src/app/(main)/po/edit/page.tsx
  15. +4
    -12
      src/app/(main)/po/page.tsx
  16. +4
    -11
      src/app/(main)/production/page.tsx
  17. +3
    -1
      src/app/(main)/scheduling/detail/edit/not-found.tsx
  18. +34
    -29
      src/app/(main)/scheduling/detail/edit/page.tsx
  19. +23
    -23
      src/app/(main)/scheduling/detail/page.tsx
  20. +2
    -2
      src/app/(main)/scheduling/page.tsx
  21. +3
    -1
      src/app/(main)/scheduling/rough/edit/not-found.tsx
  22. +39
    -36
      src/app/(main)/scheduling/rough/edit/page.tsx
  23. +28
    -28
      src/app/(main)/scheduling/rough/page.tsx
  24. +2
    -2
      src/app/(main)/settings/equipment/page.tsx
  25. +2
    -2
      src/app/(main)/settings/equipmentType/page.tsx
  26. +1
    -1
      src/app/(main)/settings/items/page.tsx
  27. +20
    -21
      src/app/(main)/settings/m18ImportTesting/page.tsx
  28. +24
    -24
      src/app/(main)/settings/mail/page.tsx
  29. +28
    -26
      src/app/(main)/settings/qcCategory/page.tsx
  30. +3
    -1
      src/app/(main)/settings/qcItem/create/not-found.tsx
  31. +13
    -11
      src/app/(main)/settings/qcItem/create/page.tsx
  32. +3
    -1
      src/app/(main)/settings/qcItem/edit/not-found.tsx
  33. +34
    -30
      src/app/(main)/settings/qcItem/edit/page.tsx
  34. +28
    -26
      src/app/(main)/settings/qcItem/page.tsx
  35. +25
    -26
      src/app/(main)/settings/rss/page.tsx
  36. +1
    -1
      src/app/(main)/settings/user/create/page.tsx
  37. +1
    -1
      src/app/(main)/settings/user/page.tsx
  38. +101
    -71
      src/app/api/dashboard/actions.ts
  39. +63
    -61
      src/app/api/dashboard/index.ts
  40. +1
    -1
      src/app/api/do/actions.tsx
  41. +12
    -12
      src/app/api/do/index.tsx
  42. +35
    -30
      src/app/api/group/actions.ts
  43. +12
    -13
      src/app/api/group/index.ts
  44. +16
    -13
      src/app/api/inventory/actions.ts
  45. +20
    -20
      src/app/api/inventory/index.ts
  46. +34
    -29
      src/app/api/jo/actions.ts
  47. +9
    -9
      src/app/api/jo/index.ts
  48. +33
    -30
      src/app/api/mail/actions.ts
  49. +29
    -29
      src/app/api/mail/index.ts
  50. +12
    -14
      src/app/api/pdf/actions.ts
  51. +169
    -117
      src/app/api/pickOrder/actions.ts
  52. +86
    -81
      src/app/api/pickOrder/index.ts
  53. +101
    -71
      src/app/api/po/actions.ts
  54. +63
    -61
      src/app/api/po/index.ts
  55. +22
    -20
      src/app/api/qc/actions.ts
  56. +15
    -17
      src/app/api/qc/index.ts
  57. +5
    -5
      src/app/api/qrcode/index.ts
  58. +54
    -43
      src/app/api/scheduling/actions.ts
  59. +70
    -63
      src/app/api/scheduling/index.ts
  60. +18
    -14
      src/app/api/settings/equipment/actions.ts
  61. +15
    -14
      src/app/api/settings/equipment/index.ts
  62. +18
    -14
      src/app/api/settings/equipmentType/actions.ts
  63. +18
    -14
      src/app/api/settings/equipmentType/index.ts
  64. +22
    -16
      src/app/api/settings/item/actions.ts
  65. +14
    -15
      src/app/api/settings/item/index.ts
  66. +39
    -37
      src/app/api/settings/m18ImportTesting/actions.ts
  67. +1
    -1
      src/app/api/settings/m18ImportTesting/index.ts
  68. +9
    -9
      src/app/api/settings/qcCategory/actions.ts
  69. +8
    -8
      src/app/api/settings/qcCategory/index.ts
  70. +13
    -13
      src/app/api/settings/qcCheck/actions.ts
  71. +35
    -29
      src/app/api/settings/qcItem/actions.ts
  72. +15
    -15
      src/app/api/settings/qcItem/index.ts
  73. +14
    -14
      src/app/api/settings/uom/index.ts
  74. +39
    -33
      src/app/api/user/actions.ts
  75. +41
    -41
      src/app/api/user/index.ts
  76. +4
    -4
      src/app/api/utils/index.ts
  77. +8
    -8
      src/app/api/warehouse/index.ts
  78. +11
    -9
      src/app/utils/commonUtil.ts
  79. +10
    -7
      src/app/utils/fetchUtil.ts
  80. +47
    -40
      src/app/utils/formatUtil.ts
  81. +9
    -9
      src/app/utils/typeEnum.ts
  82. +2
    -8
      src/authorties.ts
  83. +1
    -1
      src/components/Breadcrumb/Breadcrumb.tsx
  84. +0
    -93
      src/components/ClaimSearch/ClaimSearch.tsx
  85. +0
    -40
      src/components/ClaimSearch/ClaimSearchLoading.tsx
  86. +0
    -18
      src/components/ClaimSearch/ClaimSearchWrapper.tsx
  87. +0
    -1
      src/components/ClaimSearch/index.ts
  88. +1
    -1
      src/components/ControlledAutoComplete/index.ts
  89. +49
    -37
      src/components/CreateEquipment/CreateEquipment.tsx
  90. +2
    -1
      src/components/CreateEquipment/CreateEquipmentLoading.tsx
  91. +12
    -14
      src/components/CreateEquipment/CreateEquipmentWrapper.tsx
  92. +36
    -31
      src/components/CreateEquipment/EquipmentDetails.tsx
  93. +2
    -2
      src/components/CreateEquipment/NumberInputProps.ts
  94. +1
    -1
      src/components/CreateEquipment/index.ts
  95. +51
    -40
      src/components/CreateEquipmentType/CreateEquipmentType.tsx
  96. +2
    -1
      src/components/CreateEquipmentType/CreateEquipmentTypeLoading.tsx
  97. +10
    -9
      src/components/CreateEquipmentType/CreateEquipmentTypeWrapper.tsx
  98. +36
    -31
      src/components/CreateEquipmentType/EquipmentTypeDetails.tsx
  99. +2
    -2
      src/components/CreateEquipmentType/NumberInputProps.ts
  100. +1
    -1
      src/components/CreateEquipmentType/index.ts

+ 1
- 1
next.config.js Vedi File

@@ -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 = {


+ 2
- 1
package.json Vedi File

@@ -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",


+ 1
- 1
postcss.config.js Vedi File

@@ -3,4 +3,4 @@ module.exports = {
tailwindcss: {},
autoprefixer: {},
},
}
};

+ 26
- 22
src/app/(main)/axios/AxiosProvider.tsx Vedi File

@@ -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);
};

+ 43
- 43
src/app/(main)/axios/axiosInstance.ts Vedi File

@@ -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;

+ 4
- 11
src/app/(main)/dashboard/page.tsx Vedi File

@@ -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;

+ 0
- 0
src/app/(main)/do/edit/page.tsx Vedi File


+ 21
- 22
src/app/(main)/do/page.tsx Vedi File

@@ -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;

+ 25
- 23
src/app/(main)/inventory/page.tsx Vedi File

@@ -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;

+ 30
- 30
src/app/(main)/layout.tsx Vedi File

@@ -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>
);


+ 2
- 5
src/app/(main)/material/page.tsx Vedi File

@@ -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 />


+ 2
- 2
src/app/(main)/pickOrder/detail/page.tsx Vedi File

@@ -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>
</>


+ 26
- 26
src/app/(main)/pickOrder/page.tsx Vedi File

@@ -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;

+ 0
- 2
src/app/(main)/po/edit/page.tsx Vedi File

@@ -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";


+ 4
- 12
src/app/(main)/po/page.tsx Vedi File

@@ -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>
</>
);


+ 4
- 11
src/app/(main)/production/page.tsx Vedi File

@@ -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> */}
</>
);
};


+ 3
- 1
src/app/(main)/scheduling/detail/edit/not-found.tsx Vedi File

@@ -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>


+ 34
- 29
src/app/(main)/scheduling/detail/edit/page.tsx Vedi File

@@ -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;

+ 23
- 23
src/app/(main)/scheduling/detail/page.tsx Vedi File

@@ -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;

+ 2
- 2
src/app/(main)/scheduling/page.tsx Vedi File

@@ -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;

+ 3
- 1
src/app/(main)/scheduling/rough/edit/not-found.tsx Vedi File

@@ -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>


+ 39
- 36
src/app/(main)/scheduling/rough/edit/page.tsx Vedi File

@@ -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;

+ 28
- 28
src/app/(main)/scheduling/rough/page.tsx Vedi File

@@ -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;

+ 2
- 2
src/app/(main)/settings/equipment/page.tsx Vedi File

@@ -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>
</>


+ 2
- 2
src/app/(main)/settings/equipmentType/page.tsx Vedi File

@@ -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>
</>


+ 1
- 1
src/app/(main)/settings/items/page.tsx Vedi File

@@ -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();



+ 20
- 21
src/app/(main)/settings/m18ImportTesting/page.tsx Vedi File

@@ -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;

+ 24
- 24
src/app/(main)/settings/mail/page.tsx Vedi File

@@ -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;

+ 28
- 26
src/app/(main)/settings/qcCategory/page.tsx Vedi File

@@ -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;

+ 3
- 1
src/app/(main)/settings/qcItem/create/not-found.tsx Vedi File

@@ -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>


+ 13
- 11
src/app/(main)/settings/qcItem/create/page.tsx Vedi File

@@ -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;

+ 3
- 1
src/app/(main)/settings/qcItem/edit/not-found.tsx Vedi File

@@ -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>


+ 34
- 30
src/app/(main)/settings/qcItem/edit/page.tsx Vedi File

@@ -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;

+ 28
- 26
src/app/(main)/settings/qcItem/page.tsx Vedi File

@@ -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;

+ 25
- 26
src/app/(main)/settings/rss/page.tsx Vedi File

@@ -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;

+ 1
- 1
src/app/(main)/settings/user/create/page.tsx Vedi File

@@ -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>
</>


+ 1
- 1
src/app/(main)/settings/user/page.tsx Vedi File

@@ -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 (
<>


+ 101
- 71
src/app/api/dashboard/actions.ts Vedi File

@@ -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"] },
});
}
});
},
);
}
});

+ 63
- 61
src/app/api/dashboard/index.ts Vedi File

@@ -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"] },
});
});

+ 1
- 1
src/app/api/do/actions.tsx Vedi File

@@ -10,5 +10,5 @@ import { DoResult } from ".";
import { GridRowId, GridRowSelectionModel } from "@mui/x-data-grid";

export interface CreateConsoDoInput {
ids: GridRowSelectionModel
ids: GridRowSelectionModel;
}

+ 12
- 12
src/app/api/do/index.tsx Vedi File

@@ -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"] },
});
});

+ 35
- 30
src/app/api/group/actions.ts Vedi File

@@ -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;
};

+ 12
- 13
src/app/api/group/index.ts Vedi File

@@ -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"] },
});
});

+ 16
- 13
src/app/api/inventory/actions.ts Vedi File

@@ -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"] },
},
);
});

+ 20
- 20
src/app/api/inventory/index.ts Vedi File

@@ -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"] },
});
});

+ 34
- 29
src/app/api/jo/actions.ts Vedi File

@@ -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;
};

+ 9
- 9
src/app/api/jo/index.ts Vedi File

@@ -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;
}

+ 33
- 30
src/app/api/mail/actions.ts Vedi File

@@ -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" },
});
};

+ 29
- 29
src/app/api/mail/index.ts Vedi File

@@ -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 () => {


+ 12
- 14
src/app/api/pdf/actions.ts Vedi File

@@ -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;
};

+ 169
- 117
src/app/api/pickOrder/actions.ts Vedi File

@@ -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;
};

+ 86
- 81
src/app/api/pickOrder/index.ts Vedi File

@@ -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"],
},
},
);
});

+ 101
- 71
src/app/api/po/actions.ts Vedi File

@@ -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"] },
});
}
});
},
);
}
});

+ 63
- 61
src/app/api/po/index.ts Vedi File

@@ -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"] },
});
});

+ 22
- 20
src/app/api/qc/actions.ts Vedi File

@@ -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"] },
},
);
});

+ 15
- 17
src/app/api/qc/index.ts Vedi File

@@ -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"] },
});
});
});

+ 5
- 5
src/app/api/qrcode/index.ts Vedi File

@@ -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;
}

+ 54
- 43
src/app/api/scheduling/actions.ts Vedi File

@@ -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"],
},
},
);
});

+ 70
- 63
src/app/api/scheduling/index.ts Vedi File

@@ -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"],
},
},
);
});

+ 18
- 14
src/app/api/settings/equipment/actions.ts Vedi File

@@ -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;
};

+ 15
- 14
src/app/api/settings/equipment/index.ts Vedi File

@@ -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"] },
},
);
});

+ 18
- 14
src/app/api/settings/equipmentType/actions.ts Vedi File

@@ -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;
};

+ 18
- 14
src/app/api/settings/equipmentType/index.ts Vedi File

@@ -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"] },
},
);
});

+ 22
- 16
src/app/api/settings/item/actions.ts Vedi File

@@ -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;
};

+ 14
- 15
src/app/api/settings/item/index.ts Vedi File

@@ -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"] },
});
});
});

+ 39
- 37
src/app/api/settings/m18ImportTesting/actions.ts Vedi File

@@ -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
src/app/api/settings/m18ImportTesting/index.ts Vedi File

@@ -1 +1 @@
// "server only"
// "server only"

+ 9
- 9
src/app/api/settings/qcCategory/actions.ts Vedi File

@@ -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" },
});
};

+ 8
- 8
src/app/api/settings/qcCategory/index.ts Vedi File

@@ -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"] },
});
});

+ 13
- 13
src/app/api/settings/qcCheck/actions.ts Vedi File

@@ -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;
};

+ 35
- 29
src/app/api/settings/qcItem/actions.ts Vedi File

@@ -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;
};

+ 15
- 15
src/app/api/settings/qcItem/index.ts Vedi File

@@ -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}`] },
},
);
});

+ 14
- 14
src/app/api/settings/uom/index.ts Vedi File

@@ -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;
}

+ 39
- 33
src/app/api/user/actions.ts Vedi File

@@ -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" },
});
};
},
);
};

+ 41
- 41
src/app/api/user/index.ts Vedi File

@@ -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"] },
});
});

+ 4
- 4
src/app/api/utils/index.ts Vedi File

@@ -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;
}

+ 8
- 8
src/app/api/warehouse/index.ts Vedi File

@@ -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"] },
});
});

+ 11
- 9
src/app/utils/commonUtil.ts Vedi File

@@ -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();
};

+ 10
- 7
src/app/utils/fetchUtil.ts Vedi File

@@ -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,
);
}
}
}


+ 47
- 40
src/app/utils/formatUtil.ts Vedi File

@@ -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;
}
};

+ 9
- 9
src/app/utils/typeEnum.ts Vedi File

@@ -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,
}

+ 2
- 8
src/authorties.ts Vedi File

@@ -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",
]
];

+ 1
- 1
src/components/Breadcrumb/Breadcrumb.tsx Vedi File

@@ -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>


+ 0
- 93
src/components/ClaimSearch/ClaimSearch.tsx Vedi File

@@ -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;

+ 0
- 40
src/components/ClaimSearch/ClaimSearchLoading.tsx Vedi File

@@ -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;

+ 0
- 18
src/components/ClaimSearch/ClaimSearchWrapper.tsx Vedi File

@@ -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;

+ 0
- 1
src/components/ClaimSearch/index.ts Vedi File

@@ -1 +0,0 @@
export { default } from "./ClaimSearchWrapper";

+ 1
- 1
src/components/ControlledAutoComplete/index.ts Vedi File

@@ -1 +1 @@
export { default } from "./ControlledAutoComplete";
export { default } from "./ControlledAutoComplete";

+ 49
- 37
src/components/CreateEquipment/CreateEquipment.tsx Vedi File

@@ -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 />} */}


+ 2
- 1
src/components/CreateEquipment/CreateEquipmentLoading.tsx Vedi File

@@ -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} />


+ 12
- 14
src/components/CreateEquipment/CreateEquipmentWrapper.tsx Vedi File

@@ -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;


+ 36
- 31
src/components/CreateEquipment/EquipmentDetails.tsx Vedi File

@@ -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"}


+ 2
- 2
src/components/CreateEquipment/NumberInputProps.ts Vedi File

@@ -1,5 +1,5 @@
import { InputBaseComponentProps } from "@mui/material";

export var NumberInputProps: InputBaseComponentProps = {
step: 0.01,
};
step: 0.01,
};

+ 1
- 1
src/components/CreateEquipment/index.ts Vedi File

@@ -1 +1 @@
export { default } from "./CreateEquipmentWrapper";
export { default } from "./CreateEquipmentWrapper";

+ 51
- 40
src/components/CreateEquipmentType/CreateEquipmentType.tsx Vedi File

@@ -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 />} */}


+ 2
- 1
src/components/CreateEquipmentType/CreateEquipmentTypeLoading.tsx Vedi File

@@ -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} />


+ 10
- 9
src/components/CreateEquipmentType/CreateEquipmentTypeWrapper.tsx Vedi File

@@ -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)}


+ 36
- 31
src/components/CreateEquipmentType/EquipmentTypeDetails.tsx Vedi File

@@ -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"}


+ 2
- 2
src/components/CreateEquipmentType/NumberInputProps.ts Vedi File

@@ -1,5 +1,5 @@
import { InputBaseComponentProps } from "@mui/material";

export var NumberInputProps: InputBaseComponentProps = {
step: 0.01,
};
step: 0.01,
};

+ 1
- 1
src/components/CreateEquipmentType/index.ts Vedi File

@@ -1 +1 @@
export { default } from "./CreateEquipmentTypeWrapper";
export { default } from "./CreateEquipmentTypeWrapper";

Dato che sono stati cambiati molti file in questo diff, alcuni di essi non verranno mostrati

Caricamento…
Annulla
Salva