front-hub/src/pages/TariffConstructor/TariffItem.tsx
2024-08-19 00:44:33 +03:00

185 lines
6.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { CustomPrivilege, useThrottle } from "@frontend/kitui";
import { Box, Typography, useMediaQuery, useTheme } from "@mui/material";
import { useDiscounts } from "@root/api/price";
import { CustomSlider } from "@root/components/CustomSlider";
import NumberInputWithUnitAdornment from "@root/components/NumberInputWithUnitAdornment";
import CalendarIcon from "@root/components/icons/CalendarIcon";
import PieChartIcon from "@root/components/icons/PieChartIcon";
import { setCustomTariffsUserValue, useCustomTariffsStore } from "@root/stores/customTariffs";
import { useUserStore } from "@root/stores/user";
import { getDeclension } from "@root/utils/declension";
import { useCartTariffs } from "@root/utils/hooks/useCartTariffs";
import { useEffect, useState } from "react";
import { useDebouncedCallback } from "use-debounce";
const sliderSettingsByType = {
день: { max: 365, min: 0 },
шаблон: { max: 5000, min: 0 },
МБ: { max: 5000, min: 0 },
заявка: { max: 5000, min: 0 },
шт: {max: 100, min: 0}
};
type PrivilegeName = "день" | "шаблон" | "МБ" | "заявка" | "шт";
interface Props {
privilege: CustomPrivilege;
}
export default function TariffPrivilegeSlider({ privilege }: Props) {
const theme = useTheme();
const upMd = useMediaQuery(theme.breakpoints.up("md"));
const userValue = useCustomTariffsStore((state) => state.userValuesMap[privilege.serviceKey]?.[privilege._id]) ?? sliderSettingsByType[privilege.value]?.min;
const purchasesAmount = useUserStore((state) => state.userAccount?.wallet.spent) ?? sliderSettingsByType[privilege.value]?.min;
const cartTariffs = useCartTariffs();
const userId = useUserStore(state => state.user?._id) ?? "";
const discounts = useDiscounts(userId);
const [value, setValue] = useState<number>(userValue);
const throttledValue = useThrottle(value, 200);
useEffect(
function setStoreValue() {
setCustomTariffsUserValue(
cartTariffs ?? [],
discounts ?? [],
privilege.serviceKey,
privilege._id,
throttledValue,
purchasesAmount,
userId,
);
},
[cartTariffs, discounts, purchasesAmount, privilege._id, privilege.serviceKey, throttledValue, userId]
);
function handleSliderChange(measurement: PrivilegeName) {
return (value: number | number[]) => {
if (Number(value) < Number(sliderSettingsByType[measurement]?.min)) {
setValue(0);
return;
}
if (Array.isArray(value)) throw new Error("Slider uses multiple values instead of one");
setValue(value);
};
}
const quantityText = `${value} ${getDeclension(value, privilege.value)}`;
const setNotSmallNumber = useDebouncedCallback(() => {
if (value === sliderSettingsByType[privilege.value]?.min) return;
if (Number(value) < Number(sliderSettingsByType[privilege.value]?.min)) {
setValue(sliderSettingsByType[privilege.value]?.min);
}
if (privilege.value === "день" && Number(value) < 30 && Number(value) !== 0) {
setValue(30);
}
if (privilege.value !== "день" && Number(value) < 100 && Number(value) !== 0) {
setValue(100);
}
}, 600);
const quantityElement = (
<Box
sx={{
display: "flex",
gap: "15px",
alignItems: "center",
justifyContent: upMd ? "end" : undefined,
flexWrap: "wrap",
mt: upMd ? undefined : "12px",
}}
>
<Typography variant="p1" color={theme.palette.purple.main} textAlign="end">
{quantityText}
</Typography>
<Box
sx={{
display: "flex",
gap: "15px",
alignItems: "center",
flexWrap: "wrap",
}}
>
<Typography sx={{ fontSize: "16px", lineHeight: "19px", mt: "1px" }}>или</Typography>
<NumberInputWithUnitAdornment
id={"privilege_input_" + privilege._id}
value={value}
privilege={privilege}
adornmentText={getDeclension(0, privilege.value)}
onChange={(value) => {
setValue(value);
setNotSmallNumber();
}}
/>
</Box>
</Box>
);
const icon =
privilege.type === "day" ? (
<CalendarIcon color={theme.palette.orange.main} bgcolor="#FEDFD0" />
) : (
<PieChartIcon color={theme.palette.orange.main} bgcolor="#FEDFD0" />
);
return (
<Box>
<Typography sx={{ color: theme.palette.gray.dark, mb: "auto" }}>{privilege.description}</Typography>
<Box
sx={{
display: "flex",
flexDirection: "column",
mt: "40px",
}}
>
<Box
sx={{
display: "flex",
// flexWrap: "wrap",
alignItems: "center",
mb: "8px",
justifyContent: "space-between",
gap: "10px",
}}
>
<Box
sx={{
display: "flex",
alignItems: "center",
gap: "22px",
}}
>
{icon}
<Typography sx={{ maxWidth: "100px" }} variant="h5">
{privilege.name}
</Typography>
</Box>
{upMd && quantityElement}
</Box>
<CustomSlider
value={value}
min={sliderSettingsByType[privilege.value]?.min}
max={sliderSettingsByType[privilege.value]?.max || 100}
onChange={handleSliderChange(privilege.value)}
firstStep={
(
privilege.value !== "день" &&
privilege.value !== "МБ" &&
privilege.value !== "заявка" &&
privilege.value !== "шаблон"
) ? 1
:
privilege.value === "день" ? 30 : 100
}
/>
{!upMd && quantityElement}
</Box>
</Box>
);
}