SGAD - Sistema de Gestão Acadêmica Bem-vindo ao Sistema de Gestão Acadêmica Visão geral do sistema.
RA Nome CPF Email Curso Status Ações
ID Nome Professor Semestre Horário Status Ações
Gestão de Matrículas Matrículas Realizadas ID Aluno Turma/Disciplina Semestre Situação Status Ações
Histórico Escolar
Semestre Disciplina Nota Situação
Relatórios Acadêmicos
Aluno
Disciplina Semestre Horário Situação
Imprimir Relatório
`;
win.document.write(html);
win.document.close();
}async function loadNotasView() {
const [turmas, alunos] = await Promise.all([
apiRequest('READ', 'Turmas', { Status: 'Ativo' }),
apiRequest('READ', 'Alunos', { Status: 'Ativo' })
]);// Por Turma
const selTurma = sgadContainer.querySelector('#select-turma-notas');
selTurma.innerHTML = '
Selecione... ' + turmas.map(t => `
${t.Disciplina} (${t.Semestre}) `).join('');
sgadContainer.querySelector('#table-alunos-notas tbody').innerHTML = '';// Por Aluno
const selAluno = sgadContainer.querySelector('#select-aluno-notas');
selAluno.innerHTML = '
Selecione... ' + alunos.map(a => `
${a.Nome} `).join('');
sgadContainer.querySelector('#table-disciplinas-notas tbody').innerHTML = '';// Reset UI
sgadContainer.querySelector('input[name="modo-notas"][value="turma"]').checked = true;
toggleNotasMode('turma');
}function toggleNotasMode(mode) {
const containerTurma = sgadContainer.querySelector('#notas-por-turma-container');
const containerAluno = sgadContainer.querySelector('#notas-por-aluno-container');
if (mode === 'turma') {
containerTurma.style.display = 'block';
containerAluno.style.display = 'none';
} else {
containerTurma.style.display = 'none';
containerAluno.style.display = 'block';
}
}// Event listener for radio buttons
sgadContainer.querySelectorAll('input[name="modo-notas"]').forEach(radio => {
radio.addEventListener('change', (e) => toggleNotasMode(e.target.value));
});async function loadRelatoriosView() {
const [cursos, turmas, alunos] = await Promise.all([
apiRequest('READ', 'Cursos'),
apiRequest('READ', 'Turmas'),
apiRequest('READ', 'Alunos', { Status: 'Ativo' })
]);
const selCurso = sgadContainer.querySelector('#select-curso-relatorio');
const selTurma = sgadContainer.querySelector('#select-turma-relatorio');
const selAluno = sgadContainer.querySelector('#select-aluno-relatorio');selCurso.innerHTML = '
Selecione... ' + cursos.map(c => `
${c.Nome} `).join('');
selTurma.innerHTML = '
Selecione... ' + turmas.map(t => `
${t.Disciplina} (${t.Semestre}) `).join('');
selAluno.innerHTML = '
Selecione... ' + alunos.map(a => `
${a.Nome} `).join('');
resetReports();
}window.showReport = (reportName) => {
sgadContainer.querySelector('#relatorios-menu').style.display = 'none';
sgadContainer.querySelectorAll('.report-container').forEach(el => el.style.display = 'none');
sgadContainer.querySelector(`#report-container-${reportName}`).style.display = 'block';
};window.resetReports = () => {
sgadContainer.querySelector('#relatorios-menu').style.display = 'block';
sgadContainer.querySelectorAll('.report-container').forEach(el => el.style.display = 'none');
}// --- Manipulador de Eventos Principal (Delegação) ---
mainContent.addEventListener('click', async (e) => {
const target = e.target;
const closest = (selector) => target.closest(selector);
// Botão Buscar Histórico
if (target.id === 'btn-buscar-historico') {
const ra = sgadContainer.querySelector('#input-ra-historico').value;
if (!ra) return showToast('Digite o RA.', 'error');
const tableBody = sgadContainer.querySelector('#table-historico tbody');
const infoDiv = sgadContainer.querySelector('#historico-aluno-info');
try {
const data = await apiRequest('GET_ACADEMIC_HISTORY', '', { RA: ra });
if (data.length === 0) {
infoDiv.textContent = 'Nenhum histórico encontrado para este RA.';
tableBody.innerHTML = '';
return;
}const aluno = data[0].aluno;
infoDiv.textContent = `Aluno: ${aluno.Nome} | Curso: ${aluno.Curso}`;
tableBody.innerHTML = data.map(item => `
${item.turma ? item.turma.Semestre : '-'} ${item.disciplina ? item.disciplina.Nome : '-'} ${item.nota ? item.nota.Nota : '-'} ${item.matricula.Situacao}
`).join('');
} catch (error) {
console.error(error);
// showToast('Erro ao buscar histórico', 'error'); // apiRequest already shows toast
}
}// Botões "Novo"
if (target.id === 'btn-novo-aluno') {
const cursos = await apiRequest('READ', 'Cursos', { Status: 'Ativo' });
const optionsCursos = cursos.map(c => `
${c.Nome} `).join('');
const formHtml = `
RA
Nome
CPF
Email
Curso Selecione... ${optionsCursos}
Status Ativo Inativo
`;
openModal('Novo Aluno', formHtml, data => apiRequest('CREATE', 'Alunos', data).then(() => showToast('Aluno criado!')));
}
if (target.id === 'btn-novo-professor') {
const formHtml = `
Nome
Email
Status Ativo Inativo
`;
openModal('Novo Professor', formHtml, data => apiRequest('CREATE', 'Professores', data).then(() => showToast('Professor criado!')));
}
if (target.id === 'btn-nova-turma') {
const professores = await apiRequest('READ', 'Professores', { Status: 'Ativo' });
const optionsProfessores = professores.map(p => `
${p.Nome} `).join('');
const formHtml = `
Nome
Professor
Selecione...
${optionsProfessores}
Semestre
Horário
Status Ativo Inativo
`;
openModal('Nova Disciplina', formHtml, data => apiRequest('CREATE', 'Turmas', data).then(() => showToast('Disciplina criada!')));
}
if (target.id === 'btn-novo-curso') {
const formHtml = `
Nome do Curso
Status Ativo Inativo
`;
openModal('Novo Curso', formHtml, data => apiRequest('CREATE', 'Cursos', data).then(() => showToast('Curso criado!')));
}// Ações de Edição e Exclusão para Cursos
const editCursoBtn = closest('.btn-edit-curso');
if (editCursoBtn) {
editingId = editCursoBtn.dataset.id;
const [curso] = await apiRequest('READ', 'Cursos', { ID: editingId });
const formHtml = `
Nome do Curso
Status Ativo Inativo
`;
openModal('Editar Curso', formHtml, data => apiRequest('UPDATE', 'Cursos', data).then(() => showToast('Curso atualizado!')));
}const deleteCursoBtn = closest('.btn-delete-curso');
if (deleteCursoBtn && confirm('Deseja inativar este curso?')) {
await apiRequest('DELETE', 'Cursos', { ID: deleteCursoBtn.dataset.id });
showToast('Curso inativado!');
loadCursos();
}// Ações de Matrícula e Notas
if (target.id === 'btn-add-cesta') {
const selTurma = sgadContainer.querySelector('#select-turma-matricula');
const turmaID = selTurma.value;
if (!turmaID) return showToast("Selecione uma disciplina.", "error");
const exists = cestaMatriculas.some(item => item.id === turmaID);
if (exists) return showToast("Disciplina já adicionada.", "error");
const turmaNome = selTurma.options[selTurma.selectedIndex].text;
cestaMatriculas.push({ id: turmaID, nome: turmaNome });
updateCestaUI();
selTurma.value = "";
}if (target.id === 'btn-confirmar-matricula') {
const alunoRA = sgadContainer.querySelector('#select-aluno-matricula').value;
const alunoNome = sgadContainer.querySelector('#select-aluno-matricula').selectedOptions[0]?.text;
if (!alunoRA) return showToast("Selecione um aluno.", "error");
if (cestaMatriculas.length === 0) return showToast("Adicione disciplinas à cesta.", "error");try {
showSpinner();
// Process all enrollments in parallel
await Promise.all(cestaMatriculas.map(item =>
apiRequest('CREATE', 'Matriculas', {
Aluno_RA: alunoRA,
Turma_ID: item.id,
Status: 'Ativo',
Situacao: 'Cursando'
})
));
showToast('Matrículas realizadas com sucesso!');
generateReceipt(alunoNome, cestaMatriculas);
loadMatriculaView(); // Clear basket and refresh list
} catch (error) {
console.error(error);
// Toast handled by apiRequest
} finally {
hideSpinner();
}
}
const cancelMatriculaBtn = closest('.btn-cancelar-matricula');
if (cancelMatriculaBtn && confirm('Deseja cancelar esta matrícula?')) {
await apiRequest('DELETE', 'Matriculas', { ID: cancelMatriculaBtn.dataset.id });
showToast('Matrícula cancelada!');
loadMatriculaView();
}// Salvar Tudo
if (target.id === 'btn-salvar-tudo-turma' || target.id === 'btn-salvar-tudo-aluno') {
const inputs = sgadContainer.querySelectorAll('.input-nota');
const updates = [];
inputs.forEach(input => {
const matriculaId = input.dataset.matriculaId;
const existingNotaId = input.dataset.notaId;
const val = input.value.trim();
// Skip if empty or invalid? Maybe we want to clear grades?
// For now, assume we save if value exists.
if (val === "") return;
const notaValue = parseFloat(val);
const action = existingNotaId ? 'UPDATE' : 'CREATE';
const data = { Matricula_ID: matriculaId, Nota: notaValue, ID: existingNotaId };
updates.push(apiRequest(action, 'Notas', data));
});
if (updates.length === 0) return showToast("Nenhuma nota para salvar.", "warning");
try {
await Promise.all(updates);
showToast('Todas as notas foram salvas!');
// Refresh current view logic
if (target.id === 'btn-salvar-tudo-turma') {
sgadContainer.querySelector('#select-turma-notas').dispatchEvent(new Event('change', {bubbles: true}));
} else {
sgadContainer.querySelector('#select-aluno-notas').dispatchEvent(new Event('change', {bubbles: true}));
}} catch (e) {
console.error(e);
// Toast handled by apiRequest
}
}// Ações de Edição e Exclusão
const editAlunoBtn = closest('.btn-edit-aluno');
if (editAlunoBtn) {
editingId = editAlunoBtn.dataset.ra;
const [aluno, cursos] = await Promise.all([
apiRequest('READ', 'Alunos', { RA: editingId }).then(res => res[0]),
apiRequest('READ', 'Cursos', { Status: 'Ativo' })
]);
const optionsCursos = cursos.map(c => `
${c.Nome} `).join('');
const formHtml = `
Nome
CPF
Email
Curso Selecione... ${optionsCursos}
Status Ativo Inativo
`;
openModal('Editar Aluno', formHtml, data => apiRequest('UPDATE', 'Alunos', data).then(() => showToast('Aluno atualizado!')));
}const deleteAlunoBtn = closest('.btn-delete-aluno');
if (deleteAlunoBtn && confirm('Deseja inativar este aluno?')) {
await apiRequest('DELETE', 'Alunos', { RA: deleteAlunoBtn.dataset.ra });
showToast('Aluno inativado!');
loadAlunos();
}const editProfessorBtn = closest('.btn-edit-professor');
if (editProfessorBtn) {
editingId = editProfessorBtn.dataset.id;
const [professor] = await apiRequest('READ', 'Professores', { ID: editingId });
const formHtml = `
Nome
Email
Status Ativo Inativo
`;
openModal('Editar Professor', formHtml, data => apiRequest('UPDATE', 'Professores', data).then(() => showToast('Professor atualizado!')));
}const deleteProfessorBtn = closest('.btn-delete-professor');
if (deleteProfessorBtn && confirm('Deseja inativar este professor?')) {
await apiRequest('DELETE', 'Professores', { ID: deleteProfessorBtn.dataset.id });
showToast('Professor inativado!');
loadProfessores();
}const editTurmaBtn = closest('.btn-edit-turma');
if (editTurmaBtn) {
editingId = editTurmaBtn.dataset.id;
const [turma, professores] = await Promise.all([
apiRequest('READ', 'Turmas', { ID: editingId }).then(res => res[0]),
apiRequest('READ', 'Professores', { Status: 'Ativo' })
]);
const optionsProfessores = professores.map(p =>
`
${p.Nome} `
).join('');const formHtml = `
Nome
Professor
Selecione...
${optionsProfessores}
Semestre
Horário
Status Ativo Inativo
`;
openModal('Editar Disciplina', formHtml, data => apiRequest('UPDATE', 'Turmas', data).then(() => showToast('Disciplina atualizada!')));
}const deleteTurmaBtn = closest('.btn-delete-turma');
if (deleteTurmaBtn && confirm('Deseja inativar esta turma?')) {
await apiRequest('DELETE', 'Turmas', { ID: deleteTurmaBtn.dataset.id });
showToast('Turma inativada!');
loadTurmas();
}
});
// --- Eventos 'change' para selects dinâmicos ---
mainContent.addEventListener('change', async (e) => {
if (e.target.id === 'select-disciplina-matricula') {
const disciplina = e.target.value;
const selTurma = sgadContainer.querySelector('#select-turma-matricula');
if (!disciplina) { selTurma.disabled = true; return; }
const turmas = await apiRequest('READ', 'Turmas', { Disciplina: disciplina, Status: 'Ativo' });
selTurma.innerHTML = '
Selecione... ' + turmas.map(t => `
${t.Professor} (${t.Horario}) `).join('');
selTurma.disabled = false;
}
if (e.target.id === 'select-turma-notas') {
const turmaId = e.target.value;
const tableBody = sgadContainer.querySelector('#table-alunos-notas tbody');
const btnSalvar = sgadContainer.querySelector('#btn-salvar-tudo-turma');
if (!turmaId) {
tableBody.innerHTML = '';
btnSalvar.style.display = 'none';
return;
}
const data = await apiRequest('GET_STUDENTS_FOR_GRADING', '', { Turma_ID: turmaId });
tableBody.innerHTML = data.map(item => `
${item.aluno.RA} ${item.aluno.Nome} ${item.Situacao} `
).join('');
btnSalvar.style.display = 'block';
}
if (e.target.id === 'select-aluno-notas') {
const ra = e.target.value;
const tableBody = sgadContainer.querySelector('#table-disciplinas-notas tbody');
const btnSalvar = sgadContainer.querySelector('#btn-salvar-tudo-aluno');
if (!ra) {
tableBody.innerHTML = '';
btnSalvar.style.display = 'none';
return;
}
const data = await apiRequest('GET_STUDENT_ENROLLMENTS_FOR_GRADING', '', { RA: ra });
tableBody.innerHTML = data.map(item => `
${item.disciplina ? item.disciplina.Nome : '-'} ${item.turma ? item.turma.Semestre : '-'} ${item.matricula.Situacao} `
).join('');
btnSalvar.style.display = 'block';
}
if (e.target.id === 'select-curso-relatorio') {
const curso = e.target.value;
const tableBody = sgadContainer.querySelector('#table-relatorio-alunos-curso tbody');
if (!curso) { tableBody.innerHTML = ''; return; }
const alunos = await apiRequest('READ', 'Alunos', { Curso: curso });
tableBody.innerHTML = alunos.map(a => `
${a.RA} ${a.Nome} ${a.Status} `).join('');
}
if (e.target.id === 'select-turma-relatorio') {
const turmaId = e.target.value;
const tableBody = sgadContainer.querySelector('#table-relatorio-alunos-turma tbody');
if (!turmaId) { tableBody.innerHTML = ''; return; }
const data = await apiRequest('GET_STUDENTS_FOR_GRADING', '', { Turma_ID: turmaId });
tableBody.innerHTML = data.map(item => `
${item.aluno.RA} ${item.aluno.Nome} ${item.Situacao} `).join('');
}if (e.target.id === 'select-aluno-relatorio') {
const ra = e.target.value;
const tableBody = sgadContainer.querySelector('#table-relatorio-disciplinas-aluno tbody');
const btnPrint = sgadContainer.querySelector('#btn-imprimir-relatorio-aluno');
if (!ra) {
tableBody.innerHTML = '';
btnPrint.style.display = 'none';
return;
}// Reuse getAcademicHistory or fetch manually. getAcademicHistory is perfect as it joins Turma/Disciplina.
const data = await apiRequest('GET_ACADEMIC_HISTORY', '', { RA: ra });
// Filter only 'Cursando' if needed, or show all?
// Request says "disciplinas em que o aluno esta matriculado" (currently enrolled).
// Let's filter for active enrollments (Cursando or similar) or show status.
// The table has a 'Situação' column, so listing all is safer, but user likely means current ones.
// But the academic history returns everything. Let's show everything but sort or highlight?
// For a "report of enrollments", usually implies current semester.
// However, "Disciplinas por Aluno" could mean transcript.
// Given the context of "Relatórios", let's show what GET_ACADEMIC_HISTORY returns (which is comprehensive).
tableBody.innerHTML = data.map(item => `
${item.disciplina ? item.disciplina.Nome : '-'} ${item.turma ? item.turma.Semestre : '-'} ${item.turma ? item.turma.Horario : '-'} ${item.matricula.Situacao}
`).join('');
btnPrint.style.display = data.length ? 'block' : 'none';
// Store data for printing if needed, or read from DOM.
// Better to store:
e.target.dataset.reportData = JSON.stringify(data);
}
});// Add specific listener for the new print button (since it's not dynamic change)
const btnPrintRelatorio = sgadContainer.querySelector('#btn-imprimir-relatorio-aluno');
if (btnPrintRelatorio) {
btnPrintRelatorio.addEventListener('click', () => {
const selAluno = sgadContainer.querySelector('#select-aluno-relatorio');
const alunoNome = selAluno.options[selAluno.selectedIndex].text;
const data = JSON.parse(selAluno.dataset.reportData || '[]');
generateStudentDisciplinesReport(alunoNome, data);
});
}function generateStudentDisciplinesReport(alunoNome, data) {
const win = window.open('', '_blank');
const date = new Date().toLocaleDateString('pt-BR');
const html = `
Relatório de Disciplinas - ${alunoNome} Aluno: ${alunoNome}
Data de Emissão: ${date}
Disciplina Semestre Horário Situação
${data.map(item => `${item.disciplina ? item.disciplina.Nome : '-'} ${item.turma ? item.turma.Semestre : '-'} ${item.turma ? item.turma.Horario : '-'} ${item.matricula.Situacao}
`).join('')}
`;
win.document.write(html);
win.document.close();
}// Inicialização
switchView('dashboard');
});