// ── Dispatch v2 ops board ──────────────────────────────────────────────────────
//
// Replaces the old Planned tab + "Dispatch New" AssembleForm. Route building
// (flash matching, route offers, auto-assignment on deadline) now happens
// server-side via pg_cron `dispatch_tick()` + the `dispatch-matcher` /
// `dispatch-cron` edge functions (see docs/DISPATCH_V2_DESIGN.md). This board
// is read-only telemetry over that pipeline plus a small set of admin
// overrides, polled every 10s.
//
// ── RPC contract this file consumes ──────────────────────────────────────────
// admin_dispatch_board() → jsonb, shaped as:
// {
//   flash_matching: [{
//     delivery_id, tracking_number, order_number, store_name,
//     pickup_area, dropoff_area,
//     matching_started_at,               // → "time in matching"
//     attempt_no, max_attempts,          // → "attempts x/3"
//     pay_npr,
//     current_offer: {                   // null between attempts
//       offer_id, driver_id, driver_name, expires_at,
//     } | null,
//   }],
//   route_offers: [{
//     route_id, tier, total_stops, pay_npr, claim_deadline, offer_wave,
//     offers_sent, offers_declined, first_pickup_area, created_at,
//   }],
//   needs_attention: [{
//     route_id, attention_reason, driver_id, driver_name, total_stops,
//     flagged_at,
//   }],
//   open_flash_stale: [{                 // flash deliveries in the open queue > 10 min
//     delivery_id, tracking_number, order_number, store_name,
//     pickup_area, dropoff_area, opened_at, pay_npr,
//   }],
//   drivers: [{
//     driver_id, display_name, vehicle_type, is_online,
//     last_location_updated_at,          // → heartbeat age, stale highlight
//     is_available,                      // optional; we recompute client-side if absent
//     current_work,                      // free-text, e.g. "Flash #A1B2" | "Route #C3D4" | null
//   }],
// }
//
// Every field read below falls back to a dash/zero — the SQL side of this
// migration lands in parallel, so field-name drift should degrade gracefully
// rather than crash the board.

const { useState: useStateBd, useEffect: useEffectBd, useRef: useRefBd } = React;

const FRESH_HEARTBEAT_S = 300; // dispatch.driver.fresh_heartbeat_s default

function bdIsAvailable(d) {
  if (d.is_available != null) return !!d.is_available;
  if (!d.is_online) return false;
  if (!d.last_location_updated_at) return false;
  const ageS = (Date.now() - new Date(d.last_location_updated_at).getTime()) / 1000;
  return ageS <= FRESH_HEARTBEAT_S;
}

function bdHeartbeatAgeS(d) {
  if (!d.last_location_updated_at) return null;
  return Math.max(0, Math.floor((Date.now() - new Date(d.last_location_updated_at).getTime()) / 1000));
}

// Ticking "time since" label — own 1s interval so the board doesn't have to
// re-render as a whole just to keep clocks moving.
const BdElapsed = ({ since }) => {
  const [, force] = useStateBd(0);
  useEffectBd(() => {
    const t = setInterval(() => force(x => x + 1), 1000);
    return () => clearInterval(t);
  }, []);
  if (!since) return <span className="muted">—</span>;
  const s = Math.max(0, Math.floor((Date.now() - new Date(since).getTime()) / 1000));
  if (s < 60) return <span className="num">{s}s</span>;
  const m = Math.floor(s / 60);
  if (m < 60) return <span className="num">{m}m</span>;
  return <span className="num">{Math.floor(m / 60)}h {m % 60}m</span>;
};

// Ticking countdown to a future timestamp.
const BdCountdown = ({ to }) => {
  const [, force] = useStateBd(0);
  useEffectBd(() => {
    const t = setInterval(() => force(x => x + 1), 1000);
    return () => clearInterval(t);
  }, []);
  if (!to) return <span className="muted">—</span>;
  const ms = new Date(to).getTime() - Date.now();
  if (ms <= 0) return <span style={{ color: 'var(--neg)' }}>expired</span>;
  const s = Math.floor(ms / 1000);
  const m = Math.floor(s / 60), sec = s % 60;
  return <span className="num">{m}:{String(sec).padStart(2, '0')}</span>;
};

// Inline driver picker — available drivers first, plain <select>, no modal.
const BdDriverPicker = ({ drivers, value, onChange, onConfirm, onCancel, busy, error, confirmLabel }) => (
  <div style={{
    display: 'flex', gap: 8, alignItems: 'center', flexWrap: 'wrap', marginTop: 8,
    padding: '8px 10px', background: 'var(--surface-2)', borderRadius: 5,
  }}>
    <select
      value={value}
      onChange={e => onChange(e.target.value)}
      style={{ flex: 1, minWidth: 180, height: 30, fontSize: 12, border: '1px solid var(--hairline)', borderRadius: 5, padding: '0 8px', background: 'var(--surface)', color: 'var(--ink)' }}
    >
      <option value="">Select driver…</option>
      {drivers.map(d => (
        <option key={d.driver_id} value={d.driver_id}>
          {bdIsAvailable(d) ? '' : '(offline) '}{d.display_name || 'Driver'}{d.vehicle_type ? ` · ${d.vehicle_type}` : ''}
        </option>
      ))}
    </select>
    <button className="btn primary" style={{ height: 30, fontSize: 11.5 }} disabled={!value || busy} onClick={onConfirm}>
      {busy ? 'Assigning…' : (confirmLabel || 'Assign')}
    </button>
    <button className="btn ghost" style={{ height: 30, fontSize: 11.5 }} onClick={onCancel}>Dismiss</button>
    {error && <div style={{ fontSize: 11, color: 'var(--neg)', width: '100%' }}>{error}</div>}
  </div>
);

// Inline "Cancel route?" confirm — plain text, no window.confirm/alert.
const BdCancelConfirm = ({ busy, onConfirm, onDismiss }) => (
  <span style={{ display: 'inline-flex', gap: 6, alignItems: 'center', fontSize: 11.5, color: 'var(--ink-2)' }}>
    Cancel this route?
    <button className="btn" style={{ height: 26, fontSize: 11, color: 'var(--neg)' }} disabled={busy} onClick={onConfirm}>
      {busy ? '…' : 'Yes, cancel'}
    </button>
    <button className="btn ghost" style={{ height: 26, fontSize: 11 }} onClick={onDismiss}>No</button>
  </span>
);

window.DispatchBoard = function DispatchBoard() {
  const I = window.Icons;
  const sb = window.supabaseClient;

  const [board, setBoard] = useStateBd(null);
  const [loading, setLoading] = useStateBd(true);
  const [error, setError] = useStateBd('');
  const [lastRefreshed, setLastRefreshed] = useStateBd(null);

  const [assignTarget, setAssignTarget] = useStateBd(null); // { kind: 'route'|'delivery', id }
  const [assignDriverId, setAssignDriverId] = useStateBd('');
  const [assigning, setAssigning] = useStateBd(false);
  const [assignError, setAssignError] = useStateBd('');

  const [cancelTarget, setCancelTarget] = useStateBd(null); // route_id
  const [cancelling, setCancelling] = useStateBd(false);

  const [rebuildBusy, setRebuildBusy] = useStateBd(null); // tier being built, or null
  const [rebuildMsg, setRebuildMsg] = useStateBd('');

  const timerRef = useRefBd(null);

  const load = async (silent) => {
    if (!sb) return;
    if (!silent) setLoading(true);
    const { data, error: err } = await sb.rpc('admin_dispatch_board');
    if (err) {
      setError(err.message || 'admin_dispatch_board() failed');
    } else {
      setBoard(data || {});
      setError('');
      setLastRefreshed(new Date());
    }
    if (!silent) setLoading(false);
  };

  useEffectBd(() => {
    load(false);
    timerRef.current = setInterval(() => load(true), 10000);
    return () => { if (timerRef.current) clearInterval(timerRef.current); };
  }, []);

  const flashMatching  = board?.flash_matching  || [];
  const routeOffers    = board?.route_offers    || [];
  const needsAttention = board?.needs_attention || [];
  const openFlashStale = board?.open_flash_stale || [];
  const boardDrivers   = board?.drivers || [];

  const pickerDrivers = [...boardDrivers].sort((a, b) => {
    const av = bdIsAvailable(a), bv = bdIsAvailable(b);
    if (av !== bv) return av ? -1 : 1;
    return (a.display_name || '').localeCompare(b.display_name || '');
  });

  const openAssign = (kind, id) => { setAssignTarget({ kind, id }); setAssignDriverId(''); setAssignError(''); };
  const closeAssign = () => { setAssignTarget(null); setAssignDriverId(''); setAssignError(''); };

  const handleAssign = async () => {
    if (!assignTarget || !assignDriverId) return;
    setAssigning(true); setAssignError('');
    const fn = assignTarget.kind === 'route' ? 'admin_assign_route' : 'admin_assign_delivery';
    const params = assignTarget.kind === 'route'
      ? { p_route_id: assignTarget.id, p_driver_id: assignDriverId }
      : { p_delivery_id: assignTarget.id, p_driver_id: assignDriverId };
    const { data, error: err } = await sb.rpc(fn, params);
    setAssigning(false);
    if (err || data?.success === false) {
      setAssignError(data?.message || err?.message || 'Assign failed');
      return;
    }
    closeAssign();
    load(true);
  };

  const handleCancelRoute = async (routeId) => {
    setCancelling(true);
    const { error: err } = await sb.rpc('admin_cancel_route', { p_route_id: routeId });
    setCancelling(false);
    setCancelTarget(null);
    if (!err) load(true);
  };

  const handleRebuild = async (tier) => {
    setRebuildBusy(tier); setRebuildMsg('');
    const { error: err } = await sb.rpc('admin_rebuild_routes', { p_tier: tier });
    setRebuildBusy(null);
    if (err) setRebuildMsg(`Failed: ${err.message}`);
    else { setRebuildMsg(`Build triggered for ${tier === 'standard' ? 'Same Day' : 'Economy'}.`); load(true); }
  };

  if (error && !board) {
    return (
      <div className="panel" style={{ padding: 32, textAlign: 'center', maxWidth: 480 }}>
        <div style={{ fontSize: 13, color: 'var(--ink)', marginBottom: 6 }}>Dispatch board unavailable</div>
        <div className="muted" style={{ fontSize: 11.5, marginBottom: 14 }}>{error}</div>
        <button className="btn primary" onClick={() => load(false)}><I.refresh size={12} />Retry</button>
      </div>
    );
  }

  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>

      {/* ── Top bar: build-now + last refreshed ── */}
      <div className="panel" style={{ padding: '12px 16px', display: 'flex', alignItems: 'center', gap: 12, flexWrap: 'wrap' }}>
        <div style={{ fontSize: 12, color: 'var(--ink-2)' }}>Build routes now</div>
        {['standard', 'economy'].map(t => (
          <button
            key={t}
            className="btn"
            style={{ height: 28, fontSize: 11.5 }}
            disabled={rebuildBusy === t}
            onClick={() => handleRebuild(t)}
          >
            <I.truck size={11} />
            {rebuildBusy === t ? 'Building…' : (t === 'standard' ? 'Same Day' : 'Economy')}
          </button>
        ))}
        {rebuildMsg && <span className="muted" style={{ fontSize: 11.5 }}>{rebuildMsg}</span>}
        <div style={{ marginLeft: 'auto', display: 'flex', alignItems: 'center', gap: 10 }}>
          {lastRefreshed && (
            <span className="muted" style={{ fontSize: 10.5, fontFamily: 'var(--font-mono)' }}>
              updated {lastRefreshed.toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false })}
            </span>
          )}
          <I.refresh size={13} className="muted" style={{ cursor: 'pointer' }} onClick={() => load(false)} />
        </div>
      </div>

      <div className="mob-stack" style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 14 }}>

        {/* ── Flash matching ── */}
        <div className="panel" style={{ display: 'flex', flexDirection: 'column', overflow: 'hidden', maxHeight: 420 }}>
          <div className="panel-h">
            <span style={{ display: 'inline-flex', alignItems: 'center', gap: 5 }}><I.zap size={12} />Flash matching</span>
            <span className={`chip dot${flashMatching.length > 0 ? ' warn' : ''}`} style={{ marginLeft: 'auto' }}>{flashMatching.length}</span>
          </div>
          <div style={{ flex: 1, overflow: 'auto' }}>
            {loading && !board ? (
              <div className="muted" style={{ padding: 16, fontSize: 12 }}>Loading…</div>
            ) : flashMatching.length === 0 ? (
              <div className="muted" style={{ padding: 16, fontSize: 12 }}>Nothing in matching.</div>
            ) : flashMatching.map(item => {
              const atMax = (item.attempt_no ?? 0) >= (item.max_attempts ?? 3);
              return (
                <div key={item.delivery_id} style={{ padding: '10px 14px', borderBottom: '1px solid var(--hairline)', position: 'relative' }}>
                  {atMax && <div style={{ position: 'absolute', left: 0, top: 6, bottom: 6, width: 2, background: 'var(--warn)' }} />}
                  <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 3 }}>
                    <span className="id" style={{ color: 'var(--ink)' }}>{item.tracking_number || item.order_number || (item.delivery_id || '').slice(0, 8).toUpperCase()}</span>
                    <span className="muted" style={{ fontSize: 11 }}>{item.store_name || '—'}</span>
                    <span className={`chip dot${atMax ? ' warn' : ''}`} style={{ marginLeft: 'auto' }}>{item.attempt_no ?? '—'}/{item.max_attempts ?? 3}</span>
                  </div>
                  <div style={{ fontSize: 11.5, color: 'var(--ink-2)' }}>{item.pickup_area || '—'} → {item.dropoff_area || '—'}</div>
                  <div style={{ display: 'flex', gap: 14, marginTop: 4, fontSize: 11, fontFamily: 'var(--font-mono)', color: 'var(--ink-3)', flexWrap: 'wrap' }}>
                    <span>in matching <BdElapsed since={item.matching_started_at} /></span>
                    {item.current_offer ? (
                      <span>offer → {item.current_offer.driver_name || 'driver'} <BdCountdown to={item.current_offer.expires_at} /></span>
                    ) : (
                      <span className="muted">no active offer</span>
                    )}
                    {item.pay_npr != null && <span>{currency(item.pay_npr)}</span>}
                  </div>
                </div>
              );
            })}
          </div>
        </div>

        {/* ── Route offers ── */}
        <div className="panel" style={{ display: 'flex', flexDirection: 'column', overflow: 'hidden', maxHeight: 420 }}>
          <div className="panel-h">
            <span>Route offers</span>
            <span className={`chip dot${routeOffers.length > 0 ? ' accent' : ''}`} style={{ marginLeft: 'auto' }}>{routeOffers.length}</span>
          </div>
          <div style={{ flex: 1, overflow: 'auto' }}>
            {loading && !board ? (
              <div className="muted" style={{ padding: 16, fontSize: 12 }}>Loading…</div>
            ) : routeOffers.length === 0 ? (
              <div className="muted" style={{ padding: 16, fontSize: 12 }}>No routes currently offered.</div>
            ) : routeOffers.map(r => (
              <div key={r.route_id} style={{ padding: '10px 14px', borderBottom: '1px solid var(--hairline)' }}>
                <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 3, flexWrap: 'wrap' }}>
                  <span className="id" style={{ color: 'var(--ink)' }}>{(r.route_id || '').slice(0, 8).toUpperCase()}</span>
                  <span className={`chip dot${r.tier === 'economy' ? '' : ' accent'}`}>{r.tier === 'economy' ? 'Economy' : 'Same Day'}</span>
                  <span className="muted" style={{ fontSize: 11 }}>wave {r.offer_wave ?? 1}</span>
                  <span style={{ marginLeft: 'auto', fontWeight: 600, fontSize: 12.5, color: 'var(--ink)' }}>{currency(r.pay_npr)}</span>
                </div>
                <div style={{ fontSize: 11.5, color: 'var(--ink-2)' }}>{r.total_stops ?? 0} stops · {r.first_pickup_area || '—'}</div>
                <div style={{ display: 'flex', gap: 14, marginTop: 4, fontSize: 11, fontFamily: 'var(--font-mono)', color: 'var(--ink-3)', flexWrap: 'wrap' }}>
                  <span>claim by <BdCountdown to={r.claim_deadline} /></span>
                  <span>{r.offers_sent ?? 0} sent · {r.offers_declined ?? 0} declined</span>
                </div>
                <div style={{ display: 'flex', gap: 8, marginTop: 8, alignItems: 'center', flexWrap: 'wrap' }}>
                  <button className="btn ghost" style={{ height: 26, fontSize: 11 }} onClick={() => openAssign('route', r.route_id)}>Assign to driver</button>
                  {cancelTarget === r.route_id ? (
                    <BdCancelConfirm busy={cancelling} onConfirm={() => handleCancelRoute(r.route_id)} onDismiss={() => setCancelTarget(null)} />
                  ) : (
                    <button className="btn ghost" style={{ height: 26, fontSize: 11, color: 'var(--neg)' }} onClick={() => setCancelTarget(r.route_id)}>Cancel route</button>
                  )}
                </div>
                {assignTarget?.kind === 'route' && assignTarget.id === r.route_id && (
                  <BdDriverPicker
                    drivers={pickerDrivers} value={assignDriverId} onChange={setAssignDriverId}
                    onConfirm={handleAssign} onCancel={closeAssign} busy={assigning} error={assignError}
                    confirmLabel="Assign route"
                  />
                )}
              </div>
            ))}
          </div>
        </div>

        {/* ── Needs attention ── */}
        <div className="panel" style={{ display: 'flex', flexDirection: 'column', overflow: 'hidden', maxHeight: 360 }}>
          <div className="panel-h">
            <span>Needs attention</span>
            <span className={`chip dot${needsAttention.length > 0 ? ' neg' : ''}`} style={{ marginLeft: 'auto' }}>{needsAttention.length}</span>
          </div>
          <div style={{ flex: 1, overflow: 'auto' }}>
            {loading && !board ? (
              <div className="muted" style={{ padding: 16, fontSize: 12 }}>Loading…</div>
            ) : needsAttention.length === 0 ? (
              <div className="muted" style={{ padding: 16, fontSize: 12 }}>Nothing flagged.</div>
            ) : needsAttention.map(a => (
              <div key={a.route_id} style={{ padding: '10px 14px', borderBottom: '1px solid var(--hairline)', position: 'relative' }}>
                <div style={{ position: 'absolute', left: 0, top: 6, bottom: 6, width: 2, background: 'var(--neg)' }} />
                <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 3, flexWrap: 'wrap' }}>
                  <span className="id" style={{ color: 'var(--ink)' }}>{(a.route_id || '').slice(0, 8).toUpperCase()}</span>
                  <span style={{ fontSize: 12, color: 'var(--neg)' }}>{a.attention_reason || 'flagged'}</span>
                </div>
                <div className="muted" style={{ fontSize: 11.5 }}>
                  {a.driver_name ? `last driver: ${a.driver_name}` : 'no driver'} · {a.total_stops ?? 0} stops
                  {a.flagged_at && <> · flagged <BdElapsed since={a.flagged_at} /> ago</>}
                </div>
                <div style={{ display: 'flex', gap: 8, marginTop: 8, alignItems: 'center', flexWrap: 'wrap' }}>
                  <button className="btn ghost" style={{ height: 26, fontSize: 11 }} onClick={() => openAssign('route', a.route_id)}>Assign to driver</button>
                  {cancelTarget === a.route_id ? (
                    <BdCancelConfirm busy={cancelling} onConfirm={() => handleCancelRoute(a.route_id)} onDismiss={() => setCancelTarget(null)} />
                  ) : (
                    <button className="btn ghost" style={{ height: 26, fontSize: 11, color: 'var(--neg)' }} onClick={() => setCancelTarget(a.route_id)}>Cancel route</button>
                  )}
                </div>
                {assignTarget?.kind === 'route' && assignTarget.id === a.route_id && (
                  <BdDriverPicker
                    drivers={pickerDrivers} value={assignDriverId} onChange={setAssignDriverId}
                    onConfirm={handleAssign} onCancel={closeAssign} busy={assigning} error={assignError}
                    confirmLabel="Assign route"
                  />
                )}
              </div>
            ))}
          </div>
        </div>

        {/* ── Open flash > 10 min ── */}
        <div className="panel" style={{ display: 'flex', flexDirection: 'column', overflow: 'hidden', maxHeight: 360 }}>
          <div className="panel-h">
            <span>Open flash &gt; 10 min</span>
            <span className={`chip dot${openFlashStale.length > 0 ? ' warn' : ''}`} style={{ marginLeft: 'auto' }}>{openFlashStale.length}</span>
          </div>
          <div style={{ flex: 1, overflow: 'auto' }}>
            {loading && !board ? (
              <div className="muted" style={{ padding: 16, fontSize: 12 }}>Loading…</div>
            ) : openFlashStale.length === 0 ? (
              <div className="muted" style={{ padding: 16, fontSize: 12 }}>Nothing stale in the open queue.</div>
            ) : openFlashStale.map(item => (
              <div key={item.delivery_id} style={{ padding: '10px 14px', borderBottom: '1px solid var(--hairline)' }}>
                <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 3 }}>
                  <span className="id" style={{ color: 'var(--ink)' }}>{item.tracking_number || item.order_number || (item.delivery_id || '').slice(0, 8).toUpperCase()}</span>
                  <span className="muted" style={{ fontSize: 11 }}>{item.store_name || '—'}</span>
                  <span className="muted" style={{ marginLeft: 'auto', fontSize: 11, fontFamily: 'var(--font-mono)' }}>open <BdElapsed since={item.opened_at} /></span>
                </div>
                <div style={{ fontSize: 11.5, color: 'var(--ink-2)' }}>{item.pickup_area || '—'} → {item.dropoff_area || '—'}</div>
                <div style={{ display: 'flex', gap: 8, marginTop: 8 }}>
                  <button className="btn ghost" style={{ height: 26, fontSize: 11 }} onClick={() => openAssign('delivery', item.delivery_id)}>Assign to driver</button>
                </div>
                {assignTarget?.kind === 'delivery' && assignTarget.id === item.delivery_id && (
                  <BdDriverPicker
                    drivers={pickerDrivers} value={assignDriverId} onChange={setAssignDriverId}
                    onConfirm={handleAssign} onCancel={closeAssign} busy={assigning} error={assignError}
                    confirmLabel="Assign delivery"
                  />
                )}
              </div>
            ))}
          </div>
        </div>
      </div>

      {/* ── Drivers ── */}
      <div className="panel t-wrap" style={{ overflow: 'hidden' }}>
        <div className="panel-h">
          <span>Drivers</span>
          <span className="muted" style={{ marginLeft: 'auto', fontSize: 11 }}>
            {boardDrivers.filter(bdIsAvailable).length} available of {boardDrivers.length}
          </span>
        </div>
        <table className="t">
          <thead>
            <tr>
              <th>Driver</th>
              <th>Vehicle</th>
              <th>Status</th>
              <th>Heartbeat</th>
              <th>Current work</th>
            </tr>
          </thead>
          <tbody>
            {loading && !board ? (
              <tr><td colSpan={5} className="muted" style={{ padding: 16 }}>Loading…</td></tr>
            ) : boardDrivers.length === 0 ? (
              <tr><td colSpan={5} className="muted" style={{ padding: 16 }}>No drivers.</td></tr>
            ) : boardDrivers.map(d => {
              const ageS = bdHeartbeatAgeS(d);
              const stale = d.is_online && (ageS == null || ageS > FRESH_HEARTBEAT_S);
              return (
                <tr key={d.driver_id}>
                  <td style={{ color: 'var(--ink)' }}>{d.display_name || 'Driver'}</td>
                  <td className="muted">{d.vehicle_type || '—'}</td>
                  <td>
                    <span style={{ display: 'inline-flex', alignItems: 'center', gap: 5 }}>
                      <span style={{ width: 6, height: 6, borderRadius: '50%', background: d.is_online ? 'var(--pos)' : 'var(--ink-4)', display: 'inline-block' }} />
                      {d.is_online ? 'Online' : 'Offline'}
                    </span>
                  </td>
                  <td className="num" style={{ color: stale ? 'var(--neg)' : 'var(--ink-2)' }}>
                    {ageS == null ? '—' : ageS < 60 ? `${ageS}s ago` : `${Math.floor(ageS / 60)}m ago`}
                  </td>
                  <td className="muted">{d.current_work || 'Idle'}</td>
                </tr>
              );
            })}
          </tbody>
        </table>
      </div>
    </div>
  );
};
