refactor: enforce frontend view model boundaries
This commit is contained in:
@@ -1,11 +1,16 @@
|
||||
import type { FC, ReactNode } from "react";
|
||||
|
||||
import { AppShell as MantineAppShell, NavLink, Text } from "@mantine/core";
|
||||
import {
|
||||
BondsIcon,
|
||||
CardsIcon,
|
||||
PortfolioIcon,
|
||||
SettingsIcon,
|
||||
StocksIcon,
|
||||
} from "@wealthledger/icons";
|
||||
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 = {
|
||||
@@ -16,80 +21,34 @@ const AppShell: FC<AppShellProps> = (props) => {
|
||||
const { contentAboveOutlet } = props;
|
||||
const { t } = useTranslation();
|
||||
const { pathname } = useLocation();
|
||||
|
||||
const items = [
|
||||
{
|
||||
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"
|
||||
/>
|
||||
</>
|
||||
),
|
||||
icon: <PortfolioIcon size={20} />,
|
||||
iconClassName: classes.portfolioIcon,
|
||||
label: t("navigation.accounts"),
|
||||
to: "/accounts",
|
||||
},
|
||||
{
|
||||
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>
|
||||
</>
|
||||
),
|
||||
icon: <CardsIcon size={20} />,
|
||||
iconClassName: classes.cardsIcon,
|
||||
label: t("navigation.cards"),
|
||||
to: "/cards",
|
||||
},
|
||||
{
|
||||
icon: (
|
||||
<>
|
||||
<path d="M3 3v18h18" />
|
||||
<path
|
||||
className={classes.drawStroke}
|
||||
d="M7 14l5-5 4 3 5-7"
|
||||
pathLength={1}
|
||||
/>
|
||||
<path className={classes.stockArrow} d="M16 5h5v5" />
|
||||
</>
|
||||
),
|
||||
icon: <StocksIcon size={20} />,
|
||||
iconClassName: classes.stocksIcon,
|
||||
label: t("navigation.stocks"),
|
||||
to: "/stocks",
|
||||
},
|
||||
{
|
||||
icon: (
|
||||
<>
|
||||
<path d="M6 3h12v18l-3-2-3 2-3-2-3 2V3Z" />
|
||||
<g className={classes.couponLines}>
|
||||
<path d="M9 7h6" pathLength={1} />
|
||||
<path d="M9 11h6" pathLength={1} />
|
||||
<path d="M9 15h3" pathLength={1} />
|
||||
</g>
|
||||
</>
|
||||
),
|
||||
icon: <BondsIcon size={20} />,
|
||||
iconClassName: classes.bondsIcon,
|
||||
label: t("navigation.bonds"),
|
||||
to: "/bonds",
|
||||
},
|
||||
{
|
||||
icon: (
|
||||
<>
|
||||
<path d="M4 7h16M4 17h16" />
|
||||
<path className={classes.topSlider} d="M10 4v6h4V4h-4Z" />
|
||||
<path className={classes.bottomSlider} d="M10 14v6h4v-6h-4Z" />
|
||||
</>
|
||||
),
|
||||
icon: <SettingsIcon size={20} />,
|
||||
iconClassName: classes.settingsIcon,
|
||||
label: t("navigation.settings"),
|
||||
to: "/settings",
|
||||
@@ -105,6 +64,7 @@ const AppShell: FC<AppShellProps> = (props) => {
|
||||
<MantineAppShell.Header className={classes.header}>
|
||||
<Text fw={700}>{t("appName")}</Text>
|
||||
</MantineAppShell.Header>
|
||||
|
||||
<MantineAppShell.Navbar p="sm">
|
||||
{items.map(item => (
|
||||
<NavLink
|
||||
@@ -117,45 +77,38 @@ const AppShell: FC<AppShellProps> = (props) => {
|
||||
<span
|
||||
className={`${classes.navIcon} ${item.iconClassName ?? ""}`}
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
fill="none"
|
||||
focusable="false"
|
||||
height={20}
|
||||
ref={bindIconAnimation}
|
||||
stroke="currentColor"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="1.5"
|
||||
viewBox="0 0 24 24"
|
||||
width={20}
|
||||
>
|
||||
{item.icon}
|
||||
</svg>
|
||||
{item.icon}
|
||||
</span>
|
||||
)}
|
||||
to={item.to}
|
||||
/>
|
||||
))}
|
||||
</MantineAppShell.Navbar>
|
||||
|
||||
<MantineAppShell.Main className={classes.main}>
|
||||
<div className={classes.content}>
|
||||
{contentAboveOutlet}
|
||||
|
||||
<Outlet />
|
||||
</div>
|
||||
</MantineAppShell.Main>
|
||||
|
||||
<nav aria-label={t("appName")} className={classes.bottomNav}>
|
||||
{items.map(item => (
|
||||
<RouterNavLink
|
||||
className={
|
||||
(pathname.startsWith(item.to)) ? (classes.active) : undefined
|
||||
}
|
||||
key={item.to}
|
||||
to={item.to}
|
||||
>
|
||||
{item.label}
|
||||
</RouterNavLink>
|
||||
))}
|
||||
{items.map((item) => {
|
||||
const appearanceClass = pathname.startsWith(item.to)
|
||||
? classes.active
|
||||
: undefined;
|
||||
|
||||
return (
|
||||
<RouterNavLink
|
||||
className={appearanceClass}
|
||||
key={item.to}
|
||||
to={item.to}
|
||||
>
|
||||
{item.label}
|
||||
</RouterNavLink>
|
||||
);
|
||||
})}
|
||||
</nav>
|
||||
</MantineAppShell>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user