Merge branch 'dev' of penahub.gitlab.yandexcloud.net:frontend/marketplace into dev

This commit is contained in:
nflnkr 2023-08-11 16:56:57 +03:00
commit 392387f1d3
5 changed files with 329 additions and 230 deletions

@ -0,0 +1,3 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" stroke="black" xmlns="http://www.w3.org/2000/svg">
<path d="M0.400391 0.399902L19.6004 19.5999M0.400391 19.5999L19.6004 0.399902" />
</svg>

After

Width:  |  Height:  |  Size: 200 B

@ -1,14 +1,29 @@
import { useState } from "react";
import { Box, SvgIcon, Typography, useMediaQuery, useTheme } from "@mui/material";
import {
Box,
SvgIcon,
IconButton,
Typography,
useMediaQuery,
useTheme,
} from "@mui/material";
import ClearIcon from "@mui/icons-material/Clear";
import { currencyFormatter } from "@root/utils/currencyFormatter";
import { removeTariffFromCart } from "@root/stores/user";
import { enqueueSnackbar } from "notistack";
import { ServiceCartData, getMessageFromFetchError } from "@frontend/kitui";
import ExpandIcon from "@components/icons/ExpandIcon";
import { ReactComponent as CrossIcon } from "@root/assets/Icons/cross.svg";
const name: Record<string, string> = { templategen: "Шаблонизатор", squiz: "Опросник", reducer: "Скоращатель ссылок" };
import type { MouseEvent } from "react";
const name: Record<string, string> = {
templategen: "Шаблонизатор",
squiz: "Опросник",
reducer: "Скоращатель ссылок",
};
interface Props {
serviceData: ServiceCartData;
@ -21,19 +36,36 @@ export default function CustomWrapperDrawer({ serviceData }: Props) {
const [isExpanded, setIsExpanded] = useState<boolean>(false);
function handleItemDeleteClick(tariffId: string) {
removeTariffFromCart(tariffId).then(() => {
removeTariffFromCart(tariffId)
.then(() => {
enqueueSnackbar("Тариф удален");
}).catch(error => {
})
.catch((error) => {
const message = getMessageFromFetchError(error);
if (message) enqueueSnackbar(message);
});
}
const deleteService = async (event: MouseEvent<HTMLButtonElement>) => {
event.stopPropagation();
setIsExpanded(false);
for (const { tariffId } of serviceData.privileges) {
try {
await removeTariffFromCart(tariffId);
} catch {}
}
enqueueSnackbar("Тарифы удален");
};
return (
<Box
sx={{
overflow: "hidden",
borderRadius: "12px",
width: "100%",
}}
>
<Box
@ -56,13 +88,21 @@ export default function CustomWrapperDrawer({ serviceData }: Props) {
onClick={() => setIsExpanded((prev) => !prev)}
sx={{
height: "72px",
display: "flex",
gap: "10px",
alignItems: "center",
justifyContent: "space-between",
cursor: "pointer",
userSelect: "none",
}}
>
<ExpandIcon isExpanded={isExpanded} />
<Box
sx={{
width: "100%",
display: "flex",
justifyContent: "space-between",
}}
>
<Typography
sx={{
@ -75,7 +115,6 @@ export default function CustomWrapperDrawer({ serviceData }: Props) {
>
{name[serviceData.serviceKey]}
</Typography>
<Box
sx={{
display: "flex",
@ -85,23 +124,35 @@ export default function CustomWrapperDrawer({ serviceData }: Props) {
}}
>
<Typography
sx={{ pr: "11px", color: theme.palette.grey3.main, fontSize: upSm ? "20px" : "16px", fontWeight: 500 }}
sx={{
color: theme.palette.grey3.main,
fontSize: upSm ? "20px" : "16px",
fontWeight: 500,
}}
>
{currencyFormatter.format(serviceData.price / 100)}
</Typography>
<Box
sx={{
paddingLeft: upSm ? "24px" : 0,
height: "100%",
display: "flex",
justifyContent: "center",
alignItems: "center",
}}
></Box>
</Box>
</Box>
<IconButton
onClick={deleteService}
sx={{
padding: "3px",
height: "30px",
width: "30px",
}}
>
<CrossIcon
style={{
height: "24px",
width: "24px",
stroke: "#7E2AEA",
}}
/>
</IconButton>
</Box>
{isExpanded &&
serviceData.privileges.map(privilege => (
serviceData.privileges.map((privilege) => (
<Box
key={privilege.tariffId + privilege.privilegeId}
sx={{
@ -142,9 +193,12 @@ export default function CustomWrapperDrawer({ serviceData }: Props) {
>
{currencyFormatter.format(privilege.price / 100)}
</Typography>
<SvgIcon
sx={{ cursor: "pointer", color: "#7E2AEA" }}
sx={{
cursor: "pointer",
width: "30px",
color: "#7E2AEA",
}}
onClick={() => handleItemDeleteClick(privilege.tariffId)}
component={ClearIcon}
/>

@ -6,11 +6,9 @@ import {
useTheme,
Box,
IconButton,
SvgIcon,
Badge,
} from "@mui/material";
import ArrowBackIcon from "@mui/icons-material/ArrowBack";
import ClearIcon from "@mui/icons-material/Clear";
import { useTickets } from "@frontend/kitui";
import SectionWrapper from "./SectionWrapper";
import CustomWrapperDrawer from "./CustomWrapperDrawer";
@ -34,6 +32,7 @@ import {
import { ReactComponent as BellIcon } from "@root/assets/Icons/bell.svg";
import { ReactComponent as CartIcon } from "@root/assets/Icons/cart.svg";
import { ReactComponent as CrossIcon } from "@root/assets/Icons/cross.svg";
export default function Drawers() {
const [openNotificationsModal, setOpenNotificationsModal] =
@ -227,15 +226,22 @@ export default function Drawers() {
Корзина
</Typography>
<IconButton onClick={closeCartDrawer} sx={{ p: 0 }}>
<SvgIcon component={ClearIcon} />
<CrossIcon />
</IconButton>
</Box>
<Box sx={{ pl: "20px", pr: "20px" }}>
{cart.services.map((serviceData) => (
<Box
sx={{
display: "flex",
alignItems: "center",
}}
>
<CustomWrapperDrawer
key={serviceData.serviceKey}
serviceData={serviceData}
/>
</Box>
))}
<Box
sx={{

@ -1,4 +1,10 @@
import { Box, IconButton, Typography, useMediaQuery, useTheme } from "@mui/material";
import {
Box,
IconButton,
Typography,
useMediaQuery,
useTheme,
} from "@mui/material";
import SectionWrapper from "@components/SectionWrapper";
import ArrowBackIcon from "@mui/icons-material/ArrowBack";
import TotalPrice from "@components/TotalPrice";
@ -6,16 +12,25 @@ import CustomWrapper from "./CustomWrapper";
import { useCart } from "@root/utils/hooks/useCart";
import { useCustomTariffsStore } from "@root/stores/customTariffs";
export default function Basket() {
const theme = useTheme();
const upMd = useMediaQuery(theme.breakpoints.up("md"));
const cart = useCart();
const summaryPriceBeforeDiscountsMap = useCustomTariffsStore(state => state.summaryPriceBeforeDiscountsMap);
const summaryPriceAfterDiscountsMap = useCustomTariffsStore(state => state.summaryPriceAfterDiscountsMap);
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);
const basePrice = Object.values(summaryPriceBeforeDiscountsMap).reduce(
(a, e) => a + e,
0
);
const discountedPrice = Object.values(summaryPriceAfterDiscountsMap).reduce(
(a, e) => a + e,
0
);
const totalPriceBeforeDiscounts = cart.priceBeforeDiscounts + basePrice;
const totalPriceAfterDiscounts = cart.priceAfterDiscounts + discountedPrice;
@ -37,7 +52,9 @@ export default function Basket() {
}}
>
{!upMd && (
<IconButton sx={{ p: 0, height: "28px", width: "28px", color: "black" }}>
<IconButton
sx={{ p: 0, height: "28px", width: "28px", color: "black" }}
>
<ArrowBackIcon />
</IconButton>
)}
@ -45,17 +62,22 @@ export default function Basket() {
Корзина
</Typography>
</Box>
<Box sx={{
<Box
sx={{
mt: upMd ? "27px" : "10px",
}}>
{cart.services.map(serviceData =>
}}
>
{cart.services.map((serviceData) => (
<CustomWrapper
key={serviceData.serviceKey}
serviceData={serviceData}
/>
)}
))}
</Box>
<TotalPrice priceBeforeDiscounts={totalPriceBeforeDiscounts} priceAfterDiscounts={totalPriceAfterDiscounts} />
<TotalPrice
priceBeforeDiscounts={totalPriceBeforeDiscounts}
priceAfterDiscounts={totalPriceAfterDiscounts}
/>
</SectionWrapper>
);
}

@ -3,6 +3,7 @@ import {
Box,
SvgIcon,
Typography,
IconButton,
useMediaQuery,
useTheme,
} from "@mui/material";
@ -14,6 +15,10 @@ import { removeTariffFromCart } from "@root/stores/user";
import { enqueueSnackbar } from "notistack";
import { ServiceCartData, getMessageFromFetchError } from "@frontend/kitui";
import { ReactComponent as CrossIcon } from "@root/assets/Icons/cross.svg";
import type { MouseEvent } from "react";
const name: Record<string, string> = {
templategen: "Шаблонизатор",
squiz: "Опросник",
@ -41,6 +46,20 @@ export default function CustomWrapper({ serviceData }: Props) {
});
}
const deleteService = async (event: MouseEvent<HTMLButtonElement>) => {
event.stopPropagation();
setIsExpanded(false);
for (const { tariffId } of serviceData.privileges) {
try {
await removeTariffFromCart(tariffId);
} catch {}
}
enqueueSnackbar("Тарифы удален");
};
return (
<Box
sx={{
@ -70,26 +89,39 @@ export default function CustomWrapper({ serviceData }: Props) {
sx={{
height: "72px",
px: "20px",
display: "flex",
gap: "15px",
alignItems: "center",
justifyContent: "space-between",
cursor: "pointer",
userSelect: "none",
}}
>
<Box
sx={{
width: "50px",
height: "100%",
display: "flex",
justifyContent: "center",
alignItems: "center",
}}
>
<ExpandIcon isExpanded={isExpanded} />
</Box>
<Typography
sx={{
width: "100%",
fontSize: upMd ? "20px" : "16px",
lineHeight: upMd ? undefined : "19px",
fontWeight: 500,
color: theme.palette.text.secondary,
px: 0,
overflow: "hidden",
textOverflow: "ellipsis",
}}
>
{name[serviceData.serviceKey]}
</Typography>
<Box
sx={{
display: "flex",
@ -108,19 +140,13 @@ export default function CustomWrapper({ serviceData }: Props) {
>
{currencyFormatter.format(serviceData.price / 100)}
</Typography>
<Box
sx={{
borderLeft: upSm ? "1px solid #9A9AAF" : "none",
paddingLeft: upSm ? "24px" : 0,
height: "100%",
display: "flex",
justifyContent: "center",
alignItems: "center",
}}
</Box>
<IconButton
onClick={deleteService}
sx={{ padding: 0, height: "22px", width: "22px" }}
>
<ExpandIcon isExpanded={isExpanded} />
</Box>
</Box>
<CrossIcon style={{ height: "22 px", width: "22px" }} />
</IconButton>
</Box>
{isExpanded &&
serviceData.privileges.map((privilege) => (
@ -143,17 +169,14 @@ export default function CustomWrapper({ serviceData }: Props) {
fontSize: upMd ? undefined : "16px",
lineHeight: upMd ? undefined : "19px",
color: theme.palette.grey3.main,
width: "100%",
}}
>
{privilege.description}
</Typography>
<Box
sx={{
display: "flex",
justifyContent: "space-between",
gap: "10px",
alignItems: "center",
width: upSm ? "195px" : "123px",
width: upSm ? "140px" : "123px",
marginRight: upSm ? "65px" : 0,
}}
>
@ -166,27 +189,18 @@ export default function CustomWrapper({ serviceData }: Props) {
>
{currencyFormatter.format(privilege.price / 100)}
</Typography>
{upSm ? (
<Typography
component="div"
onClick={() => handleItemDeleteClick(privilege.tariffId)}
</Box>
<Box
sx={{
color: theme.palette.text.secondary,
borderBottom: `1px solid ${theme.palette.text.secondary}`,
width: "max-content",
lineHeight: "19px",
cursor: "pointer",
width: "35px",
display: "flex",
alignItems: "center",
justifyContent: "center",
}}
>
Удалить
</Typography>
) : (
<SvgIcon
onClick={() => handleItemDeleteClick(privilege.tariffId)}
component={ClearIcon}
sx={{ fill: "#7E2AEA" }}
/>
)}
>
<SvgIcon component={ClearIcon} sx={{ fill: "#7E2AEA" }} />
</Box>
</Box>
))}