mission-control/lib/data/tasks.ts

124 lines
3.8 KiB
TypeScript

import { fetchGanttSnapshot } from "@/lib/data/gantt-snapshot";
export interface Task {
id: string;
title: string;
description?: string;
type: "idea" | "task" | "bug" | "research" | "plan";
status: "open" | "todo" | "blocked" | "in-progress" | "review" | "validate" | "archived" | "canceled" | "done";
priority: "low" | "medium" | "high" | "urgent";
projectId: string;
sprintId?: string;
createdAt: string;
updatedAt: string;
createdById?: string;
createdByName?: string;
createdByAvatarUrl?: string;
updatedById?: string;
updatedByName?: string;
updatedByAvatarUrl?: string;
assigneeId?: string;
assigneeName?: string;
assigneeEmail?: string;
assigneeAvatarUrl?: string;
dueDate?: string;
comments: unknown[];
tags: string[];
attachments: unknown[];
}
export interface TaskStatusCounts {
open: number;
inProgress: number;
review: number;
done: number;
total: number;
}
function isDoneStatus(status: Task["status"]): boolean {
return status === "done";
}
function isOpenStatus(status: Task["status"]): boolean {
return status === "open" || status === "todo" || status === "blocked";
}
function isReviewStatus(status: Task["status"]): boolean {
return status === "review" || status === "validate";
}
function byUpdatedDesc(a: Task, b: Task): number {
return new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime();
}
function toDateOnly(value: string): string {
return value.split("T")[0];
}
async function fetchTasksFromApi(): Promise<Task[]> {
const snapshot = await fetchGanttSnapshot();
return snapshot.tasks;
}
export async function fetchAllTasks(): Promise<Task[]> {
return fetchTasksFromApi();
}
export async function fetchActiveTasks(): Promise<Task[]> {
const tasks = await fetchTasksFromApi();
return tasks.filter((task) => !isDoneStatus(task.status));
}
export async function countActiveTasks(): Promise<number> {
const tasks = await fetchTasksFromApi();
return tasks.filter((task) => !isDoneStatus(task.status)).length;
}
export async function countTotalTasks(): Promise<number> {
const tasks = await fetchTasksFromApi();
return tasks.length;
}
export async function getTaskStatusCounts(): Promise<TaskStatusCounts> {
const tasks = await fetchTasksFromApi();
const counts: TaskStatusCounts = { open: 0, inProgress: 0, review: 0, done: 0, total: tasks.length };
for (const task of tasks) {
if (isOpenStatus(task.status)) counts.open++;
else if (task.status === "in-progress") counts.inProgress++;
else if (isReviewStatus(task.status)) counts.review++;
else if (task.status === "done") counts.done++;
}
return counts;
}
export async function countHighPriorityTasks(): Promise<number> {
const tasks = await fetchTasksFromApi();
return tasks.filter((task) => (task.priority === "high" || task.priority === "urgent") && !isDoneStatus(task.status)).length;
}
export async function countOverdueTasks(): Promise<number> {
const tasks = await fetchTasksFromApi();
const today = toDateOnly(new Date().toISOString());
return tasks.filter((task) => Boolean(task.dueDate) && !isDoneStatus(task.status) && toDateOnly(task.dueDate as string) < today).length;
}
export async function fetchRecentlyUpdatedTasks(limit = 5): Promise<Task[]> {
const tasks = await fetchTasksFromApi();
return [...tasks].sort(byUpdatedDesc).slice(0, limit);
}
export async function fetchRecentlyCompletedTasks(limit = 5): Promise<Task[]> {
const tasks = await fetchTasksFromApi();
return tasks.filter((task) => isDoneStatus(task.status)).sort(byUpdatedDesc).slice(0, limit);
}
export async function fetchHighPriorityOpenTasks(limit = 5): Promise<Task[]> {
const tasks = await fetchTasksFromApi();
return tasks
.filter((task) => (task.priority === "high" || task.priority === "urgent") && !isDoneStatus(task.status))
.sort(byUpdatedDesc)
.slice(0, limit);
}