diff --git a/package.json b/package.json index 7a59c9a..a2f5b46 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "dependencies": { "@emotion/react": "^11.10.5", "@emotion/styled": "^11.10.5", - "@frontend/kitui": "^1.0.16", + "@frontend/kitui": "^1.0.17", "@mui/icons-material": "^5.10.14", "@mui/material": "^5.10.14", "@popperjs/core": "^2.11.8", diff --git a/src/assets/Icons/bell.svg b/src/assets/Icons/bell.svg new file mode 100644 index 0000000..a6f1b8d --- /dev/null +++ b/src/assets/Icons/bell.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/assets/Icons/exclamation_point.svg b/src/assets/Icons/exclamation_point.svg new file mode 100644 index 0000000..15da3f5 --- /dev/null +++ b/src/assets/Icons/exclamation_point.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/assets/Icons/wallet_icon.svg b/src/assets/Icons/wallet_icon.svg new file mode 100644 index 0000000..75ed2b7 --- /dev/null +++ b/src/assets/Icons/wallet_icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/components/AccordionWrapper.tsx b/src/components/AccordionWrapper.tsx deleted file mode 100644 index 1cf9cfb..0000000 --- a/src/components/AccordionWrapper.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import { Box } from "@mui/material"; -import CustomAccordionBasket from "./CustomAccordionBasket"; -import { cardShadow } from "@root/utils/themes/shadow"; - -interface Props { - content: { title: string; data: [string, number][] }[]; -} - -export default function AccordionWrapperBasket({ content }: Props) { - return ( - - {content.map((accordionItem, index) => ( - - ))} - - ); -} diff --git a/src/components/ComplexNavText.tsx b/src/components/ComplexNavText.tsx deleted file mode 100644 index 82c04da..0000000 --- a/src/components/ComplexNavText.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import { Typography, useTheme } from "@mui/material"; -import { useNavigate } from "react-router-dom"; - -interface Props { - text1: string; - text2?: string; -} - -export default function ComplexNavText({ text1, text2 }: Props) { - const theme = useTheme(); - const navigate = useNavigate(); - - return ( - - navigate("/tariffs")} - sx={{ - cursor: "pointer", - fontWeight: 400, - fontSize: "12px", - lineHeight: "14px", - color: theme.palette.grey2.main, - }} - > - {text1} - - {text2 && - - {text2} - - } - - ); -} diff --git a/src/components/CustomAccordionBasket.tsx b/src/components/CustomAccordionBasket.tsx deleted file mode 100644 index 260295c..0000000 --- a/src/components/CustomAccordionBasket.tsx +++ /dev/null @@ -1,154 +0,0 @@ -import { Box, SvgIcon, Typography, useMediaQuery, useTheme } from "@mui/material"; -import { useState } from "react"; -import ClearIcon from "@mui/icons-material/Clear"; -import ExpandIcon from "./icons/ExpandIcon"; - -interface Props { - header: string; - totalPrice: number; - dataSection: [string, number][]; -} - -function TotalSum(mass: [string, number][]): number { - let sum: number = 0; - mass.forEach((element) => { - sum += element[1]; - }); - return sum; -} - -export default function CustomAccordionBasket({ header, totalPrice, dataSection }: Props) { - const theme = useTheme(); - const upMd = useMediaQuery(theme.breakpoints.up("md")); - const upSm = useMediaQuery(theme.breakpoints.up("sm")); - const [isExpanded, setIsExpanded] = useState(false); - let sum: number = TotalSum(dataSection); - - return ( - - setIsExpanded((prev) => !prev)} - sx={{ - height: "72px", - px: "20px", - - display: "flex", - alignItems: "center", - justifyContent: "space-between", - cursor: "pointer", - userSelect: "none", - }} - > - - {header} - - - - - {sum} руб. - - - - - - - {isExpanded && - dataSection.map((item, index) => { - return ( - - - {item[0]} - - - - {item[1]} руб. - - {upSm ? ( - - Удалить - - ) : ( - - )} - - - ); - })} - - ); -} diff --git a/src/components/CustomRadioButtons.tsx b/src/components/CustomRadioButtons.tsx deleted file mode 100644 index 31aff55..0000000 --- a/src/components/CustomRadioButtons.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import { Dispatch, SetStateAction, useState } from "react"; -import { List, ListItem, Typography, useMediaQuery, useTheme } from "@mui/material"; - -type Props = { - setType: Dispatch>; - _mocsk_: { name: string; type: "templ" | "squiz" | "reducer" }[]; -}; - -export default function CustomRadioButtons({ setType, _mocsk_ }: Props) { - const theme = useTheme(); - const upSm = useMediaQuery(theme.breakpoints.up("sm")); - const [active, setActive] = useState(0); - - const activeType = (index: number, type: "templ" | "squiz" | "reducer") => { - setActive(index); - setType(type); - }; - - return ( - - {_mocsk_.map(({ name, type }, index) => - active === index ? ( - activeType(index, type)} sx={{ color: "#7E2AEA", cursor: "pointer" }}> - - {name} - - - ) : ( - activeType(index, type)} sx={{ cursor: "pointer" }}> - {name} - - ) - )} - - ); -} diff --git a/src/components/Drawers.tsx b/src/components/Drawers.tsx index 33f55ad..735613f 100644 --- a/src/components/Drawers.tsx +++ b/src/components/Drawers.tsx @@ -1,3 +1,4 @@ +import { useState, useRef, useCallback } from "react"; import { Typography, Drawer, @@ -6,16 +7,15 @@ import { Box, IconButton, SvgIcon, - Icon, Badge, } from "@mui/material"; -import { IconsCreate } from "@root/lib/IconsCreate"; import ArrowBackIcon from "@mui/icons-material/ArrowBack"; import ClearIcon from "@mui/icons-material/Clear"; -import BasketIcon from "../assets/Icons/BasketIcon.svg"; +import { useTickets } from "@frontend/kitui"; import SectionWrapper from "./SectionWrapper"; import CustomWrapperDrawer from "./CustomWrapperDrawer"; import CustomButton from "./CustomButton"; +import { NotificationsModal } from "./NotificationsModal"; import { useNavigate } from "react-router"; import { useCart } from "@root/utils/hooks/useCart"; import { currencyFormatter } from "@root/utils/currencyFormatter"; @@ -26,8 +26,19 @@ import { } from "@root/stores/cart"; import { useCustomTariffsStore } from "@root/stores/customTariffs"; import { useUserStore } from "@root/stores/user"; +import { + updateTickets, + setTicketCount, + useTicketStore, +} from "@root/stores/tickets"; + +import { ReactComponent as BellIcon } from "@root/assets/Icons/bell.svg"; +import { ReactComponent as CartIcon } from "@root/assets/Icons/cart.svg"; export default function Drawers() { + const [openNotificationsModal, setOpenNotificationsModal] = + useState(false); + const bellRef = useRef(null); const navigate = useNavigate(); const theme = useTheme(); const upMd = useMediaQuery(theme.breakpoints.up("md")); @@ -40,6 +51,20 @@ export default function Drawers() { (state) => state.summaryPriceAfterDiscountsMap ); const userAccount = useUserStore((state) => state.userAccount); + const { tickets, ticketCount, apiPage, ticketsPerPage } = useTicketStore( + (state) => state + ); + + useTickets({ + url: "https://hub.pena.digital/heruvym/getTickets", + ticketsPerPage, + ticketApiPage: apiPage, + onNewTickets: useCallback((result) => { + if (result.data) updateTickets(result.data); + setTicketCount(result.count); + }, []), + onError: () => {}, + }); const basePrice = Object.values(summaryPriceBeforeDiscountsMap).reduce( (a, e) => a + e, @@ -54,13 +79,33 @@ export default function Drawers() { const totalPriceAfterDiscounts = cart.priceAfterDiscounts + discountedPrice; return ( - - + setOpenNotificationsModal((isOpened) => !isOpened)} sx={{ - position: "absolute", + cursor: "pointer", + borderRadius: "6px", + 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", + }, "&:hover": { + background: theme.palette.brightPurple.main, "& .MuiBox-root": { background: theme.palette.brightPurple.main, }, @@ -68,6 +113,57 @@ export default function Drawers() { background: theme.palette.background.default, color: theme.palette.brightPurple.main, }, + "& svg > path:first-child": { fill: "#FFFFFF" }, + "& svg > path:last-child": { stroke: "#FFFFFF" }, + }, + }} + > + + + + + ({ + text: "У вас новое сообщение от техподдержки", + date: new Date(ticket.updated_at).toLocaleDateString(), + watched: ticket.user === ticket.top_message.user_id, + }))} + /> + path:nth-child(1)": { fill: "#FFFFFF" }, + "& svg > path:nth-child(2)": { fill: "#FFFFFF" }, + "& svg > path:nth-child(3)": { stroke: "#FFFFFF" }, }, }} > @@ -75,49 +171,19 @@ export default function Drawers() { badgeContent={userAccount?.cart.length} sx={{ "& .MuiBadge-badge": { + display: userAccount?.cart.length ? "flex" : "none", color: "#FFFFFF", background: theme.palette.brightPurple.main, transform: "scale(0.8) translate(50%, -50%)", - top: "10px", - right: "10px", + top: "2px", + right: "2px", fontWeight: 400, }, }} > - + - - {cart.itemCount && ( - - - {cart.itemCount} - - - )} - + - + ); } diff --git a/src/components/InputTextfield.tsx b/src/components/InputTextfield.tsx index d0c84b7..dc01ed1 100644 --- a/src/components/InputTextfield.tsx +++ b/src/components/InputTextfield.tsx @@ -1,95 +1,100 @@ import { - FormControl, - InputLabel, - SxProps, - TextField, - TextFieldProps, - Theme, - useMediaQuery, - useTheme, + FormControl, + InputLabel, + SxProps, + TextField, + TextFieldProps, + Theme, + useMediaQuery, + useTheme, } from "@mui/material"; import "./text-input.css"; interface Props { - id: string; - label?: string; - bold?: boolean; - gap?: string; - color?: string; - FormInputSx?: SxProps; - TextfieldProps: TextFieldProps; - onChange: (e: React.ChangeEvent) => void; + id: string; + label?: string; + bold?: boolean; + gap?: string; + color?: string; + FormInputSx?: SxProps; + TextfieldProps: TextFieldProps; + onChange: ( + e: React.ChangeEvent + ) => void; } export default function InputTextfield({ - id, - label, - bold = false, - gap = "10px", - onChange, - TextfieldProps, - color, - FormInputSx, + id, + label, + bold = false, + gap = "10px", + onChange, + TextfieldProps, + color, + FormInputSx, }: Props) { - const theme = useTheme(); - const upMd = useMediaQuery(theme.breakpoints.up("md")); + const theme = useTheme(); + const upMd = useMediaQuery(theme.breakpoints.up("md")); - const labelFont = upMd - ? bold - ? theme.typography.p1 - : { ...theme.typography.body1, fontWeight: 500 } - : theme.typography.body2; + const labelFont = upMd + ? bold + ? theme.typography.p1 + : { ...theme.typography.body1, fontWeight: 500 } + : theme.typography.body2; - const placeholderFont = upMd ? undefined : { fontWeight: 400, fontSize: "16px", lineHeight: "19px" }; + const placeholderFont = upMd + ? undefined + : { fontWeight: 400, fontSize: "16px", lineHeight: "19px" }; - return ( - + {label && ( + - {label && - - {label} - - } - - - ); + {label} + + )} + + + ); } diff --git a/src/components/Layout.tsx b/src/components/Layout.tsx index 4ad3d38..370ae6b 100644 --- a/src/components/Layout.tsx +++ b/src/components/Layout.tsx @@ -1,13 +1,10 @@ import { Outlet } from "react-router-dom"; import Navbar from "./Navbar/Navbar"; - export default function Layout() { - - return ( - <> - - - - ); -} \ No newline at end of file + return ( + + + + ); +} diff --git a/src/components/Navbar/DialogMenu.tsx b/src/components/Navbar/DialogMenu.tsx index 5e5475a..6d2a2d5 100644 --- a/src/components/Navbar/DialogMenu.tsx +++ b/src/components/Navbar/DialogMenu.tsx @@ -1,29 +1,20 @@ import { useState } from "react"; -import { TransitionProps } from "@mui/material/transitions"; - -import logotip from "../../assets/Icons/logoPenaHab.svg"; -import logotipBlack from "../../assets/Icons/black_logo_PenaHab.svg"; -import CustomAvatar from "./Avatar"; -import CloseIcon from "../icons/CloseIcons"; -import React from "react"; +import { Link, useLocation } from "react-router-dom"; import { - AppBar, Box, Button, - Dialog, - IconButton, List, ListItem, - Slide, - Toolbar, Typography, useMediaQuery, useTheme, } from "@mui/material"; -import { Link, useLocation } from "react-router-dom"; + import { useUserStore } from "@root/stores/user"; import { currencyFormatter } from "@root/utils/currencyFormatter"; +import CustomAvatar from "./Avatar"; + type MenuItem = { name: string; url: string; @@ -46,22 +37,11 @@ const arrayMenu: MenuItem[] = [ { name: "История", url: "/history" }, ]; -const Transition = React.forwardRef(function Transition( - props: TransitionProps & { - children: React.ReactElement; - }, - - ref: React.Ref -) { - return ; -}); - interface DialogMenuProps { - open: boolean; handleClose: () => void; } -export default function DialogMenu({ open, handleClose }: DialogMenuProps) { +export default function DialogMenu({ handleClose }: DialogMenuProps) { const [activeSubMenuIndex, setActiveSubMenuIndex] = useState(-1); const theme = useTheme(); const location = useLocation(); @@ -81,64 +61,12 @@ export default function DialogMenu({ open, handleClose }: DialogMenuProps) { ); return ( - - - - - - - {isMobile && ( - - icon - - )} - - + ))} - {isMobile ? ( - location.pathname === "/" ? ( - - ) : ( - - - - - Мой баланс - - - {currencyFormatter.format(cash / 100)} - - - - ) + {location.pathname === "/" ? ( + ) : ( - icon + + + + Мой баланс + + + {currencyFormatter.format(cash / 100)} + + )} - + ); } diff --git a/src/components/Navbar/Navbar.tsx b/src/components/Navbar/Navbar.tsx index a191c67..de1c449 100644 --- a/src/components/Navbar/Navbar.tsx +++ b/src/components/Navbar/Navbar.tsx @@ -2,14 +2,24 @@ import { useMediaQuery, useTheme } from "@mui/material"; import NavbarCollapsed from "./NavbarCollapsed"; import NavbarFull from "./NavbarFull"; +import type { ReactNode } from "react"; + interface Props { - isCollapsed?: boolean; isLoggedIn: boolean; + children: ReactNode; } -export default function Navbar({ isLoggedIn, isCollapsed = false }: Props) { +export default function Navbar({ isLoggedIn, children }: Props) { const theme = useTheme(); const upMd = useMediaQuery(theme.breakpoints.up("md")); - return upMd ? : ; + return ( + <> + {upMd ? ( + {children} + ) : ( + {children} + )} + + ); } diff --git a/src/components/Navbar/NavbarCollapsed.tsx b/src/components/Navbar/NavbarCollapsed.tsx index 2af3098..bff8752 100644 --- a/src/components/Navbar/NavbarCollapsed.tsx +++ b/src/components/Navbar/NavbarCollapsed.tsx @@ -1,34 +1,70 @@ -import { useState } from "react"; -import { Badge, IconButton, useTheme } from "@mui/material"; -import MenuIcon from "@mui/icons-material/Menu"; +import { useState, useRef, useEffect, useCallback } from "react"; +import { Box, Badge, Drawer, IconButton, useTheme } from "@mui/material"; import { Link } from "react-router-dom"; +import { useTickets } from "@frontend/kitui"; import SectionWrapper from "../SectionWrapper"; +import { NotificationsModal } from "../NotificationsModal"; + import { useUserStore } from "@root/stores/user"; +import { + updateTickets, + setTicketCount, + useTicketStore, +} from "@root/stores/tickets"; + +import MenuIcon from "@mui/icons-material/Menu"; +import { ReactComponent as CartIcon } from "@root/assets/Icons/cart.svg"; +import { ReactComponent as BellIcon } from "@root/assets/Icons/bell.svg"; -import PenaLogo from "../PenaLogo"; import DialogMenu from "./DialogMenu"; +import PenaLogo from "../PenaLogo"; +import CloseIcon from "../icons/CloseIcons"; -import cartIcon from "@root/assets/Icons/cart.svg"; +import type { ReactNode } from "react"; interface Props { isLoggedIn: boolean; + children: ReactNode; } -export default function NavbarCollapsed({ isLoggedIn }: Props) { +export default function NavbarCollapsed({ isLoggedIn, children }: Props) { const [open, setOpen] = useState(false); + const [openNotificationsModal, setOpenNotificationsModal] = + useState(false); + const bellRef = useRef(null); const userAccount = useUserStore((state) => state.userAccount); + const { ticketCount, tickets, apiPage, ticketsPerPage } = useTicketStore( + (state) => state + ); + + useTickets({ + url: "https://hub.pena.digital/heruvym/getTickets", + ticketsPerPage, + ticketApiPage: apiPage, + onNewTickets: useCallback((result) => { + if (result.data) updateTickets(result.data); + setTicketCount(result.count); + }, []), + onError: () => {}, + }); const theme = useTheme(); - const handleClickOpen = () => { - setOpen(true); - }; - const handleClose = () => { setOpen(false); }; + useEffect(() => { + if (open) { + document.body.style.overflow = "hidden"; + + return; + } + + document.body.style.overflow = "unset"; + }, [open]); + return ( - - - - setOpen((isOpened) => !isOpened)} + sx={{ + p: 0, + width: "30px", + color: theme.palette.primary.main, + }} + > + {open ? ( + + ) : ( + + )} + + + path:nth-child(1)": { fill: "#FFFFFF" }, + "& svg > path:nth-child(2)": { fill: "#FFFFFF" }, + "& svg > path:nth-child(3)": { stroke: "#FFFFFF" }, + }, + }} + > + + + + + + setOpenNotificationsModal((isOpened) => !isOpened)} aria-label="cart" sx={{ + width: "30px", + height: "30px", background: theme.palette.background.default, borderRadius: "6px", "&:hover": { @@ -67,30 +152,84 @@ export default function NavbarCollapsed({ isLoggedIn }: Props) { background: theme.palette.background.default, color: theme.palette.brightPurple.main, }, + "& svg > path:first-child": { fill: "#FFFFFF" }, + "& svg > path:last-child": { stroke: "#FFFFFF" }, }, }} > - cart + - - - - - + ({ + text: "У вас новое сообщение от техподдержки", + date: new Date(ticket.updated_at).toLocaleDateString(), + watched: ticket.user === ticket.top_message.user_id, + }))} + /> + + + + + + + + + + {children} + + ); } diff --git a/src/components/Navbar/NavbarFull.tsx b/src/components/Navbar/NavbarFull.tsx index d7dda09..0009b95 100644 --- a/src/components/Navbar/NavbarFull.tsx +++ b/src/components/Navbar/NavbarFull.tsx @@ -9,7 +9,6 @@ import { } from "@mui/material"; import SectionWrapper from "../SectionWrapper"; import LogoutIcon from "../icons/LogoutIcon"; -import WalletIcon from "../icons/WalletIcon"; import CustomAvatar from "./Avatar"; import Drawers from "../Drawers"; import PenaLogo from "../PenaLogo"; @@ -19,13 +18,19 @@ import { enqueueSnackbar } from "notistack"; import { clearUserData, useUserStore } from "@root/stores/user"; import { clearAuthToken, getMessageFromFetchError } from "@frontend/kitui"; import { clearCustomTariffs } from "@root/stores/customTariffs"; + import { currencyFormatter } from "@root/utils/currencyFormatter"; +import walletIcon from "@root/assets/Icons/wallet_icon.svg"; + +import type { ReactNode } from "react"; + interface Props { isLoggedIn: boolean; + children: ReactNode; } -export default function NavbarFull({ isLoggedIn }: Props) { +export default function NavbarFull({ isLoggedIn, children }: Props) { const theme = useTheme(); const navigate = useNavigate(); const location = useLocation(); @@ -45,104 +50,115 @@ export default function NavbarFull({ isLoggedIn }: Props) { } } - return isLoggedIn ? ( - - - - - - - - navigate("/wallet")} + return ( + + {isLoggedIn ? ( + - - - - + + + + + + navigate("/wallet")} + > + wallet + + + + Мой баланс + + + {currencyFormatter.format(cash / 100)} + + + + + + + + + ) : ( + <> + - Мой баланс - - - {currencyFormatter.format(cash / 100)} - - - - - - - - - ) : ( - <> - - - - - - + + + + + + )} + {children} + ); } diff --git a/src/components/NotificationsModal.tsx b/src/components/NotificationsModal.tsx new file mode 100644 index 0000000..b99650a --- /dev/null +++ b/src/components/NotificationsModal.tsx @@ -0,0 +1,118 @@ +import { + Popover, + List, + ListItem, + Typography, + useTheme, + useMediaQuery, +} from "@mui/material"; + +type Notification = { + text: string; + date: string; + watched?: boolean; +}; + +type NotificationsModalProps = { + open: boolean; + setOpen: (isOpen: boolean) => void; + anchorElement: Element | null; + notifications: Notification[]; +}; + +export const NotificationsModal = ({ + open, + setOpen, + anchorElement, + notifications, +}: NotificationsModalProps) => { + const theme = useTheme(); + const isMobile = useMediaQuery(theme.breakpoints.down(650)); + + return ( + setOpen(false)} + anchorOrigin={{ vertical: "bottom", horizontal: "left" }} + transformOrigin={{ vertical: "top", horizontal: "right" }} + sx={{ + "& .MuiPopover-paper": { + maxWidth: isMobile ? "calc(100vw - 30px)" : 600, + width: "100%", + maxHeight: "310px", + borderRadius: "8px", + boxShadow: + "0px 3px 18px rgba(49, 28, 77, 0.1), 0px 3px 34px rgba(49, 28, 77, 0.15)", + "&::-webkit-scrollbar": { width: "6px" }, + "&::-webkit-scrollbar-track": { + background: "#F0F0F6", + margin: "5px", + borderRadius: "5px", + }, + "&::-webkit-scrollbar-thumb": { + width: "4px", + background: "#9A9AAF", + borderRadius: "5px", + }, + }, + }} + > + + {notifications.map(({ text, date, watched = true }) => ( + + + {text} + + + {date} + + + ))} + + + ); +}; diff --git a/src/components/Select/index.tsx b/src/components/Select/index.tsx index 796d040..79db8d8 100644 --- a/src/components/Select/index.tsx +++ b/src/components/Select/index.tsx @@ -1,12 +1,18 @@ -import { useState } from "react"; -import { Select as MuiSelect, MenuItem, useTheme } from "@mui/material"; +import { useState, useRef } from "react"; +import { + Select as MuiSelect, + MenuItem, + Box, + Typography, + useTheme, +} from "@mui/material"; import classnames from "classnames"; -import { cardShadow } from "@root/utils/themes/shadow"; +import checkIcon from "@root/assets/Icons/check.svg"; import "./select.css"; -import checkIcon from "@root/assets/Icons/check.svg"; +import type { SelectChangeEvent } from "@mui/material"; type SelectProps = { items: string[]; @@ -20,36 +26,73 @@ export const Select = ({ setSelectedItem, }: SelectProps) => { const [opened, setOpened] = useState(false); + const [currentValue, setCurrentValue] = useState(items[selectedItem]); + const ref = useRef(null); const theme = useTheme(); + const selectItem = (event: SelectChangeEvent) => { + setCurrentValue(items[Number(event.target.value)]); + setSelectedItem(Number(event.target.value)); + }; + return ( - setSelectedItem(Number(event.target.value))} - sx={{ - width: "100%", - color: theme.palette.brightPurple.main, - border: "2px solid #ffffff", - borderRadius: "30px", - fontWeight: "bold", - boxShadow: cardShadow, - }} - open={opened} - onClick={() => setOpened((isOpened) => !isOpened)} - IconComponent={() => ( + + ref.current?.click()} + > + + {currentValue} + check - )} - > - {items.map((item, index) => ( - - {item} - - ))} - + + setOpened((isOpened) => !isOpened)} + > + {items.map((item, index) => ( + + {item} + + ))} + + ); }; diff --git a/src/components/Select/select.css b/src/components/Select/select.css index 2ddd8e9..53cab65 100644 --- a/src/components/Select/select.css +++ b/src/components/Select/select.css @@ -1,10 +1,3 @@ -.select.MuiInputBase-root.MuiOutlinedInput-root { - z-index: 1500; - background: #ebebf2; - box-shadow: 0px 5px 40px rgba(210, 208, 225, 0.58), - 0px 2.76726px 8.55082px rgba(210, 208, 225, 0.4); -} - .MuiOutlinedInput-root .MuiOutlinedInput-notchedOutline { border: 0; } @@ -20,7 +13,16 @@ } .MuiPaper-root.MuiMenu-paper { - padding-top: 60px; - margin-top: -60px; + padding-top: 50px; + margin-top: -50px; border-radius: 28px; } + +.MuiInputBase-root.MuiOutlinedInput-root { + display: block; +} + +.MuiInputBase-root.MuiOutlinedInput-root > div:first-child, +.MuiInputBase-root.MuiOutlinedInput-root .MuiSelect-icon { + display: none; +} diff --git a/src/components/StepperSquiz.tsx b/src/components/StepperSquiz.tsx deleted file mode 100644 index 0e0c39d..0000000 --- a/src/components/StepperSquiz.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import { Typography } from "@mui/material"; -import { useNavigate } from "react-router"; - -type Props = { - text: string; -}; - -export default function StepperSquiz({ text }: Props) { - const navigate = useNavigate(); - return ( - - navigate("/tariffs")} - component="div" - sx={{ cursor: "pointer", fontWeight: "400px", fontSize: "12px", lineHeight: "14px", marginBottom: "19px" }} - > - Все тарифы — - - - {text} - - - ); -} diff --git a/src/components/VideoGIF.tsx b/src/components/VideoGIF.tsx deleted file mode 100644 index e376eff..0000000 --- a/src/components/VideoGIF.tsx +++ /dev/null @@ -1,8 +0,0 @@ -import React from "react"; -interface Props { - - style: {width:string,height:string} -} -export default function (props:Props) { - -} diff --git a/src/components/icons/UploadIcon.tsx b/src/components/icons/UploadIcon.tsx index 6c0add8..4adbbfa 100644 --- a/src/components/icons/UploadIcon.tsx +++ b/src/components/icons/UploadIcon.tsx @@ -1,7 +1,7 @@ import { Box } from "@mui/material"; -export default function UploadIcon() { +export default function SendIcon() { return ( - + ; - TextfieldProps: TextFieldProps; - onChange: (e: React.ChangeEvent) => void; - } - - export default function ({ - id, - label, - bold = false, - gap = "10px", - onChange, - TextfieldProps, - color, - FormInputSx, - }: Props) { - const theme = useTheme(); - const upMd = useMediaQuery(theme.breakpoints.up("md")); - - const labelFont = upMd - ? bold - ? theme.typography.p1 - : { ...theme.typography.body1, fontWeight: 500 } - : theme.typography.body2; - - const placeholderFont = upMd ? undefined : { fontWeight: 400, fontSize: "16px", lineHeight: "19px" }; + FormControl, + IconButton, + InputLabel, + SxProps, + TextField, + TextFieldProps, + Theme, + useMediaQuery, + useTheme, +} from "@mui/material"; +import * as React from "react"; +import InputAdornment from "@mui/material/InputAdornment"; +import Visibility from "@mui/icons-material/Visibility"; +import VisibilityOff from "@mui/icons-material/VisibilityOff"; - const [showPassword, setShowPassword] = React.useState(false); +interface Props { + id: string; + label?: string; + bold?: boolean; + gap?: string; + color?: string; + FormInputSx?: SxProps; + TextfieldProps: TextFieldProps; + onChange: ( + e: React.ChangeEvent + ) => void; +} - const handleClickShowPassword = () => setShowPassword((show) => !show); +export default function PasswordInput({ + id, + label, + bold = false, + gap = "10px", + onChange, + TextfieldProps, + color, + FormInputSx, +}: Props) { + const theme = useTheme(); + const upMd = useMediaQuery(theme.breakpoints.up("md")); - const handleMouseDownPassword = (event: React.MouseEvent) => { - event.preventDefault(); - }; - - return ( - - setShowPassword((show) => !show); + + const handleMouseDownPassword = ( + event: React.MouseEvent + ) => { + event.preventDefault(); + }; + + return ( + + - + + + {showPassword ? : } + + + ), + sx: { + padding: "0px", + border: "1px solid" + theme.palette.grey2.main, + backgroundColor: color, + borderRadius: "8px", + height: "48px", color: "black", - transform: "none", - ...labelFont, - }} - > - {label} - - - - {showPassword ? : } - - - ), - sx: { - border: "1px solid" + theme.palette.grey2.main, - backgroundColor: color, - borderRadius: "8px", - height: "48px", - py: 0, - color: "black", - ...placeholderFont, - }, - }} - onChange={onChange} - type={showPassword ? 'text' : 'password'} - /> - - - ); - } - \ No newline at end of file + }, + }} + onChange={onChange} + type={showPassword ? "text" : "password"} + /> + + ); +} diff --git a/src/components/templCardPhoneLight.tsx b/src/components/templCardPhoneLight.tsx index ae1d963..876bf7d 100644 --- a/src/components/templCardPhoneLight.tsx +++ b/src/components/templCardPhoneLight.tsx @@ -5,14 +5,7 @@ import { useMediaQuery, useTheme, } from "@mui/material"; -import ArrowForwardIcon from "@mui/icons-material/ArrowForward"; -import CardWithLink from "@components/CardWithLink"; -import UnderlinedLink from "@components/UnderlinedLink"; -import SectionWrapper from "@components/SectionWrapper"; import card1Image from "@root/assets/landing/card1.png"; -import card2Image from "@root/assets/landing/card2.png"; -import card3Image from "@root/assets/landing/card3.png"; -import cardImageBig from "@root/assets/landing/card1big.png"; export default function () { const theme = useTheme(); diff --git a/src/components/templCardPhonePink.tsx b/src/components/templCardPhonePink.tsx index 1b83f12..68e7e67 100644 --- a/src/components/templCardPhonePink.tsx +++ b/src/components/templCardPhonePink.tsx @@ -1,31 +1,30 @@ -import {Box, Typography, useMediaQuery, useTheme} from "@mui/material"; -import ArrowForwardIcon from "@mui/icons-material/ArrowForward"; +import { Box, useMediaQuery, useTheme } from "@mui/material"; import CardWithLink from "@components/CardWithLink"; -import UnderlinedLink from "@components/UnderlinedLink"; -import SectionWrapper from "@components/SectionWrapper"; import card1Image from "@root/assets/landing/card1.png"; -import card2Image from "@root/assets/landing/card2.png"; -import card3Image from "@root/assets/landing/card3.png"; -import cardImageBig from "@root/assets/landing/card1big.png"; export default function () { - const theme = useTheme(); - const upMd = useMediaQuery(theme.breakpoints.up("md"));console.log("я узкий") - return - + backgroundColor: '"#E6E6EB', + }} + > + -} \ No newline at end of file + ); +} diff --git a/src/components/wideTemplCard.tsx b/src/components/wideTemplCard.tsx index 66ac471..942d12e 100644 --- a/src/components/wideTemplCard.tsx +++ b/src/components/wideTemplCard.tsx @@ -1,19 +1,6 @@ -import { - Box, - Typography, - useMediaQuery, - useTheme, - Button, - SxProps, - Theme, -} from "@mui/material"; +import { Box, Typography, Button, SxProps, Theme } from "@mui/material"; import ArrowForwardIcon from "@mui/icons-material/ArrowForward"; -import CardWithLink from "@components/CardWithLink"; import UnderlinedLink from "@components/UnderlinedLink"; -import SectionWrapper from "@components/SectionWrapper"; -import card1Image from "@root/assets/landing/card1.png"; -import card2Image from "@root/assets/landing/card2.png"; -import card3Image from "@root/assets/landing/card3.png"; import cardImageBig from "@root/assets/landing/card1big.png"; interface Props { @@ -22,9 +9,6 @@ interface Props { } export default function ({ light = true, sx }: Props) { - const theme = useTheme(); - const upMd = useMediaQuery(theme.breakpoints.up("md")); - return ( ( - - svg - -); diff --git a/src/model/auth.ts b/src/model/auth.ts index 49aa248..a2d4de4 100644 --- a/src/model/auth.ts +++ b/src/model/auth.ts @@ -1,4 +1,3 @@ -import type { VerificationStatus } from "@root/model/account"; import type { Attachment } from "@root/model/attachment"; type File = { diff --git a/src/pages/Basket/Basket.tsx b/src/pages/Basket/Basket.tsx index 5fd6e2b..be7bd5e 100644 --- a/src/pages/Basket/Basket.tsx +++ b/src/pages/Basket/Basket.tsx @@ -3,7 +3,6 @@ import SectionWrapper from "@components/SectionWrapper"; import ArrowBackIcon from "@mui/icons-material/ArrowBack"; import TotalPrice from "@components/TotalPrice"; import CustomWrapper from "./CustomWrapper"; -import ComplexNavText from "@root/components/ComplexNavText"; import { useCart } from "@root/utils/hooks/useCart"; import { useCustomTariffsStore } from "@root/stores/customTariffs"; @@ -29,7 +28,6 @@ export default function Basket() { mb: upMd ? "70px" : "37px", }} > - {upMd && } - {upMd && ( - - )} - {upMd && } (null); - const [paymentValueField, setPaymentValueField] = useState("0"); - const [paymentLink, setPaymentLink] = useState(""); - const location = useLocation(); + const theme = useTheme(); + const upMd = useMediaQuery(theme.breakpoints.up("md")); + const upSm = useMediaQuery(theme.breakpoints.up("sm")); + const [selectedPaymentMethod, setSelectedPaymentMethod] = + useState(null); + const [paymentValueField, setPaymentValueField] = useState("0"); + const [paymentLink, setPaymentLink] = useState(""); + const location = useLocation(); - const notEnoughMoneyAmount = location.state?.notEnoughMoneyAmount as number ?? 0; + const notEnoughMoneyAmount = + (location.state?.notEnoughMoneyAmount as number) ?? 0; - useEffect(() => { - setPaymentValueField((notEnoughMoneyAmount / 100).toString()); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); + useEffect(() => { + setPaymentValueField((notEnoughMoneyAmount / 100).toString()); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); - const paymentValue = parseFloat(paymentValueField) * 100; + useEffect(() => { + setPaymentLink(""); + }, [selectedPaymentMethod]); - function handleChoosePaymentClick() { - sendPayment().then(result => { - setPaymentLink(result.link); - }).catch(error => { - const message = getMessageFromFetchError(error); - if (message) enqueueSnackbar(message); + const paymentValue = parseFloat(paymentValueField) * 100; + + function handleChoosePaymentClick() { + if (Number(paymentValueField) !== 0) { + sendPayment() + .then((result) => { + setPaymentLink(result.link); + }) + .catch((error) => { + const message = getMessageFromFetchError(error); + if (message) enqueueSnackbar(message); }); } + } - return ( - + + {!upMd && ( + + + + )} + Способ оплаты + + {!upMd && ( + + Выберите способ оплаты + + )} + + - {upMd && } - ( + setSelectedPaymentMethod(method.name)} + /> + ))} + + + + {upMd && Выберите способ оплаты} + К оплате + {paymentLink ? ( + - {!upMd && ( - - - - )} - Способ оплаты - - {!upMd && ( - - Выберите способ оплаты - + > + {currencyFormatter.format(paymentValue / 100)} + + ) : ( + setPaymentValueField(e.target.value)} + id="payment-amount" + gap={upMd ? "16px" : "10px"} + color={"#F2F3F7"} + FormInputSx={{ mb: "28px" }} + /> )} - + {paymentLink ? ( + - - {paymentMethods.map(method => - setSelectedPaymentMethod(method.name)} - /> - )} - - - - {upMd && Выберите способ оплаты} - К оплате - {paymentLink ? - - {currencyFormatter.format(paymentValue / 100)} - - : - setPaymentValueField(e.target.value)} - id="payment-amount" - gap={upMd ? "16px" : "10px"} - color={"#F2F3F7"} - FormInputSx={{ - mb: "28px", - }} - /> - } - - {paymentLink ? - - Оплатить - - : - - Выбрать - - } - - - - ); + Оплатить + + ) : ( + + Выбрать + + )} + + + + ); } diff --git a/src/pages/SavedTariffs/index.tsx b/src/pages/SavedTariffs/index.tsx index b276008..5f8c144 100644 --- a/src/pages/SavedTariffs/index.tsx +++ b/src/pages/SavedTariffs/index.tsx @@ -1,10 +1,13 @@ -import { IconButton, useMediaQuery, useTheme } from "@mui/material"; -import { Box } from "@mui/material"; -import { Typography } from "@mui/material"; +import { + IconButton, + Box, + Typography, + useMediaQuery, + useTheme, +} from "@mui/material"; import SectionWrapper from "../../components/SectionWrapper"; import AccordionWrapper from "./AccordionWrapper"; import ArrowBackIcon from "@mui/icons-material/ArrowBack"; -import ComplexNavText from "../../components/ComplexNavText"; export default function Faq() { const theme = useTheme(); @@ -18,12 +21,6 @@ export default function Faq() { mb: upMd ? "70px" : "37px", }} > - {upMd && ( - - )} state.apiPage); - const ticketsPerPage = useTicketStore(state => state.ticketsPerPage); - const token = useToken(); + const theme = useTheme(); + const upMd = useMediaQuery(theme.breakpoints.up("md")); + const ticketId = useParams().ticketId; + const ticketApiPage = useTicketStore((state) => state.apiPage); + const ticketsPerPage = useTicketStore((state) => state.ticketsPerPage); + const token = useToken(); - const fetchState = useTickets({ - url: "https://hub.pena.digital/heruvym/getTickets", - ticketsPerPage, - ticketApiPage, - onNewTickets: useCallback(result => { - if (result.data) updateTickets(result.data); - setTicketCount(result.count); - }, []), - onError: useCallback((error: Error) => { - const message = getMessageFromFetchError(error); - if (message) enqueueSnackbar(message); - }, []) - }); + const fetchState = useTickets({ + url: "https://hub.pena.digital/heruvym/getTickets", + ticketsPerPage, + ticketApiPage, + onNewTickets: useCallback((result) => { + if (result.data) updateTickets(result.data); + setTicketCount(result.count); + }, []), + onError: useCallback((error: Error) => { + const message = getMessageFromFetchError(error); + if (message) enqueueSnackbar(message); + }, []), + }); - useSSESubscription({ - enabled: Boolean(token), - url: `https://admin.pena.digital/heruvym/subscribe?Authorization=${token}`, - onNewData: updateTickets, - onDisconnect: useCallback(() => { - clearTickets(); - }, []), - marker: "ticket" - }); + useSSESubscription({ + enabled: Boolean(token), + url: `https://admin.pena.digital/heruvym/subscribe?Authorization=${token}`, + onNewData: updateTickets, + onDisconnect: useCallback(() => { + clearTickets(); + }, []), + marker: "ticket", + }); - return ( - + + - {upMd && } - - {!upMd && ( - - - - )} - Запрос в службу техподдержки - - {ticketId ? ( - - ) : ( - - - - - )} - - ); + + + + Запрос в службу техподдержки + + + {ticketId ? ( + + ) : ( + + + + + )} + + ); } diff --git a/src/pages/Support/SupportChat.tsx b/src/pages/Support/SupportChat.tsx index 9e72d19..6509f36 100644 --- a/src/pages/Support/SupportChat.tsx +++ b/src/pages/Support/SupportChat.tsx @@ -17,6 +17,7 @@ import { getMessageFromFetchError, useEventListener, useSSESubscription, useTick export default function SupportChat() { const theme = useTheme(); const upMd = useMediaQuery(theme.breakpoints.up("md")); + const isMobile = useMediaQuery(theme.breakpoints.up(460)); const [messageField, setMessageField] = useState(""); const tickets = useTicketStore(state => state.tickets); const messages = useMessageStore(state => state.messages); @@ -134,6 +135,7 @@ export default function SupportChat() { borderRadius: "12px", p: upMd ? "20px" : undefined, gap: "40px", + height: !upMd ? `calc(100% - ${isMobile ? 90 : 115}px)` : null, boxShadow: upMd ? cardShadow : undefined, diff --git a/src/pages/Support/TicketList/TicketCard.tsx b/src/pages/Support/TicketList/TicketCard.tsx index 45599a3..5e4659a 100644 --- a/src/pages/Support/TicketList/TicketCard.tsx +++ b/src/pages/Support/TicketList/TicketCard.tsx @@ -1,20 +1,23 @@ -import { Link as RouterLink } from "react-router-dom"; import { useMemo } from "react"; +import { Link as RouterLink } from "react-router-dom"; import { Box, Typography, useMediaQuery, useTheme } from "@mui/material"; import CustomButton from "@components/CustomButton"; + import { cardShadow } from "@root/utils/themes/shadow"; -interface Props { - name: string; - body: string; - time: string; - ticketId: string; -} +import ExclamationPointIcon from "@root/assets/Icons/exclamation_point.svg"; -export default function TicketCard({ name, body, time, ticketId }: Props) { +import type { Ticket } from "@frontend/kitui"; + +type TicketCardProps = { + ticket: Ticket; +}; + +export default function TicketCard({ ticket }: TicketCardProps) { const theme = useTheme(); const upMd = useMediaQuery(theme.breakpoints.up("md")); + const adminReplied = ticket.user !== ticket.top_message.user_id; const timeText = useMemo( () => ( @@ -28,10 +31,10 @@ export default function TicketCard({ name, body, time, ticketId }: Props) { mb: "5px", }} > - {time} + {new Date(ticket.updated_at).toLocaleDateString()} ), - [theme.palette.grey2.main, time] + [theme.palette.grey2.main, ticket] ); return ( @@ -48,8 +51,22 @@ export default function TicketCard({ name, body, time, ticketId }: Props) { boxShadow: cardShadow, }} > - {!upMd && timeText} + {!upMd && {timeText}} + {adminReplied && ( + + ExclamationPoint + Вам ответили + + )} - {name} + {ticket.title} + + + {ticket.top_message.message} - {body} state.tickets); - const ticketCount = useTicketStore(state => state.ticketCount); - const ticketApiPage = useTicketStore(state => state.apiPage); - const ticketsPerPage = useTicketStore(state => state.ticketsPerPage); + const theme = useTheme(); + const tickets = useTicketStore((state) => state.tickets); + const ticketCount = useTicketStore((state) => state.ticketCount); + const ticketApiPage = useTicketStore((state) => state.apiPage); + const ticketsPerPage = useTicketStore((state) => state.ticketsPerPage); - const sortedTickets = tickets.sort(sortTicketsByUpdateTime).slice(ticketApiPage * ticketsPerPage, (ticketApiPage + 1) * ticketsPerPage); - - return ( - - - {sortedTickets.map((ticket) => ( - - - - ))} - {fetchState === "fetching" && ( - - - - )} - - {ticketCount > ticketsPerPage && - setTicketApiPage(value - 1)} - sx={{ alignSelf: "center" }} - /> - } - + const sortedTickets = tickets + .sort(sortTicketsByUpdateTime) + .slice( + ticketApiPage * ticketsPerPage, + (ticketApiPage + 1) * ticketsPerPage ); + + return ( + + + {sortedTickets.map((ticket) => ( + + + + ))} + {fetchState === "fetching" && ( + + + + )} + + {ticketCount > ticketsPerPage && ( + setTicketApiPage(value - 1)} + sx={{ alignSelf: "center" }} + /> + )} + + ); } function sortTicketsByUpdateTime(ticket1: Ticket, ticket2: Ticket) { - const date1 = new Date(ticket1.updated_at).getTime(); - const date2 = new Date(ticket2.updated_at).getTime(); - return date2 - date1; -} \ No newline at end of file + const date1 = new Date(ticket1.updated_at).getTime(); + const date2 = new Date(ticket2.updated_at).getTime(); + return date2 - date1; +} diff --git a/src/pages/TariffConstructor/Summary.tsx b/src/pages/TariffConstructor/Summary.tsx deleted file mode 100644 index 1430a11..0000000 --- a/src/pages/TariffConstructor/Summary.tsx +++ /dev/null @@ -1,82 +0,0 @@ -import { Box, Typography, useMediaQuery, useTheme } from "@mui/material"; -import CustomButton from "@root/components/CustomButton"; -import { useCustomTariffsStore } from "@root/stores/customTariffs"; -import { currencyFormatter } from "@root/utils/currencyFormatter"; - - -export default function Summary() { - const theme = useTheme(); - const upMd = useMediaQuery(theme.breakpoints.up("md")); - const summaryPriceBeforeDiscountsMap = useCustomTariffsStore(state => state.summaryPriceBeforeDiscountsMap); - const summaryPriceAfterDiscountsMap = useCustomTariffsStore(state => state.summaryPriceAfterDiscountsMap); - - const basePrice = Object.values(summaryPriceBeforeDiscountsMap).reduce((a, e) => a + e, 0); - const discountedPrice = Object.values(summaryPriceAfterDiscountsMap).reduce((a, e) => a + e, 0); - - - return ( - - - - Итоговая цена - - - Текст-заполнитель — это текст, который имеет Текст-заполнитель — это текст, который имеет Текст-заполнитель - — это текст, который имеет Текст-заполнитель — это текст, который имеет Текст-заполнитель - - - - - - {currencyFormatter.format(basePrice / 100)} руб. - - - {currencyFormatter.format(discountedPrice / 100)} руб. - - - - Выбрать - - - - ); -} diff --git a/src/pages/TariffConstructor/TariffConstructor.tsx b/src/pages/TariffConstructor/TariffConstructor.tsx index 517f78d..9de21aa 100644 --- a/src/pages/TariffConstructor/TariffConstructor.tsx +++ b/src/pages/TariffConstructor/TariffConstructor.tsx @@ -1,7 +1,6 @@ import { Box, IconButton, useMediaQuery, useTheme } from "@mui/material"; import { Link } from "react-router-dom"; import SectionWrapper from "@components/SectionWrapper"; -import ComplexNavText from "@root/components/ComplexNavText"; import { useCustomTariffsStore } from "@root/stores/customTariffs"; import ComplexHeader from "@root/components/ComplexHeader"; import CustomTariffCard from "./CustomTariffCard"; @@ -39,7 +38,6 @@ export default function TariffConstructor() { mb: upMd ? "93px" : "48px", }} > - {upMd && } ; -} - -export default function ImageTextButtonCard({ image, headerText, text, linkHref, sx }: Props) { - const theme = useTheme(); - - return ( - - {image && - - } - {headerText} - {text} - - Подробнее - - - ); -} \ No newline at end of file diff --git a/src/pages/Tariffs/TariffCard.tsx b/src/pages/Tariffs/TariffCard.tsx index eac2a89..dbd7b80 100644 --- a/src/pages/Tariffs/TariffCard.tsx +++ b/src/pages/Tariffs/TariffCard.tsx @@ -96,12 +96,13 @@ export default function TariffCard({ {line} @@ -115,12 +116,13 @@ export default function TariffCard({ sx={{ minHeight: "calc(1.185*2em)", marginBottom: "auto", - height: "42px", + height: "65px", overflow: "hidden", textOverflow: "ellipsis", display: "-webkit-box", WebkitBoxOrient: "vertical", - WebkitLineClamp: 2, + MozBoxOrient: "vertical", + WebkitLineClamp: 3, }} > {text} @@ -134,7 +136,7 @@ export default function TariffCard({ sx={{ color: theme.palette.brightPurple.main, borderColor: theme.palette.brightPurple.main, - mt: "35px", + mt: "10px", ...buttonProps.sx, }} > diff --git a/src/pages/Tariffs/TariffCardTimeAndVolume.tsx b/src/pages/Tariffs/TariffCardTimeAndVolume.tsx deleted file mode 100644 index d5e2560..0000000 --- a/src/pages/Tariffs/TariffCardTimeAndVolume.tsx +++ /dev/null @@ -1,93 +0,0 @@ -import { Box, SxProps, Theme, useTheme } from "@mui/material"; -import Typography from "@mui/material/Typography"; - -import CustomButton from "@components/CustomButton"; - -interface Props { - icon: React.ReactNode; - headerText: string; - text: string; - money?: number; - sx: SxProps; - href: string; - buttonBorderColor?: string; - buttonTextColor?: string; - moneyColor?: string; - onclick: () => void; - textButton: string; -} - -export default function TariffCardTimeAndVolume({ - icon, - headerText, - text, - sx, - href, - buttonBorderColor, - buttonTextColor, - money = 0, - moneyColor, - onclick, - textButton, -}: Props) { - const theme = useTheme(); - - return ( - - - {icon} - - {money} руб. - - - - - {headerText} - - - {text} - - - {textButton} - - - ); -} diff --git a/src/pages/Tariffs/Tariffs.tsx b/src/pages/Tariffs/Tariffs.tsx index 298fa24..caada69 100644 --- a/src/pages/Tariffs/Tariffs.tsx +++ b/src/pages/Tariffs/Tariffs.tsx @@ -1,123 +1,109 @@ -import { Outlet, Route, Routes, useNavigate } from "react-router-dom"; +import { useNavigate } from "react-router-dom"; import { useMediaQuery, useTheme, Box, Link, Typography } from "@mui/material"; import SectionWrapper from "@components/SectionWrapper"; import CustomIcon from "@components/icons/CustomIcon"; import CalendarIcon from "@components/icons/CalendarIcon"; import PieChartIcon from "@components/icons/PieChartIcon"; import TariffCard from "./TariffCard"; -import card1Image from "@root/assets/landing/card1.png"; -import card2Image from "@root/assets/landing/card2.png"; -import card3Image from "@root/assets/landing/card3.png"; -import ImageTextButtonCard from "./ImageTextButtonCard"; import WideTemplCard from "@components/wideTemplCard"; import TemplCardPhoneLight from "@components/templCardPhoneLight"; - export default function Tariffs() { - const theme = useTheme(); - const upMd = useMediaQuery(theme.breakpoints.up("md")); - const navigate = useNavigate(); + const theme = useTheme(); + const upMd = useMediaQuery(theme.breakpoints.up("md")); + const navigate = useNavigate(); - return ( - + Выберите удобный тариф + + + } + headerText="Тарифы на время" + text="безлимит на 1 месяц , 3 , 6 , 12" + buttonProps={{ + text: "Подробнее", + onClick: () => navigate("time"), + }} + sx={{ maxWidth: "360px" }} + /> + + } + headerText="Тариф на объем" + text="200 шаблонов, 1000 шаблонов, 5000 шаблонов, 10 000 шаблонов" + buttonProps={{ + text: "Подробнее", + onClick: () => navigate("volume"), + }} + sx={{ maxWidth: "360px" }} + /> + + } + headerText="Кастом" + text="Текст-заполнитель — это текст, который имеет " + buttonProps={{ + text: "Подробнее", + onClick: () => navigate("/tariffconstructor"), + }} + sx={{ maxWidth: "360px" }} + /> + + + {`Или попробуйте наш `} + - Выберите удобный тариф - - } - headerText="Тарифы на время" - text="безлимит на 1 месяц , 3 , 6 , 12" - buttonProps={{ - text: "Подробнее", - onClick: () => navigate("time") - }} - sx={{ maxWidth: "360px" }} - /> - } - headerText="Тариф на объем" - text="200 шаблонов, 1000 шаблонов, 5000 шаблонов, 10 000 шаблонов" - buttonProps={{ - text: "Подробнее", - onClick: () => navigate("volume") - }} - sx={{ maxWidth: "360px" }} - /> - } - headerText="Кастом" - text="Текст-заполнитель — это текст, который имеет " - buttonProps={{ - text: "Подробнее", - onClick: () => navigate("/tariffconstructor") - }} - sx={{ maxWidth: "360px" }} - /> - - - {`Или попробуйте наш `} - - бесплатный план - - - - Наши продукты - + бесплатный план + + + + Наши продукты + - {upMd ? - - : - } - {/**/} - {/* */} - {/* */} - {/* */} - {/**/} - - ); + {upMd ? ( + + ) : ( + + )} + + ); } diff --git a/src/pages/Tariffs/TariffsPage.tsx b/src/pages/Tariffs/TariffsPage.tsx index 282dbf1..2d74ae1 100644 --- a/src/pages/Tariffs/TariffsPage.tsx +++ b/src/pages/Tariffs/TariffsPage.tsx @@ -2,7 +2,6 @@ import { useState } from "react"; import { useLocation } from "react-router-dom"; import { Box, Typography, useMediaQuery, useTheme } from "@mui/material"; import SectionWrapper from "@components/SectionWrapper"; -import ComplexNavText from "@root/components/ComplexNavText"; import { useTariffs } from "@root/utils/hooks/useTariffs"; import { updateTariffs, useTariffStore } from "@root/stores/tariffs"; import { enqueueSnackbar } from "notistack"; @@ -128,9 +127,6 @@ export default function TariffPage() { flexDirection: "column", }} > - {upMd && ( - - )} {StepperText[unit]} @@ -149,6 +145,7 @@ export default function TariffPage() { )} - {upMd && }