chore: codify React component style
This commit is contained in:
@@ -1,10 +1,17 @@
|
||||
import { Stack, Text, Title } from "@mantine/core";
|
||||
import type { FC } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import type { BrokerageAccount } from "@/entities/brokerage-account";
|
||||
import { accountTypeKey } from "@/entities/brokerage-account";
|
||||
|
||||
export function AccountHeading({ account }: { account?: BrokerageAccount }) {
|
||||
type AccountHeadingProps = {
|
||||
account?: BrokerageAccount;
|
||||
};
|
||||
|
||||
const AccountHeading: FC<AccountHeadingProps> = (props) => {
|
||||
const { account } = props;
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<Stack gap={2}>
|
||||
<Title order={1}>{account?.name ?? t("portfolio.title")}</Title>
|
||||
@@ -15,4 +22,6 @@ export function AccountHeading({ account }: { account?: BrokerageAccount }) {
|
||||
) : null}
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export { AccountHeading };
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
import { Paper, Text } from "@mantine/core";
|
||||
import type { FC } from "react";
|
||||
import type { Portfolio } from "@/entities/portfolio";
|
||||
import { formatMoney } from "@/entities/portfolio";
|
||||
import classes from "../AccountPage.module.css";
|
||||
|
||||
export function CashBalances({
|
||||
balances,
|
||||
}: {
|
||||
type CashBalancesProps = {
|
||||
balances: Portfolio["cashBalances"];
|
||||
}) {
|
||||
};
|
||||
|
||||
const CashBalances: FC<CashBalancesProps> = (props) => {
|
||||
const { balances } = props;
|
||||
|
||||
return (
|
||||
<>
|
||||
{balances.map((balance) => (
|
||||
@@ -18,4 +21,6 @@ export function CashBalances({
|
||||
))}
|
||||
</>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export { CashBalances };
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
import { Alert, Button, Group, Loader, Stack, Text } from "@mantine/core";
|
||||
import type { FC } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
export function PortfolioRefreshState({
|
||||
refreshing,
|
||||
refreshError,
|
||||
retry,
|
||||
}: {
|
||||
type PortfolioRefreshStateProps = {
|
||||
refreshing: boolean;
|
||||
refreshError: boolean;
|
||||
retry?: () => void;
|
||||
}) {
|
||||
};
|
||||
|
||||
const PortfolioRefreshState: FC<PortfolioRefreshStateProps> = (props) => {
|
||||
const { refreshing, refreshError, retry } = props;
|
||||
const { t } = useTranslation();
|
||||
if (!refreshing && !refreshError) return null;
|
||||
|
||||
return (
|
||||
<>
|
||||
{refreshing ? (
|
||||
@@ -34,4 +35,6 @@ export function PortfolioRefreshState({
|
||||
) : null}
|
||||
</>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export { PortfolioRefreshState };
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
import { Paper, SimpleGrid, Text } from "@mantine/core";
|
||||
import type { FC } from "react";
|
||||
import type { Portfolio } from "@/entities/portfolio";
|
||||
import { formatMoney } from "@/entities/portfolio";
|
||||
import classes from "../AccountPage.module.css";
|
||||
|
||||
export function PortfolioTotals({
|
||||
totals,
|
||||
}: {
|
||||
type PortfolioTotalsProps = {
|
||||
totals: Portfolio["totalsByCurrency"];
|
||||
}) {
|
||||
};
|
||||
|
||||
const PortfolioTotals: FC<PortfolioTotalsProps> = (props) => {
|
||||
const { totals } = props;
|
||||
|
||||
return (
|
||||
<SimpleGrid cols={{ base: 1, sm: 2, md: 3 }}>
|
||||
{totals.map((total) => (
|
||||
@@ -22,4 +25,6 @@ export function PortfolioTotals({
|
||||
))}
|
||||
</SimpleGrid>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export { PortfolioTotals };
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
import { Card, Group, Stack, Text } from "@mantine/core";
|
||||
import type { FC } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { formatMoney } from "@/entities/portfolio";
|
||||
import classes from "../AccountPage.module.css";
|
||||
import type { AccountPagePosition } from "../AccountPage.vm";
|
||||
import { PositionLogo } from "./PositionLogo.view";
|
||||
|
||||
export function PositionCard({
|
||||
position,
|
||||
wide = false,
|
||||
}: {
|
||||
type PositionCardProps = {
|
||||
position: AccountPagePosition;
|
||||
wide?: boolean;
|
||||
}) {
|
||||
};
|
||||
|
||||
const PositionCard: FC<PositionCardProps> = (props) => {
|
||||
const { position, wide = false } = props;
|
||||
const { t } = useTranslation();
|
||||
const returnClass = position.returnTone
|
||||
? classes[position.returnTone]
|
||||
@@ -78,4 +79,6 @@ export function PositionCard({
|
||||
) : null}
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export { PositionCard };
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
import { Avatar } from "@mantine/core";
|
||||
import type { FC } from "react";
|
||||
import { useState } from "react";
|
||||
|
||||
export function PositionLogo({
|
||||
src,
|
||||
label,
|
||||
}: {
|
||||
type PositionLogoProps = {
|
||||
src: string | null;
|
||||
label: string;
|
||||
}) {
|
||||
};
|
||||
|
||||
const PositionLogo: FC<PositionLogoProps> = (props) => {
|
||||
const { src, label } = props;
|
||||
const [failed, setFailed] = useState(false);
|
||||
|
||||
if (src && !failed)
|
||||
return (
|
||||
<Avatar
|
||||
@@ -24,4 +26,6 @@ export function PositionLogo({
|
||||
{(label.trim()[0] ?? "?").toUpperCase()}
|
||||
</Avatar>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export { PositionLogo };
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
import { SimpleGrid } from "@mantine/core";
|
||||
import type { FC } from "react";
|
||||
import type { AccountPagePositionSection } from "../AccountPage.vm";
|
||||
import { PositionCard } from "./PositionCard.view";
|
||||
import { Section } from "./Section.view";
|
||||
|
||||
export function PositionSection({
|
||||
title,
|
||||
section,
|
||||
}: {
|
||||
type PositionSectionProps = {
|
||||
title: string;
|
||||
section: AccountPagePositionSection;
|
||||
}) {
|
||||
};
|
||||
|
||||
const PositionSection: FC<PositionSectionProps> = (props) => {
|
||||
const { title, section } = props;
|
||||
|
||||
return (
|
||||
<Section title={title}>
|
||||
<SimpleGrid cols={section.wide ? 1 : { base: 1, sm: 2, md: 3 }}>
|
||||
@@ -23,4 +25,6 @@ export function PositionSection({
|
||||
</SimpleGrid>
|
||||
</Section>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export { PositionSection };
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Alert, Button, Paper, Text } from "@mantine/core";
|
||||
import type { FC } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Link } from "react-router";
|
||||
import type { BrokerageEvent } from "@/entities/brokerage-event";
|
||||
@@ -7,8 +8,18 @@ import classes from "../AccountPage.module.css";
|
||||
import type { AccountPageRecentEvents } from "../AccountPage.vm";
|
||||
import { Section } from "./Section.view";
|
||||
|
||||
export function RecentEvents({ events }: { events: AccountPageRecentEvents }) {
|
||||
type RecentEventsProps = {
|
||||
events: AccountPageRecentEvents;
|
||||
};
|
||||
|
||||
type RecentEventProps = {
|
||||
event: BrokerageEvent;
|
||||
};
|
||||
|
||||
const RecentEvents: FC<RecentEventsProps> = (props) => {
|
||||
const { events } = props;
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<Section title={t("events.recentTitle")}>
|
||||
{events.state === "loading" ? (
|
||||
@@ -33,10 +44,12 @@ export function RecentEvents({ events }: { events: AccountPageRecentEvents }) {
|
||||
</Button>
|
||||
</Section>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
function RecentEvent({ event }: { event: BrokerageEvent }) {
|
||||
const RecentEvent: FC<RecentEventProps> = (props) => {
|
||||
const { event } = props;
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<Paper className={classes.cash} withBorder>
|
||||
<Text>{`${t(`events.type.${event.type}`)} · ${event.displayName}`}</Text>
|
||||
@@ -47,4 +60,6 @@ function RecentEvent({ event }: { event: BrokerageEvent }) {
|
||||
</Text>
|
||||
</Paper>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export { RecentEvents };
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Alert, Button, Paper, Text } from "@mantine/core";
|
||||
import type { FC } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Link } from "react-router";
|
||||
import { formatMoney } from "@/entities/portfolio";
|
||||
@@ -6,12 +7,14 @@ import classes from "../AccountPage.module.css";
|
||||
import type { AccountPageRecentOperations } from "../AccountPage.vm";
|
||||
import { Section } from "./Section.view";
|
||||
|
||||
export function RecentOperations({
|
||||
operations,
|
||||
}: {
|
||||
type RecentOperationsProps = {
|
||||
operations: AccountPageRecentOperations;
|
||||
}) {
|
||||
};
|
||||
|
||||
const RecentOperations: FC<RecentOperationsProps> = (props) => {
|
||||
const { operations } = props;
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<Section title={t("ledger.recentTitle")}>
|
||||
{operations.state === "loading" ? (
|
||||
@@ -40,4 +43,6 @@ export function RecentOperations({
|
||||
</Button>
|
||||
</Section>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export { RecentOperations };
|
||||
|
||||
@@ -1,16 +1,19 @@
|
||||
import { Stack, Title } from "@mantine/core";
|
||||
import type { FC, PropsWithChildren } from "react";
|
||||
|
||||
export function Section({
|
||||
title,
|
||||
children,
|
||||
}: {
|
||||
type SectionProps = PropsWithChildren<{
|
||||
title: string;
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
}>;
|
||||
|
||||
const Section: FC<SectionProps> = (props) => {
|
||||
const { title, children } = props;
|
||||
|
||||
return (
|
||||
<Stack gap="sm">
|
||||
<Title order={2}>{title}</Title>
|
||||
{children}
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export { Section };
|
||||
|
||||
Reference in New Issue
Block a user