front-hub/src/components/Drawers.tsx

322 lines
11 KiB
TypeScript
Raw Normal View History

2023-08-04 13:49:35 +00:00
import { useState, useRef, useCallback } from "react";
2023-07-25 22:31:04 +00:00
import {
Typography,
Drawer,
useMediaQuery,
useTheme,
Box,
IconButton,
SvgIcon,
Badge,
} from "@mui/material";
2023-03-27 12:45:44 +00:00
import ArrowBackIcon from "@mui/icons-material/ArrowBack";
import ClearIcon from "@mui/icons-material/Clear";
2023-08-03 12:14:31 +00:00
import { useTickets } from "@frontend/kitui";
2023-03-27 12:45:44 +00:00
import SectionWrapper from "./SectionWrapper";
import CustomWrapperDrawer from "./CustomWrapperDrawer";
import CustomButton from "./CustomButton";
2023-08-04 13:49:35 +00:00
import { NotificationsModal } from "./NotificationsModal";
2023-03-27 12:45:44 +00:00
import { useNavigate } from "react-router";
2023-06-30 15:35:31 +00:00
import { useCart } from "@root/utils/hooks/useCart";
import { currencyFormatter } from "@root/utils/currencyFormatter";
2023-07-25 22:31:04 +00:00
import {
closeCartDrawer,
openCartDrawer,
useCartStore,
} from "@root/stores/cart";
import { useCustomTariffsStore } from "@root/stores/customTariffs";
2023-07-28 13:24:21 +00:00
import { useUserStore } from "@root/stores/user";
2023-08-03 12:14:31 +00:00
import {
updateTickets,
setTicketCount,
useTicketStore,
} from "@root/stores/tickets";
2023-08-04 09:34:14 +00:00
import { ReactComponent as BellIcon } from "@root/assets/Icons/bell.svg";
import { ReactComponent as CartIcon } from "@root/assets/Icons/cart.svg";
2023-03-27 12:45:44 +00:00
2023-07-28 13:24:21 +00:00
export default function Drawers() {
2023-08-04 13:49:35 +00:00
const [openNotificationsModal, setOpenNotificationsModal] =
useState<boolean>(false);
const bellRef = useRef<HTMLButtonElement | null>(null);
2023-07-25 22:31:04 +00:00
const navigate = useNavigate();
const theme = useTheme();
const upMd = useMediaQuery(theme.breakpoints.up("md"));
const isDrawerOpen = useCartStore((state) => state.isDrawerOpen);
const cart = useCart();
const summaryPriceBeforeDiscountsMap = useCustomTariffsStore(
(state) => state.summaryPriceBeforeDiscountsMap
);
const summaryPriceAfterDiscountsMap = useCustomTariffsStore(
(state) => state.summaryPriceAfterDiscountsMap
);
2023-07-28 13:24:21 +00:00
const userAccount = useUserStore((state) => state.userAccount);
2023-08-07 15:16:34 +00:00
const { tickets, apiPage, ticketsPerPage } = useTicketStore((state) => state);
2023-08-03 12:14:31 +00:00
useTickets({
url: "https://hub.pena.digital/heruvym/getTickets",
ticketsPerPage,
2023-08-04 14:14:25 +00:00
ticketApiPage: apiPage,
2023-08-03 12:14:31 +00:00
onNewTickets: useCallback((result) => {
if (result.data) updateTickets(result.data);
setTicketCount(result.count);
}, []),
onError: () => {},
});
2023-07-25 22:31:04 +00:00
const basePrice = Object.values(summaryPriceBeforeDiscountsMap).reduce(
(a, e) => a + e,
0
);
const discountedPrice = Object.values(summaryPriceAfterDiscountsMap).reduce(
(a, e) => a + e,
0
);
2023-08-07 15:16:34 +00:00
const notificationsCount = tickets.filter(
({ user, top_message }) => user !== top_message.user_id
).length;
2023-07-25 22:31:04 +00:00
const totalPriceBeforeDiscounts = cart.priceBeforeDiscounts + basePrice;
const totalPriceAfterDiscounts = cart.priceAfterDiscounts + discountedPrice;
2023-03-27 12:45:44 +00:00
2023-07-25 22:31:04 +00:00
return (
2023-08-03 12:14:31 +00:00
<Box sx={{ display: "flex", gap: "20px" }}>
<IconButton
2023-08-04 13:49:35 +00:00
ref={bellRef}
2023-08-03 12:14:31 +00:00
aria-label="cart"
2023-08-04 13:49:35 +00:00
onClick={() => setOpenNotificationsModal((isOpened) => !isOpened)}
2023-08-03 12:14:31 +00:00
sx={{
2023-08-04 08:21:15 +00:00
cursor: "pointer",
2023-08-03 12:14:31 +00:00
borderRadius: "6px",
2023-08-04 13:49:35 +00:00
background: openNotificationsModal
? theme.palette.brightPurple.main
: theme.palette.background.default,
"& .MuiBadge-badge": {
background: openNotificationsModal
? theme.palette.background.default
: theme.palette.brightPurple.main,
color: openNotificationsModal
? theme.palette.brightPurple.main
: theme.palette.background.default,
},
"& svg > path:first-child": {
fill: openNotificationsModal ? "#FFFFFF" : "#9A9AAF",
},
"& svg > path:last-child": {
stroke: openNotificationsModal ? "#FFFFFF" : "#9A9AAF",
},
2023-08-04 08:21:15 +00:00
"&:hover": {
background: theme.palette.brightPurple.main,
"& .MuiBox-root": {
background: theme.palette.brightPurple.main,
},
"& .MuiBadge-badge": {
background: theme.palette.background.default,
color: theme.palette.brightPurple.main,
},
2023-08-04 09:34:14 +00:00
"& svg > path:first-child": { fill: "#FFFFFF" },
"& svg > path:last-child": { stroke: "#FFFFFF" },
2023-08-04 08:21:15 +00:00
},
2023-08-03 12:14:31 +00:00
}}
>
<Badge
2023-08-07 15:16:34 +00:00
badgeContent={notificationsCount}
2023-08-03 12:14:31 +00:00
sx={{
"& .MuiBadge-badge": {
2023-08-07 15:16:34 +00:00
display: notificationsCount ? "flex" : "none",
2023-08-03 12:14:31 +00:00
color: "#FFFFFF",
background: theme.palette.brightPurple.main,
transform: "scale(0.8) translate(50%, -50%)",
top: "2px",
right: "2px",
fontWeight: 400,
},
}}
>
2023-08-04 09:34:14 +00:00
<BellIcon />
2023-08-03 12:14:31 +00:00
</Badge>
</IconButton>
2023-08-04 13:49:35 +00:00
<NotificationsModal
2023-08-07 15:16:34 +00:00
open={notificationsCount ? openNotificationsModal : false}
2023-08-04 13:49:35 +00:00
setOpen={setOpenNotificationsModal}
anchorElement={bellRef.current}
notifications={tickets.map((ticket) => ({
text: "У вас новое сообщение от техподдержки",
date: new Date(ticket.updated_at).toLocaleDateString(),
2023-08-07 15:16:34 +00:00
url: `/support/${ticket.id}`,
2023-08-04 13:49:35 +00:00
watched: ticket.user === ticket.top_message.user_id,
}))}
/>
2023-08-04 09:34:14 +00:00
<IconButton
2023-07-25 22:31:04 +00:00
onClick={openCartDrawer}
component="div"
sx={{
2023-08-03 12:14:31 +00:00
cursor: "pointer",
2023-08-04 09:34:14 +00:00
background: theme.palette.background.default,
borderRadius: "6px",
2023-07-25 22:31:04 +00:00
"&:hover": {
2023-08-04 09:34:14 +00:00
background: theme.palette.brightPurple.main,
2023-07-25 22:31:04 +00:00
"& .MuiBox-root": {
background: theme.palette.brightPurple.main,
},
"& .MuiBadge-badge": {
background: theme.palette.background.default,
color: theme.palette.brightPurple.main,
},
2023-08-04 09:34:14 +00:00
"& svg > path:nth-child(1)": { fill: "#FFFFFF" },
"& svg > path:nth-child(2)": { fill: "#FFFFFF" },
"& svg > path:nth-child(3)": { stroke: "#FFFFFF" },
2023-07-25 22:31:04 +00:00
},
}}
>
<Badge
2023-07-28 13:24:21 +00:00
badgeContent={userAccount?.cart.length}
2023-07-25 22:31:04 +00:00
sx={{
"& .MuiBadge-badge": {
2023-08-04 08:21:15 +00:00
display: userAccount?.cart.length ? "flex" : "none",
2023-07-25 22:31:04 +00:00
color: "#FFFFFF",
background: theme.palette.brightPurple.main,
transform: "scale(0.8) translate(50%, -50%)",
2023-08-04 09:34:14 +00:00
top: "2px",
right: "2px",
2023-07-25 22:31:04 +00:00
fontWeight: 400,
},
}}
>
2023-08-04 09:34:14 +00:00
<CartIcon />
2023-07-25 22:31:04 +00:00
</Badge>
2023-08-04 09:34:14 +00:00
</IconButton>
2023-07-25 22:31:04 +00:00
<Drawer anchor={"right"} open={isDrawerOpen} onClose={closeCartDrawer}>
<SectionWrapper
maxWidth="lg"
sx={{
pl: "0px",
pr: "0px",
width: "450px",
}}
>
<Box
sx={{
width: "100%",
2023-07-28 15:56:19 +00:00
pt: "12px",
pb: "12px",
2023-07-25 22:31:04 +00:00
display: "flex",
justifyContent: "space-between",
bgcolor: "#F2F3F7",
gap: "10px",
pl: "20px",
pr: "20px",
}}
>
{!upMd && (
<IconButton
sx={{ p: 0, height: "28px", width: "28px", color: "black" }}
>
<ArrowBackIcon />
</IconButton>
)}
<Typography
component="div"
sx={{
fontSize: "18px",
lineHeight: "21px",
font: "Rubick",
}}
>
Корзина
2023-03-27 12:45:44 +00:00
</Typography>
2023-07-25 22:31:04 +00:00
<IconButton onClick={closeCartDrawer} sx={{ p: 0 }}>
<SvgIcon component={ClearIcon} />
</IconButton>
</Box>
<Box sx={{ pl: "20px", pr: "20px" }}>
{cart.services.map((serviceData) => (
<CustomWrapperDrawer
key={serviceData.serviceKey}
serviceData={serviceData}
/>
))}
<Box
sx={{
mt: "40px",
pt: upMd ? "30px" : undefined,
borderTop: upMd
? `1px solid ${theme.palette.grey2.main}`
: undefined,
}}
>
<Box
sx={{
width: upMd ? "100%" : undefined,
display: "flex",
flexWrap: "wrap",
flexDirection: "column",
}}
>
<Typography variant="h4" mb={upMd ? "18px" : "30px"}>
Итоговая цена
</Typography>
<Typography color={theme.palette.grey3.main}>
Текст-заполнитель это текст, который имеет Текст-заполнитель
это текст, который имеет Текст-заполнитель это текст,
который имеет Текст-заполнитель это текст, который имеет
Текст-заполнитель
</Typography>
</Box>
<Box
sx={{
color: theme.palette.grey3.main,
pb: "100px",
pt: "38px",
}}
>
<Box
sx={{
display: "flex",
flexDirection: upMd ? "column" : "row",
alignItems: upMd ? "start" : "center",
mt: upMd ? "10px" : "30px",
gap: "15px",
}}
>
<Typography
color={theme.palette.orange.main}
2023-03-27 12:45:44 +00:00
sx={{
2023-07-25 22:31:04 +00:00
textDecoration: "line-through",
order: upMd ? 1 : 2,
2023-03-27 12:45:44 +00:00
}}
2023-07-25 22:31:04 +00:00
>
{currencyFormatter.format(totalPriceBeforeDiscounts / 100)}
</Typography>
<Typography
variant="p1"
2023-03-27 12:45:44 +00:00
sx={{
2023-07-25 22:31:04 +00:00
fontWeight: 500,
fontSize: "26px",
lineHeight: "31px",
order: upMd ? 2 : 1,
2023-03-27 12:45:44 +00:00
}}
2023-07-25 22:31:04 +00:00
>
{currencyFormatter.format(totalPriceAfterDiscounts / 100)}
</Typography>
</Box>
<CustomButton
variant="contained"
2023-08-01 00:56:03 +00:00
onClick={() => navigate("/cart")}
2023-07-25 22:31:04 +00:00
sx={{
mt: "25px",
backgroundColor: theme.palette.brightPurple.main,
}}
2023-03-27 12:45:44 +00:00
>
2023-07-25 22:31:04 +00:00
Оплатить
</CustomButton>
</Box>
</Box>
</Box>
</SectionWrapper>
</Drawer>
2023-08-03 12:14:31 +00:00
</Box>
2023-07-25 22:31:04 +00:00
);
2023-03-27 12:45:44 +00:00
}