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 (
);
}
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(); }}
/>
);
}