← back to Ken

kalshi-dash/src/setup/steps/TestConnection.jsx

92 lines

import React, { useState, useEffect } from 'react';
import { post } from '../../api';

export default function TestConnection({ data, update, next, back }) {
  const [exchangeTest, setExchangeTest] = useState(null);
  const [authTest, setAuthTest] = useState(null);
  const [exLoading, setExLoading] = useState(true);
  const [authLoading, setAuthLoading] = useState(false);

  useEffect(() => { runExchangeTest(); }, []);

  async function runExchangeTest() {
    setExLoading(true);
    try {
      const r = await post('/kalshi', { action: 'test_connection' });
      setExchangeTest(r);
      if (r.success && data.keys && !data.skippedConnect) runAuthTest();
    } catch { setExchangeTest({ error: true }); }
    setExLoading(false);
  }

  async function runAuthTest() {
    setAuthLoading(true);
    try {
      const r = await post('/kalshi', { action: 'get_balance' });
      setAuthTest(r);
      if (r.success) update({ connectionOk: true });
    } catch { setAuthTest({ error: true }); }
    setAuthLoading(false);
  }

  const skipped = data.skippedConnect;

  const TestCard = ({ title, loading, result, skippedMsg }) => (
    <div className="card">
      <div className="flex items-center gap-2 mb-3">
        {skippedMsg ? (
          <div className="w-5 h-5 rounded-full bg-yellow-500 flex items-center justify-center"><span className="text-white text-xs font-bold">—</span></div>
        ) : loading ? (
          <div className="animate-spin w-5 h-5 border-2 border-amber-500 border-t-transparent rounded-full" />
        ) : result?.success ? (
          <div className="w-5 h-5 rounded-full bg-green-500 flex items-center justify-center">
            <svg className="w-3 h-3 text-white" fill="none" stroke="currentColor" strokeWidth="3" viewBox="0 0 24 24"><path strokeLinecap="round" strokeLinejoin="round" d="M5 13l4 4L19 7" /></svg>
          </div>
        ) : result?.error ? (
          <div className="w-5 h-5 rounded-full bg-red-500 flex items-center justify-center">
            <svg className="w-3 h-3 text-white" fill="none" stroke="currentColor" strokeWidth="3" viewBox="0 0 24 24"><path strokeLinecap="round" strokeLinejoin="round" d="M6 18L18 6M6 6l12 12" /></svg>
          </div>
        ) : <div className="w-5 h-5 rounded-full bg-gray-600" />}
        <h3 className="font-semibold text-sm">{title}</h3>
      </div>
      {skippedMsg ? (
        <p className="text-xs text-yellow-400">{skippedMsg}</p>
      ) : result?.success ? (
        <div className="space-y-1 text-xs text-gray-400">
          {result.exchange_status && <p>Exchange: <span className="text-green-400 font-mono">{result.exchange_status}</span></p>}
          {result.balance !== undefined && <p>Balance: <span className="text-green-400 font-mono">${(result.balance / 100).toFixed(2)}</span></p>}
          {result.env && <p>Env: <span className="text-amber-400 font-mono">{result.env.toUpperCase()}</span></p>}
        </div>
      ) : result?.error ? (
        <p className="text-xs text-red-400">{typeof result.error === 'string' ? result.error : 'Connection failed'}</p>
      ) : null}
    </div>
  );

  return (
    <div className="space-y-6">
      <div className="text-center">
        <h2 className="text-2xl font-bold mb-2">Let's See If This Thing Works</h2>
        <p className="text-gray-400 text-sm">I'm checking your wiring. Hold your horses.</p>
      </div>

      <div className="grid grid-cols-2 gap-4">
        <TestCard title="Is Ken Even Open?" loading={exLoading} result={exchangeTest} />
        <TestCard title="Do They Know Who You Are?" loading={authLoading} result={authTest}
          skippedMsg={skipped ? 'You skipped this — playing pretend, remember?' : (!data.keys ? 'No keys, no entry. What did you expect?' : null)} />
      </div>

      {!exLoading && !authLoading && (
        <div className="flex justify-center">
          <button onClick={runExchangeTest} className="text-xs text-gray-500 hover:text-gray-300">Try again, maybe this time it'll listen</button>
        </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} className="btn btn-p">Continue</button>
      </div>
    </div>
  );
}