From 08e11d0bf6b8a31ed6e1439569a8e14f3d08bb75 Mon Sep 17 00:00:00 2001 From: andrymodeste Date: Mon, 18 Aug 2025 06:20:50 +0200 Subject: [PATCH] derniere version --- database/Models/AnneeScolaire.js | 10 +- database/Models/Etudiants.backup.js | 2 +- database/Models/Etudiants.js | 24 +- database/Models/Matieres.js | 8 +- database/Models/Mentions.js | 8 +- database/Models/NoteSysrem.js | 4 +- database/Models/Parcours.js | 8 +- database/database.backup.js | 4 +- database/database.js | 4 +- database/database2.js | 4 +- database/function/System.js | 4 +- .../src/components/AddAnneeScolaire.jsx | 8 +- src/renderer/src/components/AddStudent.jsx | 8 +- src/renderer/src/components/AnneeScolaire.jsx | 4 +- .../src/components/ExportEtudiants.jsx | 8 +- src/renderer/src/components/Home.jsx | 4 +- src/renderer/src/components/Login.jsx | 159 +++-- .../src/components/ModalAddEtudiants.jsx | 6 +- src/renderer/src/components/ModalAddProf.jsx | 4 +- .../src/components/ModalCertificate.jsx | 6 +- .../src/components/ModalExportFichr.jsx | 2 +- src/renderer/src/components/ModalRecepice.jsx | 2 +- src/renderer/src/components/ModalStage.jsx | 2 +- src/renderer/src/components/Noteclasse.jsx | 109 +++- src/renderer/src/components/Notes.jsx | 2 +- src/renderer/src/components/Param.jsx | 208 +++---- src/renderer/src/components/ReleverNotes.jsx | 263 ++++---- src/renderer/src/components/Resultat.jsx | 562 ++++++++++++++---- src/renderer/src/components/Sidenav.jsx | 84 +-- .../src/components/SingleAnneeScolaire.jsx | 6 +- .../src/components/SingleEtudiant.jsx | 8 +- src/renderer/src/components/Student.jsx | 21 +- src/renderer/src/components/SystemeNote.jsx | 8 +- src/renderer/src/components/TesteDatagrid.jsx | 4 +- .../src/components/UpdateModalProf.jsx | 4 +- .../src/components/function/PDFEditor.js | 6 +- .../src/components/function/PDFEditorV2.js | 69 ++- .../validation/ValidationAddAnneeScolaire.js | 2 +- src/renderer/src/contexts/AuthContext.jsx | 80 ++- src/renderer/src/test/qr.html | 2 +- src/renderer/src/test/relever.html | 2 +- text.txt | 2 +- 42 files changed, 1114 insertions(+), 621 deletions(-) diff --git a/database/Models/AnneeScolaire.js b/database/Models/AnneeScolaire.js index 1b89b53..e204f1a 100644 --- a/database/Models/AnneeScolaire.js +++ b/database/Models/AnneeScolaire.js @@ -23,7 +23,7 @@ async function createAnneeScolaire(code, debut, fin) { } /** - * function to get all année scolaire + * function to get all Année Univesitaire * @returns promise */ async function getAnneeScolaire() { @@ -71,13 +71,13 @@ async function deleteAnneeScolaire(id) { if (result.affectedRows === 0) { return { success: false, - message: 'Année Scolaire non trouvé.' + message: 'Année universitaire non trouvé.' } } return { success: true, - message: 'Année Scolaire supprimé avec succès.' + message: 'Année universitaire supprimé avec succès.' } } catch (error) { return { success: false, error: 'Erreur veullez réeseyer' } @@ -93,13 +93,13 @@ async function updateAnneeScolaire(id, code, debut, fin) { if (result.affectedRows === 0) { return { success: false, - message: 'Année Scolaire non trouvé ou aucune modification effectuée.' + message: 'Année universitaire non trouvé ou aucune modification effectuée.' } } return { success: true, - message: 'Année Scolaire mis à jour avec succès.' + message: 'Année universitaire mis à jour avec succès.' } } catch (error) { return { success: false, error: 'Erreur veullez réeseyer' } diff --git a/database/Models/Etudiants.backup.js b/database/Models/Etudiants.backup.js index 0d7c58d..40a5b52 100644 --- a/database/Models/Etudiants.backup.js +++ b/database/Models/Etudiants.backup.js @@ -191,7 +191,7 @@ async function updateEtudiant( async function getDataToDashboard() { const query = database.prepare('SELECT * FROM niveaus') const query2 = database.prepare('SELECT * FROM etudiants') - const query3 = database.prepare('SELECT DISTINCT annee_scolaire FROM etudiants') // get all année scolaire sans doublan + const query3 = database.prepare('SELECT DISTINCT annee_scolaire FROM etudiants') // get all Année Univesitaire sans doublan try { let niveau = query.all() diff --git a/database/Models/Etudiants.js b/database/Models/Etudiants.js index dacab4b..dc35667 100644 --- a/database/Models/Etudiants.js +++ b/database/Models/Etudiants.js @@ -83,7 +83,7 @@ async function getAllEtudiants() { * @returns Promise */ async function getSingleEtudiant(id) { - const sql = 'SELECT * FROM etudiants WHERE id = ?' + const sql = 'SELECT e.*, m.uniter AS mentionUnite FROM etudiants e JOIN mentions m ON e.mention_id = m.id WHERE e.id = ?' try { const [rows] = await pool.query(sql, [id]) @@ -176,13 +176,13 @@ async function updateEtudiant( if (result.affectedRows === 0) { return { success: false, - message: 'Année Scolaire non trouvé.' + message: 'Année Univesitaire non trouvé.' } } return { success: true, - message: 'Année Scolaire supprimé avec succès.' + message: 'Année Univesitaire supprimé avec succès.' } } catch (error) { return error @@ -197,7 +197,7 @@ async function updateEtudiant( async function getDataToDashboard() { const query = 'SELECT * FROM niveaus' const query2 = 'SELECT * FROM etudiants' - const query3 = 'SELECT DISTINCT annee_scolaire FROM etudiants' // get all année scolaire sans doublan + const query3 = 'SELECT DISTINCT annee_scolaire FROM etudiants' // get all Année Univesitaire sans doublan try { let [rows] = await pool.query(query) @@ -222,13 +222,13 @@ async function changePDP(photos, id) { if (result.affectedRows === 0) { return { success: false, - message: 'Année Scolaire non trouvé.' + message: 'Année Univesitaire non trouvé.' } } return { success: true, - message: 'Année Scolaire supprimé avec succès.' + message: 'Année Univesitaire supprimé avec succès.' } } catch (error) { return error @@ -244,13 +244,13 @@ async function updateParcours(parcours, id) { if (result.affectedRows === 0) { return { success: false, - message: 'Année Scolaire non trouvé.' + message: 'Année Univesitaire non trouvé.' } } return { success: true, - message: 'Année Scolaire supprimé avec succès.' + message: 'Année Univesitaire supprimé avec succès.' } } catch (error) { return error @@ -294,13 +294,13 @@ async function updateTranche(id, tranchename, montant) { if (result.affectedRows === 0) { return { success: false, - message: 'Année Scolaire non trouvé.' + message: 'Année Univesitaire non trouvé.' } } return { success: true, - message: 'Année Scolaire supprimé avec succès.' + message: 'Année Univesitaire supprimé avec succès.' } } catch (error) { console.log('resultat error:',error); @@ -317,13 +317,13 @@ async function deleteTranche(id) { if (result.affectedRows === 0) { return { success: false, - message: 'Année Scolaire non trouvé.' + message: 'Année Univesitaire non trouvé.' } } return { success: true, - message: 'Année Scolaire supprimé avec succès.' + message: 'Année Univesitaire supprimé avec succès.' } } catch (error) { return error diff --git a/database/Models/Matieres.js b/database/Models/Matieres.js index 694bf01..0624ccd 100644 --- a/database/Models/Matieres.js +++ b/database/Models/Matieres.js @@ -125,13 +125,13 @@ async function updateMatiere(nom, id, credit, uniter, ue) { if (result.affectedRows === 0) { return { success: false, - message: 'Année Scolaire non trouvé ou aucune modification effectuée.' + message: 'Année Univesitaire non trouvé ou aucune modification effectuée.' } } return { success: true, - message: 'Année Scolaire mis à jour avec succès.' + message: 'Année Univesitaire mis à jour avec succès.' } } catch (error) { return { success: false, error: 'Erreur veullez réeseyer' + error } @@ -448,13 +448,13 @@ async function updateProf(matiere_id, nom, prenom, contact, date) { if (result.affectedRows === 0) { return { success: false, - message: 'Année Scolaire non trouvé.' + message: 'Année Univesitaire non trouvé.' } } return { success: true, - message: 'Année Scolaire supprimé avec succès.' + message: 'Année Univesitaire supprimé avec succès.' } } catch (error) { console.error(error) diff --git a/database/Models/Mentions.js b/database/Models/Mentions.js index d907f15..a5973a7 100644 --- a/database/Models/Mentions.js +++ b/database/Models/Mentions.js @@ -24,13 +24,13 @@ async function deleteMention(id) { if (result.affectedRows === 0) { return { success: false, - message: 'Année Scolaire non trouvé.' + message: 'Année Univesitaire non trouvé.' } } return { success: true, - message: 'Année Scolaire supprimé avec succès.' + message: 'Année Univesitaire supprimé avec succès.' } } catch (error) { return { success: false, error: 'Erreur veullez réeseyer' + error } @@ -70,13 +70,13 @@ async function updateMention(nom, uniter, id) { if (result.affectedRows === 0) { return { success: false, - message: 'Année Scolaire non trouvé ou aucune modification effectuée.' + message: 'Année Univesitaire non trouvé ou aucune modification effectuée.' } } return { success: true, - message: 'Année Scolaire mis à jour avec succès.' + message: 'Année Univesitaire mis à jour avec succès.' } } catch (error) { return { success: false, error: 'Erreur veullez réeseyer' + error } diff --git a/database/Models/NoteSysrem.js b/database/Models/NoteSysrem.js index 5a8553f..a906668 100644 --- a/database/Models/NoteSysrem.js +++ b/database/Models/NoteSysrem.js @@ -33,13 +33,13 @@ async function updateSysteme(id, admis, redouble, renvoyer) { if (result.affectedRows === 0) { return { success: false, - message: 'Année Scolaire non trouvé.' + message: 'Année Univesitaire non trouvé.' } } return { success: true, - message: 'Année Scolaire supprimé avec succès.' + message: 'Année Univesitaire supprimé avec succès.' } } catch (error) { return error diff --git a/database/Models/Parcours.js b/database/Models/Parcours.js index 93397cf..9f7309f 100644 --- a/database/Models/Parcours.js +++ b/database/Models/Parcours.js @@ -64,13 +64,13 @@ async function deletes(id) { if (result.affectedRows === 0) { return { success: false, - message: 'Année Scolaire non trouvé.' + message: 'Année Univesitaire non trouvé.' } } return { success: true, - message: 'Année Scolaire supprimé avec succès.' + message: 'Année Univesitaire supprimé avec succès.' } } catch (error) { return error @@ -86,13 +86,13 @@ async function updateparcour(id, nom, uniter, mention_id) { if (result.affectedRows === 0) { return { success: false, - message: 'Année Scolaire non trouvé ou aucune modification effectuée.' + message: 'Année Univesitaire non trouvé ou aucune modification effectuée.' } } return { success: true, - message: 'Année Scolaire mis à jour avec succès.' + message: 'Année Univesitaire mis à jour avec succès.' } } catch (error) { return error diff --git a/database/database.backup.js b/database/database.backup.js index 7ea1c7f..c10b0dd 100644 --- a/database/database.backup.js +++ b/database/database.backup.js @@ -2,9 +2,9 @@ const mysql = require('mysql2/promise') const bcrypt = require('bcryptjs') const pool = mysql.createPool({ - host: '127.0.0.1', + host: '192.168.200.200', user: 'root', - password: '', + password: 'stephane1313', database: 'university', waitForConnections: true, connectionLimit: 10, diff --git a/database/database.js b/database/database.js index b6c285f..4260948 100644 --- a/database/database.js +++ b/database/database.js @@ -2,9 +2,9 @@ const mysql = require('mysql2/promise') const bcrypt = require('bcryptjs') const pool = mysql.createPool({ - host: '127.0.0.1', + host: '192.168.200.200', user: 'root', - password: '', + password: 'stephane1313', database: 'university', waitForConnections: true, connectionLimit: 10, diff --git a/database/database2.js b/database/database2.js index de8806f..d2c4bf1 100644 --- a/database/database2.js +++ b/database/database2.js @@ -2,9 +2,9 @@ const mysql = require('mysql2/promise') const bcrypt = require('bcryptjs') const pool = mysql.createPool({ - host: '127.0.0.1', + host: '192.168.200.200', user: 'root', - password: '', + password: 'stephane1313', database: 'university', waitForConnections: true, connectionLimit: 10, diff --git a/database/function/System.js b/database/function/System.js index 7356730..c6b40fd 100644 --- a/database/function/System.js +++ b/database/function/System.js @@ -287,13 +287,13 @@ async function updateNessesaryTable(id, multiplicateur) { if (result.affectedRows === 0) { return { success: false, - message: 'Année Scolaire non trouvé.' + message: 'Année universitaire non trouvé.' } } return { success: true, - message: 'Année Scolaire supprimé avec succès.' + message: 'Année universitaire supprimé avec succès.' } } catch (error) { return error diff --git a/src/renderer/src/components/AddAnneeScolaire.jsx b/src/renderer/src/components/AddAnneeScolaire.jsx index 42b1038..5b7f460 100644 --- a/src/renderer/src/components/AddAnneeScolaire.jsx +++ b/src/renderer/src/components/AddAnneeScolaire.jsx @@ -98,7 +98,7 @@ const AddAnneeScolaire = () => { {status === 200 ? ( {' '} - Année Scolaire insérer avec succes + Année Univesitaire insérer avec succes ) : ( @@ -136,7 +136,7 @@ const AddAnneeScolaire = () => {

- Ajout Année Scolaire + Ajout Année Univesitaire

window.history.back()}>
@@ -154,4 +205,4 @@ const Login = () => { ) } -export default Login +export default Login \ No newline at end of file diff --git a/src/renderer/src/components/ModalAddEtudiants.jsx b/src/renderer/src/components/ModalAddEtudiants.jsx index c4ce7bf..fea424f 100644 --- a/src/renderer/src/components/ModalAddEtudiants.jsx +++ b/src/renderer/src/components/ModalAddEtudiants.jsx @@ -154,7 +154,7 @@ const ModalAddEtudiants = ({ open, handleClose }) => { { /> - {/* Année Scolaire and Numéro d'Inscription Fields */} + {/* Année Univesitaire and Numéro d'Inscription Fields */} { margin="normal" required name="prenom_enseignant" - label="Prenom du professeur" + label="Prénom du professeur" type="text" fullWidth - placeholder="Prenom du professeur" + placeholder="Prénom du professeur" variant="outlined" value={formData.prenom_enseignant} color="warning" diff --git a/src/renderer/src/components/ModalCertificate.jsx b/src/renderer/src/components/ModalCertificate.jsx index d513be3..8a2b4dd 100644 --- a/src/renderer/src/components/ModalCertificate.jsx +++ b/src/renderer/src/components/ModalCertificate.jsx @@ -41,14 +41,14 @@ const ModalCertificate = ({ open, onClose, json }) => { return (
- Informations sur l'élève + Informations sur l'étudiant { margin="dense" name="mere" required - label="Mère de l'élève" + label="Mère de l'étudiant" type="text" fullWidth variant="outlined" diff --git a/src/renderer/src/components/ModalExportFichr.jsx b/src/renderer/src/components/ModalExportFichr.jsx index 9ba8c1a..f7f33aa 100644 --- a/src/renderer/src/components/ModalExportFichr.jsx +++ b/src/renderer/src/components/ModalExportFichr.jsx @@ -170,7 +170,7 @@ const ModalExportFichr = () => { N° - Nom et Prenom + Nom et Prénom Mention Emergement diff --git a/src/renderer/src/components/ModalRecepice.jsx b/src/renderer/src/components/ModalRecepice.jsx index 2f27cc0..a5d47cd 100644 --- a/src/renderer/src/components/ModalRecepice.jsx +++ b/src/renderer/src/components/ModalRecepice.jsx @@ -41,7 +41,7 @@ const ModalRecepice = ({ open, onClose, json }) => { margin="dense" required name="nom" - label="Nom et prenom du chef de services" + label="Nom et prénom du chef de services" type="text" fullWidth variant="outlined" diff --git a/src/renderer/src/components/ModalStage.jsx b/src/renderer/src/components/ModalStage.jsx index 105fdc5..ce153d9 100644 --- a/src/renderer/src/components/ModalStage.jsx +++ b/src/renderer/src/components/ModalStage.jsx @@ -57,7 +57,7 @@ const ModalStage = ({ open, onClose }) => { margin="dense" name="prenom" required - label="Prenom du directeur" + label="Prénom du directeur" type="text" fullWidth variant="outlined" diff --git a/src/renderer/src/components/Noteclasse.jsx b/src/renderer/src/components/Noteclasse.jsx index 3a6d73f..491600a 100644 --- a/src/renderer/src/components/Noteclasse.jsx +++ b/src/renderer/src/components/Noteclasse.jsx @@ -8,7 +8,7 @@ import { frFR } from '@mui/x-data-grid/locales' import { createTheme, ThemeProvider } from '@mui/material/styles' import { IoNewspaperOutline } from 'react-icons/io5' import { IoMdReturnRight } from 'react-icons/io' -import { Button, Modal, Box } from '@mui/material' +import { Button, Modal, Box, Menu, MenuItem } from '@mui/material' import { Tooltip } from 'react-tooltip' import ReleverNotes from './ReleverNotes' import { FaDownload } from 'react-icons/fa' @@ -50,12 +50,23 @@ const Noteclasse = () => { } function checkNull(params) { + console.log(params); if (params == null || params == undefined) { return null } return params } + // MODIFICATION: Nouvelle fonction pour calculer la moyenne avec rattrapage + function compareSessionNotesForAverage(session1, session2) { + // Si il y a une session de rattrapage, utiliser la meilleure note + if (session2) { + return Math.max(session1, session2.note) + } + // Sinon utiliser la note normale + return session1 + } + function compareSessionNotes(session1, session2) { let notes if (session2) { @@ -94,10 +105,10 @@ const Noteclasse = () => { modelJson.mention = etudiants[index][j].mention_id modelJson.anneescolaire = etudiants[index][j].annee_scolaire - // console.log(checkNull(session[index][j])); + // MODIFICATION: Utiliser la meilleure note (rattrapage si existe) pour la moyenne générale if (session[index]) { note += - compareSessionNotes(etudiants[index][j].note, checkNull(session[index][j])) * + compareSessionNotesForAverage(etudiants[index][j].note, checkNull(session[index][j])) * etudiants[index][j].credit } else { note += etudiants[index][j].note * etudiants[index][j].credit @@ -113,15 +124,15 @@ const Noteclasse = () => { } function checkNumberSession(id) { - let sessionNumber + let sessionNumber = 1 for (let index = 0; index < session.length; index++) { for (let j = 0; j < session[index].length; j++) { if (session[index][j].etudiant_id == id) { sessionNumber = 2 - } else { - sessionNumber = 1 + break } } + if (sessionNumber === 2) break } return sessionNumber } @@ -147,9 +158,29 @@ const Noteclasse = () => { const paginationModel = { page: 0, pageSize: 5 } + // États pour le menu déroulant + const [anchorEl, setAnchorEl] = useState(null) + const [selectedStudentId, setSelectedStudentId] = useState(null) + const open = Boolean(anchorEl) + + const handleMenuClick = (event, studentId) => { + setAnchorEl(event.currentTarget) + setSelectedStudentId(studentId) + } + + const handleMenuClose = () => { + setAnchorEl(null) + setSelectedStudentId(null) + } + + const handleSessionTypeSelect = (sessionType) => { + sendData(selectedStudentId, sessionType) + handleMenuClose() + } + const columns = [ { field: 'nom', headerName: 'Nom', width: 170 }, - { field: 'prenom', headerName: 'Prenom', width: 160 }, + { field: 'prenom', headerName: 'Prénom', width: 160 }, { field: 'session', headerName: 'Nombre de Session', width: 180 }, { field: 'mention', headerName: 'Mention', width: 180 }, { field: 'moyenne', headerName: 'Moyenne Général', width: 160 }, @@ -171,19 +202,21 @@ const Noteclasse = () => { flex: 1, renderCell: (params) => (
- sendData(params.value)}> - {/* */} - - - Imprimer un relevé de notes - - + + + Imprimer un relevé de notes +
) } @@ -205,15 +238,18 @@ const Noteclasse = () => { const [form, setForm] = useState({ id: '', niveau: '', - anneescolaire: '' + anneescolaire: '', + sessionType: 'ensemble' // Par défaut }) const [selectedId, setSelectedId] = useState(null) // Store id dynamically - const sendData = (id) => { + const sendData = (id, sessionType = 'ensemble') => { setSelectedId(id) - // if (selectedId !== null) { - setOpenCart(true) - // } + setForm(prevForm => ({ + ...prevForm, + sessionType: sessionType + })) + setOpenCart(true) } useEffect(() => { @@ -229,7 +265,9 @@ const Noteclasse = () => { } } }, [openCard, selectedId]) + console.log(form) + const downloadButton = () => { setBolll(true) } @@ -265,6 +303,7 @@ const Noteclasse = () => { id={form.id} anneescolaire={scolaire} niveau={form.niveau} + sessionType={form.sessionType} refs={bolll} /> @@ -123,10 +108,10 @@ const Setting = () => { ) - const [openConfig, setOpenCOnfig] = useState(false) - const onCloseConfig = () => setOpenCOnfig(false) - - const openCOnfigFunction = () => setOpenCOnfig(true) + // IP Config + const [openConfig, setOpenConfig] = useState(false) + const onCloseConfig = () => setOpenConfig(false) + const openConfigFunction = () => setOpenConfig(true) return (
@@ -135,8 +120,8 @@ const Setting = () => {
-

setting

- +

Settings

+ @@ -144,7 +129,7 @@ const Setting = () => {
- {/* contenu */} +
{ > - - - - - - {/* */} + avatar + { onChange={handleInputChange} required InputProps={{ - startAdornment: ( - - - - ) - }} - sx={{ - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800' // Set the border color on hover - } - } + startAdornment: }} /> @@ -214,23 +181,11 @@ const Setting = () => { value={formData.email} onChange={handleInputChange} InputProps={{ - startAdornment: ( - - - - ) - }} - sx={{ - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800' // Set the border color on hover - } - } + startAdornment: }} /> - {/* matieres Mecanique general */} - + { value={formData.password} onChange={handleInputChange} InputProps={{ - startAdornment: ( - - - - ) - }} - sx={{ - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800' // Set the border color on hover - } - } + startAdornment: }} /> - {/* Matieres Resistance Materiaux */} - {/* Submit Button */} - + diff --git a/src/renderer/src/components/ReleverNotes.jsx b/src/renderer/src/components/ReleverNotes.jsx index a09d4b1..4cde1f4 100644 --- a/src/renderer/src/components/ReleverNotes.jsx +++ b/src/renderer/src/components/ReleverNotes.jsx @@ -10,11 +10,16 @@ import dayjs from 'dayjs' import getSemestre from './function/GetSemestre' import { descisionJury, getmentionAfterNotes } from './function/FonctionRelever' -const ReleverNotes = ({ id, anneescolaire, niveau, refs }) => { +const ReleverNotes = ({ id, anneescolaire, niveau, sessionType = 'ensemble', refs }) => { const [etudiant, setEtudiant] = useState([]) const [matieres, setMatieres] = useState([]) const [notes, setNotes] = useState([]) + // Fonction pour vérifier si les crédits doivent être affichés + const shouldShowCredits = () => { + return niveau !== 'L1' && niveau !== 'L2' + } + const handleDownloadPDF = async () => { const input = Telever.current @@ -166,9 +171,19 @@ const ReleverNotes = ({ id, anneescolaire, niveau, refs }) => { return acc }, {}) - const compareMoyenne = (normal, rattrapage) => { - const note = Math.max(Number(normal), Number(rattrapage)) - return note >= 10 ? 'Admis' : 'Ajourné' + // MODIFICATION: Fonction compareMoyenne mise à jour + const compareMoyenne = (normal, rattrapage, sessionType) => { + if (sessionType === 'normale') { + // Pour session normale: toujours évaluer selon la note normale uniquement + return Number(normal) >= 10 ? 'Admis' : 'Ajourné' + } else if (sessionType === 'rattrapage') { + // Pour session rattrapage: évaluer selon la note de rattrapage + return Number(rattrapage) >= 10 ? 'Admis' : 'Ajourné' + } else { + // Pour session ensemble: prendre la meilleure des deux notes + const bestNote = Math.max(Number(normal), Number(rattrapage)) + return bestNote >= 10 ? 'Admis' : 'Ajourné' + } } const TbodyContent = () => { @@ -219,7 +234,6 @@ const ReleverNotes = ({ id, anneescolaire, niveau, refs }) => { fontWeight: 'bold', textAlign: 'center', borderRight: 'solid 1px black', - // borderBottom: 'solid 1px black', borderTop: 'solid 1px black' }} > @@ -231,18 +245,29 @@ const ReleverNotes = ({ id, anneescolaire, niveau, refs }) => { {matiere.nom} - - {matiere.credit} - - - {matiere.note} - - - {matiere.credit} - - - {matiere.noterepech} - + + {/* Affichage conditionnel des colonnes selon le type de session */} + {sessionType !== 'rattrapage' && ( + <> + + {matiere.credit} + + + {matiere.note} + + + )} + + {sessionType !== 'normale' && ( + <> + + {matiere.credit} + + + {matiere.noterepech} + + + )} {/* Display the comparison value only once */} {matiereIndex === 0 && ( @@ -255,7 +280,6 @@ const ReleverNotes = ({ id, anneescolaire, niveau, refs }) => { borderTop: 'solid 1px black' }} > - {/* Replace 'hgh' with your logic for displaying the comparison */} {compareMoyenne( ( matieres.reduce((total, matiere) => total + matiere.note, 0) / @@ -264,7 +288,8 @@ const ReleverNotes = ({ id, anneescolaire, niveau, refs }) => { ( matieres.reduce((total, matiere) => total + matiere.noterepech, 0) / matieres.length - ).toFixed(2) + ).toFixed(2), + sessionType // MODIFICATION: Passer le sessionType )} )} @@ -288,57 +313,65 @@ const ReleverNotes = ({ id, anneescolaire, niveau, refs }) => { > Total de Credit et Moyenne des Notes - - {/* Calculate Total de Credit */} - {matieres.reduce((total, matiere) => total + matiere.credit, 0)} - - - {/* Calculate Moyenne des Notes */} - {( - matieres.reduce((total, matiere) => total + matiere.note, 0) / - matieres.length - ).toFixed(2)}{' '} - {/* Format to 2 decimal places */} - - - {matieres.reduce((total, matiere) => total + matiere.credit, 0)} - - - {( - matieres.reduce((total, matiere) => total + matiere.noterepech, 0) / - matieres.length - ).toFixed(2)} - + + {sessionType !== 'rattrapage' && ( + <> + + {matieres.reduce((total, matiere) => total + matiere.credit, 0)} + + + {( + matieres.reduce((total, matiere) => total + matiere.note, 0) / + matieres.length + ).toFixed(2)} + + + )} + + {sessionType !== 'normale' && ( + <> + + {matieres.reduce((total, matiere) => total + matiere.credit, 0)} + + + {( + matieres.reduce((total, matiere) => total + matiere.noterepech, 0) / + matieres.length + ).toFixed(2)} + + + )} + { ) } + // MODIFICATION: Fonction totalNotes mise à jour pour tenir compte du sessionType const totalNotes = () => { let totalNotes = document.querySelectorAll('.moyenneNotes') let totalNotesRepech = document.querySelectorAll('.moyenneNotesRattrapage') @@ -365,25 +399,29 @@ const ReleverNotes = ({ id, anneescolaire, niveau, refs }) => { let TotalNoteNumberRepech = 0 totalNotes.forEach((notes) => { - TotalNoteNumber += Number(notes.textContent / totalNotes.length) - // console.log(notes.textContent); + TotalNoteNumber += Number(notes.textContent) / totalNotes.length }) totalNotesRepech.forEach((notes) => { - TotalNoteNumberRepech += Number(notes.textContent / totalNotes.length) - // console.log(notes.textContent); + TotalNoteNumberRepech += Number(notes.textContent) / totalNotesRepech.length }) - let note = Math.max(TotalNoteNumber, TotalNoteNumberRepech) - - return note + // Retourner la note selon le type de session + if (sessionType === 'normale') { + return TotalNoteNumber + } else if (sessionType === 'rattrapage') { + return TotalNoteNumberRepech + } else { + // Pour 'ensemble', prendre la meilleure note + return Math.max(TotalNoteNumber, TotalNoteNumberRepech) + } } const [note, setNote] = useState(0) useEffect(() => { setNote(totalNotes()) - }, [TbodyContent]) + }, [TbodyContent, sessionType]) return (
@@ -391,9 +429,8 @@ const ReleverNotes = ({ id, anneescolaire, niveau, refs }) => {
{
- Prenom + Prénom
@@ -480,7 +517,7 @@ const ReleverNotes = ({ id, anneescolaire, niveau, refs }) => { { - - Normale - - - Rattrapage - + + {sessionType !== 'rattrapage' && ( + + Normale + + )} + + {sessionType !== 'normale' && ( + + Rattrapage + + )} + @@ -514,7 +558,6 @@ const ReleverNotes = ({ id, anneescolaire, niveau, refs }) => { { UE EC - crédit - Notes - crédit - Notes + + {sessionType !== 'rattrapage' && ( + <> + crédit + Notes + + )} + + {sessionType !== 'normale' && ( + <> + crédit + Notes + + )} + Observation @@ -548,7 +602,7 @@ const ReleverNotes = ({ id, anneescolaire, niveau, refs }) => { {note.toFixed(2)} /20 - + { Mention:{' '} {getmentionAfterNotes(note)} - + Décision du Jury:{' '} - - {descisionJury(note, etudiant.niveau)} - @@ -591,4 +642,4 @@ const ReleverNotes = ({ id, anneescolaire, niveau, refs }) => { ) } -export default ReleverNotes +export default ReleverNotes \ No newline at end of file diff --git a/src/renderer/src/components/Resultat.jsx b/src/renderer/src/components/Resultat.jsx index b770939..9d1d30c 100644 --- a/src/renderer/src/components/Resultat.jsx +++ b/src/renderer/src/components/Resultat.jsx @@ -3,7 +3,7 @@ import { useParams, Link } from 'react-router-dom' import classe from '../assets/AllStyleComponents.module.css' import classeHome from '../assets/Home.module.css' import Paper from '@mui/material/Paper' -import { Button, Modal, Box } from '@mui/material' +import { Button, Modal, Box, Tabs, Tab, Select, MenuItem, FormControl, InputLabel } from '@mui/material' import { IoMdReturnRight } from 'react-icons/io' import jsPDF from 'jspdf' import autoTable from 'jspdf-autotable' @@ -20,10 +20,18 @@ const Resultat = () => { const [etudiants, setEtudiants] = useState([]) const [mention, setMention] = useState([]) const [session, setSession] = useState([]) + const [tabValue, setTabValue] = useState(0) + + // États pour les sélections + const [selectedMatiere, setSelectedMatiere] = useState('') + const [selectedUE, setSelectedUE] = useState('') + const [availableMatieres, setAvailableMatieres] = useState([]) + const [availableUEs, setAvailableUEs] = useState([]) useEffect(() => { window.notes.getMoyenne(formData).then((response) => { setEtudiants(response) + extractMatieresAndUEs(response) }) window.noteRepech.getMoyenneRepech(formData).then((response) => { setSession(response) @@ -33,6 +41,28 @@ const Resultat = () => { }) }, []) + // Fonction pour extraire les matières et UEs disponibles + const extractMatieresAndUEs = (data) => { + const matieres = new Set() + const ues = new Set() + + for (let index = 0; index < data.length; index++) { + for (let j = 0; j < data[index].length; j++) { + const matiere = data[index][j].matiere || `Matière ${j + 1}` + const ue = data[index][j].ue || `UE${Math.floor(j / 2) + 1}` + matieres.add(matiere) + ues.add(ue) + } + } + + setAvailableMatieres(Array.from(matieres)) + setAvailableUEs(Array.from(ues)) + + // Sélectionner la première matière et UE par défaut + if (matieres.size > 0) setSelectedMatiere(Array.from(matieres)[0]) + if (ues.size > 0) setSelectedUE(Array.from(ues)[0]) + } + let dataToMap = [] function returnmention(id) { @@ -45,6 +75,18 @@ const Resultat = () => { return mentions } + // Fonction pour déterminer la mention selon la moyenne + function getMentionFromMoyenne(moyenne) { + const moy = parseFloat(moyenne) + if (moy >= 18) return 'Excellent' + if (moy >= 16) return 'Très Bien' + if (moy >= 14) return 'Bien' + if (moy >= 12) return 'Assez Bien' + if (moy >= 10) return 'Passable' + if (moy >= 7) return 'Autorisé à redoubler' + return 'Remise à la famille' + } + function checkNull(params) { if (params == null || params == undefined) { return null @@ -52,51 +94,6 @@ const Resultat = () => { return params } - const print = () => { - const generatePDF = () => { - try { - const pdf = new jsPDF({ - orientation: 'portrait', - unit: 'mm', - format: 'a4' - }) - - pdf.addImage(logoRelerev1, 'PNG', 10, 5, 40, 20) - pdf.addImage(logoRelerev2, 'PNG', 175, 5, 30, 30) - - // Ajouter le texte entre les logos - pdf.setFontSize(10) - pdf.text('REPOBLIKAN\'I MADAGASIKARA', 105, 10, { align: 'center' }) - pdf.text('Fitiavana-Tanindrazana-Fandrosoana', 105, 14, { align: 'center' }) - pdf.text('********************', 105, 18, { align: 'center' }) - pdf.text('MINISTÈRE DE L\'ENSEIGNEMENT SUPÉRIEUR', 105, 22, { align: 'center' }) - pdf.text('ET DE LA RECHERCHE SCIENTIFIQUE', 105, 26, { align: 'center' }) - pdf.text('********************', 105, 30, { align: 'center' }) - pdf.text('UNIVERSITÉ DE TOAMASINA', 105, 34, { align: 'center' }) - pdf.text('ÉCOLE SUPÉRIEURE POLYTECHNIQUE', 105, 38, { align: 'center' }) - - // Select the table - autoTable(pdf, { - html: '#myTable2', - startY: 50, // décalé vers le bas pour laisser la place aux logos et texte - theme: 'grid', - headStyles: { - fillColor: 'gray', - halign: 'center', - fontStyle: 'bold', - textColor: 'black' - }, - styles: { fontSize: 8, cellPadding: 2, halign: 'center' } - }) - - pdf.save(`Resultat-${niveau}-${scolaire}.pdf`) - } catch (error) { - console.error('Error generating PDF:', error) - } - } - generatePDF() - } - function compareSessionNotes(session1, session2) { let notes if (session2) { @@ -111,12 +108,13 @@ const Resultat = () => { return notes } + // Traitement des données pour résultat définitif - INCLUANT TOUS LES ÉTUDIANTS for (let index = 0; index < etudiants.length; index++) { let total = 0 let note = 0 let totalCredit = 0 + let hasValidNotes = false - // Create a new object for each student let modelJson = { id: '', nom: '', @@ -135,29 +133,389 @@ const Resultat = () => { modelJson.mention = etudiants[index][j].mention_id modelJson.anneescolaire = etudiants[index][j].annee_scolaire - // console.log(checkNull(session[index][j])); + let currentNote = etudiants[index][j].note if (session[index]) { - note += - compareSessionNotes(etudiants[index][j].note, checkNull(session[index][j])) * - etudiants[index][j].credit - } else { - note += etudiants[index][j].note * etudiants[index][j].credit + currentNote = compareSessionNotes(etudiants[index][j].note, checkNull(session[index][j])) } - totalCredit += etudiants[index][j].credit - } - total = note / totalCredit - modelJson.moyenne = total.toFixed(2) + // Vérifier si l'étudiant a des notes valides + if (currentNote != null && currentNote != undefined && !isNaN(currentNote)) { + note += currentNote * etudiants[index][j].credit + totalCredit += etudiants[index][j].credit + hasValidNotes = true + } + } - // Add the new object to the array + // Calculer la moyenne même si certaines notes manquent + if (hasValidNotes && totalCredit > 0) { + total = note / totalCredit + modelJson.moyenne = total.toFixed(2) + } else { + modelJson.moyenne = 'N/A' + } + dataToMap.push(modelJson) } - const sortedStudents = dataToMap - .filter((student) => parseFloat(student.moyenne) >= 10) - .sort((a, b) => parseFloat(b.moyenne) - parseFloat(a.moyenne)) + // Fonction pour obtenir les résultats par matière sélectionnée + const getResultsByMatiere = () => { + const results = [] + + for (let index = 0; index < etudiants.length; index++) { + for (let j = 0; j < etudiants[index].length; j++) { + const matiere = etudiants[index][j].matiere || `Matière ${j + 1}` + + if (matiere === selectedMatiere) { + let finalNote = etudiants[index][j].note + if (session[index] && session[index][j]) { + finalNote = compareSessionNotes(etudiants[index][j].note, session[index][j]) + } - console.log(sortedStudents) + results.push({ + id: etudiants[index][j].etudiant_id, + nom: etudiants[index][j].nom, + prenom: etudiants[index][j].prenom, + note: finalNote != null ? finalNote.toFixed(2) : 'N/A', + credit: etudiants[index][j].credit, + mention: returnmention(etudiants[index][j].mention_id) + }) + } + } + } + + return results.sort((a, b) => { + const noteA = a.note === 'N/A' ? -1 : parseFloat(a.note) + const noteB = b.note === 'N/A' ? -1 : parseFloat(b.note) + return noteB - noteA + }) + } + + // Fonction pour obtenir les résultats par UE sélectionnée + const getResultsByUE = () => { + const groupedStudents = {} + const matieresInUE = new Set() + + // Grouper les étudiants et collecter les matières de l'UE + for (let index = 0; index < etudiants.length; index++) { + for (let j = 0; j < etudiants[index].length; j++) { + const ue = etudiants[index][j].ue || `UE${Math.floor(j / 2) + 1}` + const matiere = etudiants[index][j].matiere || `Matière ${j + 1}` + + if (ue === selectedUE) { + matieresInUE.add(matiere) + const etudiantId = etudiants[index][j].etudiant_id + + if (!groupedStudents[etudiantId]) { + groupedStudents[etudiantId] = { + id: etudiantId, + nom: etudiants[index][j].nom, + prenom: etudiants[index][j].prenom, + matieres: {}, + totalNote: 0, + totalCredit: 0, + hasValidNotes: false + } + } + + let finalNote = etudiants[index][j].note + if (session[index] && session[index][j]) { + finalNote = compareSessionNotes(etudiants[index][j].note, session[index][j]) + } + + if (finalNote != null && finalNote != undefined && !isNaN(finalNote)) { + groupedStudents[etudiantId].matieres[matiere] = finalNote.toFixed(2) + groupedStudents[etudiantId].totalNote += finalNote * etudiants[index][j].credit + groupedStudents[etudiantId].totalCredit += etudiants[index][j].credit + groupedStudents[etudiantId].hasValidNotes = true + } else { + groupedStudents[etudiantId].matieres[matiere] = 'N/A' + } + } + } + } + + const results = Object.values(groupedStudents).map(student => ({ + ...student, + moyenneUE: student.hasValidNotes && student.totalCredit > 0 + ? (student.totalNote / student.totalCredit).toFixed(2) + : 'N/A' + })) + + return { + students: results.sort((a, b) => { + const moyA = a.moyenneUE === 'N/A' ? -1 : parseFloat(a.moyenneUE) + const moyB = b.moyenneUE === 'N/A' ? -1 : parseFloat(b.moyenneUE) + return moyB - moyA + }), + matieres: Array.from(matieresInUE) + } + } + + const sortedStudents = dataToMap.sort((a, b) => { + const moyA = a.moyenne === 'N/A' ? -1 : parseFloat(a.moyenne) + const moyB = b.moyenne === 'N/A' ? -1 : parseFloat(b.moyenne) + return moyB - moyA + }) + + const handleTabChange = (event, newValue) => { + setTabValue(newValue) + } + + const print = () => { + const generatePDF = () => { + try { + const pdf = new jsPDF({ + orientation: 'portrait', + unit: 'mm', + format: 'a4' + }) + + pdf.addImage(logoRelerev1, 'PNG', 175, 5, 32, 30) + pdf.addImage(logoRelerev2, 'PNG', 10, 5, 40, 30) + + pdf.setFontSize(10) + pdf.text('REPOBLIKAN\'I MADAGASIKARA', 105, 10, { align: 'center' }) + pdf.text('Fitiavana-Tanindrazana-Fandrosoana', 105, 14, { align: 'center' }) + pdf.text('********************', 105, 18, { align: 'center' }) + pdf.text('MINISTÈRE DE L\'ENSEIGNEMENT SUPÉRIEUR', 105, 22, { align: 'center' }) + pdf.text('ET DE LA RECHERCHE SCIENTIFIQUE', 105, 26, { align: 'center' }) + pdf.text('********************', 105, 30, { align: 'center' }) + pdf.text('UNIVERSITÉ DE TOAMASINA', 105, 34, { align: 'center' }) + pdf.text('ÉCOLE SUPÉRIEURE POLYTECHNIQUE', 105, 38, { align: 'center' }) + + const tableId = tabValue === 0 ? '#resultTable' : tabValue === 1 ? '#subjectTable' : '#ueTable' + + autoTable(pdf, { + html: tableId, + startY: 50, + theme: 'grid', + headStyles: { + fillColor: [255, 255, 255], // Fond blanc + halign: 'center', + fontStyle: 'bold', + textColor: [0, 0, 0], // Texte noir + lineColor: [0, 0, 0], // Bordure noire + lineWidth: 0.5 + }, + styles: { + fontSize: 8, + cellPadding: 2, + halign: 'center', + lineColor: [0, 0, 0], // Bordure noire pour toutes les cellules + lineWidth: 0.5 + }, + bodyStyles: { + lineColor: [0, 0, 0], // Bordure noire pour le corps du tableau + lineWidth: 0.5 + } + }) + + const suffix = tabValue === 0 ? 'definitif' : + tabValue === 1 ? `par-matiere-${selectedMatiere}` : + `par-ue-${selectedUE}` + pdf.save(`Resultat-${suffix}-${niveau}-${scolaire}.pdf`) + } catch (error) { + console.error('Error generating PDF:', error) + } + } + generatePDF() + } + + const renderHeader = () => ( +
+ Logo gauche + +
+
REPOBLIKAN'I MADAGASIKARA
+
Fitiavana-Tanindrazana-Fandrosoana
+
********************
+
MINISTÈRE DE L'ENSEIGNEMENT SUPÉRIEUR
+
ET DE LA RECHERCHE SCIENTIFIQUE
+
********************
+
UNIVERSITÉ DE TOAMASINA
+
ÉCOLE SUPÉRIEURE POLYTECHNIQUE
+
+ + Logo droite +
+ ) + + const renderResultDefinitif = () => ( + + + + + + + + + + + + + + + {sortedStudents.map((sorted, index) => ( + + + + + + + + ))} + +
+
+ Résultat Définitif : {niveau} admis en {niveau === 'L1' ? 'L2' : niveau === 'L2' ? 'L3' : 'Master'} par ordre de mérite +
+
RANGNOMSPRÉNOMSMoyenneMention
{index + 1}.{sorted.nom}{sorted.prenom}{sorted.moyenne} + {sorted.moyenne !== 'N/A' ? getMentionFromMoyenne(sorted.moyenne) : 'N/A'} +
+ ) + + const renderResultParMatiere = () => { + const results = getResultsByMatiere() + + return ( + <> +
+ + Sélectionner une matière + + +
+ + + + + + + + + + + + + + + {results.map((item, index) => ( + + + + + + + ))} + +
+
+ Résultat pour la matière : {selectedMatiere} +
+
RANGNOMSPRÉNOMSNOTE
{index + 1}.{item.nom}{item.prenom}{item.note}
+ + ) + } + + const renderResultParUE = () => { + const { students, matieres } = getResultsByUE() + + return ( + <> +
+ + Sélectionner une UE + + +
+ + + + + + + + + + + {matieres.map((matiere) => ( + + ))} + + + + + {students.map((student, index) => ( + + + + + {matieres.map((matiere) => ( + + ))} + + + ))} + +
+
+ Résultat pour l'UE : {selectedUE} +
+
RANGNOMSPRÉNOMS{matiere}MOYENNE UE
{index + 1}.{student.nom}{student.prenom} + {student.matieres[matiere] || 'N/A'} + {student.moyenneUE}
+ + ) + } return (
@@ -194,80 +552,28 @@ const Resultat = () => { padding: '2%' }} > - {/* En-tête avec logos et texte */} -
- Logo gauche - - {/* Texte centré entre les logos */} -
-
REPOBLIKAN'I MADAGASIKARA
-
Fitiavana-Tanindrazana-Fandrosoana
-
********************
-
MINISTÈRE DE L'ENSEIGNEMENT SUPÉRIEUR
-
ET DE LA RECHERCHE SCIENTIFIQUE
-
********************
-
UNIVERSITÉ DE TOAMASINA
-
ÉCOLE SUPÉRIEURE POLYTECHNIQUE
-
- - Logo droite -
+ {renderHeader()} - {/* Informations du parcours */}
Parcours : GC
Niveau : {niveau}
Année Universitaire : {scolaire}
- - - - - - - - - - - - - - {sortedStudents.map((sorted, index) => ( - - - - - - - ))} - -
-
- Résultat de la Deuxième Session : {niveau} admis en L3 par ordre de mérite -
-
RANGNOMSPRÉNOMSMoyenne
{index + 1}.{sorted.nom}{sorted.prenom}{sorted.moyenne}
+ + + + + + {tabValue === 0 && renderResultDefinitif()} + {tabValue === 1 && renderResultParMatiere()} + {tabValue === 2 && renderResultParUE()}
diff --git a/src/renderer/src/components/Sidenav.jsx b/src/renderer/src/components/Sidenav.jsx index 7e1c441..f8feaa0 100644 --- a/src/renderer/src/components/Sidenav.jsx +++ b/src/renderer/src/components/Sidenav.jsx @@ -1,4 +1,4 @@ -import React, { useState } from 'react' +import React, { useState, useEffect } from 'react' import classe from '../assets/Sidenav.module.css' import { RiDashboardHorizontalFill } from 'react-icons/ri' import { PiStudentFill } from 'react-icons/pi' @@ -21,8 +21,27 @@ import { FaClipboardList } from 'react-icons/fa6' const Sidenav = () => { const [anchorEl, setAnchorEl] = useState(null) + const [userRole, setUserRole] = useState(null) const open = Boolean(anchorEl) const { setToken } = useAuthContext() + const { user } = useAuthContext() + + // // Récupération du rôle utilisateur au montage du composant + // useEffect(() => { + // const fetchUserRole = async () => { + // try { + // // Supposant que vous avez une méthode getUser dans votre contexte ou API + // const user = await window.allUser?.users(); // ou votre méthode d'API + // console.log('Résultat de getAllUsers:', user) + // setUserRole(user?.roles?.toLowerCase()) // Normaliser en minuscule + // } catch (error) { + // console.error('Erreur lors de la récupération du rôle utilisateur:', error) + // setUserRole(null) + // } + // } + + // fetchUserRole() + // }, []) const handleClick = (event) => { setAnchorEl(event.currentTarget) @@ -40,6 +59,11 @@ const Sidenav = () => { setToken(null) } + // Fonction pour vérifier si l'utilisateur est admin +const isAdmin = () => { + console.log('Rôle de l’utilisateur:', user?.roles) + return user?.roles?.toLowerCase() === 'admin' +} return (