fix: resolve reference errors causing white screens and clean up typescript typings on portal
This commit is contained in:
parent
9ba2e11e27
commit
5862a8374d
|
|
@ -31,6 +31,7 @@
|
|||
- [x] **Regra de Registro Único:** Portal agora exibe apenas a primeira batida válida por aula, eliminando duplicidade visual de biometria.
|
||||
- [x] **Sincronia de Justificativas:** Ajustada a contagem matemática do Portal para contabilizar faltas justificadas apenas após o aceite do Admin.
|
||||
- [x] **Fix Dashboard Crash:** Corrigido erro de "tela preta" no Dashboard causado por acesso inseguro a propriedades nulas durante falhas de API.
|
||||
- [x] **Blindagem de Conversão ISO:** Resolvida falha crítica de `RangeError: Invalid time value` em todo o Portal. Agora o sistema ignora datas corrompidas ou inválidas em vez de quebrar a interface inteira.
|
||||
- [ ] Próximo Passo: Iniciar a migração do módulo Financeiro para 100% SQL seguindo o padrão do Boletim.
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -45,7 +45,8 @@ export default function Notifications() {
|
|||
message: `Identificamos ${atrasadas.length} ${atrasadas.length === 1 ? 'parcela atrasada' : 'parcelas atrasadas'}. Regularize agora para evitar suspensões.`,
|
||||
read: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
type: 'alert'
|
||||
type: 'alert',
|
||||
studentId: ''
|
||||
};
|
||||
allNotifs = [overdueNotif, ...allNotifs];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -757,9 +757,9 @@ export default function Avaliacoes() {
|
|||
<h3 style={{ fontSize: '1.05rem', fontWeight: 700, marginBottom: 4, paddingRight: isDone ? 90 : 0 }}>
|
||||
{exam.title}
|
||||
</h3>
|
||||
{exam.description && (
|
||||
{(exam as any).description && (
|
||||
<p style={{ fontSize: '0.8rem', color: 'var(--color-text-secondary)', lineHeight: 1.4 }}>
|
||||
{exam.description}
|
||||
{(exam as any).description}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -83,8 +83,9 @@ export default function Dashboard() {
|
|||
if (lesson.status === 'cancelled') return;
|
||||
validLessonsCount++;
|
||||
|
||||
const lessonFullISO = new Date(parseLessonDateTime(lesson.date, lesson.startTime || '00:00:00')).toISOString();
|
||||
const lessonStartMs = parseLessonDateTime(lesson.date, lesson.startTime || '00:00:00');
|
||||
const lessonMs = parseLessonDateTime(lesson.date, lesson.startTime || '00:00:00');
|
||||
const lessonFullISO = !isNaN(lessonMs) ? new Date(lessonMs).toISOString() : '';
|
||||
const lessonStartMs = lessonMs;
|
||||
const lessonEndMs = parseLessonDateTime(lesson.date, lesson.endTime || '00:00:00', lesson.endTime ? 0 : 60);
|
||||
|
||||
const atts = data.attendance.filter(a => {
|
||||
|
|
@ -422,7 +423,7 @@ export default function Dashboard() {
|
|||
{frequencyPercent}%
|
||||
</h3>
|
||||
<p style={{ fontSize: '0.8125rem', color: 'var(--color-text-secondary)', marginTop: '0.375rem' }}>
|
||||
{presences} presença{presences !== 1 ? 's' : ''} de {totalCourseLessons} aula{totalCourseLessons !== 1 ? 's' : ''} do curso
|
||||
{presencesCount} presença{presencesCount !== 1 ? 's' : ''} de {validLessonsCount} aula{validLessonsCount !== 1 ? 's' : ''} do curso
|
||||
</p>
|
||||
<div style={{
|
||||
marginTop: '0.75rem', height: 6, borderRadius: 3,
|
||||
|
|
|
|||
|
|
@ -145,8 +145,9 @@ export default function Frequencia() {
|
|||
|
||||
// Merge and Categorize
|
||||
const processedItems = deduplicatedLessons.map(lesson => {
|
||||
const lessonFullISO = new Date(parseLessonDateTime(lesson.date, lesson.startTime || '00:00:00')).toISOString();
|
||||
const lessonStartMs = parseLessonDateTime(lesson.date, lesson.startTime || '00:00:00');
|
||||
const lessonMs = parseLessonDateTime(lesson.date, lesson.startTime || '00:00:00');
|
||||
const lessonFullISO = !isNaN(lessonMs) ? new Date(lessonMs).toISOString() : '';
|
||||
const lessonStartMs = lessonMs;
|
||||
const lessonEndMs = parseLessonDateTime(lesson.date, lesson.endTime || '00:00:00', lesson.endTime ? 0 : 60);
|
||||
|
||||
// No Manager, ele procura o primeiro registro válido
|
||||
|
|
@ -220,8 +221,9 @@ export default function Frequencia() {
|
|||
// Check window (uses new 24h before/after logic)
|
||||
if (!isLessonWithinJustificationWindow(l, now)) return false;
|
||||
|
||||
const lessonFullISO = new Date(parseLessonDateTime(l.date, l.startTime || '00:00:00')).toISOString();
|
||||
const lessonStartMs = parseLessonDateTime(l.date, l.startTime || '00:00:00');
|
||||
const lMs = parseLessonDateTime(l.date, l.startTime || '00:00:00');
|
||||
const lessonFullISO = !isNaN(lMs) ? new Date(lMs).toISOString() : '';
|
||||
const lessonStartMs = lMs;
|
||||
const lessonEndMs = parseLessonDateTime(l.date, l.endTime || '00:00:00', l.endTime ? 0 : 60);
|
||||
|
||||
// Find if THIS SPECIFIC lesson has attendance/justification
|
||||
|
|
@ -600,7 +602,9 @@ export default function Frequencia() {
|
|||
) : canJustify ? (
|
||||
<button
|
||||
onClick={() => {
|
||||
const timestamp = new Date(parseLessonDateTime(lesson.date, lesson.startTime || '00:00:00')).toISOString();
|
||||
const lMs = parseLessonDateTime(lesson.date, lesson.startTime || '00:00:00');
|
||||
if (isNaN(lMs)) return;
|
||||
const timestamp = new Date(lMs).toISOString();
|
||||
openJustifyModal(timestamp);
|
||||
}}
|
||||
style={{
|
||||
|
|
@ -706,7 +710,9 @@ export default function Frequencia() {
|
|||
return (isNaN(msB) ? 0 : msB) - (isNaN(msA) ? 0 : msA);
|
||||
})
|
||||
.map(l => {
|
||||
const ts = new Date(parseLessonDateTime(l.date, l.startTime || '00:00:00')).toISOString();
|
||||
const lMs = parseLessonDateTime(l.date, l.startTime || '00:00:00');
|
||||
if (isNaN(lMs)) return null;
|
||||
const ts = new Date(lMs).toISOString();
|
||||
return (
|
||||
<option key={l.id} value={ts}>
|
||||
{formatDateFull(l.date)}{l.startTime ? ` — ${l.startTime.substring(0, 5)}` : ''}{l.endTime ? ` às ${l.endTime.substring(0, 5)}` : ''}
|
||||
|
|
|
|||
|
|
@ -213,7 +213,7 @@ export default function Notas() {
|
|||
{periodGrades.map((grade) => {
|
||||
const isActivity = grade.evaluationType === 'activity';
|
||||
const maxScore = grade.maxScore ?? 10;
|
||||
const isDirect = !grade.examId;
|
||||
const isDirect = !(grade as any).examId;
|
||||
|
||||
return (
|
||||
<div key={grade.id} style={{
|
||||
|
|
|
|||
Loading…
Reference in New Issue