FPSMS-frontend
Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.

CreateItem.tsx 8.1 KiB

11 miesięcy temu
11 miesięcy temu
11 miesięcy temu
11 miesięcy temu
11 miesięcy temu
10 miesięcy temu
11 miesięcy temu
10 miesięcy temu
11 miesięcy temu
11 miesięcy temu
11 miesięcy temu
11 miesięcy temu
7 miesięcy temu
11 miesięcy temu
11 miesięcy temu
10 miesięcy temu
11 miesięcy temu
11 miesięcy temu
11 miesięcy temu
11 miesięcy temu
11 miesięcy temu
11 miesięcy temu
11 miesięcy temu
10 miesięcy temu
11 miesięcy temu
11 miesięcy temu
10 miesięcy temu
11 miesięcy temu
11 miesięcy temu
11 miesięcy temu
11 miesięcy temu
11 miesięcy temu
10 miesięcy temu
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. "use client";
  2. import { useCallback, useEffect, useMemo, useState } from "react";
  3. import { useRouter, useSearchParams } from "next/navigation";
  4. import { useTranslation } from "react-i18next";
  5. import { CreateItemInputs, saveItem } from "@/app/api/settings/item/actions";
  6. import {
  7. FormProvider,
  8. SubmitErrorHandler,
  9. SubmitHandler,
  10. useForm,
  11. } from "react-hook-form";
  12. import { deleteDialog } from "../Swal/CustomAlerts";
  13. import {
  14. Box,
  15. Button,
  16. Grid,
  17. Stack,
  18. Tab,
  19. Tabs,
  20. TabsProps,
  21. Typography,
  22. } from "@mui/material";
  23. import { Check, Close, EditNote, ArrowBack } from "@mui/icons-material";
  24. import { TypeEnum } from "@/app/utils/typeEnum";
  25. import ProductDetails from "./ProductDetails";
  26. import { CreateItemResponse } from "@/app/api/utils";
  27. import QcDetails from "./QcDetails";
  28. import { ItemQc } from "@/app/api/settings/item";
  29. import { saveItemQcChecks } from "@/app/api/settings/qcCheck/actions";
  30. import { useGridApiRef } from "@mui/x-data-grid";
  31. import { QcCategoryCombo } from "@/app/api/settings/qcCategory";
  32. import { WarehouseResult } from "@/app/api/warehouse";
  33. type Props = {
  34. isEditMode: boolean;
  35. // type: TypeEnum;
  36. defaultValues: Partial<CreateItemInputs> | undefined;
  37. qcChecks: ItemQc[];
  38. qcCategoryCombo: QcCategoryCombo[];
  39. warehouses: WarehouseResult[];
  40. };
  41. const CreateItem: React.FC<Props> = ({
  42. isEditMode,
  43. // type,
  44. defaultValues,
  45. qcChecks,
  46. qcCategoryCombo,
  47. warehouses,
  48. }) => {
  49. // console.log(type)
  50. const apiRef = useGridApiRef();
  51. const params = useSearchParams();
  52. console.log(params.get("id"));
  53. const [serverError, setServerError] = useState("");
  54. const [tabIndex, setTabIndex] = useState(0);
  55. const { t } = useTranslation("items");
  56. const router = useRouter();
  57. const title = "Product / Material";
  58. const [mode, redirPath] = useMemo(() => {
  59. // var typeId = TypeEnum.CONSUMABLE_ID
  60. let title = "";
  61. let mode = "";
  62. let redirPath = "";
  63. // if (type === TypeEnum.MATERIAL) {
  64. // typeId = TypeEnum.MATERIAL_ID
  65. // title = "Material";
  66. // redirPath = "/settings/material";
  67. // }
  68. // if (type === TypeEnum.PRODUCT) {
  69. // typeId = TypeEnum.PRODUCT_ID
  70. title = "Product";
  71. redirPath = "/settings/items";
  72. // }
  73. // if (type === TypeEnum.BYPRODUCT) {
  74. // typeId = TypeEnum.BYPRODUCT_ID
  75. // title = "By-Product";
  76. // redirPath = "/settings/byProduct";
  77. // }
  78. if (isEditMode) {
  79. mode = "Edit";
  80. } else {
  81. mode = "Create";
  82. }
  83. return [mode, redirPath];
  84. }, [isEditMode]);
  85. // console.log(typeId)
  86. const formProps = useForm<CreateItemInputs>({
  87. defaultValues: defaultValues ? defaultValues : {},
  88. });
  89. const errors = formProps.formState.errors;
  90. const handleTabChange = useCallback<NonNullable<TabsProps["onChange"]>>(
  91. (_e, newValue) => {
  92. setTabIndex(newValue);
  93. },
  94. [],
  95. );
  96. const handleCancel = () => {
  97. router.replace(`/settings/product`);
  98. };
  99. const onSubmit = useCallback<SubmitHandler<CreateItemInputs & {}>>(
  100. async (data, event) => {
  101. const hasErrors = false;
  102. console.log(errors);
  103. // console.log(apiRef.current.getCellValue(2, "lowerLimit"))
  104. // apiRef.current.
  105. try {
  106. if (hasErrors) {
  107. setServerError(t("An error has occurred. Please try again later."));
  108. return false;
  109. }
  110. // Normalize LocationCode: convert empty string to null
  111. if (data.LocationCode && data.LocationCode.trim() !== "") {
  112. // Parse LocationCode and populate store_id, warehouse, area, slot
  113. const parts = data.LocationCode.split("-");
  114. if (parts.length >= 4) {
  115. data.store_id = parts[0] || undefined;
  116. data.warehouse = parts[1] || undefined;
  117. data.area = parts[2] || undefined;
  118. data.slot = parts[3] || undefined;
  119. }
  120. } else {
  121. // If LocationCode is null or empty, set LocationCode to null and clear related fields
  122. data.LocationCode = undefined;
  123. data.store_id = undefined;
  124. data.warehouse = undefined;
  125. data.area = undefined;
  126. data.slot = undefined;
  127. }
  128. console.log("data posted");
  129. console.log(data);
  130. const qcCheck =
  131. data.qcChecks.length > 0
  132. ? data.qcChecks
  133. .filter((q) => data.qcChecks_active.includes(q.id!))
  134. .map((qc) => {
  135. return {
  136. qcItemId: qc.id,
  137. instruction: qc.instruction,
  138. lowerLimit: qc.lowerLimit,
  139. upperLimit: qc.upperLimit,
  140. itemId: parseInt(params.get("id")!.toString()),
  141. };
  142. })
  143. : [];
  144. const test = data.qcChecks.filter((q) =>
  145. data.qcChecks_active.includes(q.id!),
  146. );
  147. // TODO:
  148. // 1. check field ( directly modify col def / check here )
  149. // 2. set error change tab index
  150. console.log(test);
  151. console.log(qcCheck);
  152. // return
  153. // do api
  154. const responseI = await saveItem(data);
  155. const responseQ = await saveItemQcChecks(qcCheck);
  156. if (responseI && responseQ) {
  157. if (!Boolean(responseI.id)) {
  158. formProps.setError(
  159. responseI.errorPosition! as keyof CreateItemInputs,
  160. {
  161. message: responseI.message!,
  162. type: "required",
  163. },
  164. );
  165. } else if (!Boolean(responseQ.id)) {
  166. } else if (Boolean(responseI.id) && Boolean(responseQ.id)) {
  167. router.replace(redirPath);
  168. }
  169. }
  170. } catch (e) {
  171. // backend error
  172. setServerError(t("An error has occurred. Please try again later."));
  173. console.log(e);
  174. }
  175. },
  176. [apiRef, router, t],
  177. );
  178. // multiple tabs
  179. const onSubmitError = useCallback<SubmitErrorHandler<CreateItemInputs>>(
  180. (errors) => {},
  181. [],
  182. );
  183. return (
  184. <>
  185. <FormProvider {...formProps}>
  186. <Stack
  187. spacing={2}
  188. component="form"
  189. onSubmit={formProps.handleSubmit(onSubmit, onSubmitError)}
  190. >
  191. <Grid>
  192. <Stack direction="column" spacing={1} mb={2}>
  193. <Button
  194. variant="outlined"
  195. startIcon={<ArrowBack />}
  196. onClick={() => router.push("/settings/items")}
  197. sx={{ alignSelf: "flex-start", minWidth: "auto" }}
  198. >
  199. {t("Back")}
  200. </Button>
  201. <Typography variant="h4">
  202. {t(`${mode} ${title}`)}
  203. </Typography>
  204. </Stack>
  205. </Grid>
  206. <Tabs
  207. value={tabIndex}
  208. onChange={handleTabChange}
  209. variant="scrollable"
  210. >
  211. <Tab label={t("Product / Material Details")} iconPosition="end" />
  212. {/* <Tab label={t("Qc items")} iconPosition="end" /> */}
  213. </Tabs>
  214. {serverError && (
  215. <Typography variant="body2" color="error" alignSelf="flex-end">
  216. {serverError}
  217. </Typography>
  218. )}
  219. {tabIndex === 0 && (
  220. <ProductDetails
  221. isEditMode={isEditMode}
  222. qcCategoryCombo={qcCategoryCombo}
  223. warehouses={warehouses}
  224. defaultValues={defaultValues}
  225. />
  226. )}
  227. {tabIndex === 1 && <QcDetails apiRef={apiRef} />}
  228. {/* {type === TypeEnum.MATERIAL && <MaterialDetails />} */}
  229. {/* {type === TypeEnum.BYPRODUCT && <ByProductDetails />} */}
  230. {/*
  231. <Stack direction="row" justifyContent="flex-end" gap={1}>
  232. <Button
  233. name="submit"
  234. variant="contained"
  235. startIcon={<Check />}
  236. type="submit"
  237. >
  238. {isEditMode ? t("Save") : t("Confirm")}
  239. </Button>
  240. <Button
  241. variant="outlined"
  242. startIcon={<Close />}
  243. onClick={handleCancel}
  244. >
  245. {t("Cancel")}
  246. </Button>
  247. </Stack>
  248. */}
  249. </Stack>
  250. </FormProvider>
  251. </>
  252. );
  253. };
  254. export default CreateItem;