From e58b38f01046b2d3bd466416fa6f959fe47b937a Mon Sep 17 00:00:00 2001 From: Sidney Date: Mon, 11 May 2026 19:59:02 -0300 Subject: [PATCH] =?UTF-8?q?fix:=20restaura=20importa=C3=A7=C3=B5es=20vitai?= =?UTF-8?q?s=20e=20estabiliza=20l=C3=B3gica=20de=20datas?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- manager/components/AdminNotifications.tsx | 3 ++- manager/server.selfhosted.js | 1 + portal/src/pages/Frequencia.tsx | 16 ++++++++-------- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/manager/components/AdminNotifications.tsx b/manager/components/AdminNotifications.tsx index 227588c..39a8eb2 100644 --- a/manager/components/AdminNotifications.tsx +++ b/manager/components/AdminNotifications.tsx @@ -1,4 +1,5 @@ -import { Bell, X, CheckCircle, Trash2, ShieldCheck, FileText, Paperclip, DollarSign, AlertTriangle, Info, TrendingUp, CreditCard } from 'lucide-react'; +import React, { useState, useEffect, useRef } from 'react'; +import { Bell, X, CheckCircle, Trash2, ShieldCheck, FileText, Paperclip, DollarSign, AlertTriangle, Info, TrendingUp, CreditCard, ClipboardList } from 'lucide-react'; import { SchoolData, Notification, View } from '../types'; import { dbService } from '../services/dbService'; diff --git a/manager/server.selfhosted.js b/manager/server.selfhosted.js index 10657c4..ea77973 100644 --- a/manager/server.selfhosted.js +++ b/manager/server.selfhosted.js @@ -21,6 +21,7 @@ import multer from 'multer'; import sharp from 'sharp'; import jwt from 'jsonwebtoken'; import cron from 'node-cron'; +import path from 'path'; // === Novos módulos Self-Hosted (substituem Supabase) === import { diff --git a/portal/src/pages/Frequencia.tsx b/portal/src/pages/Frequencia.tsx index fc00756..911364c 100644 --- a/portal/src/pages/Frequencia.tsx +++ b/portal/src/pages/Frequencia.tsx @@ -145,10 +145,10 @@ export default function Frequencia() { // Merge and Categorize — Clone EXATO do Manager (AttendanceQuery.tsx) const processedItems = deduplicatedLessons.map(lesson => { - // Construir janela de tempo EXATAMENTE como o Manager faz (com Date objects) - 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 presenceStartWindow = new Date(lessonStart.getTime() - 30 * 60 * 1000); // 30 mins before + // Construir janela de tempo de forma resiliente + const lessonStartMs = parseLessonDateTime(lesson.date, lesson.startTime || '00:00', 0); + const lessonEndMs = parseLessonDateTime(lesson.date, lesson.endTime || '23:59', 23); + const presenceStartWindowMs = lessonStartMs - (30 * 60 * 1000); // 30 mins before // Buscar registro com a MESMA lógica do Manager (find, não filter) let record = attendance.find(a => { @@ -158,8 +158,8 @@ export default function Frequencia() { // 2. Match exato de string (formato do JSON/sync) if (a.date === `${lesson.date}T${lesson.startTime || '00:00'}:00`) return true; // 3. Match por janela de tempo (30 min antes até fim da aula) - const recordTime = new Date(a.date); - return recordTime >= presenceStartWindow && recordTime <= lessonEnd; + const recordTimeMs = new Date(a.date).getTime(); + return recordTimeMs >= presenceStartWindowMs && recordTimeMs <= lessonEndMs; }); // Se não encontrou registro real, verificar se precisa de justificativa associada @@ -168,8 +168,8 @@ export default function Frequencia() { record = attendance.find(a => { if (!a.date || typeof a.date !== 'string' || !a.justification) return false; if (a.date === `${lesson.date}T${lesson.startTime || '00:00'}:00`) return true; - const recordTime = new Date(a.date); - return recordTime >= presenceStartWindow && recordTime <= lessonEnd; + const recordTimeMs = new Date(a.date).getTime(); + return recordTimeMs >= presenceStartWindowMs && recordTimeMs <= lessonEndMs; }) || undefined; }