FPSMS-frontend
Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

ProductDetails.tsx 11 KiB

před 11 měsíci
před 11 měsíci
před 11 měsíci
před 11 měsíci
před 11 měsíci
před 11 měsíci
před 11 měsíci
před 11 měsíci
před 11 měsíci
před 11 měsíci
před 11 měsíci
před 11 měsíci
před 11 měsíci
před 11 měsíci
před 11 měsíci
před 11 měsíci
před 11 měsíci
před 11 měsíci
před 11 měsíci
před 11 měsíci
před 11 měsíci
před 11 měsíci
před 11 měsíci
před 11 měsíci
před 11 měsíci
před 11 měsíci
před 11 měsíci
před 11 měsíci
před 11 měsíci
před 11 měsíci
před 11 měsíci
před 11 měsíci
před 11 měsíci
před 11 měsíci
před 11 měsíci
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  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;