Add LICENSE, README, and Docs tab to Mission Control

This commit is contained in:
root
2026-02-22 07:33:18 +00:00
parent 3e7b457d5f
commit 0817444dc5
68 changed files with 6677 additions and 1673 deletions
+341
View File
@@ -0,0 +1,341 @@
'use client'
import { useState, useEffect } from 'react'
import { TradingChart } from './TradingChart'
type TradingTab = 'research' | 'strategies' | 'execution' | 'journal'
interface Trader {
id: string
name: string
status: 'learning' | 'active' | 'paused'
framesAnalyzed: number
patterns: string[]
entryRules: string[]
exitRules: string[]
indicators: string[]
riskParams: string[]
}
interface Trade {
id: string
trader: string
pair: string
direction: 'long' | 'short'
entryPrice: number
exitPrice?: number
status: 'open' | 'closed' | 'cancelled'
pnl?: number
pnlPercent?: number
reason: string
setup: string
timeframe: string
openedAt: string
closedAt?: string
notes: string
isDemo: boolean
}
const defaultTraders: Trader[] = [
{
id: 'dopetrades',
name: 'DopeTrades',
status: 'learning',
framesAnalyzed: 0,
patterns: [],
entryRules: [],
exitRules: [],
indicators: [],
riskParams: []
}
]
export function TradingPanel() {
const [activeTab, setActiveTab] = useState<TradingTab>('research')
const [traders, setTraders] = useState<Trader[]>(defaultTraders)
const [selectedTrader, setSelectedTrader] = useState<string>('dopetrades')
const [trades, setTrades] = useState<Trade[]>([])
const [journalFilter, setJournalFilter] = useState<'all' | 'demo' | 'real'>('all')
// Load data
useEffect(() => {
loadTraders()
loadTrades()
}, [])
const loadTraders = async () => {
try {
const res = await fetch('/api/trading/traders')
if (res.ok) {
const data = await res.json()
if (data.traders?.length > 0) setTraders(data.traders)
}
} catch (e) {}
}
const loadTrades = async () => {
try {
const res = await fetch('/api/trading/trades')
if (res.ok) {
const data = await res.json()
if (data.trades) setTrades(data.trades)
}
} catch (e) {}
}
const tabs = [
{ id: 'research', label: '🔬 Deep Research', count: traders.filter(t => t.status === 'learning').length },
{ id: 'strategies', label: '🎯 Strategies', count: traders.filter(t => t.status === 'active').length },
{ id: 'execution', label: '⚡ Execution', count: trades.filter(t => t.status === 'open').length },
{ id: 'journal', label: '📔 Journal', count: trades.length },
]
const filteredTrades = trades.filter(t => {
if (journalFilter === 'all') return true
if (journalFilter === 'demo') return t.isDemo
return !t.isDemo
})
const openTrades = trades.filter(t => t.status === 'open')
const closedDemoTrades = trades.filter(t => t.status === 'closed' && t.isDemo)
const closedRealTrades = trades.filter(t => t.status === 'closed' && !t.isDemo)
const totalPnl = closedRealTrades.reduce((sum, t) => sum + (t.pnl || 0), 0)
const winRate = closedRealTrades.length > 0
? Math.round((closedRealTrades.filter(t => (t.pnl || 0) > 0).length / closedRealTrades.length) * 100)
: 0
return (
<div className="space-y-4">
{/* Tab Navigation */}
<div className="flex gap-2 flex-wrap">
{tabs.map(tab => (
<button
key={tab.id}
onClick={() => setActiveTab(tab.id as TradingTab)}
className={`px-4 py-2 rounded-lg text-sm font-medium transition ${
activeTab === tab.id
? 'bg-brand-pink text-white'
: 'bg-white/10 text-white/70 hover:bg-white/20'
}`}
>
{tab.label}
<span className="ml-2 text-xs opacity-70">({tab.count})</span>
</button>
))}
</div>
{/* Research Tab */}
{activeTab === 'research' && (
<div className="border border-white/20 rounded-lg p-4 bg-white/5">
<h3 className="text-lg font-bold mb-4">🔬 Deep Research</h3>
<p className="text-white/60 mb-4">Learn trading strategies from experts by analyzing their content.</p>
<div className="space-y-3">
{traders.map(trader => (
<div
key={trader.id}
className="p-4 rounded-lg bg-white/5 border border-white/10"
>
<div className="flex items-center justify-between mb-2">
<div className="flex items-center gap-3">
<span className="text-2xl">👨🏫</span>
<div>
<p className="font-medium">{trader.name}</p>
<p className="text-xs text-white/50">{trader.framesAnalyzed} frames analyzed</p>
</div>
</div>
<span className={`px-2 py-1 rounded text-xs ${
trader.status === 'learning' ? 'bg-yellow-500/20 text-yellow-400' :
trader.status === 'active' ? 'bg-green-500/20 text-green-400' :
'bg-white/10 text-white/50'
}`}>
{trader.status}
</span>
</div>
{trader.patterns.length > 0 && (
<div className="mt-2 flex flex-wrap gap-1">
{trader.patterns.map(p => (
<span key={p} className="px-2 py-0.5 bg-white/10 rounded text-xs">{p}</span>
))}
</div>
)}
<button className="mt-3 text-sm text-brand-pink hover:underline">
View full analysis
</button>
</div>
))}
</div>
<button className="mt-4 w-full py-2 border border-dashed border-white/20 rounded-lg text-white/50 hover:border-white/40 hover:text-white transition">
+ Add new trader to research
</button>
</div>
)}
{/* Strategies Tab */}
{activeTab === 'strategies' && (
<div className="border border-white/20 rounded-lg p-4 bg-white/5">
<h3 className="text-lg font-bold mb-4">🎯 Trading Strategies</h3>
<p className="text-white/60 mb-4">Select a trader style to follow for your next trade.</p>
<div className="flex gap-2 flex-wrap mb-4">
{traders.filter(t => t.status === 'active').map(trader => (
<button
key={trader.id}
onClick={() => setSelectedTrader(trader.id)}
className={`px-4 py-2 rounded-lg text-sm font-medium transition ${
selectedTrader === trader.id
? 'bg-brand-pink text-white'
: 'bg-white/10 text-white/70 hover:bg-white/20'
}`}
>
{trader.name}
</button>
))}
</div>
{traders.find(t => t.id === selectedTrader) && (
<div className="p-4 rounded-lg bg-black/30 border border-white/10">
<h4 className="font-medium mb-3">{traders.find(t => t.id === selectedTrader)?.name} Strategy</h4>
<div className="space-y-3 text-sm">
<div>
<p className="text-white/50 text-xs mb-1">Entry Rules</p>
<ul className="list-disc list-inside space-y-1">
{traders.find(t => t.id === selectedTrader)?.entryRules.map(r => (
<li key={r}>{r}</li>
))}
</ul>
{traders.find(t => t.id === selectedTrader)?.entryRules.length === 0 && (
<p className="text-white/30 italic">No entry rules defined yet</p>
)}
</div>
<div>
<p className="text-white/50 text-xs mb-1">Exit Rules</p>
<ul className="list-disc list-inside space-y-1">
{traders.find(t => t.id === selectedTrader)?.exitRules.map(r => (
<li key={r}>{r}</li>
))}
</ul>
</div>
<div>
<p className="text-white/50 text-xs mb-1">Indicators</p>
<div className="flex flex-wrap gap-1">
{traders.find(t => t.id === selectedTrader)?.indicators.map(i => (
<span key={i} className="px-2 py-0.5 bg-blue-500/20 text-blue-400 rounded text-xs">{i}</span>
))}
</div>
</div>
<div>
<p className="text-white/50 text-xs mb-1">Risk Parameters</p>
<ul className="list-disc list-inside space-y-1">
{traders.find(t => t.id === selectedTrader)?.riskParams.map(r => (
<li key={r}>{r}</li>
))}
</ul>
</div>
</div>
<button className="mt-4 w-full py-2 bg-brand-pink rounded-lg font-medium hover:bg-[#ff7bc0] transition">
Execute Trade in {traders.find(t => t.id === selectedTrader)?.name} Style
</button>
</div>
)}
</div>
)}
{/* Execution Tab */}
{activeTab === 'execution' && (
<TradingChart />
)}
{/* Journal Tab */}
{activeTab === 'journal' && (
<div className="border border-white/20 rounded-lg p-4 bg-white/5">
<h3 className="text-lg font-bold mb-4">📔 Trading Journal</h3>
{/* Stats */}
<div className="grid grid-cols-3 gap-3 mb-4">
<div className="p-3 rounded bg-white/5 text-center">
<p className="text-2xl font-bold text-green-400">${totalPnl.toFixed(2)}</p>
<p className="text-xs text-white/50">Real P&L</p>
</div>
<div className="p-3 rounded bg-white/5 text-center">
<p className="text-2xl font-bold">{winRate}%</p>
<p className="text-xs text-white/50">Win Rate</p>
</div>
<div className="p-3 rounded bg-white/5 text-center">
<p className="text-2xl font-bold">{closedRealTrades.length}</p>
<p className="text-xs text-white/50">Real Trades</p>
</div>
</div>
{/* Filter */}
<div className="flex gap-2 mb-4">
{(['all', 'demo', 'real'] as const).map(filter => (
<button
key={filter}
onClick={() => setJournalFilter(filter)}
className={`px-3 py-1 rounded text-xs ${
journalFilter === filter
? 'bg-brand-pink text-white'
: 'bg-white/10 text-white/60'
}`}
>
{filter === 'all' ? 'All' : filter === 'demo' ? 'Demo' : 'Real'}
</button>
))}
</div>
{/* Trades List */}
<div className="space-y-2 max-h-[400px] overflow-y-auto">
{filteredTrades.length === 0 ? (
<p className="text-white/40 text-center py-4">No trades yet</p>
) : (
filteredTrades.map(trade => (
<div
key={trade.id}
className={`p-3 rounded border ${
trade.isDemo
? 'bg-white/5 border-white/10'
: trade.status === 'open'
? 'bg-yellow-500/10 border-yellow-500/30'
: (trade.pnl || 0) > 0
? 'bg-green-500/10 border-green-500/30'
: 'bg-red-500/10 border-red-500/30'
}`}
>
<div className="flex justify-between items-start">
<div>
<span className="font-medium">{trade.pair}</span>
<span className={`ml-2 text-xs px-1.5 py-0.5 rounded ${
trade.direction === 'long' ? 'bg-green-500/20 text-green-400' : 'bg-red-500/20 text-red-400'
}`}>
{trade.direction.toUpperCase()}
</span>
{trade.isDemo && <span className="ml-1 text-xs text-white/40">(Demo)</span>}
</div>
{trade.status === 'closed' && (
<span className={`font-bold ${(trade.pnl || 0) >= 0 ? 'text-green-400' : 'text-red-400'}`}>
{trade.pnl >= 0 ? '+' : ''}{trade.pnl?.toFixed(2)} ({trade.pnlPercent?.toFixed(1)}%)
</span>
)}
</div>
<p className="text-xs text-white/50 mt-1">{trade.setup}</p>
<div className="flex gap-4 mt-2 text-xs text-white/40">
<span>{trade.timeframe}</span>
<span>{new Date(trade.openedAt).toLocaleDateString()}</span>
</div>
</div>
))
)}
</div>
</div>
)}
</div>
)
}