Updated event bet page.
This commit is contained in:
@ -13,6 +13,8 @@ import {
|
||||
Target,
|
||||
TrendingUp,
|
||||
TrendingDown,
|
||||
BarChart3,
|
||||
Grid3X3,
|
||||
} from 'lucide-react'
|
||||
import toast from 'react-hot-toast'
|
||||
|
||||
@ -48,6 +50,7 @@ export const TradingPanel = ({ event, onBetCreated, onBetTaken }: TradingPanelPr
|
||||
const [selectedSide, setSelectedSide] = useState<'home' | 'away'>('home')
|
||||
const [selectedSpread, setSelectedSpread] = useState(event.official_spread)
|
||||
const [stakeAmount, setStakeAmount] = useState('')
|
||||
const [activeTab, setActiveTab] = useState<'chart' | 'grid'>('chart')
|
||||
|
||||
// Update countdown every second
|
||||
useEffect(() => {
|
||||
@ -80,35 +83,32 @@ export const TradingPanel = ({ event, onBetCreated, onBetTaken }: TradingPanelPr
|
||||
return { totalVolume, totalBets, openBets, matchedBets, homeVolume, awayVolume }
|
||||
}, [event.spread_grid])
|
||||
|
||||
// Get sorted spreads for order book
|
||||
const sortedSpreads = useMemo(() => {
|
||||
return Object.keys(event.spread_grid)
|
||||
.map(Number)
|
||||
.sort((a, b) => b - a) // High to low
|
||||
}, [event.spread_grid])
|
||||
|
||||
// Split spreads at official line for order book
|
||||
const { aboveLine, belowLine, maxVolume } = useMemo(() => {
|
||||
const above: number[] = []
|
||||
const below: number[] = []
|
||||
// Calculate max volume across all spreads for order book bars
|
||||
const maxVolume = useMemo(() => {
|
||||
let max = 0
|
||||
|
||||
sortedSpreads.forEach(spread => {
|
||||
const bets = event.spread_grid[spread.toString()] || []
|
||||
Object.values(event.spread_grid).forEach(bets => {
|
||||
const vol = bets.reduce((sum, b) => sum + b.stake, 0)
|
||||
if (vol > max) max = vol
|
||||
|
||||
if (spread > event.official_spread) above.push(spread)
|
||||
else if (spread < event.official_spread) below.push(spread)
|
||||
})
|
||||
return max
|
||||
}, [event.spread_grid])
|
||||
|
||||
// Add official line to both for display
|
||||
return {
|
||||
aboveLine: above.sort((a, b) => a - b), // Low to high (closest to line at bottom)
|
||||
belowLine: below.sort((a, b) => b - a), // High to low (closest to line at top)
|
||||
maxVolume: max
|
||||
// Generate ALL spreads from min to max, split at official line for order book
|
||||
const { aboveLine, belowLine } = useMemo(() => {
|
||||
const above: number[] = []
|
||||
const below: number[] = []
|
||||
|
||||
// Generate all possible spreads in range
|
||||
for (let s = event.min_spread; s <= event.max_spread; s += 0.5) {
|
||||
if (s > event.official_spread) above.push(s)
|
||||
else if (s < event.official_spread) below.push(s)
|
||||
}
|
||||
}, [sortedSpreads, event.spread_grid, event.official_spread])
|
||||
|
||||
return {
|
||||
aboveLine: above.sort((a, b) => b - a), // High to low (highest at top)
|
||||
belowLine: below.sort((a, b) => b - a), // High to low (closest to line at top)
|
||||
}
|
||||
}, [event.min_spread, event.max_spread, event.official_spread])
|
||||
|
||||
// Get all bets for chart and recent activity (including matched)
|
||||
const allBetsWithSpread = useMemo(() => {
|
||||
@ -121,9 +121,9 @@ export const TradingPanel = ({ event, onBetCreated, onBetTaken }: TradingPanelPr
|
||||
return bets
|
||||
}, [event.spread_grid])
|
||||
|
||||
// Recent activity - all bets sorted by recency (we don't have timestamps, so just show all)
|
||||
// Recent activity - all bets
|
||||
const recentActivity = useMemo(() => {
|
||||
return allBetsWithSpread.slice(0, 15) // Show last 15
|
||||
return allBetsWithSpread
|
||||
}, [allBetsWithSpread])
|
||||
|
||||
// Chart data - volume per spread
|
||||
@ -265,6 +265,50 @@ export const TradingPanel = ({ event, onBetCreated, onBetTaken }: TradingPanelPr
|
||||
)
|
||||
}
|
||||
|
||||
// Grid view - shows all spreads in a grid format
|
||||
const renderGridView = () => {
|
||||
const spreads: number[] = []
|
||||
for (let s = event.min_spread; s <= event.max_spread; s += 0.5) {
|
||||
spreads.push(s)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="grid grid-cols-4 sm:grid-cols-6 md:grid-cols-8 lg:grid-cols-10 gap-2">
|
||||
{spreads.map(spread => {
|
||||
const bets = event.spread_grid[spread.toString()] || []
|
||||
const homeBets = bets.filter(b => b.team === 'home')
|
||||
const awayBets = bets.filter(b => b.team === 'away')
|
||||
const homeVolume = homeBets.reduce((sum, b) => sum + b.stake, 0)
|
||||
const awayVolume = awayBets.reduce((sum, b) => sum + b.stake, 0)
|
||||
const totalBets = bets.length
|
||||
const isOfficial = spread === event.official_spread
|
||||
|
||||
return (
|
||||
<button
|
||||
key={spread}
|
||||
onClick={() => setSelectedSpread(spread)}
|
||||
className={`
|
||||
p-3 rounded-lg border transition-all text-center
|
||||
${selectedSpread === spread ? 'ring-2 ring-blue-500 border-blue-500' : 'border-gray-200 hover:border-gray-300'}
|
||||
${isOfficial ? 'bg-yellow-50 border-yellow-400' : 'bg-white'}
|
||||
`}
|
||||
>
|
||||
<div className={`text-sm font-bold ${isOfficial ? 'text-yellow-600' : 'text-gray-900'}`}>
|
||||
{spread > 0 ? '+' : ''}{spread}
|
||||
</div>
|
||||
<div className="text-xs text-gray-500 mt-1">{totalBets} bets</div>
|
||||
<div className="flex justify-center gap-2 mt-1 text-xs">
|
||||
<span className="text-green-600">${homeVolume}</span>
|
||||
<span className="text-gray-300">|</span>
|
||||
<span className="text-red-600">${awayVolume}</span>
|
||||
</div>
|
||||
</button>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="bg-white rounded-xl shadow-sm border overflow-hidden">
|
||||
{/* Header - Event Info */}
|
||||
@ -352,17 +396,19 @@ export const TradingPanel = ({ event, onBetCreated, onBetTaken }: TradingPanelPr
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Main Content */}
|
||||
<div className="grid grid-cols-12 divide-x divide-gray-200">
|
||||
{/* Main Content - fixed height container */}
|
||||
<div className="grid grid-cols-12 divide-x divide-gray-200 h-[600px] overflow-hidden">
|
||||
{/* Left - Order Book */}
|
||||
<div className="col-span-3 p-4">
|
||||
<h3 className="font-semibold text-gray-900 mb-3 flex items-center gap-2">
|
||||
<Activity size={16} className="text-gray-400" />
|
||||
Order Book
|
||||
</h3>
|
||||
<div className="col-span-3 flex flex-col overflow-hidden">
|
||||
<div className="p-4 pb-2">
|
||||
<h3 className="font-semibold text-gray-900 flex items-center gap-2">
|
||||
<Activity size={16} className="text-gray-400" />
|
||||
Order Book
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
{/* Header */}
|
||||
<div className="grid grid-cols-7 gap-1 py-2 px-2 text-xs text-gray-500 border-b mb-1">
|
||||
<div className="grid grid-cols-7 gap-1 py-2 px-4 text-xs text-gray-500 border-b">
|
||||
<span className="text-right">{event.away_team.slice(0, 4)}</span>
|
||||
<span className="text-right">Vol</span>
|
||||
<span></span>
|
||||
@ -372,122 +418,187 @@ export const TradingPanel = ({ event, onBetCreated, onBetTaken }: TradingPanelPr
|
||||
<span className="text-left">{event.home_team.slice(0, 4)}</span>
|
||||
</div>
|
||||
|
||||
{/* Above official line (away favored) */}
|
||||
<div className="max-h-32 overflow-y-auto border-b border-gray-100">
|
||||
{aboveLine.map(spread => renderOrderRow(spread))}
|
||||
{/* Above official line - fills available space */}
|
||||
<div className="flex-1 overflow-y-auto border-b border-gray-100 px-2">
|
||||
{aboveLine.length > 0 ? (
|
||||
aboveLine.map(spread => renderOrderRow(spread))
|
||||
) : (
|
||||
<div className="flex items-center justify-center h-full text-gray-400 text-xs">
|
||||
No spreads above line
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Official Line */}
|
||||
<div className="bg-yellow-50 border-y-2 border-yellow-400">
|
||||
<div className="bg-yellow-50 border-y-2 border-yellow-400 px-2 flex-shrink-0">
|
||||
{renderOrderRow(event.official_spread)}
|
||||
</div>
|
||||
|
||||
{/* Below official line (home favored) */}
|
||||
<div className="max-h-32 overflow-y-auto">
|
||||
{belowLine.map(spread => renderOrderRow(spread))}
|
||||
{/* Below official line - fills available space */}
|
||||
<div className="flex-1 overflow-y-auto px-2">
|
||||
{belowLine.length > 0 ? (
|
||||
belowLine.map(spread => renderOrderRow(spread))
|
||||
) : (
|
||||
<div className="flex items-center justify-center h-full text-gray-400 text-xs">
|
||||
No spreads below line
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Center - Volume Chart */}
|
||||
<div className="col-span-6 p-4">
|
||||
<h3 className="font-semibold text-gray-900 mb-3">Market Depth</h3>
|
||||
|
||||
{/* Chart */}
|
||||
<div className="h-48 flex items-end gap-px relative bg-gray-50 rounded-lg p-2">
|
||||
{/* Official line indicator */}
|
||||
<div
|
||||
className="absolute top-0 bottom-0 w-0.5 bg-yellow-500 z-10"
|
||||
style={{
|
||||
left: `${((event.official_spread - event.min_spread) / (event.max_spread - event.min_spread)) * 100}%`
|
||||
}}
|
||||
{/* Center - Chart/Grid with Tabs */}
|
||||
<div className="col-span-6 flex flex-col overflow-hidden">
|
||||
{/* Tabs */}
|
||||
<div className="flex border-b">
|
||||
<button
|
||||
onClick={() => setActiveTab('chart')}
|
||||
className={`flex items-center gap-2 px-4 py-3 text-sm font-medium border-b-2 transition-colors ${
|
||||
activeTab === 'chart'
|
||||
? 'border-blue-500 text-blue-600'
|
||||
: 'border-transparent text-gray-500 hover:text-gray-700'
|
||||
}`}
|
||||
>
|
||||
<div className="absolute -top-1 left-1/2 -translate-x-1/2 bg-yellow-500 text-white text-xs px-1 rounded">
|
||||
{event.official_spread > 0 ? '+' : ''}{event.official_spread}
|
||||
</div>
|
||||
</div>
|
||||
<BarChart3 size={16} />
|
||||
Chart
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setActiveTab('grid')}
|
||||
className={`flex items-center gap-2 px-4 py-3 text-sm font-medium border-b-2 transition-colors ${
|
||||
activeTab === 'grid'
|
||||
? 'border-blue-500 text-blue-600'
|
||||
: 'border-transparent text-gray-500 hover:text-gray-700'
|
||||
}`}
|
||||
>
|
||||
<Grid3X3 size={16} />
|
||||
Grid
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{chartData.map((d) => (
|
||||
<div
|
||||
key={d.spread}
|
||||
className="flex-1 flex flex-col justify-end cursor-pointer group"
|
||||
onClick={() => setSelectedSpread(d.spread)}
|
||||
>
|
||||
{/* Away volume (red, on top) */}
|
||||
<div
|
||||
className={`w-full bg-red-400 hover:bg-red-500 transition-colors ${
|
||||
d.spread === selectedSpread ? 'ring-2 ring-blue-500' : ''
|
||||
}`}
|
||||
style={{ height: `${(d.awayVolume / chartMaxVolume) * 100}%`, minHeight: d.awayVolume > 0 ? '2px' : '0' }}
|
||||
/>
|
||||
{/* Home volume (green, on bottom) */}
|
||||
<div
|
||||
className={`w-full bg-green-400 hover:bg-green-500 transition-colors ${
|
||||
d.spread === selectedSpread ? 'ring-2 ring-blue-500' : ''
|
||||
}`}
|
||||
style={{ height: `${(d.homeVolume / chartMaxVolume) * 100}%`, minHeight: d.homeVolume > 0 ? '2px' : '0' }}
|
||||
/>
|
||||
{/* Tab Content */}
|
||||
<div className="flex-1 flex flex-col overflow-hidden p-4 min-h-0">
|
||||
{activeTab === 'chart' ? (
|
||||
<div className="flex flex-col h-full min-h-0">
|
||||
{/* Chart Section */}
|
||||
<div className="flex-1 flex flex-col min-h-0">
|
||||
<h3 className="font-semibold text-gray-900 mb-2 flex-shrink-0">Market Depth</h3>
|
||||
|
||||
{/* Tooltip on hover */}
|
||||
<div className="absolute bottom-full mb-2 left-1/2 -translate-x-1/2 bg-gray-900 text-white text-xs px-2 py-1 rounded opacity-0 group-hover:opacity-100 transition-opacity whitespace-nowrap pointer-events-none z-20">
|
||||
{d.spread > 0 ? '+' : ''}{d.spread}: ${d.total.toLocaleString()}
|
||||
{/* Chart container */}
|
||||
<div className="flex-1 flex items-end gap-px relative bg-gray-50 rounded-lg p-2">
|
||||
{/* Official line indicator */}
|
||||
<div
|
||||
className="absolute top-0 bottom-0 w-0.5 bg-yellow-500 z-10"
|
||||
style={{
|
||||
left: `${((event.official_spread - event.min_spread) / (event.max_spread - event.min_spread)) * 100}%`
|
||||
}}
|
||||
>
|
||||
<div className="absolute -top-1 left-1/2 -translate-x-1/2 bg-yellow-500 text-white text-xs px-1 rounded">
|
||||
{event.official_spread > 0 ? '+' : ''}{event.official_spread}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{chartData.map((d) => {
|
||||
// Calculate heights as percentage of max, ensuring max bar fills 100%
|
||||
const totalHeightPercent = (d.total / chartMaxVolume) * 100
|
||||
const homeHeightPercent = d.total > 0 ? (d.homeVolume / d.total) * totalHeightPercent : 0
|
||||
const awayHeightPercent = d.total > 0 ? (d.awayVolume / d.total) * totalHeightPercent : 0
|
||||
|
||||
return (
|
||||
<div
|
||||
key={d.spread}
|
||||
className="flex-1 h-full flex flex-col justify-end cursor-pointer group relative"
|
||||
onClick={() => setSelectedSpread(d.spread)}
|
||||
>
|
||||
{/* Away volume (red, on top) */}
|
||||
<div
|
||||
className={`w-full bg-red-400 hover:bg-red-500 transition-colors ${
|
||||
d.spread === selectedSpread ? 'ring-2 ring-blue-500' : ''
|
||||
}`}
|
||||
style={{ height: `${awayHeightPercent}%`, minHeight: d.awayVolume > 0 ? '2px' : '0' }}
|
||||
/>
|
||||
{/* Home volume (green, on bottom) */}
|
||||
<div
|
||||
className={`w-full bg-green-400 hover:bg-green-500 transition-colors ${
|
||||
d.spread === selectedSpread ? 'ring-2 ring-blue-500' : ''
|
||||
}`}
|
||||
style={{ height: `${homeHeightPercent}%`, minHeight: d.homeVolume > 0 ? '2px' : '0' }}
|
||||
/>
|
||||
|
||||
{/* Tooltip on hover */}
|
||||
<div className="absolute bottom-full mb-2 left-1/2 -translate-x-1/2 bg-gray-900 text-white text-xs px-2 py-1 rounded opacity-0 group-hover:opacity-100 transition-opacity whitespace-nowrap pointer-events-none z-20">
|
||||
{d.spread > 0 ? '+' : ''}{d.spread}: ${d.total.toLocaleString()}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
|
||||
{/* X-axis labels */}
|
||||
<div className="flex justify-between mt-1 text-xs text-gray-500 px-2 flex-shrink-0">
|
||||
<span>{event.min_spread}</span>
|
||||
<span>Spread</span>
|
||||
<span>+{event.max_spread}</span>
|
||||
</div>
|
||||
|
||||
{/* Legend */}
|
||||
<div className="flex items-center justify-center gap-6 mt-1 text-xs flex-shrink-0">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="w-3 h-3 bg-green-400 rounded" />
|
||||
<span className="text-gray-600">{event.home_team}</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="w-3 h-3 bg-red-400 rounded" />
|
||||
<span className="text-gray-600">{event.away_team}</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="w-3 h-0.5 bg-yellow-500" />
|
||||
<span className="text-gray-600">Official Line</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Recent Activity Section */}
|
||||
<div className="h-48 flex flex-col mt-3 pt-3 border-t flex-shrink-0">
|
||||
<h4 className="font-semibold text-gray-900 mb-2 text-sm flex-shrink-0">
|
||||
Recent Activity ({recentActivity.length} bets)
|
||||
</h4>
|
||||
<div className="flex-1 overflow-y-auto space-y-1">
|
||||
{recentActivity.length > 0 ? (
|
||||
recentActivity.map((bet, i) => (
|
||||
<div key={`${bet.bet_id}-${i}`} className="flex items-center justify-between text-xs py-1.5 px-2 bg-gray-50 rounded hover:bg-gray-100">
|
||||
<span className={`font-medium ${bet.team === 'home' ? 'text-green-600' : 'text-red-600'}`}>
|
||||
{bet.team === 'home' ? event.home_team : event.away_team} {bet.spread > 0 ? '+' : ''}{bet.spread}
|
||||
</span>
|
||||
<span className="text-gray-700 font-mono font-medium">${bet.stake.toFixed(0)}</span>
|
||||
<span className={`px-1.5 py-0.5 rounded text-xs font-medium ${
|
||||
bet.status === 'open' ? 'bg-green-100 text-green-700' :
|
||||
bet.status === 'matched' ? 'bg-yellow-100 text-yellow-700' :
|
||||
'bg-gray-100 text-gray-700'
|
||||
}`}>
|
||||
{bet.status}
|
||||
</span>
|
||||
<span className="text-gray-400">{bet.creator_username}</span>
|
||||
</div>
|
||||
))
|
||||
) : (
|
||||
<div className="flex items-center justify-center h-full text-gray-400">
|
||||
No bets yet
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* X-axis labels */}
|
||||
<div className="flex justify-between mt-1 text-xs text-gray-500 px-2">
|
||||
<span>{event.min_spread}</span>
|
||||
<span>Spread</span>
|
||||
<span>+{event.max_spread}</span>
|
||||
</div>
|
||||
|
||||
{/* Legend */}
|
||||
<div className="flex items-center justify-center gap-6 mt-3 text-xs">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="w-3 h-3 bg-green-400 rounded" />
|
||||
<span className="text-gray-600">{event.home_team} Volume</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="w-3 h-3 bg-red-400 rounded" />
|
||||
<span className="text-gray-600">{event.away_team} Volume</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="w-3 h-0.5 bg-yellow-500" />
|
||||
<span className="text-gray-600">Official Line</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Recent Activity */}
|
||||
<div className="mt-4 pt-4 border-t">
|
||||
<h4 className="font-semibold text-gray-900 mb-2 text-sm">Recent Activity</h4>
|
||||
<div className="max-h-32 overflow-y-auto space-y-1">
|
||||
{recentActivity.length > 0 ? (
|
||||
recentActivity.map((bet, i) => (
|
||||
<div key={`${bet.bet_id}-${i}`} className="flex items-center justify-between text-xs py-1 px-2 bg-gray-50 rounded">
|
||||
<span className={bet.team === 'home' ? 'text-green-600' : 'text-red-600'}>
|
||||
{bet.team === 'home' ? event.home_team : event.away_team} {bet.spread > 0 ? '+' : ''}{bet.spread}
|
||||
</span>
|
||||
<span className="text-gray-600 font-mono">${bet.stake.toFixed(0)}</span>
|
||||
<span className={`px-1.5 py-0.5 rounded text-xs ${
|
||||
bet.status === 'open' ? 'bg-green-100 text-green-700' :
|
||||
bet.status === 'matched' ? 'bg-yellow-100 text-yellow-700' :
|
||||
'bg-gray-100 text-gray-700'
|
||||
}`}>
|
||||
{bet.status}
|
||||
</span>
|
||||
<span className="text-gray-400">{bet.creator_username}</span>
|
||||
</div>
|
||||
))
|
||||
) : (
|
||||
<p className="text-gray-400 text-center py-4">No bets yet</p>
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
/* Grid View */
|
||||
<div className="flex-1 overflow-y-auto">
|
||||
<h3 className="font-semibold text-gray-900 mb-4">All Spreads</h3>
|
||||
{renderGridView()}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Right - Quick Trade Panel */}
|
||||
<div className="col-span-3 p-4 bg-gray-50">
|
||||
<div className="col-span-3 p-4 bg-gray-50 overflow-y-auto">
|
||||
<h3 className="font-semibold text-gray-900 mb-4 flex items-center gap-2">
|
||||
<Target size={16} className="text-gray-400" />
|
||||
Place Bet
|
||||
|
||||
BIN
frontend/test-results/event-detail.png
Normal file
BIN
frontend/test-results/event-detail.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 247 KiB |
46
frontend/tests/debug-trading-panel.spec.ts
Normal file
46
frontend/tests/debug-trading-panel.spec.ts
Normal file
@ -0,0 +1,46 @@
|
||||
import { test } from '@playwright/test';
|
||||
|
||||
test('capture trading panel screenshot', async ({ page }) => {
|
||||
// Navigate to event detail
|
||||
await page.goto('/events/1', { waitUntil: 'networkidle' });
|
||||
await page.waitForTimeout(3000);
|
||||
|
||||
// Take screenshot
|
||||
await page.screenshot({ path: 'test-results/event-detail.png', fullPage: true });
|
||||
|
||||
// Check the spread values being used
|
||||
const spreadInfo = await page.evaluate(() => {
|
||||
// Look for the spread grid to understand the range
|
||||
const spreadGridCells = document.querySelectorAll('.grid button');
|
||||
const spreads: string[] = [];
|
||||
spreadGridCells.forEach(cell => {
|
||||
const text = cell.textContent;
|
||||
if (text && (text.includes('+') || text.includes('-') || text.match(/^\\d/))) {
|
||||
spreads.push(text.substring(0, 10));
|
||||
}
|
||||
});
|
||||
|
||||
// Check order book sections
|
||||
const orderBookContainer = document.querySelector('.col-span-3');
|
||||
const aboveSection = orderBookContainer?.querySelectorAll('.flex-1.overflow-y-auto')[0];
|
||||
const belowSection = orderBookContainer?.querySelectorAll('.flex-1.overflow-y-auto')[1];
|
||||
|
||||
// Count rows in each section
|
||||
const aboveRows = aboveSection?.querySelectorAll('button').length || 0;
|
||||
const belowRows = belowSection?.querySelectorAll('button').length || 0;
|
||||
|
||||
// Get the official spread from the header
|
||||
const officialSpreadElement = document.querySelector('.text-3xl.font-bold');
|
||||
const officialSpread = officialSpreadElement?.textContent;
|
||||
|
||||
return {
|
||||
officialSpread,
|
||||
aboveRowCount: aboveRows,
|
||||
belowRowCount: belowRows,
|
||||
aboveSectionHTML: aboveSection?.innerHTML?.substring(0, 500) || 'not found',
|
||||
belowSectionHTML: belowSection?.innerHTML?.substring(0, 500) || 'not found',
|
||||
};
|
||||
});
|
||||
|
||||
console.log('Spread info:', JSON.stringify(spreadInfo, null, 2));
|
||||
});
|
||||
Reference in New Issue
Block a user