diff --git a/portal/src/pages/Dashboard.tsx b/portal/src/pages/Dashboard.tsx index 11b8805..009fcc0 100644 --- a/portal/src/pages/Dashboard.tsx +++ b/portal/src/pages/Dashboard.tsx @@ -70,7 +70,6 @@ export default function Dashboard() { // Synchronized Frequency Calculation (Matches Frequencia.tsx & Manager) let presencesCount = 0; - let validLessonsCount = 0; if (data?.lessons && data?.attendance) { 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 => { 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 const lessonStart = new Date(lesson.date + 'T' + (lesson.startTime || '00:00') + ':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; }); - // Só entra no cálculo se estiver concluída OU tiver um registro (biometria/falta/justificativa) - if (att || isCompleted) { - validLessonsCount++; - // 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++; - } + // 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 .sort((a, b) => new Date(a.dueDate).getTime() - new Date(b.dueDate).getTime())[0]; diff --git a/portal/src/pages/Frequencia.tsx b/portal/src/pages/Frequencia.tsx index 38c8004..55292ba 100644 --- a/portal/src/pages/Frequencia.tsx +++ b/portal/src/pages/Frequencia.tsx @@ -195,8 +195,7 @@ export default function Frequencia() { if (record.type === 'absence') { if (record.justificationAccepted) justified++; else absences++; - } else if (record.type === 'presence' || (!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 + } else if (record.type === 'presence' || (record.verified === true && record.type !== 'absence') || (!record.type && !(record as any).isVirtual)) { presences++; } } else if (isCompleted) {