import { useEffect, useState } from 'react'; import { Plus, ArrowLeft, ArrowRight, Trash2, CheckSquare } from 'lucide-react'; import { api, fmt } from '../api'; import { Btn, Field, inputCls, Modal, Spinner, ErrorBox, StatusBadge, Badge, EmptyState } from '../components/ui'; export const TASK_STATUS_LABELS = { todo: 'Te doen', in_progress: 'Bezig', done: 'Klaar', cancelled: 'Geannuleerd' }; export const PRIORITY_LABELS = { critical: 'Kritiek', high: 'Hoog', medium: 'Gemiddeld', low: 'Laag' }; const COLUMNS = ['todo', 'in_progress', 'done', 'cancelled']; const FLOW = ['todo', 'in_progress', 'done']; const EMPTY_FORM = { engagement_id: '', title: '', priority: 'medium', due_date: '' }; function TaskFormModal({ open, onClose, engagements, onSaved }) { const [form, setForm] = useState(EMPTY_FORM); const [saving, setSaving] = useState(false); const [error, setError] = useState(null); useEffect(() => { if (!open) return; setError(null); setForm(EMPTY_FORM); }, [open]); const set = (k) => (e) => setForm((f) => ({ ...f, [k]: e.target.value })); const submit = async (e) => { e.preventDefault(); setSaving(true); setError(null); try { await api.post('/tasks', { ...form, due_date: form.due_date || null }); onSaved(); } catch (err) { setError(err); } finally { setSaving(false); } }; return (
Annuleren Aanmaken
); } function TaskCard({ task, onMove, onDelete }) { const today = new Date().toISOString().slice(0, 10); const overdue = task.due_date && task.due_date < today && task.status !== 'done' && task.status !== 'cancelled'; const idx = FLOW.indexOf(task.status); return (
{task.title}
{task.client_name} ยท {task.engagement_title}
{task.due_date && ( {fmt.date(task.due_date)} )}
{idx > 0 && ( )} {idx >= 0 && idx < FLOW.length - 1 && ( )}
); } export default function Tasks() { const [data, setData] = useState(null); const [engagements, setEngagements] = useState([]); const [error, setError] = useState(null); const [modalOpen, setModalOpen] = useState(false); const load = () => { setError(null); api.get('/tasks').then(setData).catch(setError); }; useEffect(load, []); useEffect(() => { api.get('/engagements').then(setEngagements).catch(() => { /* opties voor modal */ }); }, []); const move = async (task, status) => { try { await api.post(`/tasks/${task.id}/status`, { status }); load(); } catch (err) { setError(err); } }; const remove = async (task) => { if (!window.confirm(`Taak "${task.title}" verwijderen?`)) return; try { await api.del(`/tasks/${task.id}`); load(); } catch (err) { setError(err); } }; return (

Taken

Kanban-overzicht van alle taken

setModalOpen(true)}> Nieuwe taak
{error && } {!data && !error && } {data && data.length === 0 && ( setModalOpen(true)}> Nieuwe taak} /> )} {data && data.length > 0 && (
{COLUMNS.map((col) => { const colTasks = data.filter((t) => t.status === col); return (
{TASK_STATUS_LABELS[col]} {colTasks.length}
{colTasks.map((t) => ( ))} {colTasks.length === 0 && (
Geen taken
)}
); })}
)} setModalOpen(false)} engagements={engagements} onSaved={() => { setModalOpen(false); load(); }} />
); }