Files
frontend/src/shared/ui/EntryGroup/EntryGroup.tsx
T
codex-bot cc45352243
Frontend verify / commits (push) Skipped
Frontend verify / security (push) Successful in 11s
Frontend verify / verify (push) Failing after 7m26s
feat: clarify grouped coupon payouts (#162) (#165)
2026-11-07 11:18:07 +03:00

106 lines
2.4 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;
tone?: "negative"
| "neutral"
| "positive";
value: string;
valueLabel: string;
};
type EntryGroupProps = PropsWithChildren<{
flat?: boolean;
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}`;
const valueClass = props.tone ? classes[props.tone] : undefined;
return (
<li aria-label={accessibleName} className={classes.accountRow}>
<Text>{props.accountName}</Text>
<Stack className={classes.accountValue} gap={2}>
<Text className={valueClass} 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) => {
const groupClass = props.flat ? `${classes.group} ${classes.flat}` : classes.group;
return (
<Paper className={groupClass} 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,
};