'use client'; import { useState, useEffect } from 'react'; import { useRouter } from 'next/navigation'; import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, } from '@/components/ui/dialog'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { Github, Loader2, CheckCircle2, Copy, ExternalLink, ChevronLeft } from 'lucide-react'; import { toast } from 'sonner'; import { auth } from '@/lib/firebase/config'; import { Card, CardContent } from '@/components/ui/card'; import { Separator } from '@/components/ui/separator'; interface ProjectCreationModalProps { open: boolean; onOpenChange: (open: boolean) => void; initialWorkspacePath?: string; workspace: string; } export function ProjectCreationModal({ open, onOpenChange, initialWorkspacePath, workspace, }: ProjectCreationModalProps) { const router = useRouter(); // Steps: 1 = Name, 2 = GitHub, 3 = Instructions const [step, setStep] = useState(1); const [productName, setProductName] = useState(''); const [selectedRepo, setSelectedRepo] = useState(null); const [createdProjectId, setCreatedProjectId] = useState(null); const [loading, setLoading] = useState(false); const [githubConnected, setGithubConnected] = useState(false); const [githubRepos, setGithubRepos] = useState([]); const [loadingGithub, setLoadingGithub] = useState(false); // Check GitHub connection on mount and when moving to step 2 useEffect(() => { async function checkGitHub() { if (!open || step !== 2) return; setLoadingGithub(true); try { const user = auth.currentUser; if (!user) { console.log('[ProjectModal] No user found'); setLoadingGithub(false); return; } const token = await user.getIdToken(); const statusResponse = await fetch('/api/github/connect', { headers: { 'Authorization': `Bearer ${token}` }, }); if (statusResponse.ok) { const statusData = await statusResponse.json(); console.log('[ProjectModal] GitHub status:', statusData); const isConnected = statusData.connected || false; setGithubConnected(isConnected); if (isConnected) { const reposResponse = await fetch('/api/github/repos', { headers: { 'Authorization': `Bearer ${token}` }, }); if (reposResponse.ok) { const repos = await reposResponse.json(); // API returns array directly, not { repos: [] } console.log('[ProjectModal] GitHub repos loaded:', repos.length, 'repos'); setGithubRepos(Array.isArray(repos) ? repos : []); } else { console.error('[ProjectModal] Failed to fetch repos:', reposResponse.status); setGithubRepos([]); } } else { console.log('[ProjectModal] GitHub not connected'); setGithubRepos([]); } } else { console.error('[ProjectModal] Failed to check GitHub status:', statusResponse.status); setGithubConnected(false); setGithubRepos([]); } } catch (error) { console.error('[ProjectModal] Error checking GitHub:', error); setGithubConnected(false); setGithubRepos([]); } finally { setLoadingGithub(false); } } checkGitHub(); }, [open, step]); const resetModal = () => { setStep(1); setProductName(''); setSelectedRepo(null); setCreatedProjectId(null); setLoading(false); }; useEffect(() => { if (!open) { // Reset after closing animation setTimeout(resetModal, 200); } }, [open]); const handleCreateProject = async () => { if (!productName.trim()) { toast.error('Product name is required'); return; } setLoading(true); try { const user = auth.currentUser; if (!user) { toast.error('You must be signed in'); return; } const token = await user.getIdToken(); const projectData = { projectName: productName.trim(), projectType: selectedRepo ? 'existing' : 'scratch', slug: productName.toLowerCase().replace(/[^a-z0-9]+/g, '-'), product: { name: productName, }, ...(selectedRepo && { githubRepo: selectedRepo.full_name, githubRepoId: selectedRepo.id, githubRepoUrl: selectedRepo.html_url, githubDefaultBranch: selectedRepo.default_branch, }), }; const response = await fetch('/api/projects/create', { method: 'POST', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json', }, body: JSON.stringify(projectData), }); if (response.ok) { const data = await response.json(); setCreatedProjectId(data.projectId); toast.success('Project created!'); setStep(3); // Move to instructions } else { const error = await response.json(); toast.error(error.error || 'Failed to create project'); } } catch (error) { console.error('Error creating project:', error); toast.error('An error occurred'); } finally { setLoading(false); } }; const copyToClipboard = (text: string) => { navigator.clipboard.writeText(text); toast.success('Copied to clipboard!'); }; const handleFinish = () => { onOpenChange(false); if (createdProjectId) { router.push(`/${workspace}/project/${createdProjectId}/v_ai_chat`); } }; return ( {step === 1 && 'Create New Project'} {step === 2 && 'Connect GitHub Repository'} {step === 3 && 'Setup Complete!'} {step === 1 && 'Give your project a name to get started.'} {step === 2 && 'Select a GitHub repository to connect (optional).'} {step === 3 && 'Add the .vibn file to your project to enable tracking.'}
{/* Step 1: Name */} {step === 1 && (
setProductName(e.target.value)} onKeyDown={(e) => { if (e.key === 'Enter' && productName.trim()) { if (githubConnected) { setStep(2); } else { handleCreateProject(); } } }} autoFocus />

{githubConnected ? 'Connect your GitHub repository (optional)' : 'Connect GitHub or skip to continue'}

)} {/* Step 2: GitHub Selection */} {step === 2 && (
{loadingGithub ? (

Checking GitHub connection...

) : ( <>
{(() => { console.log('[ProjectModal Render] githubConnected:', githubConnected, 'repos:', githubRepos.length, 'reposData:', githubRepos); return null; })()} {githubRepos.length > 0 ? ( // Show repos if we have any githubRepos.map((repo) => ( )) ) : githubConnected ? ( // Connected but no repos

No repositories found

) : ( // Not connected - show connect button

GitHub not connected yet

)}
)}
)} {/* Step 3: Instructions */} {step === 3 && createdProjectId && (

Project created successfully!

Project ID: {createdProjectId}

Create a .vibn file in your project root with the following content:

{`{
  "projectId": "${createdProjectId}",
  "version": "1.0.0"
}`}
                      

This enables:

  • • Automatic session tracking from your cursor
  • • Cost monitoring per project
  • • AI chat history linking
  • • GitHub commit tracking
{selectedRepo && ( )}
)}
); }