25'ten fazla konu seçemezsiniz Konular bir harf veya rakamla başlamalı, kısa çizgiler ('-') içerebilir ve en fazla 35 karakter uzunluğunda olabilir.
 
 

510 satır
18 KiB

  1. "use client";
  2. import {
  3. Card,
  4. CardHeader,
  5. CardContent,
  6. SxProps,
  7. Theme,
  8. Typography,
  9. Grid,
  10. TextField,
  11. FormControl,
  12. InputLabel,
  13. Select,
  14. MenuItem,
  15. Checkbox,
  16. FormControlLabel,
  17. Button,
  18. } from "@mui/material";
  19. import { DataGrid, GridColDef, GridRowSelectionModel } from "@mui/x-data-grid";
  20. import { darken, lighten, styled } from "@mui/material/styles";
  21. import { Controller, useForm, useFormContext } from "react-hook-form";
  22. import Stack from "@mui/material/Stack";
  23. import { useTranslation } from "react-i18next";
  24. import Box from "@mui/material/Box";
  25. import { LocalizationProvider } from "@mui/x-date-pickers/LocalizationProvider";
  26. import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs";
  27. import { DemoItem } from "@mui/x-date-pickers/internals/demo";
  28. import { DatePicker } from "@mui/x-date-pickers/DatePicker";
  29. import dayjs from "dayjs";
  30. import { useCallback, useEffect, useState } from "react";
  31. import { Check, Close } from "@mui/icons-material";
  32. import { NumericFormat, NumericFormatProps } from "react-number-format";
  33. import * as React from "react";
  34. // interface Option {
  35. // // Define properties of each option object
  36. // // based on your specific requirements
  37. // id: any;
  38. // value: any;
  39. // label: string;
  40. // }
  41. interface Field {
  42. // subtitle: string;
  43. id: string;
  44. label: string;
  45. type: string;
  46. value?: any;
  47. required?: boolean;
  48. pattern?: string;
  49. message?: string;
  50. options?: any[];
  51. readOnly?: boolean;
  52. size?: number;
  53. setValue?: any[];
  54. }
  55. interface CustomProps {
  56. onChange: (event: { target: { name: string; value: string } }) => void;
  57. name: string;
  58. }
  59. interface CustomInputFormProps {
  60. onSubmit: (data: any) => void;
  61. onSubmitError?: (data: any) => void;
  62. onCancel: () => void;
  63. // resetForm: () => void;
  64. Title?: string[];
  65. isActive: boolean;
  66. fieldLists: Field[][];
  67. }
  68. // interface SubComponents {
  69. // Loading: typeof CustomerSearchLoading;
  70. // }
  71. const CustomInputForm: React.FC<CustomInputFormProps> = ({
  72. Title,
  73. isActive,
  74. fieldLists,
  75. onSubmit,
  76. onSubmitError,
  77. onCancel,
  78. // resetForm,
  79. }) => {
  80. const { t } = useTranslation();
  81. const {
  82. reset,
  83. register,
  84. handleSubmit,
  85. control,
  86. formState: { errors },
  87. } = useForm();
  88. const [dateObj, setDateObj] = useState<any>(null);
  89. const [value, setValue] = useState<any>({});
  90. const [checkboxValue, setCheckboxValue] = useState({});
  91. interface DateObj {
  92. [key: string]: string;
  93. }
  94. const handleFormSubmit = (data: any) => {
  95. // if (date != null || date != undefined ) {
  96. // data.date = dayjs(date).format('YYYY-MM-DD');
  97. // }
  98. for (const key in data) {
  99. if (!isNaN(data[key])) {
  100. if (data[key] !== "") {
  101. if (Number.isInteger(parseFloat(data[key]))) {
  102. data[key] = parseInt(data[key]);
  103. } else {
  104. data[key] = parseFloat(data[key]);
  105. }
  106. }
  107. }
  108. }
  109. if (checkboxValue !== null) {
  110. data = { ...data, ...checkboxValue };
  111. }
  112. const finalData = {
  113. ...value,
  114. ...data,
  115. ...dateObj,
  116. };
  117. console.log(finalData);
  118. onSubmit(finalData);
  119. };
  120. const handleDateChange = (id: string, newValue: dayjs.Dayjs | null): void => {
  121. console.log(dayjs(newValue).format("YYYY-MM-DD"));
  122. setDateObj((prevValues: DateObj) => ({
  123. ...prevValues,
  124. [id]: newValue ? dayjs(newValue).format("YYYY-MM-DD") : "",
  125. }));
  126. };
  127. const handleCheckboxChange = (id: string, newValue: boolean): void => {
  128. setCheckboxValue((prevValues: { [key: string]: boolean }) => ({
  129. ...prevValues,
  130. [id]: newValue,
  131. }));
  132. };
  133. const handleAutocompleteChange = (id: any, newValue: any) => {
  134. setValue((prevValues: any) => ({
  135. ...prevValues,
  136. [id]: newValue,
  137. }));
  138. };
  139. const handleCancel = () => {
  140. reset();
  141. // resetForm();
  142. // setFromDate(null);
  143. setDateObj(null);
  144. setValue({});
  145. if (onCancel) {
  146. onCancel();
  147. }
  148. // if fields include setValue func
  149. // fieldLists.map((list) => {
  150. // list.map((field) => {
  151. // if (typeof field.setValue === 'function') {
  152. // field.setValue(typeof field.value === 'boolean' ? false : null);
  153. // } else if (typeof field.setValue === 'object') {
  154. // field.setValue.map((setFunc: any) => {
  155. // setFunc(null);
  156. // });
  157. // }
  158. // })
  159. // });
  160. // setToDate(null);
  161. };
  162. fieldLists.forEach((list) => {
  163. list.forEach((obj) => {
  164. if (
  165. obj.id === "created" ||
  166. obj.id === "createdBy" ||
  167. obj.id === "modified" ||
  168. obj.id === "deleted" ||
  169. obj.id === "modifiedBy"
  170. ) {
  171. obj.readOnly = true;
  172. }
  173. });
  174. });
  175. const NumericFormatCustom = React.forwardRef<NumericFormatProps, CustomProps>(
  176. function NumericFormatCustom(props, ref) {
  177. const { onChange, ...other } = props;
  178. return (
  179. <NumericFormat
  180. {...other}
  181. getInputRef={ref}
  182. onValueChange={(values) => {
  183. onChange({
  184. target: {
  185. name: props.name,
  186. value: values.value,
  187. },
  188. });
  189. }}
  190. thousandSeparator
  191. valueIsNumericString
  192. prefix="$"
  193. />
  194. );
  195. }
  196. );
  197. const [values, setValues] = React.useState({
  198. hourlyRate: "",
  199. });
  200. const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
  201. setValues({
  202. ...values,
  203. [event.target.name]: event.target.value,
  204. });
  205. };
  206. return (
  207. <form onSubmit={handleSubmit(handleFormSubmit, onSubmitError)}>
  208. <Card sx={{ display: isActive ? "block" : "none" }}>
  209. <CardContent component={Stack} spacing={4}>
  210. <>
  211. {fieldLists.map((fieldList, fieldListIndex) => (
  212. <Box key={fieldListIndex}>
  213. {Title ? (
  214. <Typography
  215. variant="overline"
  216. display="block"
  217. marginBlockEnd={1}
  218. >
  219. {t(`${Title[fieldListIndex]}`)}
  220. </Typography>
  221. ) : null}
  222. <Grid container spacing={2} columns={{ xs: 6, sm: 12 }}>
  223. {fieldList.map((field: Field) => {
  224. if (field.type === "text") {
  225. return (
  226. <Grid item xs={field.size ?? 6} key={field.id}>
  227. <TextField
  228. label={field.label}
  229. fullWidth
  230. {...register(field.id, {
  231. pattern: field.pattern
  232. ? new RegExp(field.pattern)
  233. : /.*/,
  234. })}
  235. defaultValue={!field.value ? `${field.value}` : ""}
  236. required={field.required ?? false}
  237. error={Boolean(errors[field.id])}
  238. helperText={
  239. Boolean(errors[field.id]) && field.message
  240. }
  241. />
  242. </Grid>
  243. );
  244. } else if (field.type === "email") {
  245. return (
  246. <Grid item xs={field.size ?? 6} key={field.id}>
  247. <TextField
  248. label={field.label}
  249. fullWidth
  250. {...register(field.id, {
  251. pattern:
  252. /^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,4}$/,
  253. })}
  254. defaultValue={!field.value ? `${field.value}` : ""}
  255. required={field.required ?? false}
  256. error={Boolean(errors[field.id])}
  257. helperText={
  258. Boolean(errors[field.id]) && field.message
  259. }
  260. />
  261. </Grid>
  262. );
  263. } else if (field.type === "multiDate") {
  264. return (
  265. <Grid item xs={field.size ?? 6} key={field.id}>
  266. <LocalizationProvider dateAdapter={AdapterDayjs}>
  267. <DemoItem>
  268. <DatePicker
  269. key={field.id}
  270. label={field.label}
  271. value={
  272. !dateObj
  273. ? null
  274. : !dateObj[field.id]
  275. ? null
  276. : dayjs(dateObj[field.id])
  277. } // Set initial value or use a default value from state
  278. onChange={(newValue) => {
  279. handleDateChange(field.id, newValue);
  280. }}
  281. // required = {field.required ?? false},
  282. />
  283. </DemoItem>
  284. </LocalizationProvider>
  285. </Grid>
  286. );
  287. } else if (field.type === "combo-Obj") {
  288. return (
  289. <Grid item xs={field.size ?? 6} key={field.id}>
  290. <FormControl fullWidth>
  291. <InputLabel id={`${field.id}-label`}>
  292. {field.label}
  293. </InputLabel>
  294. <Controller
  295. name={field.id}
  296. control={control}
  297. defaultValue={
  298. field.value !== undefined ? field.value : ""
  299. }
  300. render={({ field: { onChange, value } }) => (
  301. <Select
  302. labelId={`${field.id}-label`}
  303. id={field.id}
  304. value={value}
  305. onChange={(event) => {
  306. console.log(event);
  307. console.log(event.target);
  308. onChange(event.target.value);
  309. const newValue = event.target.value;
  310. const selectedOption = field.options?.find(
  311. (option) => option.id === newValue
  312. );
  313. handleAutocompleteChange(
  314. field.id,
  315. selectedOption
  316. );
  317. }}
  318. required={field.required}
  319. >
  320. {field.options?.map((option) => (
  321. <MenuItem
  322. value={
  323. option.id !== undefined
  324. ? option.id
  325. : option
  326. }
  327. key={
  328. option.id !== undefined
  329. ? option.id
  330. : option
  331. }
  332. >
  333. {option.id !== undefined
  334. ? option.label
  335. : option}
  336. </MenuItem>
  337. ))}
  338. </Select>
  339. )}
  340. />
  341. </FormControl>
  342. </Grid>
  343. );
  344. } else if (field.type === "numeric") {
  345. return (
  346. <Grid item xs={field.size ?? 6} key={field.id}>
  347. <TextField
  348. fullWidth
  349. {...register(field.id)}
  350. id={field.id}
  351. label={field.label}
  352. defaultValue={!field.value ? `${field.value}` : ""}
  353. inputProps={{
  354. inputMode: "numeric",
  355. pattern: "^-?\\d*\\.?\\d+$",
  356. }}
  357. required={field.required}
  358. />
  359. </Grid>
  360. );
  361. } else if (field.type === "numeric-testing") {
  362. return (
  363. <Grid item xs={field.size ?? 6} key={field.id}>
  364. <FormControl fullWidth>
  365. <Controller
  366. {...register(field.id)}
  367. name={field.id}
  368. control={control}
  369. defaultValue={
  370. !field.value ? `${field.value}` : ""
  371. }
  372. render={({ field }) => {
  373. console.log(field);
  374. return (
  375. <NumericFormat
  376. {...field}
  377. customInput={TextField}
  378. thousandSeparator
  379. valueIsNumericString
  380. prefix="$"
  381. label={t(field.name)}
  382. />
  383. );
  384. }}
  385. />
  386. </FormControl>
  387. </Grid>
  388. );
  389. } else if (field.type === "numeric-positive") {
  390. return (
  391. <Grid item xs={field.size ?? 6} key={field.id}>
  392. <TextField
  393. fullWidth
  394. {...register(field.id)}
  395. id={field.id}
  396. name={field.id}
  397. label={field.label}
  398. defaultValue={!field.value ? `${field.value}` : ""}
  399. inputProps={{
  400. inputMode: "numeric",
  401. pattern: "[0-9]*[.]?[0-9]*",
  402. }}
  403. required={field.required}
  404. />
  405. </Grid>
  406. );
  407. } else if (field.type === "checkbox") {
  408. return (
  409. <Grid item xs={field.size ?? 6} key={field.id}>
  410. <FormControlLabel
  411. control={
  412. <Checkbox
  413. defaultChecked={field.value}
  414. onChange={(event) => {
  415. handleCheckboxChange(
  416. field.id,
  417. event.target.checked
  418. );
  419. }}
  420. color="primary"
  421. />
  422. }
  423. label={
  424. <Typography variant="h4">
  425. {field.label}
  426. </Typography>
  427. }
  428. />
  429. </Grid>
  430. );
  431. } else if (field.type === "remarks") {
  432. return (
  433. <Grid item xs={12} key={field.id}>
  434. <TextField
  435. fullWidth
  436. multiline
  437. rows={4}
  438. variant="filled"
  439. {...register(field.id)}
  440. defaultValue={!field.value ? `${field.value}` : ""}
  441. id={field.id}
  442. label={field.label}
  443. required={field.required}
  444. />
  445. </Grid>
  446. );
  447. } else {
  448. return (
  449. <Grid item xs={field.size ?? 6} key={field.id}>
  450. <TextField
  451. fullWidth
  452. {...register(
  453. field.id
  454. // , { required: true }
  455. )}
  456. id={field.id}
  457. label={field.label}
  458. defaultValue={`${field.value}`}
  459. required={field.required}
  460. inputProps={{
  461. readOnly: field.readOnly,
  462. }}
  463. />
  464. </Grid>
  465. );
  466. }
  467. })}
  468. </Grid>
  469. </Box>
  470. ))}
  471. <Stack direction="row" justifyContent="flex-end" gap={1}>
  472. <Button
  473. variant="outlined"
  474. startIcon={<Close />}
  475. onClick={handleCancel}
  476. >
  477. {t("Cancel")}
  478. </Button>
  479. <Button variant="contained" startIcon={<Check />} type="submit">
  480. {t("Confirm")}
  481. </Button>
  482. </Stack>
  483. </>
  484. </CardContent>
  485. </Card>
  486. </form>
  487. );
  488. };
  489. // CustomInputForm.Loading = CustomerSearchLoading;
  490. export default CustomInputForm;