// Tasks / Kanban Module function Tasks() { const emptycols = { todo: { title: 'A fazer', color: '#64748B', items: [] }, doing: { title: 'Em andamento', color: '#3B82F6', items: [] }, done: { title: 'Concluído', color: '#10B981', items: [] }, }; const [cols, setCols] = React.useState(emptycols); const [loading, setLoading] = React.useState(true); const [dragItem, setDragItem] = React.useState(null); const [dragFrom, setDragFrom] = React.useState(null); const [modal, setModal] = React.useState(false); const [editModal, setEditModal] = React.useState(false); const [editingTask, setEditingTask] = React.useState(null); const [editColKey, setEditColKey] = React.useState(null); const [newTask, setNewTask] = React.useState({ title: '', event: '', assignee: '', priority: 'Média', due: '' }); const [toast, setToast] = React.useState(null); const showToast = (msg) => { setToast({ msg }); setTimeout(() => setToast(null), 3000); }; const buildCols = (rows) => { const c = { todo: { title: 'A fazer', color: '#64748B', items: [] }, doing: { title: 'Em andamento', color: '#3B82F6', items: [] }, done: { title: 'Concluído', color: '#10B981', items: [] }, }; (rows || []).forEach(row => { const task = { id: row.id, title: row.title, event: row.event_name, assignee: row.assignee, priority: row.priority, due: row.due_date, tags: row.tags || [] }; if (c[row.column_key]) c[row.column_key].items.push(task); }); return c; }; React.useEffect(() => { sb.from('tasks').select('*').order('created_at').then(({ data }) => { if (data) setCols(buildCols(data)); setLoading(false); }); }, []); const priorityColor = { 'Alta': 'danger', 'Média': 'warning', 'Baixa': 'success' }; const tagColor = { 'Operacional': 'default', 'Cliente': 'primary', 'Jurídico': 'purple', 'Criativo': 'warning', 'Fornecedor': 'default', 'Comercial': 'success' }; const onDragStart = (item, fromCol) => { setDragItem(item); setDragFrom(fromCol); }; const onDrop = async (toCol) => { if (!dragItem || dragFrom === toCol) return; const toTitle = cols[toCol].title; setCols(prev => { const next = { ...prev }; next[dragFrom] = { ...next[dragFrom], items: next[dragFrom].items.filter(i => i.id !== dragItem.id) }; next[toCol] = { ...next[toCol], items: [...next[toCol].items, dragItem] }; return next; }); await sb.from('tasks').update({ column_key: toCol }).eq('id', dragItem.id); showToast(`Tarefa movida para "${toTitle}"`); setDragItem(null); setDragFrom(null); }; const addTask = async () => { if (!newTask.title.trim()) return; const { data } = await sb.from('tasks').insert({ title: newTask.title, event_name: newTask.event, assignee: newTask.assignee, priority: newTask.priority, due_date: newTask.due, tags: ['Operacional'], column_key: 'todo', }).select().single(); if (data) { const task = { id: data.id, title: data.title, event: data.event_name, assignee: data.assignee, priority: data.priority, due: data.due_date, tags: data.tags || [] }; setCols(prev => ({ ...prev, todo: { ...prev.todo, items: [task, ...prev.todo.items] } })); showToast('Tarefa criada com sucesso!'); } setModal(false); setNewTask({ title: '', event: '', assignee: '', priority: 'Média', due: '' }); }; const openEditTask = (task, colKey) => { setEditingTask({ ...task }); setEditColKey(colKey); setEditModal(true); }; const saveEditTask = async () => { if (!editingTask.title.trim()) return; const { error } = await sb.from('tasks').update({ title: editingTask.title, event_name: editingTask.event, assignee: editingTask.assignee, priority: editingTask.priority, due_date: editingTask.due, }).eq('id', editingTask.id); if (!error) { setCols(prev => ({ ...prev, [editColKey]: { ...prev[editColKey], items: prev[editColKey].items.map(t => t.id === editingTask.id ? editingTask : t) } })); showToast('Tarefa atualizada!'); } setEditModal(false); setEditingTask(null); }; const removeTask = async (colKey, taskId) => { setCols(prev => ({ ...prev, [colKey]: { ...prev[colKey], items: prev[colKey].items.filter(i => i.id !== taskId) } })); await sb.from('tasks').delete().eq('id', taskId); showToast('Tarefa removida'); }; const totalTasks = Object.values(cols).reduce((s, c) => s + c.items.length, 0); return (

Gestão de Tarefas

{totalTasks} tarefas · {cols.doing.items.length} em andamento

setModal(true)}>Nova tarefa
{loading ? : (
{Object.entries(cols).map(([colKey, col]) => (
e.preventDefault()} onDrop={() => onDrop(colKey)} style={{ background: '#F1F5F9', borderRadius: DS.radius.lg, padding: 16, minHeight: 400, transition: 'background 0.15s' }} >
{col.title} {col.items.length}
{col.items.map(task => (
onDragStart(task, colKey)} style={{ background: '#fff', borderRadius: DS.radius.md, padding: '14px 16px', boxShadow: DS.shadow.sm, border: `1px solid ${DS.colors.border}`, cursor: 'grab', transition: 'all 0.15s', userSelect: 'none' }} onMouseEnter={e => { e.currentTarget.style.boxShadow = DS.shadow.md; e.currentTarget.style.transform = 'translateY(-1px)'; }} onMouseLeave={e => { e.currentTarget.style.boxShadow = DS.shadow.sm; e.currentTarget.style.transform = 'none'; }} >
{task.title}
{task.event &&
{task.event}
}
{task.tags.map(t => {t})} {task.priority}
{(task.assignee || '').split(' ')[0]}
{task.due}
))} {col.items.length === 0 && (
Arraste tarefas aqui
)}
))}
)} setModal(false)} title="Nova tarefa">
setNewTask(t => ({ ...t, title: v }))} placeholder="Ex: Confirmar cardápio com fornecedor" /> setNewTask(t => ({ ...t, event: v }))} placeholder="Ex: Congresso Tech 2026" />
setNewTask(t => ({ ...t, assignee: v }))} placeholder="Ex: Ana Lima" /> setNewTask(t => ({ ...t, due: v }))} placeholder="Ex: 28 Abr" />
setEditingTask(t => ({ ...t, title: v }))} /> setEditingTask(t => ({ ...t, event: v }))} />
setEditingTask(t => ({ ...t, assignee: v }))} /> setEditingTask(t => ({ ...t, due: v }))} placeholder="Ex: 28 Abr" />