Skip to content

Commit 2d3ef8c

Browse files
Zeff01claude
andcommitted
Fix attendance warnings to only count scheduled meeting days
- Added isScheduledMeetingDay helper function to check if a date matches the meeting schedule - Updated checkAttendanceWarnings to only count absences on scheduled meeting days (e.g., Tuesday/Thursday) - Updated getAttendanceWarningStatus to use the same logic for accurate absence counting - Now correctly calculates absences based on actual meeting schedule instead of all weekdays 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent a237581 commit 2d3ef8c

1 file changed

Lines changed: 41 additions & 9 deletions

File tree

‎apps/codebility/app/home/my-team/[projectId]/actions/attendance-warnings.ts‎

Lines changed: 41 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,19 @@ import { createNotification } from "@/lib/server/notification.service";
55

66
const ABSENCE_WARNING_THRESHOLD = 3;
77

8+
// Helper function to check if a date is a scheduled meeting day
9+
function isScheduledMeetingDay(date: Date, meetingSchedule: { selectedDays: string[] } | null): boolean {
10+
if (!meetingSchedule || !meetingSchedule.selectedDays || meetingSchedule.selectedDays.length === 0) {
11+
// If no schedule, consider all weekdays as meeting days
12+
const dayOfWeek = date.getDay();
13+
return dayOfWeek !== 0 && dayOfWeek !== 6; // Not Sunday (0) or Saturday (6)
14+
}
15+
16+
const dayNames = ["sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday"];
17+
const dayName = dayNames[date.getDay()];
18+
return meetingSchedule.selectedDays.includes(dayName);
19+
}
20+
821
interface AttendanceWarningResult {
922
success: boolean;
1023
warnings?: Array<{
@@ -44,6 +57,13 @@ export async function checkAttendanceWarnings(
4457
return { success: false, error: "Only team leads can check attendance warnings" };
4558
}
4659

60+
// Get the meeting schedule for the project
61+
const { data: projectData } = await supabase
62+
.from("projects")
63+
.select("meeting_schedule")
64+
.eq("id", projectId)
65+
.single();
66+
4767
// Get all members of the project
4868
const { data: members } = await supabase
4969
.from("project_members")
@@ -69,17 +89,19 @@ export async function checkAttendanceWarnings(
6989
return { success: false, error: "No attendance records found" };
7090
}
7191

72-
// Count absences per member (excluding future dates)
92+
// Count absences per member (excluding future dates and non-scheduled days)
7393
const today = new Date();
7494
today.setHours(0, 0, 0, 0); // Reset to start of day
95+
const meetingSchedule = projectData?.meeting_schedule || null;
7596

7697
const absenceCounts = new Map<string, number>();
7798
attendance.forEach(record => {
7899
// Skip future dates
79100
const recordDate = new Date(record.date);
80101
if (recordDate > today) return;
81102

82-
if (record.status === "absent") {
103+
// Only count absences on scheduled meeting days
104+
if (isScheduledMeetingDay(recordDate, meetingSchedule) && record.status === "absent") {
83105
const current = absenceCounts.get(record.codev_id) || 0;
84106
absenceCounts.set(record.codev_id, current + 1);
85107
}
@@ -176,6 +198,13 @@ export async function getAttendanceWarningStatus(
176198
const supabase = await createClientServerComponent();
177199

178200
try {
201+
// Get the meeting schedule for the project
202+
const { data: projectData } = await supabase
203+
.from("projects")
204+
.select("meeting_schedule")
205+
.eq("id", projectId)
206+
.single();
207+
179208
// Get all members
180209
const { data: members } = await supabase
181210
.from("project_members")
@@ -197,26 +226,29 @@ export async function getAttendanceWarningStatus(
197226
.gte("date", startDate)
198227
.lte("date", endDate);
199228

200-
// Count absences per member (excluding future dates)
229+
// Count absences per member (excluding future dates and non-scheduled days)
201230
const today = new Date();
202231
today.setHours(0, 0, 0, 0); // Reset to start of day
232+
const meetingSchedule = projectData?.meeting_schedule || null;
203233

204234
const memberStatus = members.map(member => {
205235
const memberAttendance = attendance?.filter(a => a.codev_id === member.codev_id) || [];
206-
// Filter out future dates before counting absences
207-
const pastAttendance = memberAttendance.filter(a => {
236+
237+
// Filter out future dates and non-scheduled days
238+
const scheduledMeetingAttendance = memberAttendance.filter(a => {
208239
const recordDate = new Date(a.date);
209-
return recordDate <= today;
240+
return recordDate <= today && isScheduledMeetingDay(recordDate, meetingSchedule);
210241
});
211-
const absences = pastAttendance.filter(a => a.status === "absent").length;
242+
243+
const absences = scheduledMeetingAttendance.filter(a => a.status === "absent").length;
212244

213245
return {
214246
codevId: member.codev_id,
215247
name: `${member.codev.first_name} ${member.codev.last_name}`,
216248
absences,
217249
hasWarning: absences >= ABSENCE_WARNING_THRESHOLD,
218-
attendancePercentage: pastAttendance.length > 0
219-
? Math.round(((pastAttendance.length - absences) / pastAttendance.length) * 100)
250+
attendancePercentage: scheduledMeetingAttendance.length > 0
251+
? Math.round(((scheduledMeetingAttendance.length - absences) / scheduledMeetingAttendance.length) * 100)
220252
: 100
221253
};
222254
});

0 commit comments

Comments
 (0)