fix: vinculo robusto por ID/Nome no Boletim e exibição de acertos/erros

This commit is contained in:
Sidney 2026-05-01 11:36:34 -03:00
parent 5adb683d4e
commit 10431ab9e8
2 changed files with 57 additions and 35 deletions

View File

@ -132,7 +132,11 @@ const ReportCard: React.FC<ReportCardProps> = ({ data, updateData }) => {
const { submissions } = await res.json(); const { submissions } = await res.json();
const subsMap: Record<string, {acertos: number, erros: number}> = {}; const subsMap: Record<string, {acertos: number, erros: number}> = {};
(submissions || []).forEach((s: any) => { (submissions || []).forEach((s: any) => {
subsMap[s.prova_id] = { acertos: s.acertos, erros: s.erros }; // Normalização agressiva para garantir o vínculo
const pId = String(s.prova_id || '').trim();
if (pId) {
subsMap[pId] = { acertos: s.acertos, erros: s.erros };
}
}); });
setStudentSubmissions(subsMap); setStudentSubmissions(subsMap);
} }
@ -148,11 +152,19 @@ const ReportCard: React.FC<ReportCardProps> = ({ data, updateData }) => {
if (linkedExams.length > 0) { if (linkedExams.length > 0) {
linkedExams.forEach(exam => { linkedExams.forEach(exam => {
const existingGrade = dbNotas.find(g => String(g.disciplina_id).trim() === String(subject.id).trim() && String(g.periodo_id).trim() === String(period.id).trim() && String(g.prova_id).trim() === String(exam.id).trim()); const existingGrade = dbNotas.find(g =>
String(g.disciplina_id).trim() === String(subject.id).trim() &&
(String(g.periodo_id).trim() === String(period.id).trim() || String(g.periodo_id).trim() === String(period.name).trim()) &&
String(g.prova_id).trim() === String(exam.id).trim()
);
periodGrades[exam.id] = existingGrade ? Number(existingGrade.valor) : ''; periodGrades[exam.id] = existingGrade ? Number(existingGrade.valor) : '';
}); });
} else { } else {
const existingGrade = dbNotas.find(g => String(g.disciplina_id).trim() === String(subject.id).trim() && String(g.periodo_id).trim() === String(period.id).trim() && !g.prova_id); const existingGrade = dbNotas.find(g =>
String(g.disciplina_id).trim() === String(subject.id).trim() &&
(String(g.periodo_id).trim() === String(period.id).trim() || String(g.periodo_id).trim() === String(period.name).trim()) &&
!g.prova_id
);
periodGrades['direct'] = existingGrade ? Number(existingGrade.valor) : ''; periodGrades['direct'] = existingGrade ? Number(existingGrade.valor) : '';
} }
initialGrades[subject.id][period.id] = periodGrades; initialGrades[subject.id][period.id] = periodGrades;
@ -579,7 +591,6 @@ const ReportCard: React.FC<ReportCardProps> = ({ data, updateData }) => {
const maxScore = (exam as any).maxScore ?? 10; const maxScore = (exam as any).maxScore ?? 10;
return ( return (
<div key={exam.id} className={`p-4 rounded-xl border flex flex-col md:flex-row md:items-center justify-between gap-4 ${isActivity ? 'bg-sky-50/50 border-sky-100' : 'bg-violet-50/50 border-violet-100'}`}> <div key={exam.id} className={`p-4 rounded-xl border flex flex-col md:flex-row md:items-center justify-between gap-4 ${isActivity ? 'bg-sky-50/50 border-sky-100' : 'bg-violet-50/50 border-violet-100'}`}>
<div className="flex-1">
<div className="flex flex-col"> <div className="flex flex-col">
<div className="text-sm font-bold text-slate-800 leading-tight mb-1 flex items-center gap-2"> <div className="text-sm font-bold text-slate-800 leading-tight mb-1 flex items-center gap-2">
<span className={`px-2 py-0.5 rounded text-[9px] uppercase tracking-wider font-black shrink-0 ${isActivity ? 'bg-sky-200 text-sky-800' : 'bg-violet-200 text-violet-800'}`}> <span className={`px-2 py-0.5 rounded text-[9px] uppercase tracking-wider font-black shrink-0 ${isActivity ? 'bg-sky-200 text-sky-800' : 'bg-violet-200 text-violet-800'}`}>
@ -591,17 +602,20 @@ const ReportCard: React.FC<ReportCardProps> = ({ data, updateData }) => {
{exam.description && ( {exam.description && (
<p className="text-xs text-slate-500 leading-snug pr-2">{exam.description}</p> <p className="text-xs text-slate-500 leading-snug pr-2">{exam.description}</p>
)} )}
{studentSubmissions[String(exam.id).trim()] && ( {(() => {
const stats = studentSubmissions[String(exam.id).trim()];
if (!stats) return null;
return (
<div className="flex gap-2 mt-2"> <div className="flex gap-2 mt-2">
<span className="text-[10px] font-bold px-2 py-0.5 rounded-full bg-emerald-100 text-emerald-700 border border-emerald-200"> <span className="text-[10px] font-bold px-2 py-0.5 rounded-full bg-emerald-100 text-emerald-700 border border-emerald-200 flex items-center gap-1">
{studentSubmissions[String(exam.id).trim()].acertos} Acertos <CheckCircle2 size={10} /> {stats.acertos} Acertos
</span> </span>
<span className="text-[10px] font-bold px-2 py-0.5 rounded-full bg-rose-100 text-rose-700 border border-rose-200"> <span className="text-[10px] font-bold px-2 py-0.5 rounded-full bg-rose-100 text-rose-700 border border-rose-200 flex items-center gap-1">
{studentSubmissions[String(exam.id).trim()].erros} Erros <X size={10} /> {stats.erros} Erros
</span> </span>
</div> </div>
)} );
</div> })()}
</div> </div>
</div> </div>

View File

@ -1,17 +1,25 @@
import pg from 'pg';
const DATABASE_URL = 'postgresql://edumanager:EduManager2026!Seguro@127.0.0.1:5432/edumanager';
const pool = new pg.Pool({ connectionString: DATABASE_URL });
async function listAll() { import pkg from 'pg';
const { Pool } = pkg;
const pool = new Pool({
connectionString: 'postgresql://postgres:postgres@localhost:5432/edumanager'
});
async function check() {
try { try {
const { rows: notas } = await pool.query('SELECT * FROM notas_boletim LIMIT 20'); console.log('--- SUBMISSÕES NO BANCO ---');
console.log('--- NOTAS NA TABELA ---'); const { rows: subs } = await pool.query('SELECT aluno_id, prova_id, acertos, erros FROM provas_submissoes');
console.log(JSON.stringify(notas, null, 2));
const { rows: subs } = await pool.query('SELECT * FROM provas_submissoes LIMIT 10');
console.log('--- SUBMISSÕES NA TABELA ---');
console.log(JSON.stringify(subs, null, 2)); console.log(JSON.stringify(subs, null, 2));
} catch (err) { console.log('ERROR:' + err.message); }
finally { await pool.end(); } console.log('\n--- NOTAS NO BOLETIM ---');
const { rows: notas } = await pool.query('SELECT aluno_id, disciplina_id, periodo_id, prova_id, valor FROM notas_boletim');
console.log(JSON.stringify(notas, null, 2));
} catch (err) {
console.error(err);
} finally {
await pool.end();
}
} }
listAll();
check();