95 lines
2.3 KiB
TypeScript
95 lines
2.3 KiB
TypeScript
import type { FC } from "react";
|
|
|
|
import { Button, Paper, Stack, Text } from "@mantine/core";
|
|
import { StateView } from "@wealthledger/ui";
|
|
import { useTranslation } from "react-i18next";
|
|
import { Link } from "react-router";
|
|
|
|
import type { IncomeSummary as IncomeSummaryData } from "@/entities/income";
|
|
|
|
import { formatMoney, formatSnapshotTime } from "@/shared/lib";
|
|
|
|
type IncomeSummaryProps
|
|
= | {
|
|
lastSuccessfulAt?: null | string;
|
|
refreshError?: boolean;
|
|
stale?: boolean;
|
|
state: "loaded";
|
|
summary: IncomeSummaryData;
|
|
to: string;
|
|
}
|
|
| { retry: () => void; state: "error"; to: string }
|
|
| { state: "empty"; to: string }
|
|
| { state: "loading"; to: string }
|
|
| { state: "partial"; to: string };
|
|
|
|
const IncomeSummary: FC<IncomeSummaryProps> = (props) => {
|
|
const { t } = useTranslation();
|
|
if (props.state === "loading" || props.state === "partial")
|
|
return (
|
|
<Text c="dimmed" role="status">
|
|
{t(
|
|
props.state === "partial"
|
|
? "investment.partial"
|
|
: "income.summaryLoading",
|
|
)}
|
|
</Text>
|
|
);
|
|
if (props.state === "error")
|
|
return (
|
|
<StateView
|
|
action={
|
|
<Button onClick={props.retry}>{t("income.summaryRetry")}</Button>
|
|
}
|
|
error
|
|
text={t("income.errorText")}
|
|
title={t("income.summaryError")}
|
|
/>
|
|
);
|
|
if (props.state === "empty")
|
|
return (
|
|
<Stack gap="xs">
|
|
<Text c="dimmed">{t("income.summaryEmpty")}</Text>
|
|
|
|
<Button component={Link} to={props.to} variant="subtle">
|
|
{t("income.open")}
|
|
</Button>
|
|
</Stack>
|
|
);
|
|
|
|
return (
|
|
<Stack gap="xs">
|
|
{!!props.lastSuccessfulAt && (
|
|
<Text c="dimmed" size="xs">
|
|
{t("investment.sourceTime", {
|
|
date: formatSnapshotTime(props.lastSuccessfulAt),
|
|
})}
|
|
</Text>
|
|
)}
|
|
|
|
{!!props.stale && <Text size="xs">{t("investment.stale")}</Text>}
|
|
|
|
{!!props.refreshError && (
|
|
<Text role="status">{t("income.refreshError")}</Text>
|
|
)}
|
|
|
|
{props.summary.totalsByCurrency.map(total => (
|
|
<Paper key={total.currency} p="sm" withBorder>
|
|
<Text fw={700}>{formatMoney(total.total)}</Text>
|
|
|
|
<Text c="dimmed" size="sm">
|
|
{t("income.coupon")}: {formatMoney(total.coupon)} ·{" "}
|
|
{t("income.dividend")}: {formatMoney(total.dividend)}
|
|
</Text>
|
|
</Paper>
|
|
))}
|
|
|
|
<Button component={Link} to={props.to} variant="subtle">
|
|
{t("income.open")}
|
|
</Button>
|
|
</Stack>
|
|
);
|
|
};
|
|
|
|
export { IncomeSummary };
|