feat: make ticker clickable on positions page — links to company detail
ci/woodpecker/push/test Pipeline was successful
ci/woodpecker/push/build-3 Pipeline failed
ci/woodpecker/push/build-1 Pipeline was successful
ci/woodpecker/push/build-2 Pipeline was successful
ci/woodpecker/push/finalize unknown status
Build and Push / lint-and-test (push) Has been cancelled
Build and Push / build-services (map[cmd:python -m services.adapters.broker_adapter name:broker-adapter]) (push) Has been cancelled
Build and Push / build-services (map[cmd:python -m services.aggregation.worker name:aggregation]) (push) Has been cancelled
Build and Push / build-services (map[cmd:python -m services.extractor.worker name:extractor]) (push) Has been cancelled
Build and Push / build-services (map[cmd:python -m services.ingestion.worker name:ingestion]) (push) Has been cancelled
Build and Push / build-services (map[cmd:python -m services.lake_publisher.worker name:lake-publisher]) (push) Has been cancelled
Build and Push / build-services (map[cmd:python -m services.parser.worker name:parser]) (push) Has been cancelled
Build and Push / build-services (map[cmd:python -m services.recommendation.worker name:recommendation]) (push) Has been cancelled
Build and Push / build-services (map[cmd:python -m services.scheduler.app name:scheduler]) (push) Has been cancelled
Build and Push / build-services (map[cmd:uvicorn services.api.app:app --host 0.0.0.0 --port 8000 name:query-api]) (push) Has been cancelled
Build and Push / build-services (map[cmd:uvicorn services.risk.app:app --host 0.0.0.0 --port 8000 name:risk]) (push) Has been cancelled
Build and Push / build-services (map[cmd:uvicorn services.symbol_registry.app:app --host 0.0.0.0 --port 8000 name:symbol-registry]) (push) Has been cancelled
Build and Push / build-services (map[cmd:uvicorn services.trading.app:app --host 0.0.0.0 --port 8000 name:trading-engine]) (push) Has been cancelled
Build and Push / build-dashboard (push) Has been cancelled
Build and Push / build-superset (push) Has been cancelled
Build and Push / integration-test (push) Has been cancelled
Build and Push / beta-gate (push) Has been cancelled
ci/woodpecker/push/test Pipeline was successful
ci/woodpecker/push/build-3 Pipeline failed
ci/woodpecker/push/build-1 Pipeline was successful
ci/woodpecker/push/build-2 Pipeline was successful
ci/woodpecker/push/finalize unknown status
Build and Push / lint-and-test (push) Has been cancelled
Build and Push / build-services (map[cmd:python -m services.adapters.broker_adapter name:broker-adapter]) (push) Has been cancelled
Build and Push / build-services (map[cmd:python -m services.aggregation.worker name:aggregation]) (push) Has been cancelled
Build and Push / build-services (map[cmd:python -m services.extractor.worker name:extractor]) (push) Has been cancelled
Build and Push / build-services (map[cmd:python -m services.ingestion.worker name:ingestion]) (push) Has been cancelled
Build and Push / build-services (map[cmd:python -m services.lake_publisher.worker name:lake-publisher]) (push) Has been cancelled
Build and Push / build-services (map[cmd:python -m services.parser.worker name:parser]) (push) Has been cancelled
Build and Push / build-services (map[cmd:python -m services.recommendation.worker name:recommendation]) (push) Has been cancelled
Build and Push / build-services (map[cmd:python -m services.scheduler.app name:scheduler]) (push) Has been cancelled
Build and Push / build-services (map[cmd:uvicorn services.api.app:app --host 0.0.0.0 --port 8000 name:query-api]) (push) Has been cancelled
Build and Push / build-services (map[cmd:uvicorn services.risk.app:app --host 0.0.0.0 --port 8000 name:risk]) (push) Has been cancelled
Build and Push / build-services (map[cmd:uvicorn services.symbol_registry.app:app --host 0.0.0.0 --port 8000 name:symbol-registry]) (push) Has been cancelled
Build and Push / build-services (map[cmd:uvicorn services.trading.app:app --host 0.0.0.0 --port 8000 name:trading-engine]) (push) Has been cancelled
Build and Push / build-dashboard (push) Has been cancelled
Build and Push / build-superset (push) Has been cancelled
Build and Push / integration-test (push) Has been cancelled
Build and Push / beta-gate (push) Has been cancelled
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