'use client'; import { useState } from 'react'; import Link from 'next/link'; import { notFound } from 'next/navigation'; import { ArrowLeft, Plus, GripVertical, Trash2 } from 'lucide-react'; import { Button } from '@/components/ui/button'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; import { Badge } from '@/components/ui/badge'; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger, } from '@/components/ui/dialog'; import { useEffect } from 'react'; interface Step { id: number; name: string; category: 'deploy' | 'verify'; type: 'bash' | 'sql' | 'text'; content: string; orderIndex: number; description?: string; } interface PageProps { params: Promise<{ id: string; }>; } export default function StepsPage({ params }: PageProps) { const [releaseId, setReleaseId] = useState(''); const [release, setRelease] = useState(null); const [deploySteps, setDeploySteps] = useState([]); const [verifySteps, setVerifySteps] = useState([]); const [isLoading, setIsLoading] = useState(true); useEffect(() => { params.then(({ id }) => { setReleaseId(id); loadData(id); }); }, [params]); async function loadData(id: string) { try { const response = await fetch(`/api/releases/${id}`); if (!response.ok) throw new Error('Failed to load'); const data = await response.json(); setRelease(data); setDeploySteps(data.templates.filter((s: Step) => s.category === 'deploy').sort((a: Step, b: Step) => a.orderIndex - b.orderIndex)); setVerifySteps(data.templates.filter((s: Step) => s.category === 'verify').sort((a: Step, b: Step) => a.orderIndex - b.orderIndex)); } catch (error) { console.error(error); } finally { setIsLoading(false); } } if (isLoading) return
Loading...
; if (!release) return notFound(); return (

Manage Steps

{release.name}

Deploy Steps ({deploySteps.length}) Verify Steps ({verifySteps.length}) loadData(releaseId)} /> loadData(releaseId)} />
); } interface StepListProps { steps: Step[]; category: 'deploy' | 'verify'; releaseId: number; onUpdate: () => void; } function StepList({ steps, category, releaseId, onUpdate }: StepListProps) { const [isDialogOpen, setIsDialogOpen] = useState(false); async function handleAddStep(formData: FormData) { try { const response = await fetch('/api/steps', { method: 'POST', body: JSON.stringify({ releaseId, category, name: formData.get('name'), type: formData.get('type'), content: formData.get('content'), description: formData.get('description'), }), }); if (response.ok) { setIsDialogOpen(false); onUpdate(); } } catch (error) { console.error(error); } } async function handleDeleteStep(stepId: number) { if (!confirm('Are you sure you want to delete this step?')) return; try { const response = await fetch(`/api/steps/${stepId}`, { method: 'DELETE' }); if (response.ok) onUpdate(); } catch (error) { console.error(error); } } return ( {category} Steps Add {category} Step