97 lines
2.1 KiB
TypeScript
97 lines
2.1 KiB
TypeScript
import type { FC, PropsWithChildren, ReactNode } from "react";
|
|
|
|
import { Paper, Stack, Text, VisuallyHidden } from "@mantine/core";
|
|
import { useTranslation } from "react-i18next";
|
|
|
|
import { formatMoney } from "@/shared/lib";
|
|
|
|
import classes from "./EntryGroup.module.css";
|
|
|
|
type AccountRowProps = {
|
|
accountName: string;
|
|
value: string;
|
|
valueLabel: string;
|
|
};
|
|
|
|
type EntryGroupProps = PropsWithChildren<{
|
|
header: ReactNode;
|
|
label: string;
|
|
}>;
|
|
|
|
type EntryGroupTotalProps = {
|
|
isSigned?: boolean;
|
|
totals: null | { currency: string; value: string }[];
|
|
};
|
|
|
|
const AccountRow: FC<AccountRowProps> = (props) => {
|
|
const accessibleName = `${props.accountName}, ${props.value}`;
|
|
|
|
return (
|
|
<li aria-label={accessibleName} className={classes.accountRow}>
|
|
<Text>{props.accountName}</Text>
|
|
|
|
<Stack className={classes.accountValue} gap={2}>
|
|
<Text fw={700}>{props.value}</Text>
|
|
|
|
<Text c="dimmed" size="xs">{props.valueLabel}</Text>
|
|
</Stack>
|
|
</li>
|
|
);
|
|
};
|
|
|
|
const AccountCardRow: FC<AccountRowProps> = props => (
|
|
<li aria-label={`${props.accountName}, ${props.value}`}>
|
|
<Paper className={classes.accountCardRow} withBorder>
|
|
<Text fw={700}>{props.accountName}</Text>
|
|
|
|
<Stack className={classes.accountValue} gap={2}>
|
|
<Text fw={700}>{props.value}</Text>
|
|
|
|
<Text c="dimmed" size="xs">{props.valueLabel}</Text>
|
|
</Stack>
|
|
</Paper>
|
|
</li>
|
|
);
|
|
|
|
const EntryGroup: FC<EntryGroupProps> = props => (
|
|
<Paper className={classes.group} component="li" withBorder>
|
|
{props.header}
|
|
|
|
<Stack
|
|
aria-label={props.label}
|
|
className={classes.accounts}
|
|
component="ul"
|
|
gap={0}
|
|
>
|
|
{props.children}
|
|
</Stack>
|
|
</Paper>
|
|
);
|
|
|
|
const EntryGroupTotal: FC<EntryGroupTotalProps> = (props) => {
|
|
const { t } = useTranslation();
|
|
|
|
if (!props.totals) {
|
|
return <VisuallyHidden>{t("entryGroup.totalUnavailable")}</VisuallyHidden>;
|
|
}
|
|
|
|
const isSigned = props.isSigned === true;
|
|
|
|
return (
|
|
<Stack gap={2}>
|
|
{props.totals.map(total => (
|
|
<span key={`${total.currency}-${total.value}`}>
|
|
{formatMoney(total, { withSign: isSigned || undefined })}
|
|
</span>
|
|
))}
|
|
</Stack>
|
|
);
|
|
};
|
|
|
|
export {
|
|
AccountCardRow,
|
|
AccountRow,
|
|
EntryGroup,
|
|
EntryGroupTotal,
|
|
};
|