← Back
import { useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { useEdgeScanner } from '../../hooks/useEdgeScanner';
import type { EdgeEntry } from '../../hooks/useEdgeScanner';
import { formatPrice } from '../../utils/format';

const SIGNALS = ['All', 'BUY_YES', 'BUY_NO'];
const CATEGORIES = ['All', 'Sports', 'Politics', 'Crypto', 'Weather', 'Tech', 'Finance'];

function ConfBadge({ conf }: { conf: string }) {
  const cls = conf === 'HIGH' ? 'es-conf-high' : conf === 'MED' ? 'es-conf-med' : 'es-conf-low';
  return <span className={`es-conf ${cls}`}>{conf}</span>;
}

function SignalBadge({ signal }: { signal: string }) {
  if (signal === 'NEUTRAL') return null;
  const cls = signal === 'BUY_YES' ? 'es-sig-yes' : 'es-sig-no';
  return <span className={`es-sig ${cls}`}>{signal === 'BUY_YES' ? 'BUY YES' : 'BUY NO'}</span>;
}

function FactorBar({ label, value }: { label: string; value: number }) {
  return (
    <div className="es-factor">
      <span className="es-factor-label">{label}</span>
      <div className="es-factor-track">
        <div className="es-factor-fill" style={{ width: `${Math.round(value * 100)}%` }} />
      </div>
      <span className="es-factor-val">{Math.round(value * 100)}%</span>
    </div>
  );
}

export default function EdgeScanner() {
  const [signal, setSignal] = useState('All');
  const [category, setCategory] = useState('All');
  const [expanded, setExpanded] = useState<string | null>(null);
  const navigate = useNavigate();

  const { edges, loading } = useEdgeScanner({
    minScore: 0.20,
    signal: signal === 'All' ? undefined : signal,
    category,
    limit: 30,
  });

  return (
    <div className="es-wrap">
      {/* Filters */}
      <div className="es-filters">
        <div className="es-filter-group">
          {SIGNALS.map(s => (
            <button key={s} className={`pill pill-sm ${signal === s ? 'pill-active' : ''}`}
              onClick={() => setSignal(s)}>
              {s === 'All' ? 'All' : s === 'BUY_YES' ? 'Buy YES' : 'Buy NO'}
            </button>
          ))}
        </div>
        <select className="es-select" value={category} onChange={e => setCategory(e.target.value)}>
          {CATEGORIES.map(c => <option key={c} value={c}>{c}</option>)}
        </select>
      </div>

      {/* Disclaimer */}
      <p className="es-disclaimer">Heuristic model — not financial advice. Factors: spread, volume, whale consensus, momentum, price range.</p>

      {/* Loading */}
      {loading && edges.length === 0 && (
        <div className="es-loading">
          {Array.from({ length: 5 }, (_, i) => (
            <div key={i} className="es-card es-skeleton">
              <div className="skeleton-img" />
              <div style={{ flex: 1 }}>
                <div className="skeleton-text" style={{ width: `${60 + (i % 3) * 12}%`, height: 14 }} />
                <div className="skeleton-text" style={{ width: 80, height: 12, marginTop: 6 }} />
              </div>
            </div>
          ))}
        </div>
      )}

      {/* Empty */}
      {!loading && edges.length === 0 && (
        <div className="sig-empty">No edge signals found. Try adjusting filters.</div>
      )}

      {/* Results */}
      {edges.length > 0 && (
        <div className="es-list">
          {edges.map((e: EdgeEntry) => {
            const pct = e.marketPrice * 100;
            const priceColor = pct >= 70 ? 'var(--profit)' : pct <= 30 ? 'var(--loss)' : 'var(--text-primary)';
            const isExpanded = expanded === e.marketId;

            return (
              <div key={e.marketId} className={`es-card ${isExpanded ? 'es-card-expanded' : ''}`}>
                <div className="es-card-main" onClick={() => setExpanded(isExpanded ? null : e.marketId)}>
                  <div className="es-left">
                    {e.imageUrl && (
                      <img src={e.imageUrl} alt="" className="es-img"
                        onError={ev => { (ev.target as HTMLImageElement).style.display = 'none'; }} />
                    )}
                    <div className="es-info">
                      <span className="es-question">{e.question}</span>
                      <div className="es-meta">
                        <span className="es-cat">{e.category}</span>
                        <SignalBadge signal={e.signal} />
                        <ConfBadge conf={e.confidence} />
                      </div>
                    </div>
                  </div>
                  <div className="es-right">
                    <span className="es-edge">{Math.round(e.edgeScore * 100)}%</span>
                    <span className="es-price" style={{ color: priceColor }}>{formatPrice(e.marketPrice)}</span>
                  </div>
                </div>

                {isExpanded && (
                  <div className="es-detail">
                    <div className="es-factors">
                      <FactorBar label="Whale" value={e.factors.whale} />
                      <FactorBar label="Volume" value={e.factors.volume} />
                      <FactorBar label="Momentum" value={e.factors.momentum} />
                      <FactorBar label="Spread" value={e.factors.spread} />
                      <FactorBar label="Price" value={e.factors.price} />
                    </div>
                    <div className="es-detail-stats">
                      <span>Whale YES: {Math.round(e.whaleYesPct * 100)}%</span>
                      <span>Vol/Liq: {e.volumeRatio.toFixed(1)}x</span>
                    </div>
                    <button className="es-view-btn" onClick={() => navigate(`/market/${e.marketId}`)}>
                      View Market →
                    </button>
                  </div>
                )}
              </div>
            );
          })}
        </div>
      )}
    </div>
  );
}

📜 Git History

6c47fa4chore: local Polikopi project home + Phase 1 redesign artifacts12 days ago
Show last diff
Loading...