feat: make ticker clickable on positions page — links to company detail
Ticker column now links to /companies/{id} using a ticker→company ID
lookup. Falls back to plain text if company not found.
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
import { usePositions } from '../api/hooks';
|
import { Link } from '@tanstack/react-router';
|
||||||
|
import { usePositions, useCompanies } from '../api/hooks';
|
||||||
import { DataTable, type Column } from '../components/DataTable';
|
import { DataTable, type Column } from '../components/DataTable';
|
||||||
import { LoadingSpinner } from '../components/ui';
|
import { LoadingSpinner } from '../components/ui';
|
||||||
import type { Position } from '../api/hooks';
|
import type { Position } from '../api/hooks';
|
||||||
@@ -25,6 +26,36 @@ const columns: Column<Position>[] = [
|
|||||||
|
|
||||||
export function PositionsPage() {
|
export function PositionsPage() {
|
||||||
const { data, isLoading } = usePositions();
|
const { data, isLoading } = usePositions();
|
||||||
|
const { data: companies } = useCompanies();
|
||||||
|
|
||||||
|
// Build ticker → company ID lookup
|
||||||
|
const tickerToId: Record<string, string> = {};
|
||||||
|
for (const c of companies ?? []) {
|
||||||
|
tickerToId[c.ticker] = c.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
const posColumns: Column<Position>[] = [
|
||||||
|
{
|
||||||
|
key: 'ticker',
|
||||||
|
header: 'Ticker',
|
||||||
|
render: (r) => {
|
||||||
|
const companyId = tickerToId[r.ticker];
|
||||||
|
return companyId ? (
|
||||||
|
<Link to="/companies/$id" params={{ id: companyId }} className="font-mono font-semibold text-brand-300 hover:underline">
|
||||||
|
{r.ticker}
|
||||||
|
</Link>
|
||||||
|
) : (
|
||||||
|
<span className="font-mono font-semibold text-brand-300">{r.ticker}</span>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ key: 'quantity', header: 'Qty' },
|
||||||
|
{ key: 'avg_entry_price', header: 'Entry', render: (r) => <span>{fmtUsd(r.avg_entry_price)}</span> },
|
||||||
|
{ key: 'current_price', header: 'Current', render: (r) => <span>{fmtUsd(r.current_price)}</span> },
|
||||||
|
{ key: 'unrealized_pnl', header: 'Unrealized P&L', render: (r) => <span className={pnlColor(r.unrealized_pnl)}>{fmtUsd(r.unrealized_pnl)}</span> },
|
||||||
|
{ key: 'realized_pnl', header: 'Realized P&L', render: (r) => <span className={pnlColor(r.realized_pnl)}>{fmtUsd(r.realized_pnl)}</span> },
|
||||||
|
{ key: 'updated_at', header: 'Updated', render: (r) => <span className="text-xs">{new Date(r.updated_at).toLocaleString()}</span> },
|
||||||
|
];
|
||||||
|
|
||||||
if (isLoading) return <LoadingSpinner />;
|
if (isLoading) return <LoadingSpinner />;
|
||||||
|
|
||||||
@@ -58,7 +89,7 @@ export function PositionsPage() {
|
|||||||
<h1 className="mb-4 text-xl font-semibold text-gray-100">Positions</h1>
|
<h1 className="mb-4 text-xl font-semibold text-gray-100">Positions</h1>
|
||||||
<DataTable<Position>
|
<DataTable<Position>
|
||||||
data={positions}
|
data={positions}
|
||||||
columns={columns}
|
columns={posColumns}
|
||||||
keyField="id"
|
keyField="id"
|
||||||
footerRow={footer}
|
footerRow={footer}
|
||||||
/>
|
/>
|
||||||
|
|||||||
Reference in New Issue
Block a user