refactor: enforce frontend view model boundaries
This commit is contained in:
@@ -19,100 +19,186 @@ import type { StockPageVm } from "../StockPage.vm";
|
||||
import classes from "../StockPage.module.css";
|
||||
|
||||
type StockEventsProps = { vm: StockPageVm };
|
||||
|
||||
const StockDividends: FC<StockEventsProps> = (props) => {
|
||||
const { vm } = props;
|
||||
const { t } = useTranslation();
|
||||
|
||||
let upcomingContent;
|
||||
|
||||
if (vm.dividends) {
|
||||
if (vm.upcoming.length > 0) {
|
||||
upcomingContent = (
|
||||
vm.upcoming.map(event => (
|
||||
<div
|
||||
className={classes.dividend}
|
||||
key={JSON.stringify([
|
||||
event.recordDate,
|
||||
event.paymentDate,
|
||||
event.perShare,
|
||||
])}
|
||||
>
|
||||
<Group align="start" justify="space-between">
|
||||
<div>
|
||||
<Badge color="green" variant="light">
|
||||
{t("stock.companyEvent")}
|
||||
</Badge>
|
||||
|
||||
<Text fw={650} mt="xs" size="xl">
|
||||
{formatMoney(event.perShare)}
|
||||
{" "}
|
||||
<Text c="dimmed" component="span" size="sm">
|
||||
{t("stock.perShare")}
|
||||
</Text>
|
||||
</Text>
|
||||
</div>
|
||||
|
||||
{!!event.estimatedAmount && (
|
||||
<div>
|
||||
<Text c="dimmed" size="xs">
|
||||
{t("stock.yourEstimate")}
|
||||
</Text>
|
||||
|
||||
<Text fw={600}>
|
||||
{formatMoney(event.estimatedAmount)}
|
||||
</Text>
|
||||
</div>
|
||||
)}
|
||||
</Group>
|
||||
|
||||
<Group gap="xl" mt="md">
|
||||
{!!event.lastBuyDate && (
|
||||
<div>
|
||||
<Text c="dimmed" size="xs">
|
||||
{t("stock.lastBuy")}
|
||||
</Text>
|
||||
|
||||
<Text>{formatDate(event.lastBuyDate)}</Text>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{!!event.recordDate && (
|
||||
<div>
|
||||
<Text c="dimmed" size="xs">
|
||||
{t("stock.record")}
|
||||
</Text>
|
||||
|
||||
<Text>{formatDate(event.recordDate)}</Text>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{!!event.paymentDate && (
|
||||
<div>
|
||||
<Text c="dimmed" size="xs">
|
||||
{t("stock.payment")}
|
||||
</Text>
|
||||
|
||||
<Text>{formatDate(event.paymentDate)}</Text>
|
||||
</div>
|
||||
)}
|
||||
</Group>
|
||||
</div>
|
||||
))
|
||||
);
|
||||
}
|
||||
else {
|
||||
upcomingContent = (
|
||||
<Text c="dimmed">
|
||||
{t("stock.noUpcoming", { to: formatDate(vm.dividends.to) })}
|
||||
</Text>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let pastDividendsContent;
|
||||
|
||||
if (vm.pastDividends.length > 0) {
|
||||
pastDividendsContent = (
|
||||
<Stack gap="sm">
|
||||
{vm.pastDividends.map(event => (
|
||||
<Paper
|
||||
key={JSON.stringify([
|
||||
event.recordDate,
|
||||
event.paymentDate,
|
||||
event.perShare,
|
||||
])}
|
||||
p="md"
|
||||
radius="md"
|
||||
withBorder
|
||||
>
|
||||
<Group align="start" justify="space-between">
|
||||
<div>
|
||||
<Text c="dimmed" size="xs">
|
||||
{t("stock.record")}
|
||||
</Text>
|
||||
|
||||
<Text fw={600}>
|
||||
{event.recordDate
|
||||
? formatDate(event.recordDate)
|
||||
: t("stock.dateUnknown")}
|
||||
</Text>
|
||||
|
||||
{!!event.paymentDate && (
|
||||
<Text c="dimmed" mt="xs" size="xs">
|
||||
{t("stock.payment")}:{" "}
|
||||
{formatDate(event.paymentDate)}
|
||||
</Text>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Text fw={650} size="lg">
|
||||
{formatMoney(event.perShare)}
|
||||
</Text>
|
||||
|
||||
<Text c="dimmed" size="xs">
|
||||
{t("stock.perShare")}
|
||||
</Text>
|
||||
</div>
|
||||
</Group>
|
||||
</Paper>
|
||||
))}
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
else {
|
||||
pastDividendsContent = (
|
||||
<Text c="dimmed">{t("stock.noDividends")}</Text>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<StockSection state={vm.dividendsState} title={t("stock.upcoming")}>
|
||||
{!!(vm.dividends) && ((
|
||||
{!!vm.dividends && (
|
||||
<Stack gap="md">
|
||||
{!!(vm.dividends.estimateUnavailable || vm.dividends.positionIsStale) && ((
|
||||
{!!(
|
||||
vm.dividends.estimateUnavailable || vm.dividends.positionIsStale
|
||||
) && (
|
||||
<Alert aria-live="polite" color="orange" role="status">
|
||||
{t("stock.estimateUnavailable")}
|
||||
</Alert>
|
||||
))}
|
||||
{vm.upcoming.length > 0
|
||||
? (
|
||||
vm.upcoming.map(event => (
|
||||
<div
|
||||
className={classes.dividend}
|
||||
key={JSON.stringify([
|
||||
event.recordDate,
|
||||
event.paymentDate,
|
||||
event.perShare,
|
||||
])}
|
||||
>
|
||||
<Group align="start" justify="space-between">
|
||||
<div>
|
||||
<Badge color="green" variant="light">
|
||||
{t("stock.companyEvent")}
|
||||
</Badge>
|
||||
<Text fw={650} mt="xs" size="xl">
|
||||
{formatMoney(event.perShare)}
|
||||
{" "}
|
||||
<Text c="dimmed" component="span" size="sm">
|
||||
{t("stock.perShare")}
|
||||
</Text>
|
||||
</Text>
|
||||
</div>
|
||||
{!!(event.estimatedAmount) && ((
|
||||
<div>
|
||||
<Text c="dimmed" size="xs">
|
||||
{t("stock.yourEstimate")}
|
||||
</Text>
|
||||
<Text fw={600}>{formatMoney(event.estimatedAmount)}</Text>
|
||||
</div>
|
||||
))}
|
||||
</Group>
|
||||
<Group gap="xl" mt="md">
|
||||
{!!(event.lastBuyDate) && ((
|
||||
<div>
|
||||
<Text c="dimmed" size="xs">
|
||||
{t("stock.lastBuy")}
|
||||
</Text>
|
||||
<Text>{formatDate(event.lastBuyDate)}</Text>
|
||||
</div>
|
||||
))}
|
||||
{!!(event.recordDate) && ((
|
||||
<div>
|
||||
<Text c="dimmed" size="xs">
|
||||
{t("stock.record")}
|
||||
</Text>
|
||||
<Text>{formatDate(event.recordDate)}</Text>
|
||||
</div>
|
||||
))}
|
||||
{!!(event.paymentDate) && ((
|
||||
<div>
|
||||
<Text c="dimmed" size="xs">
|
||||
{t("stock.payment")}
|
||||
</Text>
|
||||
<Text>{formatDate(event.paymentDate)}</Text>
|
||||
</div>
|
||||
))}
|
||||
</Group>
|
||||
</div>
|
||||
))
|
||||
)
|
||||
: (
|
||||
<Text c="dimmed">
|
||||
{t("stock.noUpcoming", { to: formatDate(vm.dividends.to) })}
|
||||
</Text>
|
||||
)}
|
||||
)}
|
||||
|
||||
{upcomingContent}
|
||||
|
||||
<Text c="dimmed" size="xs">
|
||||
{t("stock.dividendNote")}
|
||||
</Text>
|
||||
{!!(vm.dividends.positionAt) && ((
|
||||
|
||||
{!!vm.dividends.positionAt && (
|
||||
<Text c="dimmed" size="xs">
|
||||
{t("stock.snapshotAt", {
|
||||
date: formatSnapshotTime(vm.dividends.positionAt),
|
||||
})}
|
||||
</Text>
|
||||
))}
|
||||
)}
|
||||
|
||||
<Accordion radius="md" variant="contained">
|
||||
<Accordion.Item value="history">
|
||||
<Accordion.Control>
|
||||
<Text fw={600}>{t("stock.dividendHistory")}</Text>
|
||||
</Accordion.Control>
|
||||
|
||||
<Accordion.Panel>
|
||||
<Text c="dimmed" my="sm" size="xs">
|
||||
{t("stock.dividendWindow", {
|
||||
@@ -120,60 +206,13 @@ const StockDividends: FC<StockEventsProps> = (props) => {
|
||||
to: formatDate(vm.dividends.to),
|
||||
})}
|
||||
</Text>
|
||||
{vm.pastDividends.length > 0
|
||||
? (
|
||||
<Stack gap="sm">
|
||||
{vm.pastDividends.map(event => (
|
||||
<Paper
|
||||
key={JSON.stringify([
|
||||
event.recordDate,
|
||||
event.paymentDate,
|
||||
event.perShare,
|
||||
])}
|
||||
p="md"
|
||||
radius="md"
|
||||
withBorder
|
||||
>
|
||||
<Group align="start" justify="space-between">
|
||||
<div>
|
||||
<Text c="dimmed" size="xs">
|
||||
{t("stock.record")}
|
||||
</Text>
|
||||
<Text fw={600}>
|
||||
{event.recordDate
|
||||
? formatDate(event.recordDate)
|
||||
: t("stock.dateUnknown")}
|
||||
</Text>
|
||||
{!!(event.paymentDate) && ((
|
||||
<Text c="dimmed" mt="xs" size="xs">
|
||||
{t("stock.payment")}
|
||||
:
|
||||
{" "}
|
||||
{formatDate(event.paymentDate)}
|
||||
</Text>
|
||||
))}
|
||||
</div>
|
||||
<div>
|
||||
<Text fw={650} size="lg">
|
||||
{formatMoney(event.perShare)}
|
||||
</Text>
|
||||
<Text c="dimmed" size="xs">
|
||||
{t("stock.perShare")}
|
||||
</Text>
|
||||
</div>
|
||||
</Group>
|
||||
</Paper>
|
||||
))}
|
||||
</Stack>
|
||||
)
|
||||
: (
|
||||
<Text c="dimmed">{t("stock.noDividends")}</Text>
|
||||
)}
|
||||
|
||||
{pastDividendsContent}
|
||||
</Accordion.Panel>
|
||||
</Accordion.Item>
|
||||
</Accordion>
|
||||
</Stack>
|
||||
))}
|
||||
)}
|
||||
</StockSection>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user