'use client' import { useState, useEffect } from 'react' import { useParams } from 'next/navigation' import Link from 'next/link' import type { Route } from 'next' import { trpc } from '@/lib/trpc/client' import { Badge } from '@/components/ui/badge' import { Button } from '@/components/ui/button' import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from '@/components/ui/card' import { Skeleton } from '@/components/ui/skeleton' import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs' import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger, } from '@/components/ui/dropdown-menu' import { toast } from 'sonner' import { cn } from '@/lib/utils' import { ArrowLeft, Edit, MoreHorizontal, Rocket, Archive, Settings2, Layers, GitBranch, Loader2, } from 'lucide-react' import { IntakePanel } from '@/components/admin/pipeline/stage-panels/intake-panel' import { FilterPanel } from '@/components/admin/pipeline/stage-panels/filter-panel' import { EvaluationPanel } from '@/components/admin/pipeline/stage-panels/evaluation-panel' import { SelectionPanel } from '@/components/admin/pipeline/stage-panels/selection-panel' import { LiveFinalPanel } from '@/components/admin/pipeline/stage-panels/live-final-panel' import { ResultsPanel } from '@/components/admin/pipeline/stage-panels/results-panel' const statusColors: Record = { DRAFT: 'bg-gray-100 text-gray-700', ACTIVE: 'bg-emerald-100 text-emerald-700', ARCHIVED: 'bg-muted text-muted-foreground', CLOSED: 'bg-blue-100 text-blue-700', } const stageTypeColors: Record = { INTAKE: 'bg-blue-100 text-blue-700', FILTER: 'bg-amber-100 text-amber-700', EVALUATION: 'bg-purple-100 text-purple-700', SELECTION: 'bg-rose-100 text-rose-700', LIVE_FINAL: 'bg-emerald-100 text-emerald-700', RESULTS: 'bg-cyan-100 text-cyan-700', } function StagePanel({ stageId, stageType, configJson, }: { stageId: string stageType: string configJson: Record | null }) { switch (stageType) { case 'INTAKE': return case 'FILTER': return case 'EVALUATION': return case 'SELECTION': return case 'LIVE_FINAL': return case 'RESULTS': return default: return ( Unknown stage type: {stageType} ) } } export default function PipelineDetailPage() { const params = useParams() const pipelineId = params.id as string const [selectedTrackId, setSelectedTrackId] = useState(null) const [selectedStageId, setSelectedStageId] = useState(null) const { data: pipeline, isLoading } = trpc.pipeline.getDraft.useQuery({ id: pipelineId, }) // Auto-select first track and stage useEffect(() => { if (pipeline && pipeline.tracks.length > 0 && !selectedTrackId) { const firstTrack = pipeline.tracks[0] setSelectedTrackId(firstTrack.id) if (firstTrack.stages.length > 0) { setSelectedStageId(firstTrack.stages[0].id) } } }, [pipeline, selectedTrackId]) const publishMutation = trpc.pipeline.publish.useMutation({ onSuccess: () => toast.success('Pipeline published'), onError: (err) => toast.error(err.message), }) const updateMutation = trpc.pipeline.update.useMutation({ onSuccess: () => toast.success('Pipeline updated'), onError: (err) => toast.error(err.message), }) if (isLoading) { return (
) } if (!pipeline) { return (

Pipeline Not Found

The requested pipeline does not exist

) } const selectedTrack = pipeline.tracks.find((t) => t.id === selectedTrackId) const selectedStage = selectedTrack?.stages.find( (s) => s.id === selectedStageId ) const handleTrackChange = (trackId: string) => { setSelectedTrackId(trackId) const track = pipeline.tracks.find((t) => t.id === trackId) if (track && track.stages.length > 0) { setSelectedStageId(track.stages[0].id) } else { setSelectedStageId(null) } } return (
{/* Header */}

{pipeline.name}

{pipeline.status}

{pipeline.slug}

{pipeline.status === 'DRAFT' && ( publishMutation.mutate({ id: pipelineId }) } > {publishMutation.isPending ? ( ) : ( )} Publish )} {pipeline.status === 'ACTIVE' && ( updateMutation.mutate({ id: pipelineId, status: 'CLOSED', }) } > Close Pipeline )} updateMutation.mutate({ id: pipelineId, status: 'ARCHIVED', }) } > Archive
{/* Pipeline Summary */}
Tracks

{pipeline.tracks.length}

{pipeline.tracks.filter((t) => t.kind === 'MAIN').length} main,{' '} {pipeline.tracks.filter((t) => t.kind === 'AWARD').length} award

Stages

{pipeline.tracks.reduce((sum, t) => sum + t.stages.length, 0)}

across all tracks

Transitions

{pipeline.tracks.reduce( (sum, t) => sum + t.stages.reduce( (s, stage) => s + stage.transitionsFrom.length, 0 ), 0 )}

stage connections

{/* Track Tabs */} {pipeline.tracks.length > 0 && ( {pipeline.tracks .sort((a, b) => a.sortOrder - b.sortOrder) .map((track) => ( {track.name} {track.kind} ))} {pipeline.tracks.map((track) => ( {/* Track Info */}
{track.name} {track.slug}
{track.routingMode && ( {track.routingMode} )} {track.decisionMode && ( {track.decisionMode} )}
{/* Stage Tabs within Track */} {track.stages.length > 0 ? ( {track.stages .sort((a, b) => a.sortOrder - b.sortOrder) .map((stage) => ( {stage.name} {stage.stageType.replace('_', ' ')} ))} {track.stages.map((stage) => ( | null } /> ))} ) : ( No stages configured for this track )}
))}
)}
) }