"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 }) => (
{" "}

{task.task_name}

{task.priority} {" "} {showStatusBadge && ( )}
{task.project_name} WP: {task.wp} Plot: {task.plot}
{" "}
Added:{" "} {(() => { try { const addedDate = task.date_added.includes("T") ? parseISO(task.date_added) : new Date(task.date_added + "T00:00:00"); return formatDistanceToNow(addedDate, { addSuffix: true }); } catch (error) { return task.date_added; } })()} Max wait: {task.max_wait_days} days Type: {task.task_type}
{task.statusInfo && task.statusInfo.type === "overdue" && ( {task.statusInfo.days} days overdue )} {task.statusInfo && task.statusInfo.type === "due_soon" && ( Due in {task.statusInfo.days} days )}{" "} {(task.status === "pending" || task.status === "in_progress") && ( )}
); const SectionCard = ({ title, tasks, variant = "default", count }) => (

{title}

{count || tasks.length} {tasks.length === 1 ? "task" : "tasks"}
{tasks.length === 0 ? (

No tasks in this category

) : ( tasks.map((task) => ( )) )}
); const filterOptions = [ { value: "all", label: "All Categories" }, { value: "overdue", label: "Overdue" }, { value: "due_soon", label: "Due Soon" }, { value: "pending", label: "Pending" }, { value: "in_progress", label: "In Progress" }, { value: "completed", label: "Recent Activity" }, ]; if (loading) { return (
{[1, 2, 3, 4].map((i) => (
))}
); } return (
{" "} {/* Summary Stats */}
{categorizedTasks.overdue.length}
Overdue
{categorizedTasks.due_soon.length}
Due Soon
{categorizedTasks.pending.length}
Pending
{categorizedTasks.in_progress.length}
In Progress
{categorizedTasks.recent_completed.length}
Recent Activity
{/* Search and Filters */} setSearchTerm(e.target.value)} placeholder="Search tasks, projects, or WP..." resultsCount={ filter === "all" ? allTasks.length : Array.isArray(visibleTasks) ? visibleTasks.length : 0 } resultsText="tasks" filters={
} />{" "} {/* Task Sections */} {filter === "all" ? (
) : (
f.value === filter)?.label || "Tasks" } tasks={Array.isArray(visibleTasks) ? visibleTasks : []} variant={ filter === "overdue" ? "danger" : filter === "due_soon" ? "warning" : filter === "pending" ? "primary" : filter === "in_progress" ? "secondary" : "success" } />
)}
); }