import React, { useState } from 'react'; import { Plus, MoreHorizontal, Clock, UserCircle, X, DollarSign, GripVertical, Trash2, Building2 } from 'lucide-react'; import { KanbanColumn, KanbanTask, Company, Receivable } from '../types'; import { useToast } from '../contexts/ToastContext'; import { CustomSelect } from './CustomSelect'; const initialColumns: KanbanColumn[] = [ { id: 'todo', title: 'A Fazer', tasks: [ { id: 't1', title: 'Criar contrato Uda Studios', priority: 'high', dueDate: '2024-05-15', value: 12000, description: 'Negociação referente ao projeto de redesign completo.' }, { id: 't2', title: 'Revisar balanço trimestral', priority: 'medium', dueDate: '2024-05-20', value: 0, description: 'Verificar lançamentos de março e abril.' }, ] }, { id: 'progress', title: 'Em Progresso', tasks: [ { id: 't3', title: 'Design do Dashboard', priority: 'high', dueDate: '2024-05-18', value: 5000 }, ] }, { id: 'review', title: 'Revisão', tasks: [ { id: 't4', title: 'Aprovação de Orçamento', priority: 'low', dueDate: '2024-05-12', value: 3500 }, ] }, { id: 'done', title: 'Concluído', tasks: [ { id: 't5', title: 'Onboarding Angels Healthcare', priority: 'medium', dueDate: '2024-05-10', value: 15000 }, ] } ]; interface KanbanViewProps { companies: Company[]; onAddReceivable: (receivable: Receivable) => void; } export const KanbanView: React.FC = ({ companies, onAddReceivable }) => { const { addToast } = useToast(); const [columns, setColumns] = useState(initialColumns); // States para Modais const [isTaskModalOpen, setIsTaskModalOpen] = useState(false); const [isColumnModalOpen, setIsColumnModalOpen] = useState(false); // State de Edição/Criação const [currentTask, setCurrentTask] = useState>({}); const [currentColumnId, setCurrentColumnId] = useState('todo'); const [newColumnTitle, setNewColumnTitle] = useState(''); const [draggedTaskId, setDraggedTaskId] = useState(null); const [draggedSourceColumnId, setDraggedSourceColumnId] = useState(null); // --- Drag and Drop Logic --- const handleDragStart = (e: React.DragEvent, taskId: string, columnId: string) => { setDraggedTaskId(taskId); setDraggedSourceColumnId(columnId); e.dataTransfer.effectAllowed = 'move'; }; const handleDragOver = (e: React.DragEvent) => { e.preventDefault(); // Necessary to allow dropping e.dataTransfer.dropEffect = 'move'; }; const handleDrop = (e: React.DragEvent, targetColumnId: string) => { e.preventDefault(); if (!draggedTaskId || !draggedSourceColumnId) return; if (draggedSourceColumnId === targetColumnId) { setDraggedTaskId(null); setDraggedSourceColumnId(null); return; } // Move logic const sourceCol = columns.find(c => c.id === draggedSourceColumnId); const targetCol = columns.find(c => c.id === targetColumnId); const taskToMove = sourceCol?.tasks.find(t => t.id === draggedTaskId); if (sourceCol && targetCol && taskToMove) { const newColumns = columns.map(col => { if (col.id === draggedSourceColumnId) { return { ...col, tasks: col.tasks.filter(t => t.id !== draggedTaskId) }; } if (col.id === targetColumnId) { return { ...col, tasks: [...col.tasks, taskToMove] }; } return col; }); setColumns(newColumns); // INTEGRAÇÃO FINANCEIRA: Se moveu para "Concluído" (done), tem valor e cliente, sugere faturar if (targetColumnId === 'done' && taskToMove.value && taskToMove.value > 0 && taskToMove.clientId) { const client = companies.find(c => c.id === taskToMove.clientId); // Use toast with action instead of window.confirm for better UI? // For now, simpler confirmation but using toast for success if (window.confirm(`A tarefa "${taskToMove.title}" foi concluída.\n\nDeseja gerar automaticamente uma Conta a Receber no valor de R$ ${taskToMove.value.toLocaleString('pt-BR')}?`)) { const newReceivable: Receivable = { id: Math.random().toString(36).substr(2, 9), description: taskToMove.title, companyName: client?.fantasyName || client?.name || 'Cliente Kanban', category: 'Serviços', // Default category value: taskToMove.value, dueDate: taskToMove.dueDate || new Date().toISOString().split('T')[0], status: 'pending', type: 'one-time' }; onAddReceivable(newReceivable); addToast({ type: 'success', title: 'Faturamento Gerado', message: `Conta a receber criada para ${client?.fantasyName}.` }); } } } setDraggedTaskId(null); setDraggedSourceColumnId(null); }; // --- CRUD Logic --- const openNewTaskModal = () => { setCurrentTask({ priority: 'medium', dueDate: new Date().toISOString().split('T')[0], value: 0, description: '' }); setCurrentColumnId(columns[0].id); // Default to first column setIsTaskModalOpen(true); }; const openEditTaskModal = (task: KanbanTask, colId: string) => { setCurrentTask(task); setCurrentColumnId(colId); setIsTaskModalOpen(true); }; const handleSaveTask = () => { if (!currentTask.title) { addToast({ type: 'warning', title: 'Título Obrigatório', message: 'Dê um nome para a tarefa.' }); return; } // Check if updating existing or creating new if (currentTask.id) { // Logic to update existing task (potentially moving columns) const newColumns = columns.map(col => { // Remove from all columns first (in case it moved) const filteredTasks = col.tasks.filter(t => t.id !== currentTask.id); // If this is the target column, add the updated task if (col.id === currentColumnId) { return { ...col, tasks: [...filteredTasks, currentTask as KanbanTask] }; } return { ...col, tasks: filteredTasks }; }); setColumns(newColumns); addToast({ type: 'success', title: 'Tarefa Atualizada' }); } else { // Create new const newTask: KanbanTask = { ...currentTask, id: Math.random().toString(36).substr(2, 9), } as KanbanTask; const newColumns = columns.map(col => { if (col.id === currentColumnId) { return { ...col, tasks: [newTask, ...col.tasks] }; // Add to top } return col; }); setColumns(newColumns); addToast({ type: 'success', title: 'Tarefa Criada' }); } setIsTaskModalOpen(false); }; const handleDeleteTask = () => { if (!currentTask.id) return; if (window.confirm('Tem certeza que deseja excluir esta tarefa?')) { const newColumns = columns.map(col => ({ ...col, tasks: col.tasks.filter(t => t.id !== currentTask.id) })); setColumns(newColumns); setIsTaskModalOpen(false); addToast({ type: 'info', title: 'Tarefa Excluída' }); } }; const handleCreateColumn = () => { if (!newColumnTitle) return; const newCol: KanbanColumn = { id: Math.random().toString(36).substr(2, 9), title: newColumnTitle, tasks: [] }; setColumns([...columns, newCol]); setNewColumnTitle(''); setIsColumnModalOpen(false); addToast({ type: 'success', title: 'Coluna Adicionada' }); }; // Styles for Inputs (High Contrast) const labelClass = "block text-sm font-bold text-slate-800 mb-1"; const inputClass = "w-full p-2.5 bg-white border border-slate-300 rounded-xl text-slate-900 placeholder-slate-400 focus:ring-2 focus:ring-primary-500 focus:border-primary-500 outline-none transition-shadow"; return (
{/* Task Modal (Create & Edit) */} {isTaskModalOpen && (
setIsTaskModalOpen(false)}>

{currentTask.id ? 'Detalhes da Tarefa' : 'Nova Tarefa'}

{currentTask.id && ( )}
{/* Title */}
setCurrentTask({...currentTask, title: e.target.value})} placeholder="Ex: Reunião com Cliente X" />
{/* Status & Priority Row */}
setCurrentColumnId(val)} options={columns.map(col => ({ value: col.id, label: col.title }))} />
setCurrentTask({...currentTask, priority: val})} options={[ { value: 'low', label: 'Baixa' }, { value: 'medium', label: 'Média' }, { value: 'high', label: 'Alta' } ]} />
{/* CRM Linkage */}
setCurrentTask({...currentTask, clientId: val})} placeholder="Sem vínculo" icon={} options={[ { value: '', label: 'Sem vínculo' }, ...companies.map(c => ({ value: c.id, label: c.fantasyName || c.name })) ]} />

Ao concluir a tarefa, o sistema oferecerá gerar cobrança para este cliente.

{/* Commercial Data Section */}

Dados Comerciais & Agenda

setCurrentTask({...currentTask, value: Number(e.target.value)})} placeholder="0,00" />
setCurrentTask({...currentTask, dueDate: e.target.value})} />