diff --git a/app/(app)/summary/page.tsx b/app/(app)/summary/page.tsx index b9d3ca9..cbb2c4a 100644 --- a/app/(app)/summary/page.tsx +++ b/app/(app)/summary/page.tsx @@ -1,6 +1,98 @@ /** - * Summary + * @file app/summary/page.tsx + * @description Server component rendering an advanced analytical summary page with comprehensive task metrics. */ -export default function Summary() { - return
Summary
; + +import { auth } from "@/auth"; +import { redirect } from "next/navigation"; +import { TaskService } from "@/services/task.service"; +import { COLUMNS } from "@/types/task"; +import SummaryHeader from "./sections/SummaryHeader"; +import SummaryKpiGrid from "./sections/SummaryKpiGrid"; + +/** + * Calculates comprehensive analytical metrics from the user's active task collection. + * + * @param {Array<{ task: any; user: any }>} rawTasks - The collection of raw tasks and user relations. + * @returns {Object} An object containing total counts, completion rates, overdue totals, and status/priority breakdowns. + */ +function calculateTaskAnalytics(rawTasks: Array<{ task: any; user: any }>) { + const totalTasks = rawTasks.length; + + const statusCounts: Record = COLUMNS.reduce( + (acc, col) => { + acc[col.id] = 0; + return acc; + }, + {} as Record, + ); + + const priorityCounts: Record = { + high: 0, + medium: 0, + low: 0, + }; + + let completedTasks = 0; + let overdueTasks = 0; + let upcomingDueTasks = 0; + + const now = new Date(); + + rawTasks.forEach(({ task }) => { + if (statusCounts[task.status] !== undefined) statusCounts[task.status]++; + if (priorityCounts[task.priority] !== undefined) + priorityCounts[task.priority]++; + if (task.status === "done") completedTasks++; + + if (task.dueDate) { + const dueDate = new Date(task.dueDate); + if (dueDate < now && task.status !== "done") { + overdueTasks++; + } else if (dueDate >= now && task.status !== "done") { + upcomingDueTasks++; + } + } + }); + + const completionRate = + totalTasks > 0 ? Math.round((completedTasks / totalTasks) * 100) : 0; + + return { + totalTasks, + completedTasks, + completionRate, + overdueTasks, + upcomingDueTasks, + statusCounts, + priorityCounts, + }; +} + +/** + * Renders the summary analytics page with authentication validation, data retrieval via TaskService, + * KPI metrics calculation, and structural grid layouts. + * + * @async + * @returns {Promise} The rendered summary page component. + */ +export default async function SummaryPage() { + const session = await auth(); + if (!session?.user?.id) redirect("/login"); + + const rawTasks = await TaskService.findActiveTasksForUser(session.user.id); + const analytics = calculateTaskAnalytics(rawTasks); + + return ( +
+ + + +
+ ); } diff --git a/app/(app)/summary/sections/SummaryHeader.tsx b/app/(app)/summary/sections/SummaryHeader.tsx new file mode 100644 index 0000000..8d0bf3a --- /dev/null +++ b/app/(app)/summary/sections/SummaryHeader.tsx @@ -0,0 +1,34 @@ +/** + * @file app/summary/sections/SummaryHeader.tsx + * @description Client component rendering the analytical page header. + */ + +"use client"; + +import { BarChart3 } from "lucide-react"; + +/** + * Renders the analytical executive summary header featuring an analytics icon, + * workspace indicator, main title, and descriptive subtitle. + * + * @returns {JSX.Element} The rendered summary header component. + */ +export default function SummaryHeader() { + return ( +
+
+
+ + Analytics & Insights +
+

+ Executive Summary +

+

+ Real-time overview of your workspace productivity and workflow + metrics. +

+
+
+ ); +} diff --git a/app/(app)/summary/sections/SummaryKpiGrid.tsx b/app/(app)/summary/sections/SummaryKpiGrid.tsx new file mode 100644 index 0000000..f43151c --- /dev/null +++ b/app/(app)/summary/sections/SummaryKpiGrid.tsx @@ -0,0 +1,94 @@ +/** + * @file app/summary/sections/SummaryKpiGrid.tsx + * @description Client component rendering the primary KPI metrics grid. + */ + +"use client"; + +import { Layers, CheckCircle2, AlertTriangle, Clock } from "lucide-react"; + +/** + * Properties for the SummaryKpiGrid component. + * + * @interface SummaryKpiGridProps + * @property {number} totalTasks - The total count of active tasks. + * @property {number} completionRate - The calculated completion rate percentage. + * @property {number} overdueTasks - The number of tasks past their deadline. + * @property {number} upcomingDueTasks - The number of tasks with upcoming deadlines. + */ +interface SummaryKpiGridProps { + totalTasks: number; + completionRate: number; + overdueTasks: number; + upcomingDueTasks: number; +} + +/** + * Renders a responsive grid of KPI cards summarizing key task metrics, + * including active totals, completion percentages, overdue items, and upcoming targets. + * + * @param {SummaryKpiGridProps} props - The component props. + * @returns {JSX.Element} The rendered summary KPI grid component. + */ +export default function SummaryKpiGrid({ + totalTasks, + completionRate, + overdueTasks, + upcomingDueTasks, +}: SummaryKpiGridProps) { + const kpiCards = [ + { + title: "Active Tasks", + value: totalTasks, + icon: Layers, + color: "text-primary", + borderColor: "hover:border-primary/40", + }, + { + title: "Completion Rate", + value: `${completionRate}%`, + icon: CheckCircle2, + color: "text-emerald-500", + borderColor: "hover:border-emerald-500/40", + }, + { + title: "Overdue Tasks", + value: overdueTasks, + icon: AlertTriangle, + color: "text-destructive", + borderColor: "hover:border-destructive/40", + }, + { + title: "Upcoming Target", + value: upcomingDueTasks, + icon: Clock, + color: "text-amber-500", + borderColor: "hover:border-amber-500/40", + }, + ]; + + return ( +
+ {kpiCards.map(({ title, value, icon: Icon, color, borderColor }) => ( +
+
+ +
+
+ + {title} + +
+ {value} +
+
+
+ ))} +
+ ); +}