tariffs save fix
This commit is contained in:
parent
63ae005bb8
commit
52f1b30c5f
79
src/components/CustomSaveAccordion.tsx
Normal file
79
src/components/CustomSaveAccordion.tsx
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
import { Box, useMediaQuery, useTheme } from "@mui/material";
|
||||||
|
import { useState } from "react";
|
||||||
|
import ExpandIcon from "./icons/ExpandIcon";
|
||||||
|
import type { ReactNode } from "react";
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
header: ReactNode;
|
||||||
|
divide?: boolean;
|
||||||
|
privilege: ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function CustomSaveAccordion({ header, divide = false, privilege }: Props) {
|
||||||
|
const theme = useTheme();
|
||||||
|
const upMd = useMediaQuery(theme.breakpoints.up("md"));
|
||||||
|
const upXs = useMediaQuery(theme.breakpoints.up("xs"));
|
||||||
|
const [isExpanded, setIsExpanded] = useState<boolean>(false);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
backgroundColor: "white",
|
||||||
|
"&:first-of-type": {
|
||||||
|
borderTopLeftRadius: "12px",
|
||||||
|
borderTopRightRadius: "12px",
|
||||||
|
},
|
||||||
|
"&:last-of-type": {
|
||||||
|
borderBottomLeftRadius: "12px",
|
||||||
|
borderBottomRightRadius: "12px",
|
||||||
|
},
|
||||||
|
"&:not(:last-of-type)": {
|
||||||
|
borderBottom: `1px solid ${theme.palette.grey2.main}`,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Box
|
||||||
|
onClick={() => setIsExpanded((prev) => !prev)}
|
||||||
|
sx={{
|
||||||
|
minHeight: "72px",
|
||||||
|
px: "20px",
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "stretch",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
cursor: "pointer",
|
||||||
|
userSelect: "none",
|
||||||
|
rowGap: "10px",
|
||||||
|
flexDirection: upXs ? undefined : "column",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
width: "100%",
|
||||||
|
fontSize: upMd ? undefined : "16px",
|
||||||
|
lineHeight: upMd ? undefined : "19px",
|
||||||
|
fontWeight: 500,
|
||||||
|
color: theme.palette.grey3.main,
|
||||||
|
px: 0,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{header}
|
||||||
|
</Box>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
pl: "20px",
|
||||||
|
width: "52px",
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center",
|
||||||
|
borderLeft: divide ? "1px solid #000000" : "none",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ExpandIcon isExpanded={isExpanded} />
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
{isExpanded && privilege}
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}
|
@ -10,107 +10,116 @@ import { useNavigate } from "react-router-dom";
|
|||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
priceBeforeDiscounts: number;
|
priceBeforeDiscounts: number;
|
||||||
priceAfterDiscounts: number;
|
priceAfterDiscounts: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function TotalPrice({ priceAfterDiscounts, priceBeforeDiscounts }: Props) {
|
export default function TotalPrice({ priceAfterDiscounts, priceBeforeDiscounts }: Props) {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const upMd = useMediaQuery(theme.breakpoints.up("md"));
|
const upMd = useMediaQuery(theme.breakpoints.up("md"));
|
||||||
const [notEnoughMoneyAmount, setNotEnoughMoneyAmount] = useState<number>(0);
|
const [notEnoughMoneyAmount, setNotEnoughMoneyAmount] = useState<number>(0);
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
function handlePayClick() {
|
function handlePayClick() {
|
||||||
payCart().then(result => {
|
payCart()
|
||||||
setUserAccount(result);
|
.then((result) => {
|
||||||
}).catch(error => {
|
setUserAccount(result);
|
||||||
if (isAxiosError(error) && error.response?.status === 402) {
|
})
|
||||||
const notEnoughMoneyAmount = parseInt((error.response.data.message as string).replace("insufficient funds: ", ""));
|
.catch((error) => {
|
||||||
setNotEnoughMoneyAmount(notEnoughMoneyAmount);
|
if (isAxiosError(error) && error.response?.status === 500) {
|
||||||
} else {
|
enqueueSnackbar("В корзине нет товаров");
|
||||||
const message = getMessageFromFetchError(error);
|
}
|
||||||
if (message) enqueueSnackbar(message);
|
if (isAxiosError(error) && error.response?.status === 402) {
|
||||||
}
|
const notEnoughMoneyAmount = parseInt(
|
||||||
});
|
(error.response.data.message as string).replace("insufficient funds: ", "")
|
||||||
}
|
);
|
||||||
|
setNotEnoughMoneyAmount(notEnoughMoneyAmount);
|
||||||
|
}
|
||||||
|
if (!isAxiosError(error)) {
|
||||||
|
enqueueSnackbar(error.response.data.message);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function handleReplenishWallet() {
|
function handleReplenishWallet() {
|
||||||
navigate("/payment", { state: { notEnoughMoneyAmount } });
|
navigate("/payment", { state: { notEnoughMoneyAmount } });
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box sx={{
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: upMd ? "row" : "column",
|
||||||
|
mt: upMd ? "50px" : "70px",
|
||||||
|
pt: upMd ? "30px" : undefined,
|
||||||
|
borderTop: upMd ? `1px solid ${theme.palette.grey2.main}` : undefined,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
width: upMd ? "68.5%" : undefined,
|
||||||
|
pr: upMd ? "15%" : 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,
|
||||||
|
width: upMd ? "31.5%" : undefined,
|
||||||
|
pl: upMd ? "33px" : undefined,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
flexDirection: upMd ? "row" : "column",
|
flexDirection: upMd ? "column" : "row",
|
||||||
mt: upMd ? "50px" : "70px",
|
alignItems: upMd ? "start" : "center",
|
||||||
pt: upMd ? "30px" : undefined,
|
mt: upMd ? "10px" : "30px",
|
||||||
borderTop: upMd ? `1px solid ${theme.palette.grey2.main}` : undefined,
|
mb: "15px",
|
||||||
}}>
|
gap: "15px",
|
||||||
<Box sx={{
|
}}
|
||||||
width: upMd ? "68.5%" : undefined,
|
>
|
||||||
pr: upMd ? "15%" : undefined,
|
<Typography variant="oldPrice" sx={{ order: upMd ? 1 : 2 }}>
|
||||||
display: "flex",
|
{currencyFormatter.format(priceBeforeDiscounts / 100)}
|
||||||
flexWrap: "wrap",
|
</Typography>
|
||||||
flexDirection: "column",
|
<Typography
|
||||||
}}>
|
variant="price"
|
||||||
<Typography variant="h4" mb={upMd ? "18px" : "30px"}>
|
sx={{
|
||||||
Итоговая цена
|
fontWeight: 500,
|
||||||
</Typography>
|
fontSize: "26px",
|
||||||
<Typography color={theme.palette.grey3.main}>
|
lineHeight: "31px",
|
||||||
Текст-заполнитель — это текст, который имеет Текст-заполнитель — это текст, который имеет Текст-заполнитель —
|
order: upMd ? 2 : 1,
|
||||||
это текст, который имеет Текст-заполнитель — это текст, который имеет Текст-заполнитель
|
}}
|
||||||
</Typography>
|
>
|
||||||
</Box>
|
{currencyFormatter.format(priceAfterDiscounts / 100)}
|
||||||
<Box sx={{
|
</Typography>
|
||||||
color: theme.palette.grey3.main,
|
|
||||||
width: upMd ? "31.5%" : undefined,
|
|
||||||
pl: upMd ? "33px" : undefined,
|
|
||||||
}}>
|
|
||||||
<Box sx={{
|
|
||||||
display: "flex",
|
|
||||||
flexDirection: upMd ? "column" : "row",
|
|
||||||
alignItems: upMd ? "start" : "center",
|
|
||||||
mt: upMd ? "10px" : "30px",
|
|
||||||
mb: "15px",
|
|
||||||
gap: "15px",
|
|
||||||
}}>
|
|
||||||
<Typography
|
|
||||||
variant="oldPrice"
|
|
||||||
sx={{ order: upMd ? 1 : 2 }}
|
|
||||||
>
|
|
||||||
{currencyFormatter.format(priceBeforeDiscounts / 100)}
|
|
||||||
</Typography>
|
|
||||||
<Typography
|
|
||||||
variant="price"
|
|
||||||
sx={{
|
|
||||||
fontWeight: 500,
|
|
||||||
fontSize: "26px",
|
|
||||||
lineHeight: "31px",
|
|
||||||
order: upMd ? 2 : 1,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{currencyFormatter.format(priceAfterDiscounts / 100)}
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
|
||||||
{notEnoughMoneyAmount > 0 &&
|
|
||||||
<Alert
|
|
||||||
severity="error"
|
|
||||||
variant="filled"
|
|
||||||
>
|
|
||||||
Нехватает {currencyFormatter.format(notEnoughMoneyAmount / 100)}
|
|
||||||
</Alert>
|
|
||||||
}
|
|
||||||
<CustomButton
|
|
||||||
variant="contained"
|
|
||||||
onClick={notEnoughMoneyAmount === 0 ? handlePayClick : handleReplenishWallet}
|
|
||||||
sx={{
|
|
||||||
mt: "10px",
|
|
||||||
backgroundColor: theme.palette.brightPurple.main,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{notEnoughMoneyAmount === 0 ? "Оплатить" : "Пополнить"}
|
|
||||||
</CustomButton>
|
|
||||||
</Box>
|
|
||||||
</Box>
|
</Box>
|
||||||
);
|
{notEnoughMoneyAmount > 0 && (
|
||||||
|
<Alert severity="error" variant="filled">
|
||||||
|
Нехватает {currencyFormatter.format(notEnoughMoneyAmount / 100)}
|
||||||
|
</Alert>
|
||||||
|
)}
|
||||||
|
<CustomButton
|
||||||
|
variant="contained"
|
||||||
|
onClick={notEnoughMoneyAmount === 0 ? handlePayClick : handleReplenishWallet}
|
||||||
|
sx={{
|
||||||
|
mt: "10px",
|
||||||
|
backgroundColor: theme.palette.brightPurple.main,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{notEnoughMoneyAmount === 0 ? "Оплатить" : "Пополнить"}
|
||||||
|
</CustomButton>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
@ -145,6 +145,8 @@ export default function CustomWrapper({ serviceData }: Props) {
|
|||||||
serviceData.tariffs.map((tariff) => {
|
serviceData.tariffs.map((tariff) => {
|
||||||
const privilege = tariff.privileges[0];
|
const privilege = tariff.privileges[0];
|
||||||
|
|
||||||
|
console.log(tariff);
|
||||||
|
|
||||||
return tariff.privileges.length > 1 ? (
|
return tariff.privileges.length > 1 ? (
|
||||||
<CustomTariffAccordion key={tariff.id} tariffCartData={tariff} />
|
<CustomTariffAccordion key={tariff.id} tariffCartData={tariff} />
|
||||||
) : (
|
) : (
|
||||||
|
@ -4,19 +4,16 @@ import { enqueueSnackbar } from "notistack";
|
|||||||
import { Box, Typography, useMediaQuery, useTheme } from "@mui/material";
|
import { Box, Typography, useMediaQuery, useTheme } from "@mui/material";
|
||||||
import CustomButton from "@root/components/CustomButton";
|
import CustomButton from "@root/components/CustomButton";
|
||||||
|
|
||||||
import { createAndSendTariff } from "@root/stores/customTariffs";
|
|
||||||
import { updateTariffs } from "@root/stores/tariffs";
|
|
||||||
import { addTariffToCart } from "@root/stores/user";
|
import { addTariffToCart } from "@root/stores/user";
|
||||||
import CustomAccordion from "@components/CustomAccordion";
|
|
||||||
import { cardShadow } from "@root/utils/themes/shadow";
|
import { cardShadow } from "@root/utils/themes/shadow";
|
||||||
import { PrivilegeCartData, getMessageFromFetchError } from "@frontend/kitui";
|
import { TariffCartData, getMessageFromFetchError } from "@frontend/kitui";
|
||||||
|
import CustomSaveAccordion from "../../components/CustomSaveAccordion";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
content: PrivilegeCartData[];
|
content: TariffCartData[];
|
||||||
name: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const SaveWrapper: FC<Props> = ({ content, name }) => {
|
const SaveWrapper: FC<Props> = ({ content }) => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const upMd = useMediaQuery(theme.breakpoints.up("md"));
|
const upMd = useMediaQuery(theme.breakpoints.up("md"));
|
||||||
const upSm = useMediaQuery(theme.breakpoints.up("sm"));
|
const upSm = useMediaQuery(theme.breakpoints.up("sm"));
|
||||||
@ -46,12 +43,10 @@ const SaveWrapper: FC<Props> = ({ content, name }) => {
|
|||||||
boxShadow: cardShadow,
|
boxShadow: cardShadow,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{content.map(({ price, description, privilegeId }, index) => (
|
{content.map(({ name, id, price, isCustom, privileges }) => (
|
||||||
<CustomAccordion
|
<CustomSaveAccordion
|
||||||
key={index}
|
key={id}
|
||||||
divide
|
divide
|
||||||
text={description}
|
|
||||||
price={price}
|
|
||||||
header={
|
header={
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
@ -101,10 +96,13 @@ const SaveWrapper: FC<Props> = ({ content, name }) => {
|
|||||||
px: 0,
|
px: 0,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{new Intl.NumberFormat("ru-RU").format(price)} руб.
|
{new Intl.NumberFormat("ru-RU").format(price / 100)} руб.
|
||||||
</Typography>
|
</Typography>
|
||||||
<CustomButton
|
<CustomButton
|
||||||
onClick={() => handleTariffItemClick(privilegeId)}
|
onClick={(event) => {
|
||||||
|
event.stopPropagation();
|
||||||
|
handleTariffItemClick(id);
|
||||||
|
}}
|
||||||
variant="contained"
|
variant="contained"
|
||||||
sx={{
|
sx={{
|
||||||
mr: "25px",
|
mr: "25px",
|
||||||
@ -117,12 +115,39 @@ const SaveWrapper: FC<Props> = ({ content, name }) => {
|
|||||||
":hover": {
|
":hover": {
|
||||||
backgroundColor: theme.palette.background.default,
|
backgroundColor: theme.palette.background.default,
|
||||||
},
|
},
|
||||||
|
zIndex: "100",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Купить
|
Купить
|
||||||
</CustomButton>
|
</CustomButton>
|
||||||
</Box>
|
</Box>
|
||||||
}
|
}
|
||||||
|
privilege={privileges.map(({ description, price, privilegeId }) => (
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
px: "20px",
|
||||||
|
py: upMd ? "25px" : undefined,
|
||||||
|
pt: upMd ? undefined : "15px",
|
||||||
|
pb: upMd ? undefined : "25px",
|
||||||
|
backgroundColor: "#F1F2F6",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Typography
|
||||||
|
sx={{
|
||||||
|
fontSize: upMd ? undefined : "16px",
|
||||||
|
lineHeight: upMd ? undefined : "19px",
|
||||||
|
color: theme.palette.grey3.main,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{description}
|
||||||
|
</Typography>
|
||||||
|
<Typography sx={{ display: price ? "block" : "none", fontSize: "18px", mr: "120px" }}>
|
||||||
|
{price / 100} руб.
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
))}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</Box>
|
</Box>
|
||||||
|
@ -1,19 +1,21 @@
|
|||||||
import { IconButton, Box, Typography, useMediaQuery, useTheme } from "@mui/material";
|
import { IconButton, Box, Typography, useMediaQuery, useTheme } from "@mui/material";
|
||||||
import SectionWrapper from "../../components/SectionWrapper";
|
import SectionWrapper from "../../components/SectionWrapper";
|
||||||
import AccordionWrapper from "./AccordionWrapper";
|
|
||||||
import ArrowBackIcon from "@mui/icons-material/ArrowBack";
|
import ArrowBackIcon from "@mui/icons-material/ArrowBack";
|
||||||
import { useHistoryTracker } from "@root/utils/hooks/useHistoryTracker";
|
import { useHistoryTracker } from "@root/utils/hooks/useHistoryTracker";
|
||||||
import { useCart } from "@root/utils/hooks/useCart";
|
import { useCart } from "@root/utils/hooks/useCart";
|
||||||
import SaveWrapper from "./SaveWrapper";
|
import SaveWrapper from "./SaveWrapper";
|
||||||
|
import { useTariffStore } from "@root/stores/tariffs";
|
||||||
|
|
||||||
export default function Faq() {
|
export default function Faq() {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const upMd = useMediaQuery(theme.breakpoints.up("md"));
|
const upMd = useMediaQuery(theme.breakpoints.up("md"));
|
||||||
const cart = useCart();
|
const cart = useCart();
|
||||||
|
|
||||||
const handleCustomBackNavigation = useHistoryTracker();
|
const tariffs = useTariffStore((state) => state.tariffs);
|
||||||
|
|
||||||
console.log(cart);
|
console.log(tariffs);
|
||||||
|
|
||||||
|
const handleCustomBackNavigation = useHistoryTracker();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SectionWrapper
|
<SectionWrapper
|
||||||
@ -40,9 +42,7 @@ export default function Faq() {
|
|||||||
</Box>
|
</Box>
|
||||||
<Box mt={upMd ? "27px" : "10px"}>
|
<Box mt={upMd ? "27px" : "10px"}>
|
||||||
{cart.services.map(({ serviceKey, tariffs }) =>
|
{cart.services.map(({ serviceKey, tariffs }) =>
|
||||||
serviceKey === "custom"
|
serviceKey === "custom" ? <SaveWrapper content={tariffs} /> : null
|
||||||
? tariffs.map(({ privileges, name }) => <SaveWrapper name={name} content={privileges} />)
|
|
||||||
: null
|
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
</SectionWrapper>
|
</SectionWrapper>
|
||||||
|
@ -1,124 +1,112 @@
|
|||||||
import {
|
import { Box, Typography, Tooltip, SxProps, Theme, useTheme } from "@mui/material";
|
||||||
Box,
|
|
||||||
Typography,
|
|
||||||
Tooltip,
|
|
||||||
SxProps,
|
|
||||||
Theme,
|
|
||||||
useTheme,
|
|
||||||
} from "@mui/material";
|
|
||||||
import CustomButton from "@components/CustomButton";
|
import CustomButton from "@components/CustomButton";
|
||||||
import { MouseEventHandler, ReactNode } from "react";
|
import { MouseEventHandler, ReactNode } from "react";
|
||||||
import { cardShadow } from "@root/utils/themes/shadow";
|
import { cardShadow } from "@root/utils/themes/shadow";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
icon: ReactNode;
|
icon: ReactNode;
|
||||||
headerText: string;
|
headerText: string;
|
||||||
text: string | string[];
|
text: string | string[];
|
||||||
|
sx?: SxProps<Theme>;
|
||||||
|
buttonProps?: {
|
||||||
sx?: SxProps<Theme>;
|
sx?: SxProps<Theme>;
|
||||||
buttonProps?: {
|
onClick?: MouseEventHandler<HTMLButtonElement>;
|
||||||
sx?: SxProps<Theme>;
|
text?: string;
|
||||||
onClick?: MouseEventHandler<HTMLButtonElement>;
|
};
|
||||||
text?: string;
|
price?: ReactNode;
|
||||||
};
|
|
||||||
price?: ReactNode;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function TariffCard({
|
export default function TariffCard({ icon, headerText, text, sx, price, buttonProps }: Props) {
|
||||||
icon,
|
const theme = useTheme();
|
||||||
headerText,
|
|
||||||
text,
|
|
||||||
sx,
|
|
||||||
price,
|
|
||||||
buttonProps,
|
|
||||||
}: Props) {
|
|
||||||
const theme = useTheme();
|
|
||||||
|
|
||||||
text = Array.isArray(text) ? text : [text];
|
text = Array.isArray(text) ? text : [text];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
|
sx={{
|
||||||
|
width: "100%",
|
||||||
|
minHeight: "250px",
|
||||||
|
bgcolor: "white",
|
||||||
|
borderRadius: "12px",
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
alignItems: "start",
|
||||||
|
p: "20px",
|
||||||
|
boxShadow: cardShadow,
|
||||||
|
...sx,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
width: "100%",
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
alignItems: "center",
|
||||||
|
gap: "16px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{icon}
|
||||||
|
{price && (
|
||||||
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
width: "100%",
|
display: "flex",
|
||||||
minHeight: "250px",
|
alignItems: "baseline",
|
||||||
bgcolor: "white",
|
flexWrap: "wrap",
|
||||||
borderRadius: "12px",
|
columnGap: "10px",
|
||||||
display: "flex",
|
rowGap: 0,
|
||||||
flexDirection: "column",
|
|
||||||
alignItems: "start",
|
|
||||||
p: "20px",
|
|
||||||
boxShadow: cardShadow,
|
|
||||||
...sx,
|
|
||||||
}}
|
}}
|
||||||
|
>
|
||||||
|
{price}
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
<Tooltip title={<Typography>{headerText}</Typography>} placement="top">
|
||||||
|
<Typography
|
||||||
|
variant="h5"
|
||||||
|
sx={{
|
||||||
|
mt: "14px",
|
||||||
|
mb: "10px",
|
||||||
|
textOverflow: "ellipsis",
|
||||||
|
overflow: "hidden",
|
||||||
|
whiteSpace: "nowrap",
|
||||||
|
width: "100%",
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<Box
|
{headerText}
|
||||||
sx={{
|
</Typography>
|
||||||
width: "100%",
|
</Tooltip>
|
||||||
display: "flex",
|
<Tooltip
|
||||||
justifyContent: "space-between",
|
title={text.map((line, index) => (
|
||||||
alignItems: "center",
|
<Typography key={index}>{line}</Typography>
|
||||||
gap: "16px",
|
))}
|
||||||
}}
|
placement="top"
|
||||||
>
|
>
|
||||||
{icon}
|
<Box
|
||||||
{price && (
|
sx={{
|
||||||
<Box
|
overflow: "hidden",
|
||||||
sx={{
|
textOverflow: "clip",
|
||||||
display: "flex",
|
mb: "auto",
|
||||||
alignItems: "baseline",
|
}}
|
||||||
flexWrap: "wrap",
|
>
|
||||||
columnGap: "10px",
|
{text.map((line, index) => (
|
||||||
rowGap: 0,
|
<Typography key={index}>{line}</Typography>
|
||||||
}}
|
))}
|
||||||
>
|
|
||||||
{price}
|
|
||||||
</Box>
|
|
||||||
)}
|
|
||||||
</Box>
|
|
||||||
<Tooltip title={<Typography>{headerText}</Typography>} placement="top">
|
|
||||||
<Typography
|
|
||||||
variant="h5"
|
|
||||||
sx={{
|
|
||||||
mt: "14px",
|
|
||||||
mb: "10px",
|
|
||||||
textOverflow: "ellipsis",
|
|
||||||
overflow: "hidden",
|
|
||||||
whiteSpace: "nowrap",
|
|
||||||
width: "100%",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{headerText}
|
|
||||||
</Typography>
|
|
||||||
</Tooltip>
|
|
||||||
<Tooltip
|
|
||||||
title={text.map((line, index) => (
|
|
||||||
<Typography key={index}>{line}</Typography>
|
|
||||||
))}
|
|
||||||
placement="top"
|
|
||||||
>
|
|
||||||
<Box sx={{
|
|
||||||
overflow: "hidden",
|
|
||||||
textOverflow: "clip",
|
|
||||||
mb: "auto",
|
|
||||||
}}>
|
|
||||||
{text.map((line, index) => (
|
|
||||||
<Typography key={index}>{line}</Typography>
|
|
||||||
))}
|
|
||||||
</Box>
|
|
||||||
</Tooltip>
|
|
||||||
{buttonProps && (
|
|
||||||
<CustomButton
|
|
||||||
onClick={buttonProps.onClick}
|
|
||||||
variant="outlined"
|
|
||||||
sx={{
|
|
||||||
color: theme.palette.brightPurple.main,
|
|
||||||
borderColor: theme.palette.brightPurple.main,
|
|
||||||
mt: "10px",
|
|
||||||
...buttonProps.sx,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{buttonProps.text}
|
|
||||||
</CustomButton>
|
|
||||||
)}
|
|
||||||
</Box>
|
</Box>
|
||||||
);
|
</Tooltip>
|
||||||
|
{buttonProps && (
|
||||||
|
<CustomButton
|
||||||
|
onClick={buttonProps.onClick}
|
||||||
|
variant="outlined"
|
||||||
|
sx={{
|
||||||
|
color: theme.palette.brightPurple.main,
|
||||||
|
borderColor: theme.palette.brightPurple.main,
|
||||||
|
mt: "10px",
|
||||||
|
...buttonProps.sx,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{buttonProps.text}
|
||||||
|
</CustomButton>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
@ -39,6 +39,8 @@ export default function TariffPage() {
|
|||||||
const unit: string = String(location.pathname).slice(9);
|
const unit: string = String(location.pathname).slice(9);
|
||||||
const currentTariffs = Object.values(cartTariffMap).filter((tariff): tariff is Tariff => typeof tariff === "object");
|
const currentTariffs = Object.values(cartTariffMap).filter((tariff): tariff is Tariff => typeof tariff === "object");
|
||||||
|
|
||||||
|
console.log(currentTariffs);
|
||||||
|
|
||||||
useAllTariffsFetcher({
|
useAllTariffsFetcher({
|
||||||
onSuccess: updateTariffs,
|
onSuccess: updateTariffs,
|
||||||
onError: (error) => {
|
onError: (error) => {
|
||||||
@ -74,6 +76,8 @@ export default function TariffPage() {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
console.log(isCustomTariffs);
|
||||||
|
|
||||||
const createTariffElements = (filteredTariffs: Tariff[]) => {
|
const createTariffElements = (filteredTariffs: Tariff[]) => {
|
||||||
const tariffElements = filteredTariffs
|
const tariffElements = filteredTariffs
|
||||||
.filter((tariff) => tariff.privilegies.length > 0)
|
.filter((tariff) => tariff.privilegies.length > 0)
|
||||||
|
@ -7,50 +7,59 @@ import { addCartTariffs, removeMissingCartTariffs, setCartTariffStatus, useCartS
|
|||||||
import { isAxiosError } from "axios";
|
import { isAxiosError } from "axios";
|
||||||
import { useDiscountStore } from "@root/stores/discounts";
|
import { useDiscountStore } from "@root/stores/discounts";
|
||||||
|
|
||||||
|
|
||||||
export function useCart() {
|
export function useCart() {
|
||||||
const tariffs = useTariffStore(state => state.tariffs);
|
const tariffs = useTariffStore((state) => state.tariffs);
|
||||||
const cartTariffMap = useCartStore(state => state.cartTariffMap);
|
const cartTariffMap = useCartStore((state) => state.cartTariffMap);
|
||||||
const cartTariffIds = useUserStore(state => state.userAccount?.cart);
|
const cartTariffIds = useUserStore((state) => state.userAccount?.cart);
|
||||||
const cart = useCartStore(state => state.cart);
|
const cart = useCartStore((state) => state.cart);
|
||||||
const discounts = useDiscountStore(state => state.discounts);
|
const discounts = useDiscountStore((state) => state.discounts);
|
||||||
const purchasesAmount = useUserStore(state => state.userAccount?.wallet.purchasesAmount) ?? 0;
|
const purchasesAmount = useUserStore((state) => state.userAccount?.wallet.purchasesAmount) ?? 0;
|
||||||
|
|
||||||
useEffect(function addTariffsToCart() {
|
useEffect(
|
||||||
const knownTariffs: Tariff[] = [];
|
function addTariffsToCart() {
|
||||||
|
const knownTariffs: Tariff[] = [];
|
||||||
|
|
||||||
cartTariffIds?.forEach(tariffId => {
|
cartTariffIds?.forEach((tariffId) => {
|
||||||
if (typeof cartTariffMap[tariffId] === "object") return;
|
if (typeof cartTariffMap[tariffId] === "object") return;
|
||||||
|
|
||||||
const tariff = tariffs.find(tariff => tariff._id === tariffId);
|
const tariff = tariffs.find((tariff) => tariff._id === tariffId);
|
||||||
if (tariff) return knownTariffs.push(tariff);
|
if (tariff) return knownTariffs.push(tariff);
|
||||||
|
|
||||||
if (!cartTariffMap[tariffId]) {
|
if (!cartTariffMap[tariffId]) {
|
||||||
setCartTariffStatus(tariffId, "loading");
|
setCartTariffStatus(tariffId, "loading");
|
||||||
|
|
||||||
getTariffById(tariffId).then(tariff => {
|
getTariffById(tariffId)
|
||||||
devlog("Unknown tariff", tariff);
|
.then((tariff) => {
|
||||||
addCartTariffs([tariff], discounts, purchasesAmount);
|
devlog("Unknown tariff", tariff);
|
||||||
}).catch(error => {
|
addCartTariffs([tariff], discounts, purchasesAmount);
|
||||||
devlog(`Error fetching unknown tariff ${tariffId}`, error);
|
})
|
||||||
setCartTariffStatus(tariffId, "not found");
|
.catch((error) => {
|
||||||
if (isAxiosError(error) && error.response?.status === 404) {
|
devlog(`Error fetching unknown tariff ${tariffId}`, error);
|
||||||
removeTariffFromCart(tariffId).then(() => {
|
setCartTariffStatus(tariffId, "not found");
|
||||||
devlog(`Unexistant tariff with id ${tariffId} deleted from cart`);
|
if (isAxiosError(error) && error.response?.status === 404) {
|
||||||
}).catch(error => {
|
removeTariffFromCart(tariffId)
|
||||||
devlog("Error deleting unexistant tariff from cart", error);
|
.then(() => {
|
||||||
});
|
devlog(`Unexistant tariff with id ${tariffId} deleted from cart`);
|
||||||
}
|
})
|
||||||
});
|
.catch((error) => {
|
||||||
}
|
devlog("Error deleting unexistant tariff from cart", error);
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
if (knownTariffs.length > 0) addCartTariffs(knownTariffs, discounts, purchasesAmount);
|
if (knownTariffs.length > 0) addCartTariffs(knownTariffs, discounts, purchasesAmount);
|
||||||
}, [cartTariffIds, cartTariffMap, discounts, purchasesAmount, tariffs]);
|
},
|
||||||
|
[cartTariffIds, cartTariffMap, discounts, purchasesAmount, tariffs]
|
||||||
|
);
|
||||||
|
|
||||||
useEffect(function cleanUpCart() {
|
useEffect(
|
||||||
if (cartTariffIds) removeMissingCartTariffs(cartTariffIds, discounts, purchasesAmount);
|
function cleanUpCart() {
|
||||||
}, [cartTariffIds, discounts, purchasesAmount]);
|
if (cartTariffIds) removeMissingCartTariffs(cartTariffIds, discounts, purchasesAmount);
|
||||||
|
},
|
||||||
|
[cartTariffIds, discounts, purchasesAmount]
|
||||||
|
);
|
||||||
|
|
||||||
return cart;
|
return cart;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user