Fix: unify frequency percentage logic (Total Course Denominator) on Dashboard and Frequency pages

This commit is contained in:
Sidney 2026-05-14 14:16:40 -03:00
parent 4c72a9e20d
commit c55ec728e1
2 changed files with 8 additions and 14 deletions

View File

@ -70,7 +70,6 @@ export default function Dashboard() {
// Synchronized Frequency Calculation (Matches Frequencia.tsx & Manager) // Synchronized Frequency Calculation (Matches Frequencia.tsx & Manager)
let presencesCount = 0; let presencesCount = 0;
let validLessonsCount = 0;
if (data?.lessons && data?.attendance) { if (data?.lessons && data?.attendance) {
const deduplicatedLessons = data.lessons.filter((lesson, index, self) => const deduplicatedLessons = data.lessons.filter((lesson, index, self) =>
@ -79,12 +78,11 @@ export default function Dashboard() {
)) ))
); );
const totalCourseLessons = deduplicatedLessons.filter(l => l.status !== 'cancelled').length;
deduplicatedLessons.forEach(lesson => { deduplicatedLessons.forEach(lesson => {
if (lesson.status === 'cancelled') return; if (lesson.status === 'cancelled') return;
// Mesma lógica de status da página de Frequência
const { isCompleted } = getLessonTimeStatus(lesson, now);
// Construir janela de tempo EXATAMENTE como o Manager faz // Construir janela de tempo EXATAMENTE como o Manager faz
const lessonStart = new Date(lesson.date + 'T' + (lesson.startTime || '00:00') + ':00'); const lessonStart = new Date(lesson.date + 'T' + (lesson.startTime || '00:00') + ':00');
const lessonEnd = new Date(lesson.date + 'T' + (lesson.endTime || '23:59') + ':00'); const lessonEnd = new Date(lesson.date + 'T' + (lesson.endTime || '23:59') + ':00');
@ -98,17 +96,14 @@ export default function Dashboard() {
return recordTime >= presenceStartWindow && recordTime <= lessonEnd; return recordTime >= presenceStartWindow && recordTime <= lessonEnd;
}); });
// Só entra no cálculo se estiver concluída OU tiver um registro (biometria/falta/justificativa) // Mesma lógica de presença da página de Frequência (exclui type: 'absence')
if (att || isCompleted) { const isPresent = att && (att.type === 'presence' || (att.verified === true && att.type !== 'absence'));
validLessonsCount++; if (isPresent) presencesCount++;
// Mesma lógica de presença da página de Frequência (exclui type: 'absence')
const isPresent = att && (att.type === 'presence' || (att.verified === true && att.type !== 'absence'));
if (isPresent) presencesCount++;
}
}); });
} }
const frequencyPercent = validLessonsCount > 0 ? Math.round((presencesCount / validLessonsCount) * 100) : 0;
const validLessonsCount = data?.lessons?.filter((l, i, s) => l.status !== 'cancelled' && i === s.findIndex(t => t.date === l.date && t.startTime === l.startTime)).length || 0;
const frequencyPercent = validLessonsCount > 0 ? Math.round((presencesCount / validLessonsCount) * 100) : 0;
const nextDue = pendingPayments const nextDue = pendingPayments
.sort((a, b) => new Date(a.dueDate).getTime() - new Date(b.dueDate).getTime())[0]; .sort((a, b) => new Date(a.dueDate).getTime() - new Date(b.dueDate).getTime())[0];

View File

@ -195,8 +195,7 @@ export default function Frequencia() {
if (record.type === 'absence') { if (record.type === 'absence') {
if (record.justificationAccepted) justified++; if (record.justificationAccepted) justified++;
else absences++; else absences++;
} else if (record.type === 'presence' || (!record.type && !(record as any).isVirtual)) { } else if (record.type === 'presence' || (record.verified === true && record.type !== 'absence') || (!record.type && !(record as any).isVirtual)) {
// No portal, só contamos como presença nas estatísticas se a aula terminou ou se já foi marcada
presences++; presences++;
} }
} else if (isCompleted) { } else if (isCompleted) {