From 3fe0d964a526972f775a5a077d835df780866be1 Mon Sep 17 00:00:00 2001 From: Sidney Date: Mon, 25 May 2026 08:12:08 -0300 Subject: [PATCH] fix(attendance): complete SQL-First migration for frequencias and fix portal justification logic --- manager/components/AdminNotifications.tsx | 3 + manager/components/AttendanceCapture.tsx | 11 ++-- manager/components/AttendanceQuery.tsx | 23 +++++--- manager/server.selfhosted.js | 51 +++++++++++++++++ manager/services/database.js | 68 ++++++++++++++++------- portal/server.selfhosted.js | 30 +++++++++- portal/src/pages/Frequencia.tsx | 44 ++++++++++++++- 7 files changed, 191 insertions(+), 39 deletions(-) diff --git a/manager/components/AdminNotifications.tsx b/manager/components/AdminNotifications.tsx index 7c0ea62..2f68167 100644 --- a/manager/components/AdminNotifications.tsx +++ b/manager/components/AdminNotifications.tsx @@ -147,6 +147,9 @@ const AdminNotifications: React.FC = ({ data, updateData, setView, onNavi a.id === matchedAbsence.id ? { ...a, justificationAccepted: true } : a ); + const modifiedRecord = updatedAttendance.find(a => a.id === matchedAbsence.id); + fetch(`/api/frequencias/${matchedAbsence.id}`, { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(modifiedRecord) }); + updateData({ attendance: updatedAttendance }); dbService.saveData({ ...data, attendance: updatedAttendance }); handleMarkAsRead(notif.id); diff --git a/manager/components/AttendanceCapture.tsx b/manager/components/AttendanceCapture.tsx index d4d28c2..6dec72e 100644 --- a/manager/components/AttendanceCapture.tsx +++ b/manager/components/AttendanceCapture.tsx @@ -280,14 +280,15 @@ const AttendanceCapture: React.FC = ({ data, updateData verified: true }; + fetch('/api/frequencias', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(newAttendance) + }); + const updatedAttendance = [...filteredAttendance, newAttendance]; updateData({ attendance: updatedAttendance }); - // Sincronização em duas etapas: Local e Servidor (SQL) - const updatedData = { ...data, attendance: updatedAttendance }; - dbService.saveData(updatedData); - dbService.saveToCloud(updatedData); - // Reset de interface setCapturedImage(null); setShowConfirmModal(false); diff --git a/manager/components/AttendanceQuery.tsx b/manager/components/AttendanceQuery.tsx index db83662..97333c5 100644 --- a/manager/components/AttendanceQuery.tsx +++ b/manager/components/AttendanceQuery.tsx @@ -106,21 +106,22 @@ const AttendanceQuery: React.FC = ({ data, updateData, dee if (existingIdx >= 0) { updatedAttendance[existingIdx] = { ...updatedAttendance[existingIdx], type: newType, justification: undefined, justificationAccepted: undefined }; + fetch(`/api/frequencias/${updatedAttendance[existingIdx].id}`, { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(updatedAttendance[existingIdx]) }); } else { updatedAttendance.push(newRecord); + fetch('/api/frequencias', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(newRecord) }); } } else { // Toggle existing record const newType = record.type === 'absence' ? 'presence' : 'absence'; + const modifiedRecord = { ...record, type: newType, justification: undefined, justificationAccepted: undefined }; updatedAttendance = updatedAttendance.map(a => - a.id === record.id ? { ...a, type: newType, justification: undefined, justificationAccepted: undefined } : a + a.id === record.id ? modifiedRecord : a ); + fetch(`/api/frequencias/${record.id}`, { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(modifiedRecord) }); } updateData({ attendance: updatedAttendance }); - const updatedData = { ...data, attendance: updatedAttendance }; - dbService.saveData(updatedData); - dbService.saveToCloud(updatedData); // Sincronia imediata com SQL showAlert('Sucesso', 'Status de frequência atualizado com sucesso.', 'success'); }; @@ -137,8 +138,10 @@ const AttendanceQuery: React.FC = ({ data, updateData, dee a.id === attendanceForAttachment.id ? { ...a, justification: updatedJustification } : a ); + const modifiedRecord = updatedAttendance.find(a => a.id === attendanceForAttachment.id); + fetch(`/api/frequencias/${attendanceForAttachment.id}`, { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(modifiedRecord) }); + updateData({ attendance: updatedAttendance }); - dbService.saveData({ ...data, attendance: updatedAttendance }); setViewingAttachment(null); setAttendanceForAttachment(null); showAlert('Sucesso', 'Arquivo removido com sucesso.', 'success'); @@ -203,6 +206,7 @@ const AttendanceQuery: React.FC = ({ data, updateData, dee verified: true, lessonId: lesson.id as any }; + fetch(`/api/frequencias/${updatedAttendance[existingIndex].id}`, { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(updatedAttendance[existingIndex]) }); } else { const newAbsence: Attendance = { id: crypto.randomUUID(), @@ -216,12 +220,11 @@ const AttendanceQuery: React.FC = ({ data, updateData, dee ...(lesson ? { lessonId: lesson.id } : {}) as any }; updatedAttendance.push(newAbsence); + fetch('/api/frequencias', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(newAbsence) }); } - const updatedData = { ...data, attendance: updatedAttendance }; updateData({ attendance: updatedAttendance }); - dbService.saveData(updatedData); - dbService.saveToCloud(updatedData); // Sincronia imediata com SQL + dbService.saveData({ ...data, attendance: updatedAttendance }); setAbsenceStudentId(''); setAbsenceJustification(''); @@ -744,6 +747,8 @@ const AttendanceQuery: React.FC = ({ data, updateData, dee