- Add BatchStatusPage (/flows/:id/batches/:batchId): per-target Start/Resume/View cards, progress bar, 5s polling while in-progress, completion outcome summary - Add BatchStatusCard: handles not-started/in-progress/complete states with step progress for in-progress targets - Add ActiveBatchBanner: amber banner on detail page when a batch is running, links to BatchStatusPage - Add MaintenanceContextStrip: amber strip in ProceduralNavigationPage for maintenance flows showing target name, batch progress (X/Y complete), and Back to Batch nav - Update MaintenanceFlowDetailPage: active batch banner, clickable run history rows with mini progress dots and outcome summaries, Run button loading state, post-launch navigates to BatchStatusPage - Update ProceduralNavigationPage: renders MaintenanceContextStrip between top bar and content when tree_type === 'maintenance'; fetches batch progress once on mount - Add batch_id filter to GET /sessions backend endpoint and SessionListParams frontend type - Add /flows/:id/batches/:batchId route to router Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
47 lines
1.7 KiB
TypeScript
47 lines
1.7 KiB
TypeScript
import { X, RefreshCw, ChevronRight } from 'lucide-react'
|
|
import { useNavigate } from 'react-router-dom'
|
|
import type { Session } from '@/types'
|
|
|
|
interface ActiveBatchBannerProps {
|
|
treeId: string
|
|
sessions: Session[]
|
|
onDismiss: () => void
|
|
}
|
|
|
|
export function ActiveBatchBanner({ treeId, sessions, onDismiss }: ActiveBatchBannerProps) {
|
|
const navigate = useNavigate()
|
|
|
|
// Find the most recently started in-progress batch
|
|
const inProgressSessions = sessions.filter(s => s.started_at && !s.completed_at && s.batch_id)
|
|
if (inProgressSessions.length === 0) return null
|
|
|
|
const batchId = inProgressSessions[0].batch_id!
|
|
|
|
// Count all sessions in this batch
|
|
const batchSessions = sessions.filter(s => s.batch_id === batchId)
|
|
const completed = batchSessions.filter(s => s.completed_at).length
|
|
const total = batchSessions.length
|
|
|
|
return (
|
|
<div className="flex items-center gap-3 rounded-xl border border-amber-500/30 bg-amber-500/5 px-4 py-3">
|
|
<RefreshCw className="h-4 w-4 shrink-0 animate-spin text-amber-400" />
|
|
<p className="flex-1 text-[0.875rem] text-amber-300">
|
|
Batch in progress · <span className="font-medium">{completed} of {total}</span> targets complete
|
|
</p>
|
|
<button
|
|
onClick={() => navigate(`/flows/${treeId}/batches/${batchId}`)}
|
|
className="flex items-center gap-1 text-[0.8125rem] font-medium text-amber-400 hover:text-amber-300 transition-colors"
|
|
>
|
|
View Batch
|
|
<ChevronRight className="h-3.5 w-3.5" />
|
|
</button>
|
|
<button
|
|
onClick={onDismiss}
|
|
className="rounded-md p-1 text-muted-foreground hover:bg-accent hover:text-foreground transition-colors"
|
|
>
|
|
<X className="h-3.5 w-3.5" />
|
|
</button>
|
|
</div>
|
|
)
|
|
}
|