import { useEffect, useRef, useState } from 'react'; import { Badge } from '@renderer/components/ui/badge'; import { Button } from '@renderer/components/ui/button'; import { cn } from '@renderer/lib/utils'; import { useStore } from '@renderer/store'; import { CheckCircle2, X } from 'lucide-react'; import { useShallow } from 'zustand/react/shallow'; import { STEP_LABELS, STEP_ORDER } from './provisioningSteps'; import type { ProvisioningStep } from './provisioningSteps'; import type { TeamProvisioningProgress } from '@shared/types'; interface TeamProvisioningBannerProps { teamName: string; } function findProgressForTeam( runs: Record, teamName: string ): TeamProvisioningProgress | null { const entries = Object.values(runs); const matching = entries .filter((r) => r.teamName === teamName) .sort((a, b) => b.updatedAt.localeCompare(a.updatedAt)); return matching[0] ?? null; } const READY_DISMISS_MS = 5_000; export const TeamProvisioningBanner = ({ teamName, }: TeamProvisioningBannerProps): React.JSX.Element | null => { const { provisioningRuns, cancelProvisioning } = useStore( useShallow((s) => ({ provisioningRuns: s.provisioningRuns, cancelProvisioning: s.cancelProvisioning, })) ); const progress = findProgressForTeam(provisioningRuns, teamName); const [dismissed, setDismissed] = useState(false); const prevRunIdRef = useRef(progress?.runId); if (prevRunIdRef.current !== progress?.runId) { prevRunIdRef.current = progress?.runId; if (dismissed) { setDismissed(false); } } useEffect(() => { if (progress?.state !== 'ready') { return; } const timer = window.setTimeout(() => { setDismissed(true); }, READY_DISMISS_MS); return () => { window.clearTimeout(timer); }; }, [progress?.state, progress?.runId]); if (!progress || dismissed) { return null; } if (progress.state === 'cancelled') { return null; } const isReady = progress.state === 'ready'; const isFailed = progress.state === 'failed'; const isDisconnected = progress.state === 'disconnected'; const isActive = progress.state === 'validating' || progress.state === 'spawning' || progress.state === 'monitoring' || progress.state === 'verifying'; const canCancel = progress.state === 'spawning' || progress.state === 'monitoring' || progress.state === 'verifying'; const progressStepIndex = STEP_ORDER.indexOf(progress.state as ProvisioningStep); if (isFailed) { return (

{progress.message}

); } if (isDisconnected) { return (

Team offline

); } if (isReady) { return (

Team launched — process alive

); } if (isActive) { return (

{progress.message}

{canCancel ? ( ) : null}
{STEP_ORDER.map((step, index) => { const isDone = progressStepIndex >= 0 && index < progressStepIndex; const isCurrent = progressStepIndex >= 0 && index === progressStepIndex; return (
{index + 1} {STEP_LABELS[step]} {index < STEP_ORDER.length - 1 ? ( ) : null}
); })}
); } return null; };