Merge branch 'dev' into 'staging'

Dev

See merge request frontend/marketplace!172
This commit is contained in:
Nastya 2024-04-11 14:29:36 +00:00
commit 48c38bb64f
7 changed files with 200 additions and 142 deletions

@ -5,36 +5,37 @@ import { parseAxiosError } from "@root/utils/parse-error";
import { enqueueSnackbar } from "notistack";
import useSWR from "swr";
const apiUrl = process.env.REACT_APP_DOMAIN + "/price";
export async function getDiscounts(userId:string|null) {
console.log("перед запросом я получил айдишник юзера ", userId)
if (userId === null) throw new Error(`Не авторизован.`);
try {
const discountsResponse = await makeRequest<never, GetDiscountsResponse>({
url: `${apiUrl}/discount/user/${userId}`,
method: "get",
useToken: true,
});
export async function getDiscounts(userId: string | null) {
if (userId === null) {
return;
}
return discountsResponse.Discounts;
} catch (nativeError) {
const [error] = parseAxiosError(nativeError);
throw new Error(`Ошибка получения списка скидок. ${error}`);
}
}
export function useDiscounts(userId:string|null) {
const { data } = useSWR("discounts", () => getDiscounts(userId), {
keepPreviousData: true,
onError: (error) => {
if (!(error instanceof Error)) return;
enqueueSnackbar(error.message, { variant: "error" });
}
try {
const discountsResponse = await makeRequest<never, GetDiscountsResponse>({
url: `${apiUrl}/discount/user/${userId}`,
method: "get",
useToken: true,
});
return data;
return discountsResponse.Discounts;
} catch (nativeError) {
const [error] = parseAxiosError(nativeError);
throw new Error(`Ошибка получения списка скидок. ${error}`);
}
}
export function useDiscounts(userId: string | null) {
const { data } = useSWR("discounts", () => getDiscounts(userId), {
keepPreviousData: true,
onError: (error) => {
if (!(error instanceof Error)) return;
enqueueSnackbar(error.message, { variant: "error" });
},
});
return data;
}

@ -1,6 +1,14 @@
import { useState } from "react";
import { Link, useLocation, useNavigate } from "react-router-dom";
import { Box, Button, Container, IconButton, Typography, useMediaQuery, useTheme } from "@mui/material";
import {
Box,
Button,
Container,
IconButton,
Typography,
useMediaQuery,
useTheme,
} from "@mui/material";
import SectionWrapper from "../SectionWrapper";
import LogoutIcon from "../icons/LogoutIcon";
import DialogMenu from "./DialogMenu";
@ -12,7 +20,11 @@ import Menu from "../Menu";
import { logout } from "@root/api/auth";
import { enqueueSnackbar } from "notistack";
import { clearUserData, useUserStore } from "@root/stores/user";
import { BurgerButton, clearAuthToken, getMessageFromFetchError } from "@frontend/kitui";
import {
BurgerButton,
clearAuthToken,
getMessageFromFetchError,
} from "@frontend/kitui";
import { currencyFormatter } from "@root/utils/currencyFormatter";
import { clearCustomTariffs } from "@root/stores/customTariffs";
import { clearTickets } from "@root/stores/tickets";
@ -31,17 +43,17 @@ export default function NavbarFull({ isLoggedIn }: Props) {
const [open, setOpen] = useState(false);
async function handleLogoutClick() {
const [_, logoutError] = await logout();
if (logoutError) {
return enqueueSnackbar(logoutError);
}
clearAuthToken();
clearUserData();
clearCustomTariffs();
clearTickets();
navigate("/");
const [_, logoutError] = await logout();
if (logoutError) {
return enqueueSnackbar(logoutError);
}
}
return isLoggedIn ? (
@ -71,7 +83,10 @@ export default function NavbarFull({ isLoggedIn }: Props) {
}}
>
<Drawers />
<IconButton sx={{ p: 0, ml: "8px" }} onClick={() => navigate("/wallet")}>
<IconButton
sx={{ p: 0, ml: "8px" }}
onClick={() => navigate("/wallet")}
>
<WalletIcon color={theme.palette.gray.main} bgcolor="#F2F3F7" />
</IconButton>
<Box sx={{ ml: "8px", whiteSpace: "nowrap" }}>
@ -124,7 +139,12 @@ export default function NavbarFull({ isLoggedIn }: Props) {
gap: "50px",
}}
>
<Box width="457px" justifyContent="space-between" display="inline-flex" alignItems="center">
<Box
width="457px"
justifyContent="space-between"
display="inline-flex"
alignItems="center"
>
<PenaLogo width={150} color="white" />
{!isTablet ? null : <Menu />}
</Box>
@ -151,7 +171,10 @@ export default function NavbarFull({ isLoggedIn }: Props) {
</Button>
)}
<BurgerButton onClick={() => setOpen(!open)} sx={{ color: "white", display: !isTablet ? "block" : "none" }} />
<BurgerButton
onClick={() => setOpen(!open)}
sx={{ color: "white", display: !isTablet ? "block" : "none" }}
/>
</SectionWrapper>
<DialogMenu open={open} handleClose={() => setOpen(false)} />
</>

@ -1,6 +1,14 @@
import { useState } from "react";
import { Link, useLocation, useNavigate } from "react-router-dom";
import { Box, Button, List, ListItem, Typography, useMediaQuery, useTheme } from "@mui/material";
import {
Box,
Button,
List,
ListItem,
Typography,
useMediaQuery,
useTheme,
} from "@mui/material";
import { clearUserData, useUserStore } from "@root/stores/user";
import { currencyFormatter } from "@root/utils/currencyFormatter";
import { cardShadow } from "@root/utils/theme";
@ -31,7 +39,7 @@ const arrayMenu: MenuItem[] = [
{ name: "Корзина", url: "/cart" },
{ name: "Поддержка", url: "/support" },
{ name: "История", url: "/history" },
{name: "Мой кошелёк", url: "/wallet"},
{ name: "Мой кошелёк", url: "/wallet" },
];
interface DialogMenuProps {
@ -57,20 +65,23 @@ export default function DialogMenu({ handleClose }: DialogMenuProps) {
};
async function handleLogoutClick() {
const [_, logoutError] = await logout();
if (logoutError) {
return enqueueSnackbar(logoutError);
}
clearAuthToken();
clearUserData();
clearCustomTariffs();
clearTickets();
navigate("/");
const [_, logoutError] = await logout();
if (logoutError) {
return enqueueSnackbar(logoutError);
}
}
const handleSubMenu = (index: number) => setActiveSubMenuIndex((activeIndex) => (activeIndex !== index ? index : -1));
const handleSubMenu = (index: number) =>
setActiveSubMenuIndex((activeIndex) =>
activeIndex !== index ? index : -1
);
return (
<Box sx={{ height: "100%", maxHeight: "calc(100vh - 51px)" }}>
@ -98,18 +109,28 @@ export default function DialogMenu({ handleClose }: DialogMenuProps) {
state={{ previousUrl: location.pathname }}
disableRipple
variant="text"
onClick={() => (!subMenu.length ? closeDialogMenu() : handleSubMenu(index))}
onClick={() =>
!subMenu.length ? closeDialogMenu() : handleSubMenu(index)
}
sx={{
padding: "10px 10px 10px 20px",
display: "block",
fontWeight: 500,
color: location.pathname === url ? "#7E2AEA" : location.pathname === "/" ? "white" : "black",
color:
location.pathname === url
? "#7E2AEA"
: location.pathname === "/"
? "white"
: "black",
textTransform: "none",
fontSize: "16px",
borderRadius: 0,
"&:hover, &:active": {
color: "#7E2AEA",
background: index === activeSubMenuIndex ? theme.palette.background.default : "none",
background:
index === activeSubMenuIndex
? theme.palette.background.default
: "none",
},
}}
>
@ -143,7 +164,11 @@ export default function DialogMenu({ handleClose }: DialogMenuProps) {
whiteSpace: "nowrap",
fontWeight: 400,
color:
location.pathname === url ? "#7E2AEA" : location.pathname === "/" ? "white" : "black",
location.pathname === url
? "#7E2AEA"
: location.pathname === "/"
? "white"
: "black",
}}
>
{name}

@ -1,94 +1,94 @@
import { Link, useNavigate } from "react-router-dom"
import { Box, Container, Typography, useTheme } from "@mui/material"
import Drawers from "../Drawers"
import PenaLogo from "../PenaLogo"
import Menu from "../Menu"
import { logout } from "@root/api/auth"
import { enqueueSnackbar } from "notistack"
import { clearUserData, useUserStore } from "@root/stores/user"
import { Link, useNavigate } from "react-router-dom";
import { Box, Container, Typography, useTheme } from "@mui/material";
import Drawers from "../Drawers";
import PenaLogo from "../PenaLogo";
import Menu from "../Menu";
import { logout } from "@root/api/auth";
import { enqueueSnackbar } from "notistack";
import { clearUserData, useUserStore } from "@root/stores/user";
import {
AvatarButton,
LogoutButton,
WalletButton,
clearAuthToken,
} from "@frontend/kitui"
import { clearCustomTariffs } from "@root/stores/customTariffs"
import { currencyFormatter } from "@root/utils/currencyFormatter"
import { clearTickets } from "@root/stores/tickets"
AvatarButton,
LogoutButton,
WalletButton,
clearAuthToken,
} from "@frontend/kitui";
import { clearCustomTariffs } from "@root/stores/customTariffs";
import { currencyFormatter } from "@root/utils/currencyFormatter";
import { clearTickets } from "@root/stores/tickets";
import type { ReactNode } from "react"
import type { ReactNode } from "react";
interface Props {
children: ReactNode;
}
export default function NavbarFull({ children }: Props) {
const theme = useTheme()
const navigate = useNavigate()
const cash = useUserStore((state) => state.userAccount?.wallet.cash) ?? 0
const initials = useUserStore((state) => state.initials)
const theme = useTheme();
const navigate = useNavigate();
const cash = useUserStore((state) => state.userAccount?.wallet.cash) ?? 0;
const initials = useUserStore((state) => state.initials);
async function handleLogoutClick() {
const [_, logoutError] = await logout()
async function handleLogoutClick() {
clearAuthToken();
clearUserData();
clearCustomTariffs();
clearTickets();
navigate("/");
if (logoutError) {
return enqueueSnackbar(logoutError)
}
const [_, logoutError] = await logout();
clearAuthToken()
clearUserData()
clearCustomTariffs()
clearTickets()
navigate("/")
}
if (logoutError) {
return enqueueSnackbar(logoutError);
}
}
return (
<Box>
<Container
component="nav"
disableGutters
maxWidth={false}
sx={{
zIndex: 1,
position: "fixed",
top: "0",
px: "16px",
display: "flex",
height: "80px",
alignItems: "center",
gap: "60px",
bgcolor: "white",
borderBottom: "1px solid #E3E3E3",
}}
>
<Link to="/">
<PenaLogo width={124} color="black" />
</Link>
<Menu />
<Box sx={{ display: "flex", ml: "auto" }}>
<Drawers />
<WalletButton component={Link} to="/wallet" sx={{ ml: "20px" }} />
<Box sx={{ ml: "8px", whiteSpace: "nowrap" }}>
<Typography
sx={{
fontSize: "12px",
lineHeight: "14px",
color: theme.palette.gray.dark,
}}
>
return (
<Box>
<Container
component="nav"
disableGutters
maxWidth={false}
sx={{
zIndex: 1,
position: "fixed",
top: "0",
px: "16px",
display: "flex",
height: "80px",
alignItems: "center",
gap: "60px",
bgcolor: "white",
borderBottom: "1px solid #E3E3E3",
}}
>
<Link to="/">
<PenaLogo width={124} color="black" />
</Link>
<Menu />
<Box sx={{ display: "flex", ml: "auto" }}>
<Drawers />
<WalletButton component={Link} to="/wallet" sx={{ ml: "20px" }} />
<Box sx={{ ml: "8px", whiteSpace: "nowrap" }}>
<Typography
sx={{
fontSize: "12px",
lineHeight: "14px",
color: theme.palette.gray.dark,
}}
>
Мой баланс
</Typography>
<Typography variant="body2" color={theme.palette.purple.main}>
{currencyFormatter.format(cash / 100)}
</Typography>
</Box>
<AvatarButton component={Link} to="/settings" sx={{ ml: "27px" }}>
{initials}
</AvatarButton>
<LogoutButton onClick={handleLogoutClick} sx={{ ml: "20px" }} />
</Box>
</Container>
<Box>{children}</Box>
</Box>
)
</Typography>
<Typography variant="body2" color={theme.palette.purple.main}>
{currencyFormatter.format(cash / 100)}
</Typography>
</Box>
<AvatarButton component={Link} to="/settings" sx={{ ml: "27px" }}>
{initials}
</AvatarButton>
<LogoutButton onClick={handleLogoutClick} sx={{ ml: "20px" }} />
</Box>
</Container>
<Box>{children}</Box>
</Box>
);
}

@ -1,5 +1,11 @@
import { Link, useNavigate } from "react-router-dom";
import { Box, IconButton, Typography, useTheme, useMediaQuery } from "@mui/material";
import {
Box,
IconButton,
Typography,
useTheme,
useMediaQuery,
} from "@mui/material";
import LogoutIcon from "../icons/LogoutIcon";
import Drawers from "../Drawers";
import { logout } from "@root/api/auth";
@ -21,17 +27,17 @@ export const NavbarPanel = () => {
const initials = useUserStore((state) => state.initials);
async function handleLogoutClick() {
const [_, logoutError] = await logout();
if (logoutError) {
return enqueueSnackbar(logoutError);
}
clearAuthToken();
clearUserData();
clearCustomTariffs();
clearTickets();
navigate("/");
const [_, logoutError] = await logout();
if (logoutError) {
return enqueueSnackbar(logoutError);
}
}
return (

@ -284,7 +284,7 @@ export default function Payment() {
mb: "28px",
}}
>
{currencyFormatter.format(paymentValue / 100)}
{currencyFormatter.format(Math.trunc(paymentValue) / 100)}
</Typography>
) : (
<InputTextfield

@ -50,7 +50,9 @@ export default function QuizPayment() {
useEffect(
function redirectIfSignedIn() {
if (!first && user?._id === userId)
navigate(`/payment?action=${action}&dif=${dif}&user=${userId}`, { replace: true });
navigate(`/payment?action=${action}&dif=${dif}&user=${userId}`, {
replace: true,
});
},
[navigate, user]
);
@ -61,7 +63,7 @@ export default function QuizPayment() {
history.pushState(null, document.title, "/quizpayment");
try {
first = false;
if (user?._id === userId) {
return;
}
@ -71,11 +73,12 @@ export default function QuizPayment() {
// const data = await refresh(token)
// console.log(token)
if (getAuthToken()) {
await logout();
clearAuthToken();
clearUserData();
clearCustomTariffs();
clearTickets();
await logout();
}
setAuthToken(token);