FPSMS-frontend
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 

341 строка
11 KiB

  1. "use client";
  2. import {
  3. Autocomplete,
  4. Box,
  5. Button,
  6. Card,
  7. CardContent,
  8. FormControl,
  9. FormControlLabel,
  10. FormLabel,
  11. Grid,
  12. InputLabel,
  13. MenuItem,
  14. Radio,
  15. RadioGroup,
  16. Select,
  17. Stack,
  18. TextField,
  19. Typography,
  20. } from "@mui/material";
  21. import { Check, EditNote } from "@mui/icons-material";
  22. import { Controller, useFormContext } from "react-hook-form";
  23. import { useTranslation } from "react-i18next";
  24. import InputDataGrid from "../InputDataGrid";
  25. import { SyntheticEvent, useCallback, useEffect, useMemo, useState } from "react";
  26. import { GridColDef, GridRowModel } from "@mui/x-data-grid";
  27. import { InputDataGridProps, TableRow } from "../InputDataGrid/InputDataGrid";
  28. import { TypeEnum } from "@/app/utils/typeEnum";
  29. import { CreateItemInputs } from "@/app/api/settings/item/actions";
  30. import { ItemQc } from "@/app/api/settings/item";
  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. isEditMode: boolean;
  37. // type: TypeEnum;
  38. defaultValues?: Partial<CreateItemInputs> | undefined;
  39. qcChecks?: ItemQc[];
  40. qcCategoryCombo: QcCategoryCombo[];
  41. warehouses: WarehouseResult[];
  42. };
  43. const ProductDetails: React.FC<Props> = ({ isEditMode, qcCategoryCombo, warehouses, defaultValues: initialDefaultValues }) => {
  44. const {
  45. t,
  46. i18n: { language },
  47. } = useTranslation();
  48. const {
  49. register,
  50. formState: { errors, touchedFields },
  51. watch,
  52. control,
  53. setValue,
  54. getValues,
  55. setError,
  56. clearErrors,
  57. } = useFormContext<CreateItemInputs>();
  58. // const typeColumns = useMemo<GridColDef[]>(
  59. // () => [
  60. // {
  61. // field: "type",
  62. // headerName: "type",
  63. // flex: 1,
  64. // editable: true,
  65. // },
  66. // ],
  67. // []
  68. // );
  69. // const weightUnitColumns = useMemo<GridColDef[]>(
  70. // () => [
  71. // {
  72. // field: "weightUnit",
  73. // headerName: "Weight Unit",
  74. // flex: 1,
  75. // editable: true,
  76. // },
  77. // {
  78. // field: "conversion",
  79. // headerName: "conversion", // show base unit
  80. // flex: 1,
  81. // type: "number",
  82. // editable: true,
  83. // },
  84. // ],
  85. // []
  86. // );
  87. // const uomColumns = useMemo<GridColDef[]>(
  88. // () => [
  89. // {
  90. // field: "uom",
  91. // headerName: "uom",
  92. // flex: 1,
  93. // editable: true,
  94. // },
  95. // ],
  96. // []
  97. // );
  98. // const validationTest = useCallback(
  99. // (
  100. // newRow: GridRowModel<TableRow<Partial<CreateItemInputs>, EntryError>>
  101. // ): EntryError => {
  102. // const error: EntryError = {};
  103. // console.log(newRow);
  104. // return Object.keys(error).length > 0 ? error : undefined;
  105. // },
  106. // []
  107. // );
  108. const handleAutoCompleteChange = useCallback((event: SyntheticEvent<Element, Event>, value: QcCategoryCombo, onChange: (...event: any[]) => void) => {
  109. onChange(value.id)
  110. }, [])
  111. // Ensure LocationCode is set from defaultValues when component mounts
  112. useEffect(() => {
  113. if (initialDefaultValues?.LocationCode && !getValues("LocationCode")) {
  114. setValue("LocationCode", initialDefaultValues.LocationCode);
  115. }
  116. }, [initialDefaultValues, setValue, getValues]);
  117. return (
  118. <Card sx={{ display: "block" }}>
  119. <CardContent component={Stack} spacing={4}>
  120. <Box>
  121. <Typography variant="overline" display="block" marginBlockEnd={1}>
  122. {t("Product Details")}
  123. </Typography>
  124. <Grid container spacing={2} columns={{ xs: 6, sm: 12 }}>
  125. <Grid item xs={6}>
  126. <TextField
  127. label={t("Name")}
  128. fullWidth
  129. disabled
  130. {...register("name", {
  131. required: "name required!",
  132. })}
  133. error={Boolean(errors.name)}
  134. helperText={errors.name?.message}
  135. />
  136. </Grid>
  137. <Grid item xs={6}>
  138. <TextField
  139. label={t("Code")}
  140. fullWidth
  141. disabled
  142. {...register("code", {
  143. required: "code required!",
  144. })}
  145. error={Boolean(errors.code)}
  146. helperText={errors.code?.message}
  147. />
  148. </Grid>
  149. <Grid item xs={6}>
  150. <Controller
  151. control={control}
  152. name="type"
  153. rules={{
  154. required: "type required!",
  155. }}
  156. render={({ field }) => (
  157. <FormControl fullWidth error={Boolean(errors.type)}>
  158. <InputLabel>{t("Type")}</InputLabel>
  159. <Select
  160. value={field.value || ""}
  161. label={t("Type")}
  162. onChange={field.onChange}
  163. onBlur={field.onBlur}
  164. >
  165. <MenuItem value="fg">FG</MenuItem>
  166. <MenuItem value="wip">WIP</MenuItem>
  167. <MenuItem value="mat">MAT</MenuItem>
  168. <MenuItem value="cmb">CMB</MenuItem>
  169. <MenuItem value="nm">NM</MenuItem>
  170. </Select>
  171. {errors.type && (
  172. <Typography variant="caption" color="error" sx={{ mt: 0.5, ml: 1.5 }}>
  173. {errors.type.message}
  174. </Typography>
  175. )}
  176. </FormControl>
  177. )}
  178. />
  179. </Grid>
  180. <Grid item xs={6}>
  181. <TextField
  182. label={t("description")}
  183. fullWidth
  184. disabled
  185. {...register("description")}
  186. />
  187. </Grid>
  188. <Grid item xs={6}>
  189. <Controller
  190. control={control}
  191. name="qcCategoryId"
  192. render={({ field }) => (
  193. <Autocomplete
  194. disableClearable
  195. options={qcCategoryCombo}
  196. defaultValue={qcCategoryCombo.find(qc => qc.id === field.value)}
  197. onChange={(event, value) => {
  198. handleAutoCompleteChange(event, value, field.onChange)
  199. }}
  200. onBlur={field.onBlur}
  201. renderInput={(params) => (
  202. <TextField
  203. {...params}
  204. variant="outlined"
  205. label={t("Qc Category")}
  206. />
  207. )}
  208. />
  209. )}
  210. />
  211. </Grid>
  212. <Grid item xs={6}>
  213. <Controller
  214. control={control}
  215. name="LocationCode"
  216. render={({ field }) => (
  217. <Autocomplete
  218. freeSolo
  219. options={warehouses.map((w) => ({
  220. label: `${w.code}`,
  221. code: w.code,
  222. }))}
  223. getOptionLabel={(option) =>
  224. typeof option === "string"
  225. ? option
  226. : option.label ?? option.code ?? ""
  227. }
  228. value={
  229. warehouses
  230. .map((w) => ({
  231. label: `${w.code}`,
  232. code: w.code,
  233. }))
  234. .find((opt) => opt.code === field.value) ||
  235. (field.value
  236. ? { label: field.value as string, code: field.value as string }
  237. : null)
  238. }
  239. onChange={(_e, value) => {
  240. if (typeof value === "string") {
  241. field.onChange(value.trim() === "" ? undefined : value);
  242. } else {
  243. field.onChange(value?.code ? (value.code.trim() === "" ? undefined : value.code) : undefined);
  244. }
  245. }}
  246. onInputChange={(_e, value) => {
  247. // keep manual input synced - convert empty string to undefined
  248. field.onChange(value.trim() === "" ? undefined : value);
  249. }}
  250. renderInput={(params) => (
  251. <TextField
  252. {...params}
  253. label={t("DefaultLocationCode")}
  254. fullWidth
  255. error={Boolean(errors.LocationCode)}
  256. helperText={errors.LocationCode?.message}
  257. />
  258. )}
  259. />
  260. )}
  261. />
  262. </Grid>
  263. <Grid item xs={12}>
  264. <FormControl component="fieldset">
  265. <FormLabel component="legend">{t("Special Type")}</FormLabel>
  266. <RadioGroup
  267. row
  268. value={
  269. watch("isEgg") === true ? "isEgg" :
  270. watch("isFee") === true ? "isFee" :
  271. watch("isBag") === true ? "isBag" :
  272. "none"
  273. }
  274. onChange={(e) => {
  275. const value = e.target.value;
  276. setValue("isEgg", value === "isEgg", { shouldValidate: true });
  277. setValue("isFee", value === "isFee", { shouldValidate: true });
  278. setValue("isBag", value === "isBag", { shouldValidate: true });
  279. }}
  280. >
  281. <FormControlLabel value="none" control={<Radio />} label={t("None")} />
  282. <FormControlLabel value="isEgg" control={<Radio />} label={t("isEgg")} />
  283. <FormControlLabel value="isFee" control={<Radio />} label={t("isFee")} />
  284. <FormControlLabel value="isBag" control={<Radio />} label={t("isBag")} />
  285. </RadioGroup>
  286. </FormControl>
  287. </Grid>
  288. <Grid item xs={12}>
  289. <Stack
  290. direction="row"
  291. justifyContent="flex-end"
  292. spacing={2}
  293. sx={{ mt: 2 }}
  294. >
  295. <Button
  296. name="submit"
  297. variant="contained"
  298. startIcon={<Check />}
  299. type="submit"
  300. // disabled={submitDisabled}
  301. >
  302. {isEditMode ? t("Save") : t("Confirm")}
  303. </Button>
  304. </Stack>
  305. </Grid>
  306. {/* <Grid item xs={6}>
  307. <InputDataGrid<CreateItemInputs, EntryError>
  308. _formKey={"type"}
  309. columns={typeColumns}
  310. validateRow={validationTest}
  311. />
  312. </Grid>
  313. <Grid item xs={6}>
  314. <InputDataGrid<CreateItemInputs, EntryError>
  315. _formKey={"uom"}
  316. columns={uomColumns}
  317. validateRow={validationTest}
  318. />
  319. </Grid>
  320. <Grid item xs={12}>
  321. <InputDataGrid<CreateItemInputs, EntryError>
  322. _formKey={"weightUnit"}
  323. columns={weightUnitColumns}
  324. validateRow={validationTest}
  325. />
  326. </Grid>*/}
  327. </Grid>
  328. </Box>
  329. </CardContent>
  330. </Card>
  331. );
  332. };
  333. export default ProductDetails;