'use client' import { useState } from 'react' import { Plus, X } from 'lucide-react' import { createProject, updateProjectStatus, deleteProject } from '@/lib/actions' import { toast } from 'sonner' import { useConfirm } from '@/components/ui/confirm' import type { Tables } from '@/types/database' import { PageTitle } from '@/components/ui/page-title' import { Empty, EmptyHeader, EmptyMedia, EmptyTitle, EmptyDescription, EmptyContent } from '@/components/ui/empty' import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog' type Project = Tables<'projects'> const STATUS_COLS = [ { key: 'backlog', label: 'BACKLOG', color: 'text-muted-foreground', dot: 'bg-muted-foreground' }, { key: 'in_progress', label: 'IN PROGRESS', color: 'text-primary', dot: 'bg-primary' }, { key: 'review', label: 'REVIEW', color: 'text-blue-600', dot: 'bg-blue-500' }, { key: 'done', label: 'DONE', color: 'text-muted-foreground', dot: 'bg-muted-foreground' }, ] const DEFAULT_AREAS = ['3D Printing', 'Electronics', 'Woodshop', 'Laser', 'Metal Shop', 'Facilities', 'Admin', 'Software', 'General'] export function ProjectsClient({ projects: initialProjects, spaceId, areas, }: { projects: Project[]; spaceId: string; areas?: string[] }) { const confirm = useConfirm() const AREAS = areas && areas.length > 0 ? areas : DEFAULT_AREAS const [projects, setProjects] = useState(initialProjects) const [showCreate, setShowCreate] = useState(false) const [form, setForm] = useState({ title: '', description: '', area: '', tags: '', due_date: '' }) const [formLoading, setFormLoading] = useState(false) const [formError, setFormError] = useState('') const columns: Record = {} STATUS_COLS.forEach(col => { columns[col.key] = projects.filter(p => p.status === col.key) }) async function handleCreate(e: React.FormEvent) { e.preventDefault() setFormLoading(true) setFormError('') const result = await createProject({ title: form.title, description: form.description, area: form.area, tags: form.tags ? form.tags.split(',').map(t => t.trim()).filter(Boolean) : [], due_date: form.due_date, }) if (result.error) { setFormError(result.error); setFormLoading(false); return } if (result.data) setProjects(prev => [result.data as Project, ...prev]) setShowCreate(false) setForm({ title: '', description: '', area: '', tags: '', due_date: '' }) setFormLoading(false) } async function handleStatusChange(projectId: string, newStatus: string) { const result = await updateProjectStatus(projectId, newStatus) if (result?.error) { toast.error(result.error); return } setProjects(prev => prev.map(p => p.id === projectId ? { ...p, status: newStatus } : p)) } async function handleDelete(projectId: string) { if (!(await confirm({ title: 'Delete project', description: 'This project will be permanently removed.', confirmText: 'Delete', destructive: true }))) return const result = await deleteProject(projectId) if (result?.error) { toast.error(result.error); return } setProjects(prev => prev.filter(p => p.id !== projectId)) } return (
Projects
{projects.length === 0 ? ( No projects yet Track shop builds and tasks across backlog, in progress, review, and done. ) : (
{STATUS_COLS.map(col => { const items = columns[col.key] ?? [] return (

{col.label}

{items.length}
{items.map(project => (

{project.title}

{project.description && (

{project.description}

)}

{[project.area, project.due_date ? `due ${new Date(project.due_date).toLocaleDateString('en-US', { month: 'short', day: 'numeric' })}` : null].filter(Boolean).join(' ยท ')}

{project.progress !== undefined && project.progress !== null && (
)}
{project.tags?.map((tag: string) => ( {tag.toUpperCase()} ))}
{/* Status change */}
))}
) })}
)}
{ if (!o) setShowCreate(false) }}> New Project
setForm(f => ({ ...f, title: e.target.value }))} placeholder="CNC Controller Upgrade" className="w-full bg-background border border-border rounded px-3 py-2 font-sans text-sm text-foreground placeholder:text-muted-foreground focus:outline-none focus:border-primary transition" />