import { fetchGanttApi } from "@/lib/data/gantt-api"; import { Task, fetchAllTasks } from "./tasks"; export interface Project { id: string; name: string; description?: string; color: string; createdAt: string; } export interface Sprint { id: string; name: string; status: "planning" | "active" | "completed" | "cancelled"; startDate: string; endDate: string; projectId: string; goal?: string; } export interface ProjectStats { project: Project; totalTasks: number; completedTasks: number; inProgressTasks: number; urgentTasks: number; highPriorityTasks: number; progress: number; recentTasks: Task[]; } interface GanttProjectsResponse { projects?: Array<{ id: string; name: string; description?: string | null; color?: string | null; created_at?: string; createdAt?: string; }>; } interface GanttSprintsResponse { sprints?: Array<{ id: string; name: string; status: Sprint["status"]; start_date?: string; end_date?: string; startDate?: string; endDate?: string; project_id?: string; projectId?: string; goal?: string | null; }>; } interface GanttCurrentSprintResponse { sprint?: { id: string; name: string; status: Sprint["status"]; startDate: string; endDate: string; projectId: string; goal?: string | null; } | null; } function mapProject(project: NonNullable[number]): Project { return { id: project.id, name: project.name, description: project.description ?? undefined, color: project.color || "#3b82f6", createdAt: project.createdAt || project.created_at || new Date().toISOString(), }; } function mapSprint(sprint: NonNullable[number]): Sprint { return { id: sprint.id, name: sprint.name, status: sprint.status, startDate: sprint.startDate || sprint.start_date || new Date().toISOString(), endDate: sprint.endDate || sprint.end_date || new Date().toISOString(), projectId: sprint.projectId || sprint.project_id || "", goal: sprint.goal ?? undefined, }; } export async function fetchAllProjects(): Promise { try { const response = await fetchGanttApi("/projects"); return Array.isArray(response.projects) ? response.projects.map(mapProject) : []; } catch (error) { console.error("Error fetching projects from gantt-board API:", error); return []; } } export async function countProjects(): Promise { const projects = await fetchAllProjects(); return projects.length; } export async function fetchAllSprints(): Promise { try { const response = await fetchGanttApi("/sprints"); return Array.isArray(response.sprints) ? response.sprints.map(mapSprint) : []; } catch (error) { console.error("Error fetching sprints from gantt-board API:", error); return []; } } export async function fetchProjectSprints(projectId: string): Promise { const sprints = await fetchAllSprints(); return sprints.filter((sprint) => sprint.projectId === projectId); } export async function fetchActiveSprint(): Promise { try { const response = await fetchGanttApi("/sprints/current"); if (!response.sprint) return null; return { id: response.sprint.id, name: response.sprint.name, status: response.sprint.status, startDate: response.sprint.startDate, endDate: response.sprint.endDate, projectId: response.sprint.projectId, goal: response.sprint.goal ?? undefined, }; } catch (error) { console.error("Error fetching current sprint from gantt-board API:", error); return null; } } export async function countSprintsByStatus(): Promise<{ planning: number; active: number; completed: number; total: number }> { const sprints = await fetchAllSprints(); const counts = { planning: 0, active: 0, completed: 0, total: sprints.length }; for (const sprint of sprints) { if (sprint.status === "planning") counts.planning++; else if (sprint.status === "active") counts.active++; else if (sprint.status === "completed") counts.completed++; } return counts; } export function calculateProjectStats(project: Project, tasks: Task[]): ProjectStats { const projectTasks = tasks.filter((task) => task.projectId === project.id); const completedTasks = projectTasks.filter((task) => task.status === "done"); const inProgressTasks = projectTasks.filter((task) => task.status === "in-progress"); const urgentTasks = projectTasks.filter((task) => task.priority === "urgent" && task.status !== "done"); const highPriorityTasks = projectTasks.filter((task) => task.priority === "high" && task.status !== "done"); const totalTasks = projectTasks.length; const progress = totalTasks > 0 ? Math.round((completedTasks.length / totalTasks) * 100) : 0; const recentTasks = [...projectTasks] .sort((a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime()) .slice(0, 5); return { project, totalTasks, completedTasks: completedTasks.length, inProgressTasks: inProgressTasks.length, urgentTasks: urgentTasks.length, highPriorityTasks: highPriorityTasks.length, progress, recentTasks, }; } export async function fetchProjectsWithStats(): Promise { const [projects, tasks] = await Promise.all([fetchAllProjects(), fetchAllTasks()]); return projects.map((project) => calculateProjectStats(project, tasks)); } export function getProjectHealth(stats: ProjectStats): { status: "healthy" | "warning" | "critical"; label: string; color: string; } { const { progress, urgentTasks, highPriorityTasks, totalTasks } = stats; if (urgentTasks > 0 || (totalTasks > 5 && progress === 0)) { return { status: "critical", label: "Needs Attention", color: "text-red-500" }; } if (highPriorityTasks > 2 || (totalTasks > 10 && progress < 30)) { return { status: "warning", label: "At Risk", color: "text-yellow-500" }; } return { status: "healthy", label: "On Track", color: "text-green-500" }; } export function getSprintDaysRemaining(sprint: Sprint): number { const endDate = new Date(sprint.endDate); const today = new Date(); const diffTime = endDate.getTime() - today.getTime(); return Math.ceil(diffTime / (1000 * 60 * 60 * 24)); } export function formatSprintDateRange(sprint: Sprint): string { const start = new Date(sprint.startDate); const end = new Date(sprint.endDate); return `${start.toLocaleDateString("en-US", { month: "short", day: "numeric" })} - ${end.toLocaleDateString("en-US", { month: "short", day: "numeric", })}`; }