add apply promocode button

This commit is contained in:
nflnkr 2024-03-21 19:34:44 +03:00
parent 3ffa3418c0
commit 82e2f550c7
4 changed files with 470 additions and 272 deletions

32
src/api/promocode.ts Normal file

@ -0,0 +1,32 @@
import { makeRequest } from "@frontend/kitui";
import { isAxiosError } from "axios";
const apiUrl = process.env.REACT_APP_DOMAIN + "/codeword/promocode";
export async function activatePromocode(promocode: string) {
try {
const response = await makeRequest<{
codeword: string;
} | {
fastLink: string;
}, {
greetings: string;
}>({
url: apiUrl + "/activate",
method: "POST",
body: {
codeword: promocode,
}
});
return response.greetings;
} catch (error) {
let message = "Неизвестная ошибка";
if (isAxiosError(error) && error.status === 404) {
message = "Промокод не найден";
}
throw new Error(message);
}
}

@ -0,0 +1,26 @@
import { Box, SxProps, Theme } from "@mui/material";
type Props = {
sx?: SxProps<Theme>;
};
export default function SimpleArrowDown({ sx }: Props) {
return (
<Box sx={{
width: "14px",
height: "9px",
display: "flex",
alignItems: "center",
justifyContent: "center",
flexShrink: 0,
...sx,
}}>
<svg width="14" height="9" viewBox="0 0 14 9" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M13 1.48535L7 7.48535" stroke="#7E2AEA" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
<path d="M1 1.48535L7 7.48535" stroke="#7E2AEA" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
</svg>
</Box>
);
}

@ -1,6 +1,8 @@
import {
Box,
Button,
Collapse,
Grow,
IconButton,
Typography,
useMediaQuery,
@ -28,6 +30,9 @@ import { useUserStore } from "@root/stores/user";
import { VerificationStatus } from "@root/model/account";
import { WarnModal } from "./WarnModal";
import { SorryModal } from "./SorryModal";
import SimpleArrowDown from "@root/components/icons/SimpleArrowDown";
import PromocodeTextField from "./PromocodeTextField";
import { activatePromocode } from "@root/api/promocode";
type PaymentMethod = {
label: string;
@ -51,7 +56,8 @@ export default function Payment() {
const upMd = useMediaQuery(theme.breakpoints.up("md"));
const upSm = useMediaQuery(theme.breakpoints.up("sm"));
const isTablet = useMediaQuery(theme.breakpoints.down(1000));
const [promocodeField, setPromocodeField] = useState<string>("");
const [isPromocodeFieldOpen, setIsPromocodeFieldOpen] = useState<boolean>(false);
const [selectedPaymentMethod, setSelectedPaymentMethod] =
useState<PaymentMethodType | null>("");
const [warnModalOpen, setWarnModalOpen] = useState<boolean>(false);
@ -81,18 +87,14 @@ export default function Payment() {
console.log(fromSquiz);
}, []);
useEffect(() => {
setPaymentLink("");
}, [selectedPaymentMethod]);
async function handleChoosePaymentClick() {
if (!selectedPaymentMethod) {
enqueueSnackbar("Введите метод оплаты")
enqueueSnackbar("Введите метод оплаты");
return;
}
if (Number(paymentValueField) === 0) {
enqueueSnackbar("Введите сумму")
enqueueSnackbar("Введите сумму");
return;
}
@ -111,9 +113,9 @@ export default function Payment() {
return;
}
console.log(paymentValueField)
console.log(paymentValueField);
if (Number(paymentValueField) < 900) {
enqueueSnackbar("Минимальная сумма 900р")
enqueueSnackbar("Минимальная сумма 900р");
return;
}
@ -146,9 +148,9 @@ export default function Payment() {
return;
}
console.log(paymentValueField)
console.log(paymentValueField);
if (Number(paymentValueField) < 900) {
enqueueSnackbar("Минимальная сумма 900р")
enqueueSnackbar("Минимальная сумма 900р");
return;
}
@ -169,6 +171,15 @@ export default function Payment() {
}
function handleApplyPromocode() {
if (!promocodeField) return;
activatePromocode(promocodeField).then(response => {
enqueueSnackbar(response);
}).catch(error => {
enqueueSnackbar(error.message);
});
}
return (
<SectionWrapper
@ -216,6 +227,15 @@ export default function Payment() {
width: upMd ? "68.5%" : undefined,
p: upMd ? "20px" : undefined,
display: "flex",
flexDirection: "column",
alignItems: "start",
gap: "40px",
}}
>
<Box
sx={{
width: "100%",
display: "flex",
flexDirection: upSm ? "row" : "column",
flexWrap: "wrap",
gap: upMd ? "14px" : "20px",
@ -229,7 +249,8 @@ export default function Payment() {
label={label}
image={image}
onClick={() => {
setSelectedPaymentMethod(name)
setSelectedPaymentMethod(name);
setPaymentLink("");
}}
unpopular={false}
/>
@ -239,11 +260,52 @@ export default function Payment() {
label={"Расчётный счёт"}
image={rsPayLogo}
onClick={async () => {
setSelectedPaymentMethod("rspay")
setSelectedPaymentMethod("rspay");
setPaymentLink("");
}}
unpopular={false}
/>
</Box>
<Box sx={{
width: "100%",
display: "flex",
flexDirection: "column",
alignItems: "start",
}}>
<Button
variant="pena-text"
onClick={() => setIsPromocodeFieldOpen(p => !p)}
sx={{
fontWeight: 400,
fontSize: "18px",
lineHeight: "21.33px",
textUnderlineOffset: "1px",
".MuiButton-endIcon": {
mr: 0,
ml: "15px",
},
}}
endIcon={
<SimpleArrowDown sx={{
transform: isPromocodeFieldOpen ? "scaleY(-1)" : undefined,
transition: "transform 0.3s ease",
}} />
}
>У меня есть промокод</Button>
<Collapse
in={isPromocodeFieldOpen}
sx={{
width: "100%",
}}
>
<PromocodeTextField
value={promocodeField}
onChange={e => setPromocodeField(e.target.value)}
onApplyClick={handleApplyPromocode}
/>
</Collapse>
</Box>
</Box>
<Box
sx={{
display: "flex",
@ -287,7 +349,7 @@ export default function Payment() {
value: paymentValueField,
type: "number",
}}
onChange={(e) => setPaymentValueField(e.target.value.replace(/^0+(?=\d\.)/, ''))}
onChange={(e) => setPaymentValueField(e.target.value.replace(/^0+(?=\d\.)/, ""))}
id="payment-amount"
gap={upMd ? "16px" : "10px"}
color={"#F2F3F7"}

@ -0,0 +1,78 @@
import { Box, Button, TextField, useMediaQuery, useTheme } from "@mui/material";
interface Props {
value?: string;
onChange?: (e: React.ChangeEvent<HTMLTextAreaElement | HTMLInputElement>) => void;
onApplyClick?: () => void;
}
export default function PromocodeTextField({ value, onChange, onApplyClick }: Props) {
const theme = useTheme();
const upSm = useMediaQuery(theme.breakpoints.up("sm"));
return (
<Box
sx={{
width: upSm ? "407px" : "100%",
mt: "20px",
display: "flex",
flexDirection: upSm ? "row" : "column",
}}
>
<TextField
fullWidth
placeholder="Введите промокод"
value={value}
onChange={onChange}
sx={{
height: "48px",
"& .MuiInputBase-root": {
height: "100%",
borderRadius: "8px",
border: "1px solid #9A9AAF",
...(upSm ? {
borderTopRightRadius: 0,
borderBottomRightRadius: 0,
} : {
borderBottomLeftRadius: 0,
borderBottomRightRadius: 0,
}),
},
}}
inputProps={{
sx: {
color: "#7E2AEA",
backgroundColor: "#7E2AEA1A",
height: "100%",
boxSizing: "border-box",
borderRadius: "8px",
py: 0,
...(upSm ? {
borderTopRightRadius: 0,
borderBottomRightRadius: 0,
} : {
borderBottomLeftRadius: 0,
borderBottomRightRadius: 0,
}),
},
}}
/>
<Button
variant="pena-contained-dark"
onClick={onApplyClick}
sx={{
px: "25px",
minWidth: 0,
...(upSm ? {
borderTopLeftRadius: 0,
borderBottomLeftRadius: 0,
} : {
borderTopLeftRadius: 0,
borderTopRightRadius: 0,
}),
}}
>Применить</Button>
</Box>
);
}