From c07e02855e889ba963bda479d94329f9cd474bfb Mon Sep 17 00:00:00 2001 From: lorentz Date: Tue, 14 Apr 2026 00:27:47 +0000 Subject: [PATCH] Fix overdue counts on manager page - teamMembers query now scoped to Shape clients + active tasks only - TeamMembersByDepartment overdue calc uses overdueWindowDays window (default 7d) - Workload API per-user fetch now only loads active tasks (massive perf win) - Remove Completed/Completion% columns from workload table (no longer meaningful) - overdueWindowDays passed through page -> client -> component chain --- ondeck/src/app/(dashboard)/manager/page.tsx | 21 ++++++++++++------- .../src/app/api/dashboard/workload/route.ts | 19 ++++++----------- .../components/dashboard/workload-kpis.tsx | 15 ++----------- .../manager/manager-page-client.tsx | 4 +++- .../manager/team-members-by-department.tsx | 10 +++++++-- 5 files changed, 33 insertions(+), 36 deletions(-) diff --git a/ondeck/src/app/(dashboard)/manager/page.tsx b/ondeck/src/app/(dashboard)/manager/page.tsx index beaaaa5..1110f1c 100644 --- a/ondeck/src/app/(dashboard)/manager/page.tsx +++ b/ondeck/src/app/(dashboard)/manager/page.tsx @@ -3,6 +3,7 @@ import { authOptions } from '@/lib/auth' import { redirect } from 'next/navigation' import { prisma } from '@/lib/db' import { ManagerPageClient } from '@/components/manager/manager-page-client' +import { OVERDUE_WINDOW_KEY, OVERDUE_WINDOW_DEFAULT } from '@/app/api/admin/manager-settings/route' export default async function ManagerPage() { const session = await getServerSession(authOptions) @@ -34,7 +35,15 @@ export default async function ManagerPage() { }), ]) - // Fetch team members with their task counts + const overdueSetting = await prisma.appSetting.findUnique({ where: { key: OVERDUE_WINDOW_KEY } }) + const overdueWindowDays = parseInt(overdueSetting?.value ?? String(OVERDUE_WINDOW_DEFAULT), 10) + + const shapeClientIds = (await prisma.client.findMany({ + where: { designation: { name: { in: ['Shape', 'Shape 2'] } } }, + select: { id: true }, + })).map((c) => c.id) + + // Fetch team members with their active task counts (Shape clients only) const teamMembers = await prisma.user.findMany({ where: { isActive: true }, select: { @@ -45,7 +54,8 @@ export default async function ManagerPage() { taskAssignments: { where: { task: { - status: { not: 'COMPLETED' } + clientId: { in: shapeClientIds }, + status: { notIn: ['COMPLETED', 'CANCELLED', 'NA'] }, } }, select: { @@ -60,11 +70,7 @@ export default async function ManagerPage() { }, userRoles: { include: { - role: { - select: { - name: true, - } - } + role: { select: { name: true } } } } }, @@ -93,6 +99,7 @@ export default async function ManagerPage() { teamMembers={teamMembers} recentTasks={recentTasks} setupQueueCount={setupQueueCount} + overdueWindowDays={overdueWindowDays} /> ) } diff --git a/ondeck/src/app/api/dashboard/workload/route.ts b/ondeck/src/app/api/dashboard/workload/route.ts index 13afaa4..6bc3650 100644 --- a/ondeck/src/app/api/dashboard/workload/route.ts +++ b/ondeck/src/app/api/dashboard/workload/route.ts @@ -126,7 +126,7 @@ export async function GET(request: NextRequest) { email: true, department: true, taskAssignments: { - where: { task: deptTaskWhere }, + where: { task: { ...deptTaskWhere, status: { notIn: ['COMPLETED', 'CANCELLED', 'NA'] } } }, include: { task: { select: { @@ -174,13 +174,9 @@ export async function GET(request: NextRequest) { }), ]) - // Calculate user-level metrics + // Calculate user-level metrics (taskAssignments only contains active tasks) const userMetrics = userWorkload.map((user) => { - const tasks = user.taskAssignments.map((a) => a.task) - const activeTasks = tasks.filter( - (t) => !['COMPLETED', 'CANCELLED', 'NA'].includes(t.status) - ) - const completedTasks = tasks.filter((t) => t.status === 'COMPLETED') + const activeTasks = user.taskAssignments.map((a) => a.task) const overdue = activeTasks.filter( (t) => new Date(t.dueDate) >= overdueFrom && new Date(t.dueDate) < today ) @@ -192,15 +188,12 @@ export async function GET(request: NextRequest) { id: user.id, name: user.displayName || user.email, department: user.department, - totalAssigned: tasks.length, + totalAssigned: activeTasks.length, activeTasks: activeTasks.length, - completedTasks: completedTasks.length, + completedTasks: 0, overdueTasks: overdue.length, highPriorityTasks: highPriority.length, - completionRate: - tasks.length > 0 - ? Math.round((completedTasks.length / tasks.length) * 100) - : 0, + completionRate: 0, } }) diff --git a/ondeck/src/components/dashboard/workload-kpis.tsx b/ondeck/src/components/dashboard/workload-kpis.tsx index 411dae3..47130d8 100644 --- a/ondeck/src/components/dashboard/workload-kpis.tsx +++ b/ondeck/src/components/dashboard/workload-kpis.tsx @@ -392,10 +392,8 @@ export function WorkloadKPIs({ department }: WorkloadKPIsProps = {}) { Team Member Active - Completed Overdue High Priority - Completion % @@ -410,14 +408,11 @@ export function WorkloadKPIs({ department }: WorkloadKPIsProps = {}) { {user.activeTasks} - - {user.completedTasks} - {user.overdueTasks > 0 ? ( {user.overdueTasks} ) : ( - 0 + )} @@ -426,15 +421,9 @@ export function WorkloadKPIs({ department }: WorkloadKPIsProps = {}) { {user.highPriorityTasks} ) : ( - 0 + )} - -
- - {user.completionRate}% -
- ))} diff --git a/ondeck/src/components/manager/manager-page-client.tsx b/ondeck/src/components/manager/manager-page-client.tsx index f799356..607b444 100644 --- a/ondeck/src/components/manager/manager-page-client.tsx +++ b/ondeck/src/components/manager/manager-page-client.tsx @@ -15,6 +15,7 @@ interface ManagerPageClientProps { teamMembers: any[] recentTasks: any[] setupQueueCount: number + overdueWindowDays: number } export function ManagerPageClient({ @@ -22,6 +23,7 @@ export function ManagerPageClient({ teamMembers, recentTasks, setupQueueCount, + overdueWindowDays, }: ManagerPageClientProps) { const [claimsOnly, setClaimsOnly] = useState(true) @@ -128,7 +130,7 @@ export function ManagerPageClient({ - + diff --git a/ondeck/src/components/manager/team-members-by-department.tsx b/ondeck/src/components/manager/team-members-by-department.tsx index 2ea945e..6f13787 100644 --- a/ondeck/src/components/manager/team-members-by-department.tsx +++ b/ondeck/src/components/manager/team-members-by-department.tsx @@ -25,9 +25,13 @@ interface TeamMember { interface TeamMembersByDepartmentProps { teamMembers: TeamMember[] + overdueWindowDays: number } -export function TeamMembersByDepartment({ teamMembers }: TeamMembersByDepartmentProps) { +export function TeamMembersByDepartment({ teamMembers, overdueWindowDays }: TeamMembersByDepartmentProps) { + const today = new Date() + today.setHours(0, 0, 0, 0) + const overdueFrom = new Date(today.getTime() - overdueWindowDays * 24 * 60 * 60 * 1000) // Group members by department const groupedByDepartment = teamMembers.reduce((acc, member) => { const dept = member.department || 'Unassigned' @@ -103,7 +107,9 @@ export function TeamMembersByDepartment({ teamMembers }: TeamMembersByDepartment {members.map((member) => { const activeTasks = member.taskAssignments.length const overdue = member.taskAssignments.filter( - a => a.task.dueDate && new Date(a.task.dueDate) < new Date() + a => a.task.dueDate && + new Date(a.task.dueDate) >= overdueFrom && + new Date(a.task.dueDate) < today ).length const roles = member.userRoles.map(ur => ur.role.name).join(', ')