diff --git a/src/components/NumberInputWithUnitAdornment.tsx b/src/components/NumberInputWithUnitAdornment.tsx new file mode 100644 index 0000000..42140bb --- /dev/null +++ b/src/components/NumberInputWithUnitAdornment.tsx @@ -0,0 +1,87 @@ +import { InputAdornment, TextField, Typography, useTheme } from "@mui/material"; +import { useState } from "react"; + + +interface Props { + id: string; + adornmentText: string; + onChange: (value: number) => void; +} + +export default function NumberInputWithUnitAdornment({ id, adornmentText, onChange }: Props) { + const theme = useTheme(); + const [valueField, setValueField] = useState(""); + + return ( + { + let n = parseInt(e.target.value); + + if (!isFinite(n)) n = 0; + + onChange(n); + setValueField(n.toString()); + }} + sx={{ + maxWidth: "200px", + minWidth: "200px", + ".MuiInputBase-root": { + pr: 0, + height: "48px", + borderRadius: "8px", + backgroundColor: "#F2F3F7", + "fieldset": { + border: "1px solid" + theme.palette.grey2.main, + }, + "&.Mui-focused fieldset": { + borderColor: theme.palette.brightPurple.main, + }, + "input": { + height: "31px", + borderRight: !valueField ? "none" : "1px solid #9A9AAF", + }, + "&.Mui-focused input": { + borderRight: "1px solid #9A9AAF", + }, + "&:not(.Mui-focused) .MuiInputAdornment-root": { + display: !valueField ? "none" : undefined, + }, + "&.Mui-focused ::-webkit-input-placeholder": { + color: "transparent", + }, + + // Hiding arrows + "input::-webkit-outer-spin-button, input::-webkit-inner-spin-button": { + "WebkitAppearance": "none", + margin: 0, + }, + "input[type = number]": { + "MozAppearance": "textfield", + } + }, + }} + InputProps={{ + endAdornment: ( + + + {adornmentText} + + + ) + }} + /> + ); +} diff --git a/src/pages/TariffConstructor/CustomTariffCard.tsx b/src/pages/TariffConstructor/CustomTariffCard.tsx index de6c94c..212a3fd 100644 --- a/src/pages/TariffConstructor/CustomTariffCard.tsx +++ b/src/pages/TariffConstructor/CustomTariffCard.tsx @@ -11,10 +11,10 @@ import { enqueueSnackbar } from "notistack"; interface Props { serviceKey: string; - tariffs: Privilege[]; + privileges: Privilege[]; } -export default function CustomTariffCard({ serviceKey, tariffs }: Props) { +export default function CustomTariffCard({ serviceKey, privileges }: Props) { const theme = useTheme(); const upMd = useMediaQuery(theme.breakpoints.up("md")); const summaryPriceBeforeDiscounts = useCustomTariffsStore(state => state.summaryPriceBeforeDiscountsMap); @@ -43,29 +43,31 @@ export default function CustomTariffCard({ serviceKey, tariffs }: Props) { boxShadow: cardShadow, }}> - {tariffs.map(tariff => + {privileges.map(privilege => )} {!upMd && } a + e, 0); const discountedPrice = Object.values(summaryPriceAfterDiscountsMap).reduce((a, e) => a + e, 0); - - return ( - - {upMd && } - - {Object.entries(customTariffs).map(([serviceKey, tariffs], index) => ( - - - {!upMd && index === 0 && ( - - - - )} - - - - - ))} - - {upMd && ( - - Ваши сохраненные тарифы - - )} - - - ); + {upMd && } + + {Object.entries(customTariffs).map(([serviceKey, privileges], index) => ( + + + {!upMd && index === 0 && ( + + + + )} + + + + + ))} + + {upMd && ( + + Ваши сохраненные тарифы + + )} + + + ); } diff --git a/src/pages/TariffConstructor/TariffItem.tsx b/src/pages/TariffConstructor/TariffItem.tsx index a98fd1d..70e0998 100644 --- a/src/pages/TariffConstructor/TariffItem.tsx +++ b/src/pages/TariffConstructor/TariffItem.tsx @@ -1,6 +1,7 @@ import { useThrottle } from "@frontend/kitui"; import { Box, SliderProps, Typography, useMediaQuery, useTheme } from "@mui/material"; 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 { Privilege, PrivilegeValueType } from "@root/model/privilege"; @@ -8,14 +9,13 @@ import { useCartStore } from "@root/stores/cart"; import { setCustomTariffsUserValue, useCustomTariffsStore } from "@root/stores/customTariffs"; import { useDiscountStore } from "@root/stores/discounts"; import { useUserStore } from "@root/stores/user"; -import { formatDateWithDeclention } from "@root/utils/date"; import { getDeclension } from "@root/utils/declension"; import { useEffect, useState } from "react"; const sliderSettingsByType: Record> = { "день": { - max: 366, + max: 365, step: 1, }, "шаблон": { @@ -29,30 +29,29 @@ const sliderSettingsByType: Record> = { }; interface Props { - tariff: Privilege; + privilege: Privilege; } -export default function TariffPrivilegeSlider({ tariff }: Props) { +export default function TariffPrivilegeSlider({ privilege }: Props) { const theme = useTheme(); const upMd = useMediaQuery(theme.breakpoints.up("md")); - const userValue = useCustomTariffsStore(state => state.userValuesMap[tariff.serviceKey]?.[tariff._id]) ?? 0; + const userValue = useCustomTariffsStore(state => state.userValuesMap[privilege.serviceKey]?.[privilege._id]) ?? 0; const discounts = useDiscountStore(state => state.discounts); const currentCartTotal = useCartStore(state => state.cart.priceAfterDiscounts); const purchasesAmount = useUserStore(state => state.userAccount?.wallet.purchasesAmount) ?? 0; const [value, setValue] = useState(userValue); const throttledValue = useThrottle(value, 200); - const quantityText = `${value} ${getDeclension(value, tariff.value)}`; - - const quantityElement = ( - - {quantityText} - - ); - - const icon = tariff.type === "day" - ? - : ; + useEffect(function setStoreValue() { + setCustomTariffsUserValue( + privilege.serviceKey, + privilege._id, + throttledValue, + discounts, + currentCartTotal, + purchasesAmount + ); + }, [currentCartTotal, discounts, purchasesAmount, privilege._id, privilege.serviceKey, throttledValue]); function handleSliderChange(event: Event, value: number | number[]) { if (Array.isArray(value)) throw new Error("Slider uses multiple values instead of one"); @@ -60,22 +59,44 @@ export default function TariffPrivilegeSlider({ tariff }: Props) { setValue(value); } - useEffect(function setStoreValue() { - console.log(currentCartTotal) - setCustomTariffsUserValue( - tariff.serviceKey, - tariff._id, - throttledValue, - discounts, - currentCartTotal, - purchasesAmount - ); - }, [currentCartTotal, discounts, purchasesAmount, tariff._id, tariff.serviceKey, throttledValue]); + const quantityText = `${value} ${getDeclension(value, privilege.value)}`; + + const quantityElement = ( + + + {quantityText} + + + или + setValue(value)} + /> + + + ); + + const icon = privilege.type === "day" + ? + : ; return ( - {tariff.description} + {privilege.description} {icon} - {tariff.name} + {privilege.name} {upMd && quantityElement} @@ -102,7 +126,7 @@ export default function TariffPrivilegeSlider({ tariff }: Props) { defaultValue={0} min={0} onChange={handleSliderChange} - {...sliderSettingsByType[tariff.value]} + {...sliderSettingsByType[privilege.value]} /> {!upMd && quantityElement} diff --git a/src/utils/serviceKeys.ts b/src/utils/serviceKeys.ts new file mode 100644 index 0000000..2f81db5 --- /dev/null +++ b/src/utils/serviceKeys.ts @@ -0,0 +1,5 @@ +export const serviceNameByKey: Record = { + templategen: "Шаблонизатор", + squiz: "Опросник", + reducer: "Сокращатель ссылок", +};