Open-Generative-AI/components/batch/BatchDetailShell.jsx
Anuragp22 4cf0d503b8 feat(batch): batch detail page with progress, controls, retry, CSV export
Slice 5 of the batch feature. Marketing team can now click into a
batch from the list, watch a live progress dashboard, drive it with
Start/Pause/Resume/Cancel, retry individual failed jobs, and pull a
results CSV when it's done.

Includes a stakeholder-demo helper that simulates worker progress
(slice 4 hasn't shipped yet) so non-technical viewers see a realistic
running state without needing real MuAPI generations.

Backend
-------
- POST /api/batches/[id]/start: draft|paused -> running, requeues
  any cancelled jobs.
- POST /api/batches/[id]/pause: running -> paused.
- POST /api/batches/[id]/resume: paused -> running.
- POST /api/batches/[id]/cancel: any -> cancelled, marks queued/draft
  jobs as cancelled (in-flight ones complete naturally).
- POST /api/batches/[id]/simulate: demo-only. Picks ~10% of queued
  jobs, marks ~90% of those done with a placeholder video URL and
  ~10% failed. Updates batch counters atomically.
- GET /api/batches/[id]/export: streams a CSV with row-index,
  practice, trainer, studio, status, video URL, error, retries.
  Properly quotes cells, slugifies the filename.
- POST /api/jobs/[id]/retry: resets a failed job to queued so the
  worker re-attempts it.

UI
--
- app/batch/[id]/page.js: leaf route mounting BatchDetailShell.
- components/batch/BatchDetailShell.jsx: same MuAPI-key gate as
  BatchShell so opening a deep link works in a fresh browser.
- components/batch/BatchDetail.jsx: full progress dashboard.
  - Top header: back link, batch name, live status pill, CSV
    download button.
  - Progress card: done/total numbers, breakdown line
    (failed / running / queued), animated yellow bar, "auto-refresh
    every 3s" indicator while the batch is running or paused.
  - Settings strip: model / duration / quality / aspect / concurrency.
  - Filter pills: All | Pending | Done | Failed.
  - Demo button: " Simulate progress (demo)".
  - Jobs table: row index, practice (with inline error message),
    trainer, studio, status pill, ▶ Play (opens video preview modal),
    Retry (only on failed rows).
  - 3s polling driven by the running/paused state.
- components/batch/BatchesTab.jsx: rows are now clickable, the
  wizard navigates straight to the new batch's detail page after
  saving so the demo flow is one continuous click-through.

Verification
------------
- Created a 5-row batch via the API.
- start -> status went to running.
- simulate -> 1 done with placeholder URL, 0 failed (10% of 5 = 0
  failed by design).
- GET detail returned the batch with jobs joined to trainer/studio.
- /batch/[id] page returned 200.
- CSV export returned text/csv with the right columns and rows.
2026-04-23 08:48:42 +05:30

41 lines
1.1 KiB
JavaScript

'use client';
import { useEffect, useState } from 'react';
import ApiKeyModal from '@/components/ApiKeyModal';
import BatchDetail from './BatchDetail';
const STORAGE_KEY = 'muapi_key';
export default function BatchDetailShell({ batchId }) {
const [apiKey, setApiKey] = useState(null);
const [hasMounted, setHasMounted] = useState(false);
useEffect(() => {
setHasMounted(true);
const stored = typeof window !== 'undefined' ? localStorage.getItem(STORAGE_KEY) : null;
if (stored) {
setApiKey(stored);
document.cookie = `muapi_key=${stored}; path=/; max-age=31536000; SameSite=Lax`;
}
}, []);
const handleKeySave = (key) => {
localStorage.setItem(STORAGE_KEY, key);
document.cookie = `muapi_key=${key}; path=/; max-age=31536000; SameSite=Lax`;
setApiKey(key);
};
if (!hasMounted) {
return (
<div className="min-h-screen bg-[#050505] flex items-center justify-center">
<div className="animate-spin text-[#d9ff00] text-3xl"></div>
</div>
);
}
if (!apiKey) {
return <ApiKeyModal onSave={handleKeySave} />;
}
return <BatchDetail batchId={batchId} apiKey={apiKey} />;
}