index.js 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. import { Box, Button, Stack, Table, TableBody, TableCell, TableRow, Typography } from "@mui/material";
  2. import { useFormik } from "formik";
  3. import { useContext, useEffect, useState } from "react";
  4. import { connect, useSelector } from "react-redux";
  5. import { useNavigate } from "react-router-dom";
  6. import { actionOrderUpdate } from "../../actions/actionOrderUpdate";
  7. import { actionCartDelete } from "../../reducers";
  8. import { UIContext } from "../UIContext";
  9. import { CCartItem } from "./CartItem";
  10. export const CartPage = ({ onConfirm, promiseStatus, serverErrors, onDeleteClick }) => {
  11. const cart = useSelector((state) => state.cart || {});
  12. const { setAlert } = useContext(UIContext);
  13. const sum = Object.entries(cart).reduce((prev, [_id, order]) => prev + order.count * order.good.price, 0);
  14. const [promiseTimeOut, setPromiseTimeOut] = useState(null);
  15. const navigate = useNavigate();
  16. const formik = useFormik({
  17. initialValues: {},
  18. onSubmit: () => {
  19. setPromiseTimeOut(setTimeout(() => formik.setSubmitting(false), 3000));
  20. onConfirm && Object.keys(cart).length && onConfirm({ orderGoods: Object.values(cart) });
  21. },
  22. });
  23. useEffect(() => {
  24. if (!Object.entries(cart).length) {
  25. navigate("/");
  26. }
  27. return () => {
  28. promiseTimeOut && clearTimeout(promiseTimeOut);
  29. };
  30. }, []);
  31. useEffect(() => {
  32. !Object.keys(cart).length && navigate("/");
  33. }, [cart]);
  34. useEffect(() => {
  35. if (promiseStatus === "FULFILLED") {
  36. formik.setSubmitting(false);
  37. promiseTimeOut && clearTimeout(promiseTimeOut);
  38. setPromiseTimeOut(null);
  39. setAlert({
  40. show: true,
  41. severity: "success",
  42. message: "Готово",
  43. });
  44. }
  45. if (promiseStatus === "REJECTED") {
  46. const errorMessage = (serverErrors ? [].concat(serverErrors) : []).reduce((prev, curr) => prev + "\n" + curr.message, "");
  47. formik.setSubmitting(false);
  48. promiseTimeOut && clearTimeout(promiseTimeOut);
  49. setPromiseTimeOut(null);
  50. setAlert({
  51. show: true,
  52. severity: "error",
  53. message: errorMessage,
  54. });
  55. }
  56. }, [promiseStatus]);
  57. return (
  58. <Box className="CartPage" component="form" onSubmit={formik.handleSubmit}>
  59. <Stack spacing={2}>
  60. <Typography>Оформлення замовлення</Typography>
  61. <Table className="table">
  62. <TableBody>
  63. {Object.entries(cart).map(([_id, order]) => (
  64. <CCartItem order={order} onDeleteClick={(good) => onDeleteClick(good)} key={_id} />
  65. ))}
  66. <TableRow>
  67. <TableCell colSpan={3}>
  68. <Typography variant="body1" sx={{ fontWeight: "bold" }}>
  69. Всього:
  70. </Typography>
  71. </TableCell>
  72. <TableCell>
  73. <Typography textAlign="center">{sum} ₴</Typography>
  74. </TableCell>
  75. <TableCell></TableCell>
  76. </TableRow>
  77. <TableRow>
  78. <TableCell colSpan={4}></TableCell>
  79. <TableCell>
  80. <Button variant="contained" disabled={formik.isSubmitting} type="submit">
  81. Підтвердити
  82. </Button>
  83. </TableCell>
  84. </TableRow>
  85. </TableBody>
  86. </Table>
  87. </Stack>
  88. </Box>
  89. );
  90. };
  91. export const CCartPage = connect(
  92. (state) => ({
  93. promiseStatus: state.promise.orderUpsert?.status || null,
  94. serverErrors: state.promise.orderUpsert?.error || null,
  95. }),
  96. {
  97. onConfirm: (order) => actionOrderUpdate(order),
  98. onDeleteClick: (good) => actionCartDelete(good),
  99. }
  100. )(CartPage);