import { useState } from 'react'
import { useNavigate } from 'react-router-dom'
import { useProject } from '../contexts/ProjectContext'
import { projectsApi } from '../api'
const COLORS = ['#0073ea', '#00c875', '#e2445c', '#fdab3d', '#a25ddc', '#037f4c', '#ff7575', '#579bfc', '#ff642e', '#00d0b0']
function ColorPicker({ value, onChange }) {
return (
{COLORS.map(c => (
)
}
function ProjectCard({ project, onSelect, onEdit, onDelete }) {
return (
e.currentTarget.style.boxShadow = '0 4px 16px rgba(0,0,0,0.12)'}
onMouseLeave={e => e.currentTarget.style.boxShadow = ''}
>
{project.name}
{project.description && (
{project.description}
)}
Created {new Date(project.created_at).toLocaleDateString()}
)
}
function ProjectModal({ project, onClose, onSave }) {
const [name, setName] = useState(project?.name || '')
const [description, setDescription] = useState(project?.description || '')
const [color, setColor] = useState(project?.color || COLORS[0])
const [saving, setSaving] = useState(false)
const [error, setError] = useState(null)
const handleSubmit = async (e) => {
e.preventDefault()
if (!name.trim()) { setError('Name is required'); return }
setSaving(true)
setError(null)
try {
const data = { name: name.trim(), description: description.trim() || null, color }
const result = project
? await projectsApi.update(project.id, data)
: await projectsApi.create(data)
onSave(result)
} catch (err) {
setError(err.message)
setSaving(false)
}
}
return (
{project ? 'Edit project' : 'New project'}
{error &&
{error}
}
)
}
export default function Projects() {
const { projects, activeProject, selectProject, addProject, updateProject, removeProject } = useProject()
const navigate = useNavigate()
const [modal, setModal] = useState(null) // null | 'new' | project object
const [deleting, setDeleting] = useState(null)
const [error, setError] = useState(null)
const handleSelect = (project) => {
selectProject(project)
navigate('/leads')
}
const handleSave = (result) => {
if (modal && modal !== 'new') updateProject(result)
else addProject(result)
setModal(null)
}
const handleDelete = async (project) => {
if (!window.confirm(`Delete project "${project.name}"? Leads won't be deleted.`)) return
setDeleting(project.id)
try {
await projectsApi.delete(project.id)
removeProject(project.id)
} catch (err) {
setError(err.message)
}
setDeleting(null)
}
return (
Projects
Organise your lead generation campaigns
{error &&
{error}
}
{projects.length === 0 ? (
◆
No projects yet
Create your first project to organise your leads
) : (
{projects.map(p => (
setModal(p)}
onDelete={handleDelete}
/>
))}
)}
{modal && (
setModal(null)}
onSave={handleSave}
/>
)}
)
}