front-hub/src/pages/Payment/Payment.tsx

207 lines
6.7 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 { Box, IconButton, Typography, useMediaQuery, useTheme } from "@mui/material";
import ArrowBackIcon from "@mui/icons-material/ArrowBack";
import CustomButton from "@components/CustomButton";
import SectionWrapper from "@components/SectionWrapper";
import PaymentMethodCard from "./PaymentMethodCard";
import mastercardLogo from "../../assets/bank-logo/logo-mastercard.png";
import visaLogo from "../../assets/bank-logo/logo-visa.png";
import qiwiLogo from "../../assets/bank-logo/logo-qiwi.png";
import mirLogo from "../../assets/bank-logo/logo-mir.png";
import tinkoffLogo from "../../assets/bank-logo/logo-tinkoff.png";
import { cardShadow } from "@root/utils/themes/shadow";
import { useEffect, useState } from "react";
import InputTextfield from "@root/components/InputTextfield";
import { sendPayment } from "@root/api/wallet";
import { getMessageFromFetchError } from "@frontend/kitui";
import { enqueueSnackbar } from "notistack";
import { currencyFormatter } from "@root/utils/currencyFormatter";
import { useLocation } from "react-router-dom";
import { useHistoryTracker } from "@root/utils/hooks/useHistoryTracker";
const paymentMethods = [
{ name: "Mastercard", image: mastercardLogo },
{ name: "Visa", image: visaLogo },
{ name: "QIWI Кошелек", image: qiwiLogo },
{ name: "Мир", image: mirLogo },
{ name: "Тинькофф", image: tinkoffLogo },
] as const;
type PaymentMethod = (typeof paymentMethods)[number]["name"];
export default function Payment() {
const theme = useTheme();
const upMd = useMediaQuery(theme.breakpoints.up("md"));
const upSm = useMediaQuery(theme.breakpoints.up("sm"));
const [selectedPaymentMethod, setSelectedPaymentMethod] = useState<PaymentMethod | null>(null);
const [paymentValueField, setPaymentValueField] = useState<string>("0");
const [paymentLink, setPaymentLink] = useState<string>("");
const location = useLocation();
const notEnoughMoneyAmount = (location.state?.notEnoughMoneyAmount as number) ?? 0;
useEffect(() => {
setPaymentValueField((notEnoughMoneyAmount / 100).toString());
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
useEffect(() => {
setPaymentLink("");
}, [selectedPaymentMethod]);
const paymentValue = parseFloat(paymentValueField) * 100;
function handleChoosePaymentClick() {
if (Number(paymentValueField) !== 0) {
sendPayment()
.then((result) => {
setPaymentLink(result.link);
})
.catch((error) => {
const message = getMessageFromFetchError(error);
if (message) enqueueSnackbar(message);
});
}
}
const handleCustomBackNavigation = useHistoryTracker();
return (
<SectionWrapper
maxWidth="lg"
sx={{
mt: "25px",
mb: "70px",
}}
>
<Box
sx={{
mt: "20px",
mb: "40px",
display: "flex",
gap: "10px",
}}
>
{!upMd && (
<IconButton onClick={handleCustomBackNavigation} sx={{ p: 0, height: "28px", width: "28px", color: "black" }}>
<ArrowBackIcon />
</IconButton>
)}
<Typography variant="h4">Способ оплаты</Typography>
</Box>
{!upMd && (
<Typography variant="body2" mb="30px">
Выберите способ оплаты
</Typography>
)}
<Box
sx={{
backgroundColor: upMd ? "white" : undefined,
display: "flex",
flexDirection: upMd ? "row" : "column",
borderRadius: "12px",
boxShadow: upMd ? cardShadow : undefined,
}}
>
<Box
sx={{
width: upMd ? "68.5%" : undefined,
p: upMd ? "20px" : undefined,
display: "flex",
flexDirection: upSm ? "row" : "column",
flexWrap: "wrap",
gap: upMd ? "14px" : "20px",
alignContent: "start",
}}
>
{paymentMethods.map((method) => (
<PaymentMethodCard
isSelected={selectedPaymentMethod === method.name}
key={method.name}
name={method.name}
image={method.image}
onClick={() => setSelectedPaymentMethod(method.name)}
/>
))}
</Box>
<Box
sx={{
display: "flex",
flexDirection: "column",
justifyContent: "space-between",
alignItems: "start",
color: theme.palette.grey3.main,
width: upMd ? "31.5%" : undefined,
p: upMd ? "20px" : undefined,
pl: upMd ? "33px" : undefined,
mt: upMd ? undefined : "30px",
borderLeft: upMd ? `1px solid ${theme.palette.grey2.main}` : undefined,
}}
>
<Box
sx={{
display: "flex",
flexDirection: "column",
maxWidth: "85%",
}}
>
{upMd && <Typography mb="56px">Выберите способ оплаты</Typography>}
<Typography mb="20px">К оплате</Typography>
{paymentLink ? (
<Typography
sx={{
fontWeight: 500,
fontSize: "20px",
lineHeight: "48px",
mb: "28px",
}}
>
{currencyFormatter.format(paymentValue / 100)}
</Typography>
) : (
<InputTextfield
TextfieldProps={{
placeholder: "К оплате",
value: paymentValueField,
type: "number",
}}
onChange={(e) => setPaymentValueField(e.target.value)}
id="payment-amount"
gap={upMd ? "16px" : "10px"}
color={"#F2F3F7"}
FormInputSx={{ mb: "28px" }}
/>
)}
</Box>
{paymentLink ? (
<CustomButton
component="a"
href={paymentLink}
variant={"contained"}
sx={{
borderColor: theme.palette.brightPurple.main,
backgroundColor: theme.palette.brightPurple.main,
mt: "auto",
}}
>
Оплатить
</CustomButton>
) : (
<CustomButton
disabled={!isFinite(paymentValue)}
variant={"outlined"}
onClick={handleChoosePaymentClick}
sx={{
borderColor: theme.palette.brightPurple.main,
backgroundColor: "",
mt: "auto",
}}
>
Выбрать
</CustomButton>
)}
</Box>
</Box>
</SectionWrapper>
);
}