Files
zeekay e0ec477433 feat: full docs modernization — zero 404s, 585 pages, dep updates
- Enable all 15 finance component docs (from .disabled → .mdx)
- Create stock-market.mdx, 8 chart docs, 8 block docs, 2 framework docs
- Add direction.tsx component (RTL/LTR support from upstream shadcn)
- Add xs/icon-xs button sizes, data-variant/data-size attributes
- Fix build-registry.mts to handle default exports in namespace re-exports
- Add default props to order-entry, positions-list, orders-history, trading-panel
- Fix 18 navigation stubs → re-export from root implementations
- Add 44 orphaned MDX files to nav (installation, dark-mode, desktop, guides, etc)
- Migrate 6 framer-motion imports → motion/react
- Bump React 19.2.0→19.2.4, Next.js 16.0.1→16.1.6, motion→12.34.0
- Align lucide-react, sonner v2, tailwind-merge v3, postcss-selector-parser v7
- Remove framer-motion dep (superseded by motion)
- Fix @types/react-dom, TypeScript versions across workspaces
2026-03-03 07:34:51 -08:00

108 lines
3.4 KiB
TypeScript

"use client"
import { TrendingDown, TrendingUp } from "lucide-react"
export interface Position {
symbol: string
shares: number
avgPrice: number
currentPrice: number
}
export interface PositionsListProps {
positions: Position[]
onPositionClick?: (position: Position) => void
}
export function PositionsList({
positions = [],
onPositionClick,
}: Partial<PositionsListProps>) {
const getTickerFromSymbol = (symbol: string) => {
return symbol.split(":")[1] || symbol
}
if (positions.length === 0) {
return (
<div className="p-4 text-center py-8 text-white/40">
<p className="text-sm">No open positions</p>
</div>
)
}
return (
<div className="p-4 space-y-2">
{positions.map((position) => {
const pl = (position.currentPrice - position.avgPrice) * position.shares
const plPercent =
((position.currentPrice - position.avgPrice) / position.avgPrice) *
100
const totalValue = position.currentPrice * position.shares
return (
<div
key={position.symbol}
className={`bg-white/5 rounded-lg p-3 ${onPositionClick ? "cursor-pointer hover:bg-white/10 transition-colors" : ""}`}
onClick={() => onPositionClick?.(position)}
>
<div className="flex items-center justify-between mb-2">
<div className="font-semibold text-white">
{getTickerFromSymbol(position.symbol)}
</div>
<div
className={`flex items-center gap-1 text-sm ${pl >= 0 ? "text-success" : "text-danger"}`}
>
{pl >= 0 ? (
<TrendingUp size={14} />
) : (
<TrendingDown size={14} />
)}
{pl >= 0 ? "+" : ""}
{plPercent.toFixed(2)}%
</div>
</div>
<div className="grid grid-cols-2 gap-2 text-xs">
<div>
<div className="text-white/60">Shares</div>
<div className="text-white font-medium">{position.shares}</div>
</div>
<div>
<div className="text-white/60">Avg Price</div>
<div className="text-white font-medium">
${position.avgPrice.toFixed(2)}
</div>
</div>
</div>
<div className="grid grid-cols-2 gap-2 text-xs mt-2 pt-2 border-t border-white/10">
<div>
<div className="text-white/60">Current Price</div>
<div className="text-white font-medium">
${position.currentPrice.toFixed(2)}
</div>
</div>
<div>
<div className="text-white/60">Total Value</div>
<div className="text-white font-medium">
${totalValue.toFixed(2)}
</div>
</div>
</div>
<div className="mt-2 pt-2 border-t border-white/10">
<div className="flex justify-between items-center text-xs">
<span className="text-white/60">P&L</span>
<span
className={`font-semibold ${pl >= 0 ? "text-success" : "text-danger"}`}
>
{pl >= 0 ? "+" : ""}${pl.toFixed(2)}
</span>
</div>
</div>
</div>
)
})}
</div>
)
}
export default PositionsList