Parcourir la source

update

feature/axios_provider
MSI\derek il y a 5 mois
Parent
révision
e60e2c054e
33 fichiers modifiés avec 218 ajouts et 433 suppressions
  1. +2
    -2
      src/app/(main)/settings/byProduct/create/page.tsx
  2. +1
    -1
      src/app/(main)/settings/byProduct/edit/page.tsx
  3. +1
    -1
      src/app/(main)/settings/byProduct/page.tsx
  4. +1
    -1
      src/app/(main)/settings/material/create/page.tsx
  5. +2
    -2
      src/app/(main)/settings/material/edit/page.tsx
  6. +2
    -2
      src/app/(main)/settings/material/page.tsx
  7. +1
    -1
      src/app/(main)/settings/product/create/page.tsx
  8. +1
    -1
      src/app/(main)/settings/product/edit/page.tsx
  9. +1
    -1
      src/app/(main)/settings/product/page.tsx
  10. +0
    -39
      src/app/api/settings/byProduct/actions.ts
  11. +0
    -40
      src/app/api/settings/byProduct/index.ts
  12. +9
    -13
      src/app/api/settings/item/actions.ts
  13. +10
    -11
      src/app/api/settings/item/index.ts
  14. +0
    -37
      src/app/api/settings/product/actions.ts
  15. +0
    -40
      src/app/api/settings/product/index.ts
  16. +7
    -2
      src/app/utils/typeEnum.ts
  17. +24
    -32
      src/components/CreateItem/ByProductDetails.tsx
  18. +28
    -38
      src/components/CreateItem/CreateItem.tsx
  19. +2
    -2
      src/components/CreateItem/CreateItemLoading.tsx
  20. +53
    -0
      src/components/CreateItem/CreateItemWrapper.tsx
  21. +15
    -30
      src/components/CreateItem/MaterialDetails.tsx
  22. +0
    -0
      src/components/CreateItem/NumberInputProps.ts
  23. +10
    -11
      src/components/CreateItem/ProductDetails.tsx
  24. +1
    -0
      src/components/CreateItem/index.ts
  25. +0
    -67
      src/components/CreateProductMaterial/CreateProductMaterialWrapper.tsx
  26. +0
    -1
      src/components/CreateProductMaterial/index.ts
  27. +2
    -2
      src/components/InputDataGrid/InputDataGrid.tsx
  28. +16
    -18
      src/components/ItemsSearch/ItemsSearch.tsx
  29. +2
    -2
      src/components/ItemsSearch/ItemsSearchLoading.tsx
  30. +26
    -0
      src/components/ItemsSearch/ItemsSearchWrapper.tsx
  31. +1
    -0
      src/components/ItemsSearch/index.ts
  32. +0
    -35
      src/components/ProductMaterialSearch/ProductMaterialSearchWrapper.tsx
  33. +0
    -1
      src/components/ProductMaterialSearch/index.ts

+ 2
- 2
src/app/(main)/settings/byProduct/create/page.tsx Voir le fichier

@@ -1,6 +1,6 @@
import { SearchParams } from "@/app/utils/fetchUtil";
import { TypeEnum } from "@/app/utils/typeEnum";
import CreateProductMaterial from "@/components/CreateProductMaterial";
import CreateProductMaterial from "@/components/CreateItem";
import { I18nProvider, getServerI18n } from "@/i18n";
import { Typography } from "@mui/material";
import { isString } from "lodash";
@@ -15,7 +15,7 @@ const byProductSetting: React.FC<Props> = async ({ searchParams }) => {
return (
<>
{/* <Typography variant="h4">{t("Create Material")}</Typography> */}
<I18nProvider namespaces={[type]}>
<I18nProvider namespaces={[type.toString()]}>
<CreateProductMaterial type={type} />
</I18nProvider>
</>


+ 1
- 1
src/app/(main)/settings/byProduct/edit/page.tsx Voir le fichier

@@ -1,6 +1,6 @@
import { SearchParams } from "@/app/utils/fetchUtil";
import { TypeEnum } from "@/app/utils/typeEnum";
import CreateProductMaterial from "@/components/CreateProductMaterial";
import CreateProductMaterial from "@/components/CreateItem";
import { I18nProvider, getServerI18n } from "@/i18n";
import { Typography } from "@mui/material";
import { isString } from "lodash";


+ 1
- 1
src/app/(main)/settings/byProduct/page.tsx Voir le fichier

@@ -1,5 +1,5 @@
import { TypeEnum } from "@/app/utils/typeEnum";
import MaterialSearch from "@/components/ProductMaterialSearch";
import MaterialSearch from "@/components/ItemsSearch";
import { getServerI18n } from "@/i18n";
import Add from "@mui/icons-material/Add";
import Button from "@mui/material/Button";


+ 1
- 1
src/app/(main)/settings/material/create/page.tsx Voir le fichier

@@ -1,6 +1,6 @@
import { SearchParams } from "@/app/utils/fetchUtil";
import { TypeEnum } from "@/app/utils/typeEnum";
import CreateProductMaterial from "@/components/CreateProductMaterial";
import CreateProductMaterial from "@/components/CreateItem";
import { I18nProvider, getServerI18n } from "@/i18n";
import { Typography } from "@mui/material";
import { isString } from "lodash";


+ 2
- 2
src/app/(main)/settings/material/edit/page.tsx Voir le fichier

@@ -1,6 +1,6 @@
import { SearchParams } from "@/app/utils/fetchUtil";
import { TypeEnum } from "@/app/utils/typeEnum";
import CreateProductMaterial from "@/components/CreateProductMaterial";
import CreateProductMaterial from "@/components/CreateItem";
import { I18nProvider, getServerI18n } from "@/i18n";
import { Typography } from "@mui/material";
import { isString } from "lodash";
@@ -22,7 +22,7 @@ const materialSetting: React.FC<Props> = async ({ searchParams }) => {
return (
<>
{/* <Typography variant="h4">{t("Create Material")}</Typography> */}
<I18nProvider namespaces={[type]}>
<I18nProvider namespaces={[type.toString()]}>
<CreateProductMaterial type={type} id={id} />
</I18nProvider>
</>


+ 2
- 2
src/app/(main)/settings/material/page.tsx Voir le fichier

@@ -1,5 +1,5 @@
import { TypeEnum } from "@/app/utils/typeEnum";
import MaterialSearch from "@/components/ProductMaterialSearch";
import MaterialSearch from "@/components/ItemsSearch";
import { getServerI18n } from "@/i18n";
import Add from "@mui/icons-material/Add";
import Button from "@mui/material/Button";
@@ -15,7 +15,7 @@ export const metadata: Metadata = {

const materialSetting: React.FC = async () => {
const material = TypeEnum.MATERIAL
const { t } = await getServerI18n(material);
const { t } = await getServerI18n("material");
// preloadClaims();

return (


+ 1
- 1
src/app/(main)/settings/product/create/page.tsx Voir le fichier

@@ -1,6 +1,6 @@
import { SearchParams } from "@/app/utils/fetchUtil";
import { TypeEnum } from "@/app/utils/typeEnum";
import CreateProductMaterial from "@/components/CreateProductMaterial";
import CreateProductMaterial from "@/components/CreateItem";
import { I18nProvider, getServerI18n } from "@/i18n";
import { Typography } from "@mui/material";
import isString from "lodash/isString";


+ 1
- 1
src/app/(main)/settings/product/edit/page.tsx Voir le fichier

@@ -1,6 +1,6 @@
import { SearchParams } from "@/app/utils/fetchUtil";
import { TypeEnum } from "@/app/utils/typeEnum";
import CreateProductMaterial from "@/components/CreateProductMaterial";
import CreateProductMaterial from "@/components/CreateItem";
import { I18nProvider, getServerI18n } from "@/i18n";
import { Typography } from "@mui/material";
import isString from "lodash/isString";


+ 1
- 1
src/app/(main)/settings/product/page.tsx Voir le fichier

@@ -1,5 +1,5 @@
import { TypeEnum } from "@/app/utils/typeEnum";
import MaterialSearch from "@/components/ProductMaterialSearch";
import MaterialSearch from "@/components/ItemsSearch";
import { getServerI18n } from "@/i18n";
import Add from "@mui/icons-material/Add";
import Button from "@mui/material/Button";


+ 0
- 39
src/app/api/settings/byProduct/actions.ts Voir le fichier

@@ -1,39 +0,0 @@
"use server";
import { ServerFetchError, serverFetchJson, serverFetchWithNoContent } from "@/app/utils/fetchUtil";
import { revalidateTag } from "next/cache";
import { BASE_API_URL } from "@/config/api";
import { TypeInputs, UomInputs, WeightUnitInputs } from "../material/actions";
import { CreateItemResponse } from "../../utils";

export type CreateByProductInputs = {
id?: string | number
code: string;
name: string;
// same goes for other props
// change backend for null or not null
description?: string | undefined;
remarks?: string | undefined;
shelfLife?: Number | undefined;
countryOfOrigin?: string | undefined;
minHumid?: number | undefined;
maxHumid?: number | undefined;
minTemp?: number | undefined;
maxTemp?: number | undefined;
sampleRate?: number | undefined;
passingRate?: number | undefined;
netWeight?: number | undefined;
type?: TypeInputs[];
uom?: UomInputs[];
weightUnit?: WeightUnitInputs[];
}

export const saveByProduct = async (data: CreateByProductInputs) => {
// try {
const byProduct = await serverFetchJson<CreateItemResponse<CreateByProductInputs>>(`${BASE_API_URL}/byProduct/new`, {
method: "POST",
body: JSON.stringify(data),
headers: { "Content-Type": "application/json" },
});
revalidateTag("byProduct");
return byProduct
};

+ 0
- 40
src/app/api/settings/byProduct/index.ts Voir le fichier

@@ -1,40 +0,0 @@
import { cache } from "react";
import "server-only";
import { serverFetchJson } from "@/app/utils/fetchUtil";
import { BASE_API_URL } from "@/config/api";
import { TypeInputs, UomInputs, WeightUnitInputs } from "../material/actions";

export type ByProductResult = {
id: string | number
code: string;
name: string;
description: string | undefined;
remarks: string | undefined;
shelfLife: Number | undefined;
countryOfOrigin: string | undefined;
minHumid: number | undefined;
maxHumid: number | undefined;
minTemp: number | undefined;
maxTemp: number | undefined;
sampleRate: number | undefined;
passingRate: number | undefined;
netWeight: number | undefined;
uom: UomInputs[];
weightUnit: WeightUnitInputs[];
type: TypeInputs[];
action?: any;
}


export const fetchAllByProduct = cache(async () => {
return serverFetchJson<ByProductResult[]>(`${BASE_API_URL}/byProduct`, {
next: { tags: ["byProduct"] },
});
});


export const fetchByProduct = cache(async (id: number) => {
return serverFetchJson<ByProductResult>(`${BASE_API_URL}/byProduct/details/${id}`, {
next: { tags: ["byProduct"] },
});
});

src/app/api/settings/material/actions.ts → src/app/api/settings/item/actions.ts Voir le fichier

@@ -6,7 +6,8 @@ import { HTMLInputTypeAttribute } from "react";
import { CreateItemResponse } from "../../utils";

export type TypeInputs = {
type: string
id: number;
name: string
}
export type UomInputs = {
uom: string
@@ -15,13 +16,10 @@ export type WeightUnitInputs = {
weightUnit: string
conversion: number
}
export type CreateMaterialInputs = {
export type CreateItemInputs = {
id?: string | number
code: string;
name: string;
isConsumables: boolean;
// same goes for other props
// change backend for null or not null
description?: string | undefined;
remarks?: string | undefined;
shelfLife?: Number | undefined;
@@ -32,19 +30,17 @@ export type CreateMaterialInputs = {
maxTemp?: number | undefined;
sampleRate?: number | undefined;
passingRate?: number | undefined;
netWeight?: number | undefined;
type?: TypeInputs[];
uom?: UomInputs[];
weightUnit?: WeightUnitInputs[];
netWeight: number;
typeId: number;
}

export const saveMaterial = async (data: CreateMaterialInputs) => {
export const saveItem = async (data: CreateItemInputs) => {
// try {
const material = await serverFetchJson<CreateItemResponse<CreateMaterialInputs>>(`${BASE_API_URL}/material/new`, {
const item = await serverFetchJson<CreateItemResponse<CreateItemInputs>>(`${BASE_API_URL}/items/new`, {
method: "POST",
body: JSON.stringify(data),
headers: { "Content-Type": "application/json" },
});
revalidateTag("material");
return material
revalidateTag("items");
return item
};

src/app/api/settings/material/index.ts → src/app/api/settings/item/index.ts Voir le fichier

@@ -4,11 +4,10 @@ import { serverFetchJson } from "@/app/utils/fetchUtil";
import { BASE_API_URL } from "@/config/api";
import { TypeInputs, UomInputs, WeightUnitInputs } from "./actions";

export type MaterialResult = {
export type ItemsResult = {
id: string | number
code: string;
name: string;
isConsumables: boolean;
description: string | undefined;
remarks: string | undefined;
shelfLife: Number | undefined;
@@ -20,22 +19,22 @@ export type MaterialResult = {
sampleRate: number | undefined;
passingRate: number | undefined;
netWeight: number | undefined;
uom: UomInputs[];
weightUnit: WeightUnitInputs[];
type: TypeInputs[];
// uom: UomInputs[];
// weightUnit: WeightUnitInputs[];
type: TypeInputs;
action?: any
}


export const fetchAllMaterials = cache(async () => {
return serverFetchJson<MaterialResult[]>(`${BASE_API_URL}/material`, {
next: { tags: ["material"] },
export const fetchAllItems = cache(async () => {
return serverFetchJson<ItemsResult[]>(`${BASE_API_URL}/items`, {
next: { tags: ["items"] },
});
});


export const fetchMaterial = cache(async (id: number) => {
return serverFetchJson<MaterialResult>(`${BASE_API_URL}/material/details/${id}`, {
next: { tags: ["material"] },
export const fetchItem = cache(async (id: number) => {
return serverFetchJson<ItemsResult>(`${BASE_API_URL}/items/details/${id}`, {
next: { tags: ["items"] },
});
});

+ 0
- 37
src/app/api/settings/product/actions.ts Voir le fichier

@@ -1,37 +0,0 @@
"use server";
import { ServerFetchError, serverFetchJson, serverFetchWithNoContent } from "@/app/utils/fetchUtil";
import { revalidateTag } from "next/cache";
import { BASE_API_URL } from "@/config/api";
import { TypeInputs, UomInputs, WeightUnitInputs } from "../material/actions";
import { CreateItemResponse } from "../../utils";

export type CreateProductInputs = {
id?: string | number
code: string;
name: string;
description?: string | undefined;
remarks?: string | undefined;
shelfLife?: number | undefined;
countryOfOrigin?: string | undefined;
minHumid?: number | undefined;
maxHumid?: number | undefined;
minTemp?: number | undefined;
maxTemp?: number | undefined;
sampleRate?: number | undefined;
passingRate?: number | undefined;
netWeight?: number | undefined;
type?: TypeInputs[];
uom?: UomInputs[];
weightUnit?: WeightUnitInputs[];
}

export const saveProduct = async (data: CreateProductInputs) => {
// try {
const product = await serverFetchJson<CreateItemResponse<CreateProductInputs>>(`${BASE_API_URL}/product/new`, {
method: "POST",
body: JSON.stringify(data),
headers: { "Content-Type": "application/json" },
});
revalidateTag("product");
return product
};

+ 0
- 40
src/app/api/settings/product/index.ts Voir le fichier

@@ -1,40 +0,0 @@
import { cache } from "react";
import "server-only";
import { serverFetchJson } from "@/app/utils/fetchUtil";
import { BASE_API_URL } from "@/config/api";
import { TypeInputs, UomInputs, WeightUnitInputs } from "../material/actions";

export type ProductResult = {
id: string | number
code: string;
name: string;
description: string | undefined;
remarks: string | undefined;
shelfLife: Number | undefined;
countryOfOrigin: string | undefined;
minHumid: number | undefined;
maxHumid: number | undefined;
minTemp: number | undefined;
maxTemp: number | undefined;
sampleRate: number | undefined;
passingRate: number | undefined;
netWeight: number | undefined;
uom: UomInputs[];
weightUnit: WeightUnitInputs[];
type: TypeInputs[];
action?: any;
}


export const fetchAllProduct = cache(async () => {
return serverFetchJson<ProductResult[]>(`${BASE_API_URL}/product`, {
next: { tags: ["product"] },
});
});


export const fetchProduct = cache(async (id: number) => {
return serverFetchJson<ProductResult>(`${BASE_API_URL}/product/details/${id}`, {
next: { tags: ["product"] },
});
});

+ 7
- 2
src/app/utils/typeEnum.ts Voir le fichier

@@ -1,5 +1,10 @@
export enum TypeEnum {
PRODUCT = "product",
MATERIAL = "material",
MATERIAL_ID = 1,
PRODUCT = "product",
PRODUCT_ID = 2,
BYPRODUCT = "byProduct",
}
BYPRODUCT_ID = 3,
CONSUMABLE = "consumables",
CONSUMABLE_ID = 4,
}

src/components/CreateProductMaterial/ByProductDetails.tsx → src/components/CreateItem/ByProductDetails.tsx Voir le fichier

@@ -1,5 +1,5 @@
"use client";
import { CreateMaterialInputs } from "@/app/api/settings/material/actions";
import { CreateItemInputs } from "@/app/api/settings/item/actions";
import {
Box,
Card,
@@ -12,27 +12,24 @@ import {
import { useFormContext } from "react-hook-form";
import { useTranslation } from "react-i18next";
import InputDataGrid from "../InputDataGrid";
import { useCallback, useMemo, useState } from "react";
import { useCallback, useEffect, useMemo, useState } from "react";
import { GridColDef, GridRowModel } from "@mui/x-data-grid";
import { InputDataGridProps, TableRow } from "../InputDataGrid/InputDataGrid";
import { TypeEnum } from "@/app/utils/typeEnum";
import { CreateByProductInputs } from "@/app/api/settings/byProduct/actions";
import { NumberInputProps } from "./NumberInputProps";

type Props = {
// isEditMode: boolean;
// type: TypeEnum;
// isEditMode: boolean;
// type: TypeEnum;
};

export type EntryError =
| {
[field in keyof CreateByProductInputs]?: string;
[field in keyof CreateItemInputs]?: string;
}
| undefined;

const ByProductDetails: React.FC<Props> = ({
}) => {
const ByProductDetails: React.FC<Props> = ({}) => {
const {
t,
i18n: { language },
@@ -49,7 +46,7 @@ const ByProductDetails: React.FC<Props> = ({
resetField,
setError,
clearErrors,
} = useFormContext<CreateByProductInputs>();
} = useFormContext<CreateItemInputs>();
const typeColumns = useMemo<GridColDef[]>(
() => [
{
@@ -93,7 +90,7 @@ const ByProductDetails: React.FC<Props> = ({

const validationTest = useCallback(
(
newRow: GridRowModel<TableRow<Partial<CreateByProductInputs>, EntryError>>
newRow: GridRowModel<TableRow<Partial<CreateItemInputs>, EntryError>>
): EntryError => {
const error: EntryError = {};
console.log(newRow);
@@ -102,6 +99,22 @@ const ByProductDetails: React.FC<Props> = ({
[]
);

const validateUom = useCallback(
(
newRow: GridRowModel<TableRow<Partial<CreateItemInputs>, EntryError>>
): EntryError => {
const error: EntryError = {};
console.log(newRow);
// if (!newRow.uom) {
// error.uom = "Uom cannot be empty";
// }
return Object.keys(error).length > 0 ? error : undefined;
},
[]
);
useEffect(() => {
console.log(errors)
}, [errors])
return (
<Card sx={{ display: "block" }}>
<CardContent component={Stack} spacing={4}>
@@ -272,27 +285,6 @@ const ByProductDetails: React.FC<Props> = ({
helperText={errors.netWeight?.message}
/>
</Grid>
<Grid item xs={6}>
<InputDataGrid<CreateByProductInputs, EntryError>
_formKey={"type"}
columns={typeColumns}
validateRow={validationTest}
/>
</Grid>
<Grid item xs={6}>
<InputDataGrid<CreateByProductInputs, EntryError>
_formKey={"uom"}
columns={uomColumns}
validateRow={validationTest}
/>
</Grid>
<Grid item xs={12}>
<InputDataGrid<CreateByProductInputs, EntryError>
_formKey={"weightUnit"}
columns={weightUnitColumns}
validateRow={validationTest}
/>
</Grid>
</Grid>
</Box>
</CardContent>

src/components/CreateProductMaterial/CreateProductMaterial.tsx → src/components/CreateItem/CreateItem.tsx Voir le fichier

@@ -4,9 +4,9 @@ import { useCallback, useEffect, useMemo, useState } from "react";
import { useRouter, useSearchParams } from "next/navigation";
import { useTranslation } from "react-i18next";
import {
CreateMaterialInputs,
saveMaterial,
} from "@/app/api/settings/material/actions";
CreateItemInputs,
saveItem,
} from "@/app/api/settings/item/actions";
import {
FormProvider,
SubmitErrorHandler,
@@ -17,67 +17,69 @@ import { deleteDialog } from "../Swal/CustomAlerts";
import { Box, Button, Grid, Stack, Typography } from "@mui/material";
import { Check, Close, EditNote } from "@mui/icons-material";
import { TypeEnum } from "@/app/utils/typeEnum";
import {
CreateProductInputs,
saveProduct,
} from "@/app/api/settings/product/actions";
import { CreateInputsFields } from "./CreateProductMaterialWrapper";
import MaterialDetails from "./MaterialDetails";
import ProductDetails from "./ProductDetails";
import { CreateItemResponse } from "@/app/api/utils";
import { CreateByProductInputs, saveByProduct } from "@/app/api/settings/byProduct/actions";
import ByProductDetails from "./ByProductDetails";

type Props = {
isEditMode: boolean;
type: TypeEnum;
defaultValues: Partial<CreateInputsFields> | undefined;
defaultValues: Partial<CreateItemInputs> | undefined;
};

const CreateProductMaterial: React.FC<Props> = ({
const CreateItem: React.FC<Props> = ({
isEditMode,
type,
defaultValues,
}) => {
console.log(type)
const [serverError, setServerError] = useState("");
const [tabIndex, setTabIndex] = useState(0);
const { t } = useTranslation();
const router = useRouter();
const [title, mode, redirPath] = useMemo(() => {
const [typeId, title, mode, redirPath] = useMemo(() => {
var typeId = TypeEnum.CONSUMABLE_ID
var title = "";
var mode = "";
var redirPath = "";
if (type === TypeEnum.MATERIAL) {
typeId = TypeEnum.MATERIAL_ID
title = "Material";
redirPath = "/material";
redirPath = "/settings/material";
}
if (type === TypeEnum.PRODUCT) {
typeId = TypeEnum.PRODUCT_ID
title = "Product";
redirPath = "/product";
redirPath = "/settings/product";
}
if (type === TypeEnum.BYPRODUCT) {
typeId = TypeEnum.BYPRODUCT_ID
title = "By-Product";
redirPath = "/byProduct";
redirPath = "/settings/byProduct";
}
if (isEditMode) {
mode = "Edit";
} else {
mode = "Create";
}
return [title, mode, redirPath];
return [typeId, title, mode, redirPath];
}, [type, isEditMode]);

const formProps = useForm<CreateInputsFields>({
defaultValues: defaultValues ? defaultValues : {},
console.log(typeId)
const formProps = useForm<CreateItemInputs>({
defaultValues: defaultValues ? defaultValues : {
typeId: typeId
},
});
const errors = formProps.formState.errors;

const handleCancel = () => {
router.replace(`/settings/${type}`);
};
const onSubmit = useCallback<SubmitHandler<CreateInputsFields>>(
const onSubmit = useCallback<SubmitHandler<CreateItemInputs>>(
async (data, event) => {
let hasErrors = false;
console.log("dasasdasd")
try {
// checking humid input
if (data.maxHumid && data.minHumid!! > data.maxHumid!!) {
@@ -135,31 +137,19 @@ const CreateProductMaterial: React.FC<Props> = ({
}
console.log("data posted");
console.log(data);
// do api
var response;
if (type === TypeEnum.MATERIAL) {
response = await saveMaterial(data as CreateMaterialInputs);
} else if (type === TypeEnum.PRODUCT) {
response = await saveProduct(data as CreateProductInputs);
} else if (type === TypeEnum.BYPRODUCT) {
// response = await saveByProduct(data as CreateByProductInputs);

} else {
// Handle unexpected type
throw new Error("Invalid type provided");
}
// return
// do api
var response = await saveItem(data);
if (response) {
if (!Boolean(response.id)) {
formProps.setError(response.errorPosition!! as keyof CreateInputsFields, {
formProps.setError(response.errorPosition!! as keyof CreateItemInputs, {
message: response.message!!,
type: "required",
});
throw response;
} else if (Boolean(response.id)) {
router.replace(redirPath);
}
} else {
throw "no response";
}
} catch (e) {
// backend error
@@ -171,7 +161,7 @@ const CreateProductMaterial: React.FC<Props> = ({
);

// multiple tabs
const onSubmitError = useCallback<SubmitErrorHandler<CreateInputsFields>>(
const onSubmitError = useCallback<SubmitErrorHandler<CreateItemInputs>>(
(errors) => {},
[]
);
@@ -220,4 +210,4 @@ const CreateProductMaterial: React.FC<Props> = ({
</>
);
};
export default CreateProductMaterial;
export default CreateItem;

src/components/CreateProductMaterial/CreateProductMaterialLoading.tsx → src/components/CreateItem/CreateItemLoading.tsx Voir le fichier

@@ -5,7 +5,7 @@ import Stack from "@mui/material/Stack";
import React from "react";

// Can make this nicer
export const CreateProductMaterialLoading: React.FC = () => {
export const CreateItemLoading: React.FC = () => {
return (
<>
<Card>
@@ -37,4 +37,4 @@ export const CreateProductMaterialLoading: React.FC = () => {
);
};

export default CreateProductMaterialLoading;
export default CreateItemLoading;

+ 53
- 0
src/components/CreateItem/CreateItemWrapper.tsx Voir le fichier

@@ -0,0 +1,53 @@
import { TypeEnum } from "@/app/utils/typeEnum";
import CreateItem from "./CreateItem";
import CreateItemLoading from "./CreateItemLoading";
import { CreateItemInputs } from "@/app/api/settings/item/actions";
import { notFound } from "next/navigation";
import { fetchItem } from "@/app/api/settings/item";
interface SubComponents {
Loading: typeof CreateItemLoading;
}

type Props = {
id?: number
type: TypeEnum;
};

const CreateItemWrapper: React.FC<Props> &
SubComponents = async ({ type, id }) => {
var result
var defaultValues: Partial<CreateItemInputs> | undefined
console.log(type)
if (id) {
result = await fetchItem(id);
console.log(result)
defaultValues = {
typeId: result?.type.id,
id: result?.id,
code: result?.code,
name: result?.name,
description: result?.description,
remarks: result?.remarks,
shelfLife: result?.shelfLife,
countryOfOrigin: result?.countryOfOrigin,
minHumid: result?.minHumid,
maxHumid: result?.maxHumid,
minTemp: result?.minTemp,
maxTemp: result?.maxTemp,
sampleRate: result?.sampleRate,
passingRate: result?.passingRate,
netWeight: result?.netWeight
};
}
return (
<CreateItem
isEditMode={Boolean(id)}
type={type}
defaultValues={defaultValues}
/>
);
};
CreateItemWrapper.Loading = CreateItemLoading;

export default CreateItemWrapper;

src/components/CreateProductMaterial/MaterialDetails.tsx → src/components/CreateItem/MaterialDetails.tsx Voir le fichier

@@ -1,5 +1,5 @@
"use client";
import { CreateMaterialInputs } from "@/app/api/settings/material/actions";
import { CreateItemInputs } from "@/app/api/settings/item/actions";
import {
Box,
Card,
@@ -31,7 +31,7 @@ type Props = {

export type EntryError =
| {
[field in keyof CreateMaterialInputs]?: string;
[field in keyof CreateItemInputs]?: string;
}
| undefined;

@@ -52,8 +52,9 @@ const MaterialDetails: React.FC<Props> = ({}) => {
resetField,
setError,
clearErrors,
} = useFormContext<CreateMaterialInputs>();
} = useFormContext<CreateItemInputs>();
// textfield error msg locale problem
console.log(defaultValues)
const typeColumns = useMemo<GridColDef[]>(
() => [
{
@@ -97,7 +98,7 @@ const MaterialDetails: React.FC<Props> = ({}) => {

const validationTest = useCallback(
(
newRow: GridRowModel<TableRow<Partial<CreateMaterialInputs>, EntryError>>
newRow: GridRowModel<TableRow<Partial<CreateItemInputs>, EntryError>>
): EntryError => {
const error: EntryError = {};
console.log(newRow);
@@ -117,15 +118,20 @@ const MaterialDetails: React.FC<Props> = ({}) => {
<FormControlLabel
control={
<Controller
name={"isConsumables"}
name={"typeId"}
control={control}
render={({ field: props }) => (
render={({ field: props }) => {
console.log(props)
return (
<Checkbox
{...props}
checked={props.value}
onChange={(e) => props.onChange(e.target.checked)}
checked={props.value === TypeEnum.CONSUMABLE_ID}
onChange={(e) => {
const newValue = e.target.checked ? TypeEnum.CONSUMABLE_ID : TypeEnum.MATERIAL_ID;
props.onChange(newValue);
}}
/>
)}
)}}
/>
}
label={
@@ -310,27 +316,6 @@ const MaterialDetails: React.FC<Props> = ({}) => {
helperText={errors.netWeight?.message}
/>
</Grid>
<Grid item xs={6}>
<InputDataGrid<CreateMaterialInputs, EntryError>
_formKey={"type"}
columns={typeColumns}
validateRow={validationTest}
/>
</Grid>
<Grid item xs={6}>
<InputDataGrid<CreateMaterialInputs, EntryError>
_formKey={"uom"}
columns={uomColumns}
validateRow={validationTest}
/>
</Grid>
<Grid item xs={12}>
<InputDataGrid<CreateMaterialInputs, EntryError>
_formKey={"weightUnit"}
columns={weightUnitColumns}
validateRow={validationTest}
/>
</Grid>
</Grid>
</Box>
</CardContent>

src/components/CreateProductMaterial/NumberInputProps.ts → src/components/CreateItem/NumberInputProps.ts Voir le fichier


src/components/CreateProductMaterial/ProductDetails.tsx → src/components/CreateItem/ProductDetails.tsx Voir le fichier

@@ -1,5 +1,4 @@
"use client";
import { CreateMaterialInputs } from "@/app/api/settings/material/actions";
import {
Box,
Card,
@@ -16,8 +15,8 @@ import { useCallback, useMemo, useState } from "react";
import { GridColDef, GridRowModel } from "@mui/x-data-grid";
import { InputDataGridProps, TableRow } from "../InputDataGrid/InputDataGrid";
import { TypeEnum } from "@/app/utils/typeEnum";
import { CreateProductInputs } from "@/app/api/settings/product/actions";
import { NumberInputProps } from "./NumberInputProps";
import { CreateItemInputs } from "@/app/api/settings/item/actions";

type Props = {
// isEditMode: boolean;
@@ -26,7 +25,7 @@ type Props = {

export type EntryError =
| {
[field in keyof CreateProductInputs]?: string;
[field in keyof CreateItemInputs]?: string;
}
| undefined;

@@ -49,7 +48,7 @@ const ProductDetails: React.FC<Props> = ({
resetField,
setError,
clearErrors,
} = useFormContext<CreateProductInputs>();
} = useFormContext<CreateItemInputs>();
const typeColumns = useMemo<GridColDef[]>(
() => [
{
@@ -93,7 +92,7 @@ const ProductDetails: React.FC<Props> = ({

const validationTest = useCallback(
(
newRow: GridRowModel<TableRow<Partial<CreateProductInputs>, EntryError>>
newRow: GridRowModel<TableRow<Partial<CreateItemInputs>, EntryError>>
): EntryError => {
const error: EntryError = {};
console.log(newRow);
@@ -276,28 +275,28 @@ const ProductDetails: React.FC<Props> = ({
helperText={errors.netWeight?.message}
/>
</Grid>
<Grid item xs={6}>
<InputDataGrid<CreateProductInputs, EntryError>
{/* <Grid item xs={6}>
<InputDataGrid<CreateItemInputs, EntryError>
_formKey={"type"}
columns={typeColumns}
validateRow={validationTest}
/>
</Grid>
<Grid item xs={6}>
<InputDataGrid<CreateProductInputs, EntryError>
<InputDataGrid<CreateItemInputs, EntryError>
_formKey={"uom"}
columns={uomColumns}
validateRow={validationTest}
/>
</Grid>
<Grid item xs={12}>
<InputDataGrid<CreateProductInputs, EntryError>
<InputDataGrid<CreateItemInputs, EntryError>
_formKey={"weightUnit"}
columns={weightUnitColumns}
validateRow={validationTest}
/>
</Grid>
</Grid>
</Grid>*/}
</Grid>
</Box>
</CardContent>
</Card>

+ 1
- 0
src/components/CreateItem/index.ts Voir le fichier

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

+ 0
- 67
src/components/CreateProductMaterial/CreateProductMaterialWrapper.tsx Voir le fichier

@@ -1,67 +0,0 @@
import { TypeEnum } from "@/app/utils/typeEnum";
import CreateProductMaterial from "./CreateProductMaterial";
import CreateMaterialLoading from "./CreateProductMaterialLoading";
import { CreateMaterialInputs } from "@/app/api/settings/material/actions";
import { CreateProductInputs } from "@/app/api/settings/product/actions";
import { fetchMaterial } from "@/app/api/settings/material";
import { fetchProduct } from "@/app/api/settings/product";
import { fetchByProduct } from "@/app/api/settings/byProduct";
import { notFound } from "next/navigation";
import { CreateByProductInputs } from "@/app/api/settings/byProduct/actions";
interface SubComponents {
Loading: typeof CreateMaterialLoading;
}

type Props = {
id?: number
type: TypeEnum;
};

export type CreateInputsFields = CreateMaterialInputs | CreateProductInputs | CreateByProductInputs;

const CreateProductMaterialWrapper: React.FC<Props> &
SubComponents = async ({ type, id }) => {
var defaultValues: Partial<CreateInputsFields> = {};
var result
if (id && type === TypeEnum.MATERIAL) {
result = await fetchMaterial(id);
defaultValues = {
isConsumables: result.isConsumables
}
} else if (id && type === TypeEnum.PRODUCT) {
result = await fetchProduct(id);
} else if (id && type === TypeEnum.BYPRODUCT) {
result = await fetchByProduct(id);
}
defaultValues = {
...defaultValues,
id: result?.id,
code: result?.code,
name: result?.name,
description: result?.description,
type: result?.type,
remarks: result?.remarks,
shelfLife: result?.shelfLife,
countryOfOrigin: result?.countryOfOrigin,
minHumid: result?.minHumid,
maxHumid: result?.maxHumid,
minTemp: result?.minTemp,
maxTemp: result?.maxTemp,
sampleRate: result?.sampleRate,
passingRate: result?.passingRate,
netWeight: result?.netWeight,
uom: result?.uom,
weightUnit: result?.weightUnit,
};
return (
<CreateProductMaterial
isEditMode={Boolean(id)}
type={type}
defaultValues={defaultValues}
/>
);
};
CreateProductMaterialWrapper.Loading = CreateMaterialLoading;

export default CreateProductMaterialWrapper;

+ 0
- 1
src/components/CreateProductMaterial/index.ts Voir le fichier

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

+ 2
- 2
src/components/InputDataGrid/InputDataGrid.tsx Voir le fichier

@@ -151,7 +151,7 @@ function InputDataGrid<T, E>({

const reset = useCallback(() => {
setRowModesModel({})
setRows([])
setRows(originalRows)
}, []);

const handleCancel = useCallback(
@@ -239,7 +239,7 @@ function InputDataGrid<T, E>({
<Button
disableRipple
variant="outlined"
startIcon={<Add />}
startIcon={<Add />}
onClick={addRow}
size="small"
>


src/components/ProductMaterialSearch/ProductMaterialSearch.tsx → src/components/ItemsSearch/ItemsSearch.tsx Voir le fichier

@@ -2,26 +2,24 @@

import { useCallback, useMemo, useState } from "react";
import SearchBox, { Criterion } from "../SearchBox";
import { MaterialResult } from "@/app/api/settings/material";
import { ItemsResult } from "@/app/api/settings/item";
import { useTranslation } from "react-i18next";
import SearchResults, { Column } from "../SearchResults";
import { EditNote } from "@mui/icons-material";
import { useRouter, useSearchParams } from "next/navigation";
import { GridDeleteIcon } from "@mui/x-data-grid";
import { TypeEnum } from "@/app/utils/typeEnum";
import { ProductResult } from "@/app/api/settings/product";

export type ListResult = MaterialResult | ProductResult;
type Props = {
productMaterial: ListResult[];
items: ItemsResult[];
type: TypeEnum;
};
type SearchQuery = Partial<Omit<ListResult, "id">>;
type SearchQuery = Partial<Omit<ItemsResult, "id">>;
type SearchParamNames = keyof SearchQuery;

const MaterialSearch: React.FC<Props> = ({ productMaterial, type }) => {
const [filteredItems, setFilteredItems] = useState<ListResult[]>(productMaterial);
const { t } = useTranslation(type);
const ItemsSearch: React.FC<Props> = ({ items, type }) => {
const [filteredItems, setFilteredItems] = useState<ItemsResult[]>(items);
const { t } = useTranslation(type.toString());
const router = useRouter();

const searchCriteria: Criterion<SearchParamNames>[] = useMemo(
@@ -38,22 +36,22 @@ const MaterialSearch: React.FC<Props> = ({ productMaterial, type }) => {
}
return searchCriteria
},
[t, productMaterial]
[t, items]
);

const onDetailClick = useCallback(
(productMaterial: ListResult) => {
router.push(`/settings/${type}/edit?id=${productMaterial.id}`);
(item: ItemsResult) => {
router.push(`/settings/${type}/edit?id=${item.id}`);
},
[type, router]
);

const onDeleteClick = useCallback(
(productMaterial: ListResult) => {},
(item: ItemsResult) => {},
[router]
);

const columns = useMemo<Column<ListResult>[]>(
const columns = useMemo<Column<ItemsResult>[]>(
() => [
{
name: "id",
@@ -80,8 +78,8 @@ const MaterialSearch: React.FC<Props> = ({ productMaterial, type }) => {
);

const onReset = useCallback(() => {
setFilteredItems(productMaterial);
}, [productMaterial]);
setFilteredItems(items);
}, [items]);

return (
<>
@@ -89,7 +87,7 @@ const MaterialSearch: React.FC<Props> = ({ productMaterial, type }) => {
criteria={searchCriteria}
onSearch={(query) => {
setFilteredItems(
productMaterial.filter((pm) => {
items.filter((pm) => {
if (type === TypeEnum.MATERIAL) {
return (
pm.code.toLowerCase().includes(query.code.toLowerCase()) &&
@@ -111,9 +109,9 @@ const MaterialSearch: React.FC<Props> = ({ productMaterial, type }) => {
}}
onReset={onReset}
/>
<SearchResults<ListResult> items={filteredItems} columns={columns} />
<SearchResults<ItemsResult> items={filteredItems} columns={columns} />
</>
);
};

export default MaterialSearch;
export default ItemsSearch;

src/components/ProductMaterialSearch/ProductMaterialSearchLoading.tsx → src/components/ItemsSearch/ItemsSearchLoading.tsx Voir le fichier

@@ -5,7 +5,7 @@ import Stack from "@mui/material/Stack";
import React from "react";

// Can make this nicer
export const ProductMaterialSearchLoading: React.FC = () => {
export const ItemsSearchLoading: React.FC = () => {
return (
<>
<Card>
@@ -37,4 +37,4 @@ export const ProductMaterialSearchLoading: React.FC = () => {
);
};

export default ProductMaterialSearchLoading;
export default ItemsSearchLoading;

+ 26
- 0
src/components/ItemsSearch/ItemsSearchWrapper.tsx Voir le fichier

@@ -0,0 +1,26 @@
import { fetchAllItems, } from "@/app/api/settings/item";
import ItemsSearch from "./ItemsSearch";
import ItemsSearchLoading from "./ItemsSearchLoading";
import { SearchParams } from "@/app/utils/fetchUtil";
import { TypeEnum } from "@/app/utils/typeEnum";
import { notFound } from "next/navigation";

interface SubComponents {
Loading: typeof ItemsSearchLoading;
}

type Props = {
type: TypeEnum;
};

const ItemsSearchWrapper: React.FC<Props> & SubComponents = async ({
type,
}) => {
console.log(type)
var result = await fetchAllItems()
return <ItemsSearch items={result} type={type} />;
};

ItemsSearchWrapper.Loading = ItemsSearchLoading;

export default ItemsSearchWrapper;

+ 1
- 0
src/components/ItemsSearch/index.ts Voir le fichier

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

+ 0
- 35
src/components/ProductMaterialSearch/ProductMaterialSearchWrapper.tsx Voir le fichier

@@ -1,35 +0,0 @@
import { fetchAllMaterials, MaterialResult } from "@/app/api/settings/material";
import ProductMaterialSearch, { ListResult } from "./ProductMaterialSearch";
import MaterialSearchLoading from "./ProductMaterialSearchLoading";
import { SearchParams } from "@/app/utils/fetchUtil";
import { TypeEnum } from "@/app/utils/typeEnum";
import { notFound } from "next/navigation";

interface SubComponents {
Loading: typeof MaterialSearchLoading;
}

type Props = {
type: TypeEnum;
};

const ProductMaterialSearchWrapper: React.FC<Props> & SubComponents = async ({
type,
}) => {
var result: ListResult[] = [];
if (TypeEnum.PRODUCT === type) {
result = [];
} else if (TypeEnum.MATERIAL === type) {
result = await fetchAllMaterials();
} else if (TypeEnum.BYPRODUCT === type) {
result = [];
} else {
notFound();
}

return <ProductMaterialSearch productMaterial={result} type={type} />;
};

ProductMaterialSearchWrapper.Loading = MaterialSearchLoading;

export default ProductMaterialSearchWrapper;

+ 0
- 1
src/components/ProductMaterialSearch/index.ts Voir le fichier

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

Chargement…
Annuler
Enregistrer