- Delete shared/api/responses.ts, move type re-exports to index.ts - Update all 55+ imports from shared/api/responses to shared/api - Delete stale client.test.ts (tested deleted client.ts) - Run biome checks and fix import ordering - Update tasks.md and plan.md to reflect actual approach
274 lines
8.0 KiB
TypeScript
274 lines
8.0 KiB
TypeScript
import type { PositionWithPrice } from '@/shared/api'
|
||
import { BondPositionRow } from './BondPositionRow'
|
||
|
||
interface Props {
|
||
positions: PositionWithPrice[]
|
||
onUpdatePosition: (
|
||
positionId: number,
|
||
data: { quantity?: number; buyPrice?: number; buyDate?: string },
|
||
) => void
|
||
onDeletePosition: (positionId: number) => void
|
||
}
|
||
|
||
export function BondPositionTable({ positions, onUpdatePosition, onDeletePosition }: Props) {
|
||
if (positions.length === 0) return null
|
||
|
||
return (
|
||
<div style={{ marginTop: 24 }}>
|
||
<h3 style={{ margin: '0 0 12px', fontSize: 15, fontWeight: 600, color: 'var(--color-text)' }}>
|
||
Облигации
|
||
</h3>
|
||
<div style={{ overflowX: 'auto' }}>
|
||
<table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 14 }}>
|
||
<thead>
|
||
<tr style={{ borderBottom: '2px solid #e0e0e0' }}>
|
||
<th
|
||
style={{
|
||
textAlign: 'left',
|
||
padding: '8px 12px',
|
||
fontWeight: 600,
|
||
fontSize: 12,
|
||
color: 'var(--color-text-secondary)',
|
||
}}
|
||
>
|
||
Тикер
|
||
</th>
|
||
<th
|
||
style={{
|
||
textAlign: 'left',
|
||
padding: '8px 12px',
|
||
fontWeight: 600,
|
||
fontSize: 12,
|
||
color: 'var(--color-text-secondary)',
|
||
}}
|
||
>
|
||
Название
|
||
</th>
|
||
<th
|
||
style={{
|
||
textAlign: 'left',
|
||
padding: '8px 12px',
|
||
fontWeight: 600,
|
||
fontSize: 12,
|
||
color: 'var(--color-text-secondary)',
|
||
}}
|
||
>
|
||
Тип
|
||
</th>
|
||
<th
|
||
style={{
|
||
textAlign: 'left',
|
||
padding: '8px 12px',
|
||
fontWeight: 600,
|
||
fontSize: 12,
|
||
color: 'var(--color-text-secondary)',
|
||
}}
|
||
>
|
||
Количество
|
||
</th>
|
||
<th
|
||
style={{
|
||
textAlign: 'right',
|
||
padding: '8px 12px',
|
||
fontWeight: 600,
|
||
fontSize: 12,
|
||
color: 'var(--color-text-secondary)',
|
||
}}
|
||
>
|
||
Цена пок.
|
||
</th>
|
||
<th
|
||
style={{
|
||
textAlign: 'right',
|
||
padding: '8px 12px',
|
||
fontWeight: 600,
|
||
fontSize: 12,
|
||
color: 'var(--color-text-secondary)',
|
||
}}
|
||
>
|
||
Цена
|
||
</th>
|
||
<th
|
||
style={{
|
||
textAlign: 'right',
|
||
padding: '8px 12px',
|
||
fontWeight: 600,
|
||
fontSize: 12,
|
||
color: 'var(--color-text-secondary)',
|
||
}}
|
||
>
|
||
Бид
|
||
</th>
|
||
<th
|
||
style={{
|
||
textAlign: 'right',
|
||
padding: '8px 12px',
|
||
fontWeight: 600,
|
||
fontSize: 12,
|
||
color: 'var(--color-text-secondary)',
|
||
}}
|
||
>
|
||
Оффер
|
||
</th>
|
||
<th
|
||
style={{
|
||
textAlign: 'right',
|
||
padding: '8px 12px',
|
||
fontWeight: 600,
|
||
fontSize: 12,
|
||
color: 'var(--color-text-secondary)',
|
||
}}
|
||
>
|
||
Доходность
|
||
</th>
|
||
<th
|
||
style={{
|
||
textAlign: 'right',
|
||
padding: '8px 12px',
|
||
fontWeight: 600,
|
||
fontSize: 12,
|
||
color: 'var(--color-text-secondary)',
|
||
}}
|
||
>
|
||
Дюрация
|
||
</th>
|
||
<th
|
||
style={{
|
||
textAlign: 'right',
|
||
padding: '8px 12px',
|
||
fontWeight: 600,
|
||
fontSize: 12,
|
||
color: 'var(--color-text-secondary)',
|
||
}}
|
||
>
|
||
Купон
|
||
</th>
|
||
<th
|
||
style={{
|
||
textAlign: 'right',
|
||
padding: '8px 12px',
|
||
fontWeight: 600,
|
||
fontSize: 12,
|
||
color: 'var(--color-text-secondary)',
|
||
}}
|
||
>
|
||
Куп. %
|
||
</th>
|
||
<th
|
||
style={{
|
||
textAlign: 'right',
|
||
padding: '8px 12px',
|
||
fontWeight: 600,
|
||
fontSize: 12,
|
||
color: 'var(--color-text-secondary)',
|
||
}}
|
||
>
|
||
Период
|
||
</th>
|
||
<th
|
||
style={{
|
||
textAlign: 'right',
|
||
padding: '8px 12px',
|
||
fontWeight: 600,
|
||
fontSize: 12,
|
||
color: 'var(--color-text-secondary)',
|
||
}}
|
||
>
|
||
НКД
|
||
</th>
|
||
<th
|
||
style={{
|
||
textAlign: 'right',
|
||
padding: '8px 12px',
|
||
fontWeight: 600,
|
||
fontSize: 12,
|
||
color: 'var(--color-text-secondary)',
|
||
}}
|
||
>
|
||
Затраты
|
||
</th>
|
||
<th
|
||
style={{
|
||
textAlign: 'right',
|
||
padding: '8px 12px',
|
||
fontWeight: 600,
|
||
fontSize: 12,
|
||
color: 'var(--color-text-secondary)',
|
||
}}
|
||
>
|
||
P&L
|
||
</th>
|
||
<th
|
||
style={{
|
||
textAlign: 'right',
|
||
padding: '8px 12px',
|
||
fontWeight: 600,
|
||
fontSize: 12,
|
||
color: 'var(--color-text-secondary)',
|
||
}}
|
||
>
|
||
P&L %
|
||
</th>
|
||
<th
|
||
style={{
|
||
textAlign: 'right',
|
||
padding: '8px 12px',
|
||
fontWeight: 600,
|
||
fontSize: 12,
|
||
color: 'var(--color-text-secondary)',
|
||
}}
|
||
>
|
||
След. купон
|
||
</th>
|
||
<th
|
||
style={{
|
||
textAlign: 'right',
|
||
padding: '8px 12px',
|
||
fontWeight: 600,
|
||
fontSize: 12,
|
||
color: 'var(--color-text-secondary)',
|
||
}}
|
||
>
|
||
Погашение
|
||
</th>
|
||
<th
|
||
style={{
|
||
textAlign: 'right',
|
||
padding: '8px 12px',
|
||
fontWeight: 600,
|
||
fontSize: 12,
|
||
color: 'var(--color-text-secondary)',
|
||
}}
|
||
>
|
||
Оферта
|
||
</th>
|
||
<th
|
||
style={{
|
||
textAlign: 'right',
|
||
padding: '8px 12px',
|
||
fontWeight: 600,
|
||
fontSize: 12,
|
||
color: 'var(--color-text-secondary)',
|
||
}}
|
||
>
|
||
Доля
|
||
</th>
|
||
<th style={{ padding: '8px 12px', width: 40 }}></th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
{positions.map((pos) => (
|
||
<BondPositionRow
|
||
key={pos.id}
|
||
position={pos}
|
||
onUpdate={(data) => onUpdatePosition(pos.id, data)}
|
||
onDelete={() => onDeletePosition(pos.id)}
|
||
/>
|
||
))}
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
)
|
||
}
|