Frontend security / security (push) Successful in 9s
Frontend verify / verify (push) Successful in 5m10s
Conventional commits / commits (pull_request) Successful in 25s
Frontend security / security (pull_request) Successful in 9s
Frontend verify / verify (pull_request) Successful in 5m10s
162 lines
3.9 KiB
TypeScript
162 lines
3.9 KiB
TypeScript
import { AppShell as MantineAppShell, NavLink, Text } from "@mantine/core";
|
|
import type { FC, ReactNode } from "react";
|
|
import { useTranslation } from "react-i18next";
|
|
import { Outlet, NavLink as RouterNavLink, useLocation } from "react-router";
|
|
import { bindIconAnimation } from "@/shared/lib";
|
|
import classes from "./AppShell.module.css";
|
|
|
|
type AppShellProps = {
|
|
contentAboveOutlet?: ReactNode;
|
|
};
|
|
|
|
const AppShell: FC<AppShellProps> = (props) => {
|
|
const { contentAboveOutlet } = props;
|
|
const { t } = useTranslation();
|
|
const { pathname } = useLocation();
|
|
const items = [
|
|
{
|
|
to: "/accounts",
|
|
label: t("navigation.accounts"),
|
|
iconClassName: classes.portfolioIcon,
|
|
icon: (
|
|
<>
|
|
<path d="M3 10v9h18v-9" />
|
|
<path className={classes.portfolioHandle} d="M8 6V4h8v2" />
|
|
<path
|
|
className={classes.portfolioLid}
|
|
d="M3 10V8a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v2H3Zm6 0v3h6v-3"
|
|
/>
|
|
<path
|
|
className={classes.portfolioRuble}
|
|
d="M10 18v-7h3a2 2 0 0 1 0 4H9m0 1.5h4"
|
|
/>
|
|
</>
|
|
),
|
|
},
|
|
{
|
|
to: "/cards",
|
|
label: t("navigation.cards"),
|
|
iconClassName: classes.cardsIcon,
|
|
icon: (
|
|
<>
|
|
<path d="M3 5h18v14H3V5Zm0 4h18M6 15h4" />
|
|
<g className={classes.rubles}>
|
|
<path d="M10 12V4h3a2 2 0 0 1 0 4H9m0 2h4" />
|
|
<path d="M10 12V4h3a2 2 0 0 1 0 4H9m0 2h4" />
|
|
<path d="M10 12V4h3a2 2 0 0 1 0 4H9m0 2h4" />
|
|
</g>
|
|
</>
|
|
),
|
|
},
|
|
{
|
|
to: "/stocks",
|
|
label: t("navigation.stocks"),
|
|
iconClassName: classes.stocksIcon,
|
|
icon: (
|
|
<>
|
|
<path d="M3 3v18h18" />
|
|
<path
|
|
className={classes.drawStroke}
|
|
pathLength={1}
|
|
d="M7 14l5-5 4 3 5-7"
|
|
/>
|
|
<path className={classes.stockArrow} d="M16 5h5v5" />
|
|
</>
|
|
),
|
|
},
|
|
{
|
|
to: "/bonds",
|
|
label: t("navigation.bonds"),
|
|
iconClassName: classes.bondsIcon,
|
|
icon: (
|
|
<>
|
|
<path d="M6 3h12v18l-3-2-3 2-3-2-3 2V3Z" />
|
|
<g className={classes.couponLines}>
|
|
<path pathLength={1} d="M9 7h6" />
|
|
<path pathLength={1} d="M9 11h6" />
|
|
<path pathLength={1} d="M9 15h3" />
|
|
</g>
|
|
</>
|
|
),
|
|
},
|
|
{
|
|
to: "/settings",
|
|
label: t("navigation.settings"),
|
|
iconClassName: classes.settingsIcon,
|
|
icon: (
|
|
<>
|
|
<path d="M4 7h16M4 17h16" />
|
|
<path className={classes.topSlider} d="M10 4v6h4V4h-4Z" />
|
|
<path className={classes.bottomSlider} d="M10 14v6h4v-6h-4Z" />
|
|
</>
|
|
),
|
|
},
|
|
];
|
|
|
|
return (
|
|
<MantineAppShell
|
|
header={{ height: 60 }}
|
|
navbar={{ width: 220, breakpoint: "sm", collapsed: { mobile: true } }}
|
|
padding="md"
|
|
>
|
|
<MantineAppShell.Header className={classes.header}>
|
|
<Text fw={700}>{t("appName")}</Text>
|
|
</MantineAppShell.Header>
|
|
<MantineAppShell.Navbar p="sm">
|
|
{items.map((item) => (
|
|
<NavLink
|
|
component={RouterNavLink}
|
|
className={classes.navLink}
|
|
key={item.to}
|
|
to={item.to}
|
|
label={item.label}
|
|
leftSection={
|
|
<span
|
|
className={`${classes.navIcon} ${item.iconClassName ?? ""}`}
|
|
>
|
|
<svg
|
|
ref={bindIconAnimation}
|
|
width={20}
|
|
height={20}
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
strokeWidth="1.5"
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
aria-hidden="true"
|
|
focusable="false"
|
|
>
|
|
{item.icon}
|
|
</svg>
|
|
</span>
|
|
}
|
|
active={pathname.startsWith(item.to)}
|
|
/>
|
|
))}
|
|
</MantineAppShell.Navbar>
|
|
<MantineAppShell.Main className={classes.main}>
|
|
<div className={classes.content}>
|
|
{contentAboveOutlet}
|
|
<Outlet />
|
|
</div>
|
|
</MantineAppShell.Main>
|
|
<nav className={classes.bottomNav} aria-label={t("appName")}>
|
|
{items.map((item) => (
|
|
<RouterNavLink
|
|
className={
|
|
pathname.startsWith(item.to) ? classes.active : undefined
|
|
}
|
|
key={item.to}
|
|
to={item.to}
|
|
>
|
|
{item.label}
|
|
</RouterNavLink>
|
|
))}
|
|
</nav>
|
|
</MantineAppShell>
|
|
);
|
|
};
|
|
|
|
export { AppShell };
|