OrderForm.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. import { connect, useSelector } from 'react-redux';
  2. import React, { useState, useEffect, useContext } from 'react';
  3. import { actionPromise, actionPromiseClear } from '../../../reducers';
  4. import Select from 'react-select';
  5. import { actionOrderUpdate } from '../../../actions/actionOrderUpdate';
  6. import { EntityEditor } from '../../common/EntityEditor';
  7. import { actionUploadFiles } from '../../../actions/actionUploadFiles';
  8. import { UIContext } from '../../UIContext';
  9. import {
  10. Box,
  11. Button,
  12. Chip,
  13. FormControl,
  14. Grid,
  15. InputLabel,
  16. MenuItem,
  17. OutlinedInput,
  18. Stack,
  19. TextareaAutosize,
  20. TextField,
  21. Typography,
  22. } from '@mui/material';
  23. import { FormikProvider, useFormik } from 'formik';
  24. import * as Yup from 'yup';
  25. import { Error } from '../../common/Error';
  26. import { statusNumber, statusOptions } from '../../../helpers';
  27. import { OrderGoodsEditor } from './OrderGoodsEditor';
  28. const deliveryOptions = [
  29. { label: 'Нова пошта', value: 'nova-poshta' },
  30. { label: 'Justin', value: 'justin' },
  31. ];
  32. const orderSchema = Yup.object().shape({
  33. email: Yup.string().required("Обов'язкове"),
  34. phoneNumber: Yup.string().required("Обов'язкове"),
  35. name: Yup.string(),
  36. address: Yup.string().required("Обов'язкове"),
  37. surname: Yup.string(),
  38. delivery: Yup.string()
  39. .required("обов'язкове")
  40. .oneOf(
  41. deliveryOptions.map((option) => option.value),
  42. 'не знайдено'
  43. ),
  44. });
  45. export const OrderForm = ({ serverErrors = [], onSaveClick, onSave, onClose, promiseStatus, order = {} } = {}) => {
  46. const [inputStatus, setInputStatus] = useState(null);
  47. const { setAlert } = useContext(UIContext);
  48. const goodList = useSelector((state) => state.promise?.goodsAll?.payload || []);
  49. const [inputOrderGoods, setInputOrderGoods] = useState([]);
  50. const formik = useFormik({
  51. initialValues: {
  52. email: '',
  53. name: '',
  54. surname: '',
  55. phoneNumber: '',
  56. delivery: '',
  57. address: '',
  58. },
  59. validationSchema: orderSchema,
  60. validateOnChange: true,
  61. onSubmit: () => {
  62. let orderToSave = {};
  63. order?._id && (orderToSave._id = order._id);
  64. orderToSave.name = formik.values.name;
  65. orderToSave.email = formik.values.email;
  66. orderToSave.status = inputStatus;
  67. orderToSave.surname = formik.values.surname;
  68. orderToSave.phoneNumber = formik.values.phoneNumber;
  69. orderToSave.address = formik.values.address;
  70. orderToSave.delivery = formik.values.delivery;
  71. orderToSave.orderGoods = inputOrderGoods;
  72. onSaveClick && onSaveClick();
  73. onSave(orderToSave);
  74. },
  75. });
  76. useEffect(() => {
  77. setInputStatus(order?.status || null);
  78. setInputOrderGoods(order.orderGoods || []);
  79. formik.setFieldValue('email', order.email || '');
  80. formik.setFieldValue('name', order.name || '');
  81. formik.setFieldValue('address', order.address || '');
  82. formik.setFieldValue('surname', order.surname || '');
  83. formik.setFieldValue('phoneNumber', order.phoneNumber || '');
  84. formik.setFieldValue('delivery', order.delivery || '');
  85. }, [order]);
  86. useEffect(() => {
  87. formik.validateForm();
  88. }, [formik.values]);
  89. useEffect(() => {
  90. if (promiseStatus === 'FULFILLED') {
  91. formik.setSubmitting(false);
  92. setAlert({
  93. show: true,
  94. severity: 'success',
  95. message: 'Готово',
  96. });
  97. }
  98. if (promiseStatus === 'REJECTED') {
  99. const errorMessage = serverErrors.reduce((prev, curr) => prev + '\n' + curr.message, '');
  100. formik.setSubmitting(false);
  101. setAlert({
  102. show: true,
  103. severity: 'error',
  104. message: errorMessage,
  105. });
  106. }
  107. }, [promiseStatus]);
  108. useEffect(() => {
  109. return () => {
  110. onClose && onClose();
  111. };
  112. }, []);
  113. return (
  114. <Box className="OrderForm" component="form" onSubmit={formik.handleSubmit}>
  115. {(serverErrors || []).map((error) => (
  116. <Error>{error?.message}</Error>
  117. ))}
  118. <Grid container spacing={5}>
  119. <Grid item xs={6}>
  120. <TextField
  121. id="email"
  122. name="email"
  123. variant="outlined"
  124. label="Email"
  125. size="small"
  126. error={formik.touched.email && Boolean(formik.errors.email)}
  127. value={formik.values.email}
  128. onBlur={formik.handleBlur}
  129. onChange={formik.handleChange}
  130. helperText={formik.touched.email && formik.errors.email}
  131. fullWidth
  132. sx={{ mt: 2 }}
  133. />
  134. <TextField
  135. id="name"
  136. name="name"
  137. variant="outlined"
  138. label="Ім'я"
  139. size="small"
  140. error={formik.touched.name && Boolean(formik.errors.name)}
  141. value={formik.values.name}
  142. onBlur={formik.handleBlur}
  143. onChange={formik.handleChange}
  144. helperText={formik.touched.name && formik.errors.name}
  145. fullWidth
  146. sx={{ mt: 2 }}
  147. />
  148. <Box sx={{ mt: 3 }}>
  149. <InputLabel className="form-label">Статус</InputLabel>
  150. <Select
  151. value={{
  152. value: inputStatus || null,
  153. label: inputStatus ? statusNumber[inputStatus] : null,
  154. }}
  155. onChange={(e) => setInputStatus(e.value)}
  156. options={statusOptions}
  157. />
  158. </Box>
  159. <Box sx={{ mt: 3 }}>
  160. <InputLabel className="form-label">Товари</InputLabel>
  161. <OrderGoodsEditor
  162. orderGoods={inputOrderGoods}
  163. goodList={goodList}
  164. onChange={(orderGoods) => {
  165. setInputOrderGoods([...orderGoods]);
  166. }}
  167. />
  168. </Box>
  169. <Box direction="row" sx={{ mt: 3 }} justifyContent="flex-end">
  170. <Button
  171. variant="contained"
  172. disabled={Boolean(!formik.isValid || formik.isSubmitting)}
  173. type="submit"
  174. fullWidth
  175. >
  176. Зберегти
  177. </Button>
  178. </Box>
  179. </Grid>
  180. <Grid item xs={6}>
  181. <TextField
  182. variant="outlined"
  183. id="phoneNumber"
  184. name="phoneNumber"
  185. label="Номер"
  186. size="small"
  187. error={formik.touched.phoneNumber && Boolean(formik.errors.phoneNumber)}
  188. value={formik.values.phoneNumber}
  189. onBlur={formik.handleBlur}
  190. onChange={formik.handleChange}
  191. helperText={formik.touched.phoneNumber && formik.errors.phoneNumber}
  192. multiline
  193. fullWidth
  194. sx={{ mt: 2 }}
  195. />
  196. <TextField
  197. id="surname"
  198. name="surname"
  199. variant="outlined"
  200. label="Прізвище"
  201. size="small"
  202. error={formik.touched.surname && Boolean(formik.errors.surname)}
  203. value={formik.values.surname}
  204. onBlur={formik.handleBlur}
  205. onChange={formik.handleChange}
  206. helperText={formik.touched.surname && formik.errors.surname}
  207. fullWidth
  208. sx={{ mt: 2 }}
  209. />
  210. <TextField
  211. id="address"
  212. name="address"
  213. variant="outlined"
  214. label="Адреса"
  215. size="small"
  216. error={formik.touched.address && Boolean(formik.errors.address)}
  217. value={formik.values.address}
  218. onBlur={formik.handleBlur}
  219. onChange={formik.handleChange}
  220. helperText={formik.touched.address && formik.errors.address}
  221. fullWidth
  222. sx={{ mt: 2 }}
  223. />
  224. <TextField
  225. id="delivery"
  226. name="delivery"
  227. variant="outlined"
  228. label="Тип доставкі"
  229. size="small"
  230. select
  231. error={formik.touched.delivery && Boolean(formik.errors.delivery)}
  232. value={formik.values.delivery}
  233. onBlur={formik.handleBlur}
  234. onChange={formik.handleChange}
  235. helperText={formik.touched.delivery && formik.errors.delivery}
  236. fullWidth
  237. sx={{ mt: 2 }}
  238. >
  239. {deliveryOptions.map((option) => (
  240. <MenuItem key={option.value} value={option.value} t>
  241. {option.label}
  242. </MenuItem>
  243. ))}
  244. </TextField>
  245. </Grid>
  246. </Grid>
  247. </Box>
  248. );
  249. };
  250. export const COrderForm = connect(
  251. (state) => ({
  252. promiseStatus: state.promise.orderUpsert?.status || null,
  253. serverErrors: state.promise.orderUpsert?.error || null,
  254. order: state.promise?.adminOrderById?.payload || {},
  255. }),
  256. {
  257. onSave: (order) => actionOrderUpdate(order),
  258. onClose: () => actionPromiseClear('orderUpsert'),
  259. }
  260. )(OrderForm);