FPSMS-frontend
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

преди 11 месеца
преди 11 месеца
преди 11 месеца
преди 7 месеца
преди 11 месеца
преди 1 месец
преди 11 месеца
преди 1 месец
преди 11 месеца
преди 1 месец
преди 11 месеца
преди 11 месеца
преди 7 месеца
преди 3 седмици
преди 11 месеца
преди 11 месеца
преди 11 месеца
преди 7 месеца
преди 1 месец
преди 11 месеца
преди 9 месеца
преди 7 месеца
преди 7 месеца
преди 1 месец
преди 11 месеца
преди 11 месеца
преди 1 месец
преди 11 месеца
преди 11 месеца
преди 11 месеца
преди 1 месец
преди 11 месеца
преди 11 месеца
преди 9 месеца
преди 11 месеца
преди 9 месеца
преди 3 седмици
преди 11 месеца
преди 11 месеца
преди 11 месеца
преди 11 месеца
преди 11 месеца
преди 11 месеца
преди 1 месец
преди 11 месеца
преди 11 месеца
преди 11 месеца
преди 11 месеца
преди 11 месеца
преди 11 месеца
преди 1 месец
преди 11 месеца
преди 11 месеца
преди 11 месеца
преди 9 месеца
преди 1 месец
преди 9 месеца
преди 1 месец
преди 9 месеца
преди 11 месеца
преди 1 месец
преди 11 месеца
преди 11 месеца
преди 1 месец
преди 7 месеца
преди 11 месеца
преди 11 месеца
преди 11 месеца
преди 11 месеца
преди 11 месеца
преди 11 месеца
преди 11 месеца
преди 11 месеца
преди 11 месеца
преди 11 месеца
преди 11 месеца
преди 9 месеца
преди 11 месеца
преди 11 месеца
преди 11 месеца
преди 11 месеца
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;