"use client"; import { useState, useEffect } from "react"; import { Card, CardHeader, CardContent } from "./ui/Card"; import Button from "./ui/Button"; import Badge from "./ui/Badge"; import TaskStatusDropdownSimple from "./TaskStatusDropdownSimple"; import SearchBar from "./ui/SearchBar"; import { Select } from "./ui/Input"; import Link from "next/link"; import { differenceInCalendarDays, parseISO, formatDistanceToNow, } from "date-fns"; import { formatDate } from "@/lib/utils"; export default function ProjectTasksDashboard() { const [allTasks, setAllTasks] = useState([]); const [loading, setLoading] = useState(true); const [filter, setFilter] = useState("all"); const [searchTerm, setSearchTerm] = useState(""); useEffect(() => { const fetchAllTasks = async () => { try { const res = await fetch("/api/all-project-tasks"); const tasks = await res.json(); setAllTasks(tasks); } catch (error) { console.error("Failed to fetch project tasks:", error); } finally { setLoading(false); } }; fetchAllTasks(); }, []); // Calculate task status based on date_added and max_wait_days const getTaskStatus = (task) => { if (task.status === "completed" || task.status === "cancelled") { return { type: "completed", days: 0 }; } try { // Handle different date formats const addedDate = task.date_added.includes("T") ? parseISO(task.date_added) : new Date(task.date_added + "T00:00:00"); const daysElapsed = differenceInCalendarDays(new Date(), addedDate); const maxWaitDays = task.max_wait_days || 0; const daysOverdue = daysElapsed - maxWaitDays; if (daysOverdue > 0) { return { type: "overdue", days: daysOverdue }; } else if (maxWaitDays - daysElapsed <= 2) { return { type: "due_soon", days: maxWaitDays - daysElapsed }; } else { return { type: "pending", days: maxWaitDays - daysElapsed }; } } catch (error) { console.error("Error parsing date:", task.date_added, error); return { type: "pending", days: 0 }; } }; // Categorize tasks const categorizeTasks = () => { const now = new Date(); const categories = { overdue: [], due_soon: [], pending: [], in_progress: [], recent_completed: [], }; allTasks.forEach((task) => { const taskStatus = getTaskStatus(task); try { const addedDate = task.date_added.includes("T") ? parseISO(task.date_added) : new Date(task.date_added + "T00:00:00"); const daysAgo = differenceInCalendarDays(now, addedDate); // First check if task is overdue (regardless of status) if ( taskStatus.type === "overdue" && task.status !== "completed" && task.status !== "cancelled" ) { categories.overdue.push({ ...task, statusInfo: taskStatus }); } // Then check if it's due soon (regardless of status) else if ( taskStatus.type === "due_soon" && task.status !== "completed" && task.status !== "cancelled" ) { categories.due_soon.push({ ...task, statusInfo: taskStatus }); } // Then categorize by actual status else if (task.status === "pending") { categories.pending.push({ ...task, statusInfo: taskStatus }); } else if (task.status === "in_progress") { categories.in_progress.push({ ...task, statusInfo: taskStatus }); } else if (task.status === "completed" || task.status === "cancelled") { // Show all completed/cancelled tasks (most recent activity) categories.recent_completed.push({ ...task, statusInfo: taskStatus }); } } catch (error) { console.error("Error processing task:", task, error); // Still add to appropriate category if there's an error if (task.status === "pending") { categories.pending.push({ ...task, statusInfo: { type: "pending", days: 0 }, }); } else if (task.status === "in_progress") { categories.in_progress.push({ ...task, statusInfo: { type: "pending", days: 0 }, }); } } }); // Sort each category categories.overdue.sort((a, b) => b.statusInfo.days - a.statusInfo.days); categories.due_soon.sort((a, b) => a.statusInfo.days - b.statusInfo.days); categories.pending.sort((a, b) => { try { const dateA = a.date_added.includes("T") ? parseISO(a.date_added) : new Date(a.date_added + "T00:00:00"); const dateB = b.date_added.includes("T") ? parseISO(b.date_added) : new Date(b.date_added + "T00:00:00"); return dateB - dateA; } catch (error) { return 0; } }); categories.in_progress.sort((a, b) => { try { const dateA = a.date_added.includes("T") ? parseISO(a.date_added) : new Date(a.date_added + "T00:00:00"); const dateB = b.date_added.includes("T") ? parseISO(b.date_added) : new Date(b.date_added + "T00:00:00"); return dateB - dateA; } catch (error) { return 0; } }); categories.recent_completed.sort((a, b) => { try { const dateA = a.date_added.includes("T") ? parseISO(a.date_added) : new Date(a.date_added + "T00:00:00"); const dateB = b.date_added.includes("T") ? parseISO(b.date_added) : new Date(b.date_added + "T00:00:00"); return dateB - dateA; } catch (error) { return 0; } }); return categories; }; const categorizedTasks = categorizeTasks(); // Filter tasks based on search and filter const filterTasks = (tasks) => { if (!searchTerm) return tasks; return tasks.filter( (task) => task.task_name.toLowerCase().includes(searchTerm.toLowerCase()) || task.project_name.toLowerCase().includes(searchTerm.toLowerCase()) || task.wp.toLowerCase().includes(searchTerm.toLowerCase()) ); }; const getVisibleTasks = () => { switch (filter) { case "overdue": return filterTasks(categorizedTasks.overdue); case "due_soon": return filterTasks(categorizedTasks.due_soon); case "pending": return filterTasks(categorizedTasks.pending); case "in_progress": return filterTasks(categorizedTasks.in_progress); case "completed": return filterTasks(categorizedTasks.recent_completed); default: return { overdue: filterTasks(categorizedTasks.overdue), due_soon: filterTasks(categorizedTasks.due_soon), pending: filterTasks(categorizedTasks.pending), in_progress: filterTasks(categorizedTasks.in_progress), recent_completed: filterTasks(categorizedTasks.recent_completed), }; } }; const visibleTasks = getVisibleTasks(); const handleStatusChange = async (taskId, newStatus) => { try { const res = await fetch(`/api/project-tasks/${taskId}`, { method: "PATCH", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ status: newStatus }), }); if (res.ok) { // Refresh tasks const res2 = await fetch("/api/all-project-tasks"); const tasks = await res2.json(); setAllTasks(tasks); } else { alert("Failed to update task status"); } } catch (error) { alert("Error updating task status"); } }; const getPriorityVariant = (priority) => { switch (priority) { case "urgent": return "urgent"; case "high": return "high"; case "normal": return "normal"; case "low": return "low"; default: return "default"; } }; const getOverdueBadgeVariant = (days) => { if (days > 7) return "danger"; if (days > 3) return "warning"; return "high"; }; const TaskCard = ({ task, showStatusBadge = false }) => (
No tasks in this category