"use client";
import { useState, useEffect, useCallback, useRef } from "react";
import { FolderKanban, RefreshCw, LayoutDashboard, ListTodo, FileText, GanttChartSquare } from "lucide-react";
import { toast } from "sonner";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { Button } from "@/components/ui/button";
import { Skeleton } from "@/components/ui/skeleton";
import { Card, CardContent } from "@/components/ui/card";
import { ProjectHeader } from "./project-header";
import { ProjectStats } from "./project-stats";
import { ProjectInfo } from "./project-info";
import { TasksSection } from "./tasks-section";
import { ProjectTaskGantt } from "./project-task-gantt";
import { Project } from "@/types/project";
import { Task } from "@/types/task";
import { getTasksByProjectId, calculateTaskStats } from "@/lib/tasksService";
interface ProjectDetailViewProps {
project: Project;
}
// Skeleton para loading (exportado para uso externo)
export function ProjectDetailSkeleton() {
return (
{/* Header skeleton */}
{/* Stats skeleton */}
{Array.from({ length: 4 }).map((_, i) => (
))}
{/* Content skeleton */}
);
}
// Estado de error
function ErrorState({ onRetry }: { onRetry: () => void }) {
return (
Error al cargar las tareas
No se pudieron cargar las tareas del proyecto. Por favor, intenta de nuevo.
);
}
export function ProjectDetailView({ project: initialProject }: ProjectDetailViewProps) {
const [project, setProject] = useState(initialProject);
const [tasks, setTasks] = useState([]);
const [isLoadingTasks, setIsLoadingTasks] = useState(true);
const [tasksError, setTasksError] = useState(null);
const hasShownReminders = useRef(false);
// Cargar tareas
const fetchTasks = useCallback(async () => {
setIsLoadingTasks(true);
setTasksError(null);
try {
const projectTasks = await getTasksByProjectId(project.id);
setTasks(projectTasks);
} catch (error) {
console.error("Error fetching tasks:", error);
setTasksError("Error al cargar las tareas");
} finally {
setIsLoadingTasks(false);
}
}, [project.id]);
useEffect(() => {
fetchTasks();
}, [fetchTasks]);
useEffect(() => {
if (isLoadingTasks || tasksError || hasShownReminders.current) return;
const now = new Date();
const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
const upcomingThreshold = new Date(today);
upcomingThreshold.setDate(upcomingThreshold.getDate() + 7);
const overdueTasks = tasks.filter((task) => {
const endDate = task.endDate || task.plannedEndDate;
if (!endDate) return false;
return new Date(endDate) < today && task.status !== "2";
});
const upcomingTasks = tasks.filter((task) => {
const endDate = task.endDate || task.plannedEndDate;
if (!endDate) return false;
const due = new Date(endDate);
return due >= today && due <= upcomingThreshold && task.status !== "2";
});
const undatedTasks = tasks.filter((task) => {
return !task.startDate && !task.endDate && !task.plannedStartDate && !task.plannedEndDate;
});
if (overdueTasks.length === 0 && upcomingTasks.length === 0 && undatedTasks.length === 0) {
hasShownReminders.current = true;
return;
}
const lines: string[] = [];
if (overdueTasks.length > 0) lines.push(`• ${overdueTasks.length} tareas retrasadas`);
if (upcomingTasks.length > 0) lines.push(`• ${upcomingTasks.length} próximas a vencer (≤ 7 días)`);
if (undatedTasks.length > 0) lines.push(`• ${undatedTasks.length} sin fecha asignada`);
toast("Recordatorios del proyecto", {
description: lines.join("\n"),
});
hasShownReminders.current = true;
}, [isLoadingTasks, tasksError, tasks]);
// Handler para cuando se actualiza el proyecto
const handleProjectUpdated = (updatedProject: Project) => {
setProject(updatedProject);
};
// Handler para cuando se crea una tarea
const handleTaskCreated = (newTask: Task) => {
setTasks(prevTasks => [newTask, ...prevTasks]);
};
// Handler para cuando se actualiza una tarea
const handleTaskUpdated = (updatedTask: Task) => {
setTasks(prevTasks =>
prevTasks.map(task => task.id === updatedTask.id ? updatedTask : task)
);
};
// Handler para cuando se elimina una tarea
const handleTaskDeleted = (taskId: number) => {
setTasks(prevTasks => prevTasks.filter(task => task.id !== taskId));
};
// Calcular estadísticas de tareas
const taskStats = calculateTaskStats(tasks);
return (
{/* Header del proyecto */}
{/* Contenido principal */}
{/* Stats cards */}
{/* Tabs de contenido */}
Resumen
Tareas
{tasks.length > 0 && (
{tasks.length}
)}
Gantt
Detalles
{/* Tab: Resumen */}
{/* Preview de tareas */}
{!isLoadingTasks && tasks.length > 0 && (
)}
{/* Tab: Tareas */}
{isLoadingTasks ? (
{Array.from({ length: 5 }).map((_, i) => (
))}
) : tasksError ? (
) : (
)}
{/* Tab: Gantt de tareas */}
{isLoadingTasks ? (
) : tasksError ? (
) : (
)}
{/* Tab: Detalles */}
);
}