← back to Ken
kalshi-dash/src/setup/steps/BrowseMarkets.jsx
95 lines
import React, { useState, useEffect } from 'react';
import { post } from '../../api';
export default function BrowseMarkets({ data, update, next, back }) {
const [loading, setLoading] = useState(true);
const [result, setResult] = useState(null);
const [error, setError] = useState(null);
useEffect(() => { loadMarkets(); }, []);
async function loadMarkets() {
setLoading(true); setError(null);
try {
const r = await post('/kalshi', { action: 'get_events', params: { status: 'open', limit: 50 } });
setResult(r);
const count = r.events?.length || 0;
update({ marketsLoaded: count });
} catch { setError('Failed to load markets'); }
setLoading(false);
}
const weatherEvents = (result?.events || []).filter(e =>
(e.category || '').toLowerCase().includes('climate') ||
(e.category || '').toLowerCase().includes('weather') ||
(e.title || '').toLowerCase().includes('temperature') ||
(e.title || '').toLowerCase().includes('rain') ||
(e.title || '').toLowerCase().includes('snow') ||
(e.title || '').toLowerCase().includes('precipitation')
);
return (
<div className="space-y-6">
<div className="text-center">
<h2 className="text-2xl font-bold mb-2">Let's See What They're Selling</h2>
<p className="text-gray-400 text-sm">I'm snooping through the markets. You're welcome.</p>
</div>
<div className="card">
{loading ? (
<div className="flex flex-col items-center justify-center py-12 gap-4">
<div className="animate-spin w-10 h-10 border-3 border-amber-500 border-t-transparent rounded-full" />
<p className="text-sm text-gray-400">Schlepping markets from Ken... patience is a virtue</p>
</div>
) : error ? (
<div className="text-center py-8">
<p className="text-red-400 text-sm mb-3">{error}</p>
<button onClick={loadMarkets} className="btn btn-s text-sm">Retry</button>
</div>
) : (
<div className="space-y-4">
<div className="grid grid-cols-3 gap-4">
<div className="text-center">
<p className="stat-v text-amber-400">{result?.events?.length || 0}</p>
<p className="text-xs text-gray-500 mt-1">Things to Bet On</p>
</div>
<div className="text-center">
<p className="stat-v text-blue-400">{weatherEvents.length}</p>
<p className="text-xs text-gray-500 mt-1">Weather Bets (Our Thing)</p>
</div>
<div className="text-center">
<p className="stat-v text-green-400">{result?.markets?.length || '—'}</p>
<p className="text-xs text-gray-500 mt-1">Individual Contracts</p>
</div>
</div>
{weatherEvents.length > 0 && (
<div className="border-t border-gray-800 pt-3">
<p className="text-xs text-gray-500 mb-2 uppercase font-medium">Weather Bets I Found For You</p>
<div className="space-y-1.5 max-h-48 overflow-y-auto">
{weatherEvents.slice(0, 12).map((e, i) => (
<div key={i} className="flex items-center gap-2 text-xs">
<span className="w-1.5 h-1.5 rounded-full bg-amber-500 flex-shrink-0" />
<span className="text-gray-300 truncate">{e.title}</span>
<span className="text-gray-600 ml-auto font-mono text-[10px]">{e.event_ticker}</span>
</div>
))}
</div>
</div>
)}
{weatherEvents.length === 0 && (
<p className="text-center text-gray-500 text-sm py-4">No weather bets right now. What, the weather took a day off? Other markets are there at least.</p>
)}
</div>
)}
</div>
<div className="flex items-center justify-between">
<button onClick={back} className="text-sm text-gray-500 hover:text-gray-300">Back</button>
<button onClick={next} disabled={loading} className="btn btn-p">{loading ? 'Loading...' : 'Continue'}</button>
</div>
</div>
);
}