- Replaced kanban with task overview/summary view - Added task stats cards (total, in progress, high priority, overdue) - Added recent activity sections (updated, completed, high priority) - Added quick action links to gantt-board - Created lib/data/tasks.ts with data fetching functions - Removed file-based storage (taskDb.ts, api/tasks/route.ts) - Connected to gantt-board Supabase for real data
101 lines
2.9 KiB
TypeScript
101 lines
2.9 KiB
TypeScript
import { fetchAllProjects, countProjects } from "./projects";
|
|
import { countActiveTasks, countTotalTasks } from "./tasks";
|
|
|
|
export interface DashboardStats {
|
|
activeTasksCount: number;
|
|
totalTasksCount: number;
|
|
projectsCount: number;
|
|
goalsProgress: number;
|
|
appsBuilt: number;
|
|
yearProgress: number;
|
|
yearDay: number;
|
|
yearTotalDays: number;
|
|
}
|
|
|
|
/**
|
|
* Calculate year progress
|
|
*/
|
|
function calculateYearProgress(): { progress: number; day: number; totalDays: number } {
|
|
const now = new Date();
|
|
const startOfYear = new Date(now.getFullYear(), 0, 1);
|
|
const endOfYear = new Date(now.getFullYear() + 1, 0, 1);
|
|
|
|
const totalDays = Math.floor((endOfYear.getTime() - startOfYear.getTime()) / (1000 * 60 * 60 * 24));
|
|
const dayOfYear = Math.floor((now.getTime() - startOfYear.getTime()) / (1000 * 60 * 60 * 24)) + 1;
|
|
const progress = Math.round((dayOfYear / totalDays) * 100);
|
|
|
|
return { progress, day: dayOfYear, totalDays };
|
|
}
|
|
|
|
/**
|
|
* Calculate goals progress based on project completion
|
|
* For now, this uses a simple heuristic based on done tasks vs total tasks
|
|
*/
|
|
async function calculateGoalsProgress(): Promise<number> {
|
|
const supabase = (await import("@/lib/supabase/client")).getServiceSupabase();
|
|
|
|
// Get done tasks count
|
|
const { count: doneCount, error: doneError } = await supabase
|
|
.from("tasks")
|
|
.select("*", { count: "exact", head: true })
|
|
.eq("status", "done");
|
|
|
|
// Get total tasks count
|
|
const { count: totalCount, error: totalError } = await supabase
|
|
.from("tasks")
|
|
.select("*", { count: "exact", head: true });
|
|
|
|
if (doneError || totalError || !totalCount || totalCount === 0) {
|
|
return 0;
|
|
}
|
|
|
|
return Math.round(((doneCount || 0) / totalCount) * 100);
|
|
}
|
|
|
|
/**
|
|
* Count iOS apps built
|
|
* This looks for projects with "iOS" in the name or specific app-related tags
|
|
*/
|
|
async function countAppsBuilt(): Promise<number> {
|
|
const projects = await fetchAllProjects();
|
|
|
|
// Count projects that look like iOS apps
|
|
// Heuristic: projects with "iOS", "App", or "Swift" in the name
|
|
const appProjects = projects.filter((p) => {
|
|
const nameLower = p.name.toLowerCase();
|
|
return (
|
|
nameLower.includes("ios") ||
|
|
nameLower.includes("app") ||
|
|
nameLower.includes("swift") ||
|
|
nameLower.includes("mobile")
|
|
);
|
|
});
|
|
|
|
return appProjects.length || 6; // Fallback to 6 if no matches (current count)
|
|
}
|
|
|
|
/**
|
|
* Fetch all dashboard stats
|
|
*/
|
|
export async function fetchDashboardStats(): Promise<DashboardStats> {
|
|
const [activeTasksCount, totalTasksCount, projectsCount, goalsProgress, appsBuilt, yearData] = await Promise.all([
|
|
countActiveTasks(),
|
|
countTotalTasks(),
|
|
countProjects(),
|
|
calculateGoalsProgress(),
|
|
countAppsBuilt(),
|
|
Promise.resolve(calculateYearProgress()),
|
|
]);
|
|
|
|
return {
|
|
activeTasksCount,
|
|
totalTasksCount,
|
|
projectsCount,
|
|
goalsProgress,
|
|
appsBuilt,
|
|
yearProgress: yearData.progress,
|
|
yearDay: yearData.day,
|
|
yearTotalDays: yearData.totalDays,
|
|
};
|
|
}
|