diff --git a/apps/frontend/src/pages/broker-account/ui/BrokerAccountOverviewPage.tsx b/apps/frontend/src/pages/broker-account/ui/BrokerAccountOverviewPage.tsx
index f7909e6..e7b4b79 100644
--- a/apps/frontend/src/pages/broker-account/ui/BrokerAccountOverviewPage.tsx
+++ b/apps/frontend/src/pages/broker-account/ui/BrokerAccountOverviewPage.tsx
@@ -1,131 +1,9 @@
import { Link } from 'react-router-dom';
-import type { BrokerMoney, BrokerPortfolio } from '@/shared/api/responses';
-import { SkeletonBlock } from '@/shared/ui/SkeletonBlock';
import { useBrokerOperations } from '@/entities/broker-operation';
import { useBrokerAccountContext } from '@/widgets/broker-account-layout';
import { BrokerAllocationChart } from '@/widgets/broker-allocation-chart';
import { BrokerOperationsTable } from '@/widgets/broker-operations-table';
-import {
- formatBrokerMoney as formatMoney,
- formatBrokerPercent as formatPercent,
- pluralize,
-} from '@/shared/lib/formatters';
-
-function BrokerSummary({ portfolio }: { portfolio: BrokerPortfolio }) {
- return (
-
-
- Стоимость портфеля
-
- {formatMoney(portfolio.totals.portfolio)}
-
- За день: {formatMoney(portfolio.yields.daily)}
- Дневная доходность: {formatPercent(portfolio.yields.dailyPercent)}
- Ожидаемая доходность: {formatPercent(portfolio.yields.expectedPercent)}
-
-
-
Денежный остаток
- {portfolio.cash.length === 0 ? (
-
Нет денежных остатков
- ) : (
-
- {portfolio.cash.map((money, index) => (
- -
- {money.currency}
- {formatMoney(money)}
-
- ))}
-
- )}
-
-
- );
-}
-
-function allocationPercent(value: BrokerMoney | null, total: BrokerMoney | null) {
- if (!value || !total || total.value <= 0) return null;
- return (value.value / total.value) * 100;
-}
-
-function formatAllocationPercent(value: number | null) {
- return value === null ? '—' : `${value.toFixed(1)}%`;
-}
-
-function BrokerAssetCards({
- accountId,
- portfolio,
-}: {
- accountId: string;
- portfolio: BrokerPortfolio;
-}) {
- const basePath = `/broker/${encodeURIComponent(accountId)}`;
- const cards = [
- {
- label: 'Акции',
- count: portfolio.positionCounts.shares,
- countLabel: pluralize(portfolio.positionCounts.shares, 'позиция', 'позиции', 'позиций'),
- value: portfolio.totals.shares,
- path: `${basePath}/shares`,
- },
- {
- label: 'Облигации',
- count: portfolio.positionCounts.bonds,
- countLabel: pluralize(portfolio.positionCounts.bonds, 'выпуск', 'выпуска', 'выпусков'),
- value: portfolio.totals.bonds,
- path: `${basePath}/bonds`,
- },
- ];
-
- return (
-
- {cards.map((card) => (
-
- {card.label}
-
- {card.count} {card.countLabel}
-
- {formatMoney(card.value)}
-
- {formatAllocationPercent(allocationPercent(card.value, portfolio.totals.portfolio))}
-
-
- ))}
-
- );
-}
-
-function BrokerOverviewSkeleton() {
- return (
-
-
- {[1, 2].map((item) => (
-
-
-
-
-
- ))}
-
-
-
-
-
-
- {[1, 2].map((item) => (
-
-
-
-
-
- ))}
-
-
- );
-}
+import { BrokerSummary, BrokerAssetCards, BrokerOverviewSkeleton } from '@/widgets/broker-overview';
export function BrokerAccountOverviewPage() {
const { accountId, portfolio } = useBrokerAccountContext();
diff --git a/apps/frontend/src/widgets/broker-overview/index.ts b/apps/frontend/src/widgets/broker-overview/index.ts
new file mode 100644
index 0000000..8d49b7e
--- /dev/null
+++ b/apps/frontend/src/widgets/broker-overview/index.ts
@@ -0,0 +1,3 @@
+export { BrokerSummary } from './ui/BrokerSummary';
+export { BrokerAssetCards } from './ui/BrokerAssetCards';
+export { BrokerOverviewSkeleton } from './ui/BrokerOverviewSkeleton';
diff --git a/apps/frontend/src/widgets/broker-overview/ui/BrokerAssetCards.tsx b/apps/frontend/src/widgets/broker-overview/ui/BrokerAssetCards.tsx
new file mode 100644
index 0000000..662dbe9
--- /dev/null
+++ b/apps/frontend/src/widgets/broker-overview/ui/BrokerAssetCards.tsx
@@ -0,0 +1,59 @@
+import { Link } from 'react-router-dom';
+import type { BrokerMoney, BrokerPortfolio } from '@/shared/api/responses';
+import { formatBrokerMoney, pluralize } from '@/shared/lib/formatters';
+
+function allocationPercent(value: BrokerMoney | null, total: BrokerMoney | null) {
+ if (!value || !total || total.value <= 0) return null;
+ return (value.value / total.value) * 100;
+}
+
+function formatAllocationPercent(value: number | null) {
+ return value === null ? '\u2014' : `${value.toFixed(1)}%`;
+}
+
+export function BrokerAssetCards({
+ accountId,
+ portfolio,
+}: {
+ accountId: string;
+ portfolio: BrokerPortfolio;
+}) {
+ const basePath = `/broker/${encodeURIComponent(accountId)}`;
+ const cards = [
+ {
+ label: 'Акции',
+ count: portfolio.positionCounts.shares,
+ countLabel: pluralize(portfolio.positionCounts.shares, 'позиция', 'позиции', 'позиций'),
+ value: portfolio.totals.shares,
+ path: `${basePath}/shares`,
+ },
+ {
+ label: 'Облигации',
+ count: portfolio.positionCounts.bonds,
+ countLabel: pluralize(portfolio.positionCounts.bonds, 'выпуск', 'выпуска', 'выпусков'),
+ value: portfolio.totals.bonds,
+ path: `${basePath}/bonds`,
+ },
+ ];
+
+ return (
+
+ {cards.map((card) => (
+
+ {card.label}
+
+ {card.count} {card.countLabel}
+
+ {formatBrokerMoney(card.value)}
+
+ {formatAllocationPercent(allocationPercent(card.value, portfolio.totals.portfolio))}
+
+
+ ))}
+
+ );
+}
diff --git a/apps/frontend/src/widgets/broker-overview/ui/BrokerOverviewSkeleton.tsx b/apps/frontend/src/widgets/broker-overview/ui/BrokerOverviewSkeleton.tsx
new file mode 100644
index 0000000..984978a
--- /dev/null
+++ b/apps/frontend/src/widgets/broker-overview/ui/BrokerOverviewSkeleton.tsx
@@ -0,0 +1,30 @@
+import { SkeletonBlock } from '@/shared/ui/SkeletonBlock';
+
+export function BrokerOverviewSkeleton() {
+ return (
+
+
+ {[1, 2].map((item) => (
+
+
+
+
+
+ ))}
+
+
+
+
+
+
+ {[1, 2].map((item) => (
+
+
+
+
+
+ ))}
+
+
+ );
+}
diff --git a/apps/frontend/src/widgets/broker-overview/ui/BrokerSummary.tsx b/apps/frontend/src/widgets/broker-overview/ui/BrokerSummary.tsx
new file mode 100644
index 0000000..fd7dde4
--- /dev/null
+++ b/apps/frontend/src/widgets/broker-overview/ui/BrokerSummary.tsx
@@ -0,0 +1,36 @@
+import type { BrokerPortfolio } from '@/shared/api/responses';
+import {
+ formatBrokerMoney as formatMoney,
+ formatBrokerPercent as formatPercent,
+} from '@/shared/lib/formatters';
+
+export function BrokerSummary({ portfolio }: { portfolio: BrokerPortfolio }) {
+ return (
+
+
+ Стоимость портфеля
+
+ {formatMoney(portfolio.totals.portfolio)}
+
+ За день: {formatMoney(portfolio.yields.daily)}
+ Дневная доходность: {formatPercent(portfolio.yields.dailyPercent)}
+ Ожидаемая доходность: {formatPercent(portfolio.yields.expectedPercent)}
+
+
+
Денежный остаток
+ {portfolio.cash.length === 0 ? (
+
Нет денежных остатков
+ ) : (
+
+ {portfolio.cash.map((money, index) => (
+ -
+ {money.currency}
+ {formatMoney(money)}
+
+ ))}
+
+ )}
+
+
+ );
+}