'use client'; import { useState, useEffect, useRef } from 'react'; import { useRouter } from 'next/navigation'; import { toast } from 'sonner'; interface ProjectCreationModalProps { open: boolean; onOpenChange: (open: boolean) => void; workspace: string; initialWorkspacePath?: string; } const PROJECT_TYPES = [ { id: 'web-app', label: 'Web App', icon: '⬡', desc: 'SaaS product users log into — dashboards, accounts, core features' }, { id: 'website', label: 'Website', icon: '◎', desc: 'Marketing site, landing page, or content-driven public site' }, { id: 'marketplace', label: 'Marketplace', icon: '⇄', desc: 'Two-sided platform connecting buyers and sellers or providers' }, { id: 'mobile', label: 'Mobile App', icon: '▢', desc: 'iOS and Android app — touch-first, native feel' }, { id: 'internal', label: 'Internal Tool', icon: '◫', desc: 'Admin panel, ops dashboard, or business process tool' }, { id: 'ai-product', label: 'AI Product', icon: '◈', desc: 'AI-native product — copilot, agent, or model-powered workflow' }, ]; export function ProjectCreationModal({ open, onOpenChange, workspace }: ProjectCreationModalProps) { const router = useRouter(); const [step, setStep] = useState<1 | 2>(1); const [productName, setProductName] = useState(''); const [projectType, setProjectType] = useState(null); const [loading, setLoading] = useState(false); const inputRef = useRef(null); useEffect(() => { if (open) { setStep(1); setProductName(''); setProjectType(null); setLoading(false); setTimeout(() => inputRef.current?.focus(), 80); } }, [open]); useEffect(() => { if (!open) return; const handler = (e: KeyboardEvent) => { if (e.key === 'Escape') onOpenChange(false); }; window.addEventListener('keydown', handler); return () => window.removeEventListener('keydown', handler); }, [open, onOpenChange]); const handleCreate = async () => { if (!productName.trim() || !projectType) return; setLoading(true); try { const res = await fetch('/api/projects/create', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ projectName: productName.trim(), projectType, slug: productName.toLowerCase().replace(/[^a-z0-9]+/g, '-'), product: { name: productName.trim(), type: projectType }, }), }); if (!res.ok) { const err = await res.json(); toast.error(err.error || 'Failed to create project'); return; } const data = await res.json(); onOpenChange(false); router.push(`/${workspace}/project/${data.projectId}/overview`); } catch { toast.error('Something went wrong'); } finally { setLoading(false); } }; if (!open) return null; return ( <> {/* Backdrop */}
onOpenChange(false)} style={{ position: 'fixed', inset: 0, zIndex: 50, background: 'rgba(26,26,26,0.35)', animation: 'fadeIn 0.15s ease', }} /> {/* Modal */}
e.stopPropagation()} style={{ background: '#fff', borderRadius: 14, boxShadow: '0 8px 40px rgba(26,26,26,0.14)', padding: '32px 36px', width: '100%', maxWidth: step === 2 ? 560 : 460, fontFamily: 'Outfit, sans-serif', pointerEvents: 'all', animation: 'slideUp 0.18s cubic-bezier(0.4,0,0.2,1)', transition: 'max-width 0.2s ease', }} > {/* Header */}
{step === 2 && ( )}

{step === 1 ? 'New project' : `What are you building?`}

{step === 1 ? 'Give your project a name to get started.' : `Choose the type that best fits "${productName}".`}

{/* Step 1 — Name */} {step === 1 && (
setProductName(e.target.value)} onKeyDown={e => { if (e.key === 'Enter' && productName.trim()) setStep(2); }} placeholder="e.g. Foxglove, Meridian, OpsAI…" style={{ width: '100%', padding: '11px 14px', marginBottom: 16, borderRadius: 8, border: '1px solid #e0dcd4', background: '#faf8f5', fontSize: '0.9rem', fontFamily: 'Outfit, sans-serif', color: '#1a1a1a', outline: 'none', transition: 'border-color 0.12s', boxSizing: 'border-box', }} onFocus={e => (e.currentTarget.style.borderColor = '#1a1a1a')} onBlur={e => (e.currentTarget.style.borderColor = '#e0dcd4')} />
)} {/* Step 2 — Project type */} {step === 2 && (
{PROJECT_TYPES.map(type => { const isSelected = projectType === type.id; return ( ); })}
)}
); }