import React, { useState, useEffect } from 'react'; import { Task, User } from '../types'; import { Plus, Search, Calendar, User as UserIcon, CheckCircle2, Clock, AlertCircle, Trash2, CheckCircle, MessageSquare, X } from 'lucide-react'; import { CommentSection } from './Collaboration'; import { useLocalCollection } from '../hooks/useLocalCollection'; interface TaskManagerProps { projectId: string; currentUser: User; } const TaskManager: React.FC = ({ projectId, currentUser }) => { const { data: tasks, add: addTask, update: updateTask, remove: removeTask } = useLocalCollection(`tasks_${projectId}`); const [users, setUsers] = useState([]); const [isModalOpen, setIsModalOpen] = useState(false); const [selectedTaskId, setSelectedTaskId] = useState(null); const [searchQuery, setSearchQuery] = useState(''); const [statusFilter, setStatusFilter] = useState('ALL'); const [newTask, setNewTask] = useState({ title: '', description: '', assignedTo: '', dueDate: new Date().toISOString().split('T')[0], priority: 'MEDIUM' as 'LOW' | 'MEDIUM' | 'HIGH' }); useEffect(() => { // In local mode, fetch from generic API fetch('/api/collections/users') .then(res => res.json()) .then(data => setUsers(data && data.length > 0 ? data : [currentUser])) .catch(e => { console.error(e); setUsers([currentUser]); }); }, [currentUser]); const handleCreateTask = async (e: React.FormEvent) => { e.preventDefault(); const taskId = `TASK-${Date.now()}`; const taskData: Task & { id: string } = { id: taskId, ...newTask, projectId, status: 'PENDING', createdAt: new Date().toISOString() }; await addTask(taskData); // Create a local notification via API if (newTask.assignedTo) { await fetch(`/api/collections/notifications_${newTask.assignedTo}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ id: `NOTIF-${Date.now()}`, recipientUid: newTask.assignedTo, type: 'TASK_ASSIGNED', title: 'New Task Assigned', message: `You have been assigned a new task: ${newTask.title}`, targetId: taskId, isRead: false, createdAt: new Date().toISOString() }) }); } setIsModalOpen(false); setNewTask({ title: '', description: '', assignedTo: '', dueDate: new Date().toISOString().split('T')[0], priority: 'MEDIUM' }); }; const handleUpdateStatus = async (taskId: string, newStatus: string) => { updateTask(taskId, { status: newStatus as any }); }; const handleDeleteTask = async (taskId: string) => { removeTask(taskId); if (selectedTaskId === taskId) setSelectedTaskId(null); }; const filteredTasks = tasks.filter(t => { const matchesSearch = t.title.toLowerCase().includes(searchQuery.toLowerCase()) || t.description.toLowerCase().includes(searchQuery.toLowerCase()); const matchesStatus = statusFilter === 'ALL' || t.status === statusFilter; return matchesSearch && matchesStatus; }); const getPriorityColor = (priority: string) => { switch(priority) { case 'HIGH': return 'text-red-600 bg-red-50 border-red-100'; case 'MEDIUM': return 'text-amber-600 bg-amber-50 border-amber-100'; case 'LOW': return 'text-blue-600 bg-blue-50 border-blue-100'; default: return 'text-slate-600 bg-slate-50 border-slate-100'; } }; const getStatusIcon = (status: string) => { switch(status) { case 'COMPLETED': return ; case 'IN_PROGRESS': return ; default: return ; } }; return (
{/* Header & Filters */}
setSearchQuery(e.target.value)} className="w-full pl-10 pr-4 py-2 bg-slate-50 border border-slate-200 rounded-lg focus:ring-2 focus:ring-blue-500 outline-none text-sm transition-all" />
{/* Task List */}
{filteredTasks.length > 0 ? ( filteredTasks.map((task) => (
setSelectedTaskId(task.id)} className={`bg-white p-4 rounded-xl border transition-all cursor-pointer group ${ selectedTaskId === task.id ? 'border-blue-500 shadow-md ring-1 ring-blue-500' : 'border-slate-200 hover:border-blue-300 hover:shadow-sm' }`} >
{task.title}
{task.priority}
{new Date(task.dueDate).toLocaleDateString()}

{task.description}

{task.assignedTo ? (
{users.find(u => u.uid === task.assignedTo)?.name || 'Assigned'}
) : ( Unassigned )}
Comments
)) ) : (

No tasks found matching your criteria.

)}
{/* Task Details / Comments Sidebar */} {selectedTaskId && (
)} {/* New Task Modal */} {isModalOpen && (

Create New Task

setNewTask({ ...newTask, title: e.target.value })} className="w-full px-4 py-2.5 bg-slate-50 border border-slate-200 rounded-xl focus:ring-2 focus:ring-blue-500 outline-none text-sm transition-all" placeholder="e.g. Complete foundation concrete" />