feat: add bond pages and portfolio navigation

This commit is contained in:
2026-09-10 22:30:47 +03:00
parent 561222e468
commit 232d7f9990
39 changed files with 4217 additions and 221 deletions
+19 -13
View File
@@ -25,7 +25,7 @@ type AccountPagePosition = Portfolio["positions"][number] & {
returnText: string | null;
returnTone?: AccountPageReturnTone;
logoSrc: string | null;
stockTo?: string;
instrumentTo?: string;
};
type AccountPagePositionGroup = {
@@ -87,13 +87,14 @@ function useAccountPageViewModel(scopeId?: string): AccountPageViewModel {
const { accountId: routeAccountId } = useParams();
const accountId = scopeId ?? routeAccountId;
const portfolio = usePortfolio(accountId);
const stockDetails = useStocks(
const stocks = useStocks(
portfolio.data?.positions.flatMap((position) =>
position.type === "STOCK" && position.instrumentUid
? [position.instrumentUid]
: [],
) ?? [],
);
const instrumentDetails = stocks;
const operations = useBrokerageOperations(accountId, {
limit: 5,
});
@@ -136,7 +137,7 @@ function useAccountPageViewModel(scopeId?: string): AccountPageViewModel {
portfolio: portfolio.data,
positionSections: toAccountPagePositionSections(
portfolio.data,
stockDetails,
instrumentDetails,
),
recentOperations,
recentEvents,
@@ -182,7 +183,7 @@ function toRecentEvents(
function toAccountPagePositionSections(
portfolio: Portfolio,
stockDetails: ReturnType<typeof useStocks> = new Map(),
instrumentDetails: Map<string, { slug: string } | undefined> = new Map(),
): AccountPagePositionSection[] {
const denominators = new Map<string, number>();
for (const position of portfolio.positions) {
@@ -193,9 +194,14 @@ function toAccountPagePositionSections(
(denominators.get(currency) ?? 0) + Number(position.currentValue.value),
);
}
const stocks = toSection("stocks", portfolio, denominators, stockDetails);
const bonds = toSection("bonds", portfolio, denominators, stockDetails);
const other = toSection("other", portfolio, denominators, stockDetails);
const stocks = toSection(
"stocks",
portfolio,
denominators,
instrumentDetails,
);
const bonds = toSection("bonds", portfolio, denominators, instrumentDetails);
const other = toSection("other", portfolio, denominators, instrumentDetails);
return [stocks, bonds, other].filter((section) => section.groups.length > 0);
}
@@ -203,7 +209,7 @@ function toSection(
kind: PositionSectionKind,
portfolio: Portfolio,
denominators: Map<string, number>,
stockDetails: ReturnType<typeof useStocks>,
instrumentDetails: Map<string, { slug: string } | undefined>,
): AccountPagePositionSection {
return {
kind,
@@ -223,7 +229,7 @@ function toSection(
position,
denominators,
kind,
stockDetails.get(position.instrumentUid ?? "")?.slug,
instrumentDetails.get(position.instrumentUid ?? "")?.slug,
),
),
),
@@ -265,7 +271,7 @@ function toPosition(
position: Portfolio["positions"][number],
denominators: Map<string, number>,
kind: PositionSectionKind,
stockSlug: string | undefined,
instrumentSlug: string | undefined,
): AccountPagePosition {
const expanded = kind !== "other";
const returnValue = position.absoluteReturn
@@ -279,9 +285,9 @@ function toPosition(
: "negative";
return {
...position,
stockTo:
kind === "stocks" && position.instrumentUid
? `/stocks/${encodeURIComponent(stockSlug ?? position.instrumentUid)}`
instrumentTo:
(kind === "stocks" || kind === "bonds") && position.instrumentUid
? `/${kind}/${encodeURIComponent(instrumentSlug ?? position.instrumentUid)}`
: undefined,
shareText: position.currentValue?.currency
? formatShare(position.currentValue, {