Files
frontend/src/entities/broker-operation/ui/LedgerEntryRow.tsx
T
codex-bot 43b0f5574a
Frontend verify / commits (push) Skipped
Frontend verify / security (push) Successful in 10s
Frontend verify / verify (push) Successful in 7m18s
feat: unify income payment cards and remove comparisons (WealthLedger/main#33) (#74)
feat: unify income payment cards and remove comparisons (WealthLedger/main#33)
2026-10-13 18:17:35 +03:00

117 lines
2.8 KiB
TypeScript

import type { FC } from "react";
import { Anchor, Group, Text } from "@mantine/core";
import { EntryCard } from "@wealthledger/ui";
import { useTranslation } from "react-i18next";
import { Link } from "react-router";
import {
formatDecimal,
formatMoney,
formatSnapshotTime,
instrumentLogoUrl,
} from "@/shared/lib";
import { PayoutCard } from "@/shared/ui";
import type { BrokerageOperation } from "../api/useBrokerageOperations";
import { isIncomePayment, operationLabelKey, paymentPresentation } from "../model/display";
type LedgerEntryRowProps = {
operation: BrokerageOperation;
withDetails?: boolean;
wrap?: boolean;
};
const LedgerEntryRow: FC<LedgerEntryRowProps> = (props) => {
const { operation } = props;
const { t } = useTranslation();
const instrument
= operation.ticker ?? operation.instrumentType ?? t("ledger.noInstrument");
const payment = paymentPresentation(operation);
const metadata = [
t("ledger.occurredAt", { date: formatSnapshotTime(operation.occurredAt) }),
instrument,
props.withDetails
? null
: operation.account?.name,
]
.filter(Boolean)
.join(" · ");
let details;
if (props.withDetails) {
details = (
<>
<Group gap="sm">
{operation.quantity != undefined && (
<Text c="dimmed" size="xs">
{t("ledger.quantity", {
value: formatDecimal(operation.quantity),
})}
</Text>
)}
{!!operation.price && (
<Text c="dimmed" size="xs">
{t("ledger.price", { value: formatMoney(operation.price) })}
</Text>
)}
</Group>
{!!operation.account && (
<Anchor
component={Link}
size="sm"
to={`/accounts/${encodeURIComponent(operation.account.id)}`}
>
{operation.account.name}
</Anchor>
)}
</>
);
}
else details = undefined;
if (isIncomePayment(operation)) {
const extraMetadata = [
instrument,
props.withDetails ? null : operation.account?.name,
].filter(Boolean).join(" · ");
return (
<PayoutCard
details={details}
extraMetadata={extraMetadata}
imageSrc={instrumentLogoUrl(operation.logoName)}
initial={(instrument.trim()[0] ?? "?").toUpperCase()}
kind="executed"
occurredAt={formatSnapshotTime(operation.occurredAt)}
payment={operation.payment}
title={operation.description || t(operationLabelKey(operation.type))}
typeLabel={t(paymentPresentation(operation).label)}
wrap={props.wrap}
/>
);
}
return (
<EntryCard
details={details}
imageSrc={instrumentLogoUrl(operation.logoName)}
initial={(instrument.trim()[0] ?? "?").toUpperCase()}
metadata={metadata}
title={operation.description || t(operationLabelKey(operation.type))}
tone={payment.tone}
value={payment.amount}
valueLabel={t(payment.label)}
wrap={props.wrap}
/>
);
};
export { LedgerEntryRow };