Browse Source

derniere version

master
andrymodeste 4 months ago
parent
commit
08e11d0bf6
  1. 10
      database/Models/AnneeScolaire.js
  2. 2
      database/Models/Etudiants.backup.js
  3. 24
      database/Models/Etudiants.js
  4. 8
      database/Models/Matieres.js
  5. 8
      database/Models/Mentions.js
  6. 4
      database/Models/NoteSysrem.js
  7. 8
      database/Models/Parcours.js
  8. 4
      database/database.backup.js
  9. 4
      database/database.js
  10. 4
      database/database2.js
  11. 4
      database/function/System.js
  12. 8
      src/renderer/src/components/AddAnneeScolaire.jsx
  13. 8
      src/renderer/src/components/AddStudent.jsx
  14. 4
      src/renderer/src/components/AnneeScolaire.jsx
  15. 8
      src/renderer/src/components/ExportEtudiants.jsx
  16. 4
      src/renderer/src/components/Home.jsx
  17. 147
      src/renderer/src/components/Login.jsx
  18. 6
      src/renderer/src/components/ModalAddEtudiants.jsx
  19. 4
      src/renderer/src/components/ModalAddProf.jsx
  20. 6
      src/renderer/src/components/ModalCertificate.jsx
  21. 2
      src/renderer/src/components/ModalExportFichr.jsx
  22. 2
      src/renderer/src/components/ModalRecepice.jsx
  23. 2
      src/renderer/src/components/ModalStage.jsx
  24. 107
      src/renderer/src/components/Noteclasse.jsx
  25. 2
      src/renderer/src/components/Notes.jsx
  26. 208
      src/renderer/src/components/Param.jsx
  27. 261
      src/renderer/src/components/ReleverNotes.jsx
  28. 560
      src/renderer/src/components/Resultat.jsx
  29. 82
      src/renderer/src/components/Sidenav.jsx
  30. 6
      src/renderer/src/components/SingleAnneeScolaire.jsx
  31. 8
      src/renderer/src/components/SingleEtudiant.jsx
  32. 21
      src/renderer/src/components/Student.jsx
  33. 8
      src/renderer/src/components/SystemeNote.jsx
  34. 4
      src/renderer/src/components/TesteDatagrid.jsx
  35. 4
      src/renderer/src/components/UpdateModalProf.jsx
  36. 6
      src/renderer/src/components/function/PDFEditor.js
  37. 69
      src/renderer/src/components/function/PDFEditorV2.js
  38. 2
      src/renderer/src/components/validation/ValidationAddAnneeScolaire.js
  39. 78
      src/renderer/src/contexts/AuthContext.jsx
  40. 2
      src/renderer/src/test/qr.html
  41. 2
      src/renderer/src/test/relever.html
  42. 2
      text.txt

10
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 * @returns promise
*/ */
async function getAnneeScolaire() { async function getAnneeScolaire() {
@ -71,13 +71,13 @@ async function deleteAnneeScolaire(id) {
if (result.affectedRows === 0) { if (result.affectedRows === 0) {
return { return {
success: false, success: false,
message: 'Année Scolaire non trouvé.' message: 'Année universitaire non trouvé.'
} }
} }
return { return {
success: true, success: true,
message: 'Année Scolaire supprimé avec succès.' message: 'Année universitaire supprimé avec succès.'
} }
} catch (error) { } catch (error) {
return { success: false, error: 'Erreur veullez réeseyer' } return { success: false, error: 'Erreur veullez réeseyer' }
@ -93,13 +93,13 @@ async function updateAnneeScolaire(id, code, debut, fin) {
if (result.affectedRows === 0) { if (result.affectedRows === 0) {
return { return {
success: false, 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 { return {
success: true, success: true,
message: 'Année Scolaire mis à jour avec succès.' message: 'Année universitaire mis à jour avec succès.'
} }
} catch (error) { } catch (error) {
return { success: false, error: 'Erreur veullez réeseyer' } return { success: false, error: 'Erreur veullez réeseyer' }

2
database/Models/Etudiants.backup.js

@ -191,7 +191,7 @@ async function updateEtudiant(
async function getDataToDashboard() { async function getDataToDashboard() {
const query = database.prepare('SELECT * FROM niveaus') const query = database.prepare('SELECT * FROM niveaus')
const query2 = database.prepare('SELECT * FROM etudiants') 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 { try {
let niveau = query.all() let niveau = query.all()

24
database/Models/Etudiants.js

@ -83,7 +83,7 @@ async function getAllEtudiants() {
* @returns Promise * @returns Promise
*/ */
async function getSingleEtudiant(id) { 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 { try {
const [rows] = await pool.query(sql, [id]) const [rows] = await pool.query(sql, [id])
@ -176,13 +176,13 @@ async function updateEtudiant(
if (result.affectedRows === 0) { if (result.affectedRows === 0) {
return { return {
success: false, success: false,
message: 'Année Scolaire non trouvé.' message: 'Année Univesitaire non trouvé.'
} }
} }
return { return {
success: true, success: true,
message: 'Année Scolaire supprimé avec succès.' message: 'Année Univesitaire supprimé avec succès.'
} }
} catch (error) { } catch (error) {
return error return error
@ -197,7 +197,7 @@ async function updateEtudiant(
async function getDataToDashboard() { async function getDataToDashboard() {
const query = 'SELECT * FROM niveaus' const query = 'SELECT * FROM niveaus'
const query2 = 'SELECT * FROM etudiants' 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 { try {
let [rows] = await pool.query(query) let [rows] = await pool.query(query)
@ -222,13 +222,13 @@ async function changePDP(photos, id) {
if (result.affectedRows === 0) { if (result.affectedRows === 0) {
return { return {
success: false, success: false,
message: 'Année Scolaire non trouvé.' message: 'Année Univesitaire non trouvé.'
} }
} }
return { return {
success: true, success: true,
message: 'Année Scolaire supprimé avec succès.' message: 'Année Univesitaire supprimé avec succès.'
} }
} catch (error) { } catch (error) {
return error return error
@ -244,13 +244,13 @@ async function updateParcours(parcours, id) {
if (result.affectedRows === 0) { if (result.affectedRows === 0) {
return { return {
success: false, success: false,
message: 'Année Scolaire non trouvé.' message: 'Année Univesitaire non trouvé.'
} }
} }
return { return {
success: true, success: true,
message: 'Année Scolaire supprimé avec succès.' message: 'Année Univesitaire supprimé avec succès.'
} }
} catch (error) { } catch (error) {
return error return error
@ -294,13 +294,13 @@ async function updateTranche(id, tranchename, montant) {
if (result.affectedRows === 0) { if (result.affectedRows === 0) {
return { return {
success: false, success: false,
message: 'Année Scolaire non trouvé.' message: 'Année Univesitaire non trouvé.'
} }
} }
return { return {
success: true, success: true,
message: 'Année Scolaire supprimé avec succès.' message: 'Année Univesitaire supprimé avec succès.'
} }
} catch (error) { } catch (error) {
console.log('resultat error:',error); console.log('resultat error:',error);
@ -317,13 +317,13 @@ async function deleteTranche(id) {
if (result.affectedRows === 0) { if (result.affectedRows === 0) {
return { return {
success: false, success: false,
message: 'Année Scolaire non trouvé.' message: 'Année Univesitaire non trouvé.'
} }
} }
return { return {
success: true, success: true,
message: 'Année Scolaire supprimé avec succès.' message: 'Année Univesitaire supprimé avec succès.'
} }
} catch (error) { } catch (error) {
return error return error

8
database/Models/Matieres.js

@ -125,13 +125,13 @@ async function updateMatiere(nom, id, credit, uniter, ue) {
if (result.affectedRows === 0) { if (result.affectedRows === 0) {
return { return {
success: false, 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 { return {
success: true, success: true,
message: 'Année Scolaire mis à jour avec succès.' message: 'Année Univesitaire mis à jour avec succès.'
} }
} catch (error) { } catch (error) {
return { success: false, error: 'Erreur veullez réeseyer' + 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) { if (result.affectedRows === 0) {
return { return {
success: false, success: false,
message: 'Année Scolaire non trouvé.' message: 'Année Univesitaire non trouvé.'
} }
} }
return { return {
success: true, success: true,
message: 'Année Scolaire supprimé avec succès.' message: 'Année Univesitaire supprimé avec succès.'
} }
} catch (error) { } catch (error) {
console.error(error) console.error(error)

8
database/Models/Mentions.js

@ -24,13 +24,13 @@ async function deleteMention(id) {
if (result.affectedRows === 0) { if (result.affectedRows === 0) {
return { return {
success: false, success: false,
message: 'Année Scolaire non trouvé.' message: 'Année Univesitaire non trouvé.'
} }
} }
return { return {
success: true, success: true,
message: 'Année Scolaire supprimé avec succès.' message: 'Année Univesitaire supprimé avec succès.'
} }
} catch (error) { } catch (error) {
return { success: false, error: 'Erreur veullez réeseyer' + error } return { success: false, error: 'Erreur veullez réeseyer' + error }
@ -70,13 +70,13 @@ async function updateMention(nom, uniter, id) {
if (result.affectedRows === 0) { if (result.affectedRows === 0) {
return { return {
success: false, 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 { return {
success: true, success: true,
message: 'Année Scolaire mis à jour avec succès.' message: 'Année Univesitaire mis à jour avec succès.'
} }
} catch (error) { } catch (error) {
return { success: false, error: 'Erreur veullez réeseyer' + error } return { success: false, error: 'Erreur veullez réeseyer' + error }

4
database/Models/NoteSysrem.js

@ -33,13 +33,13 @@ async function updateSysteme(id, admis, redouble, renvoyer) {
if (result.affectedRows === 0) { if (result.affectedRows === 0) {
return { return {
success: false, success: false,
message: 'Année Scolaire non trouvé.' message: 'Année Univesitaire non trouvé.'
} }
} }
return { return {
success: true, success: true,
message: 'Année Scolaire supprimé avec succès.' message: 'Année Univesitaire supprimé avec succès.'
} }
} catch (error) { } catch (error) {
return error return error

8
database/Models/Parcours.js

@ -64,13 +64,13 @@ async function deletes(id) {
if (result.affectedRows === 0) { if (result.affectedRows === 0) {
return { return {
success: false, success: false,
message: 'Année Scolaire non trouvé.' message: 'Année Univesitaire non trouvé.'
} }
} }
return { return {
success: true, success: true,
message: 'Année Scolaire supprimé avec succès.' message: 'Année Univesitaire supprimé avec succès.'
} }
} catch (error) { } catch (error) {
return error return error
@ -86,13 +86,13 @@ async function updateparcour(id, nom, uniter, mention_id) {
if (result.affectedRows === 0) { if (result.affectedRows === 0) {
return { return {
success: false, 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 { return {
success: true, success: true,
message: 'Année Scolaire mis à jour avec succès.' message: 'Année Univesitaire mis à jour avec succès.'
} }
} catch (error) { } catch (error) {
return error return error

4
database/database.backup.js

@ -2,9 +2,9 @@ const mysql = require('mysql2/promise')
const bcrypt = require('bcryptjs') const bcrypt = require('bcryptjs')
const pool = mysql.createPool({ const pool = mysql.createPool({
host: '127.0.0.1', host: '192.168.200.200',
user: 'root', user: 'root',
password: '', password: 'stephane1313',
database: 'university', database: 'university',
waitForConnections: true, waitForConnections: true,
connectionLimit: 10, connectionLimit: 10,

4
database/database.js

@ -2,9 +2,9 @@ const mysql = require('mysql2/promise')
const bcrypt = require('bcryptjs') const bcrypt = require('bcryptjs')
const pool = mysql.createPool({ const pool = mysql.createPool({
host: '127.0.0.1', host: '192.168.200.200',
user: 'root', user: 'root',
password: '', password: 'stephane1313',
database: 'university', database: 'university',
waitForConnections: true, waitForConnections: true,
connectionLimit: 10, connectionLimit: 10,

4
database/database2.js

@ -2,9 +2,9 @@ const mysql = require('mysql2/promise')
const bcrypt = require('bcryptjs') const bcrypt = require('bcryptjs')
const pool = mysql.createPool({ const pool = mysql.createPool({
host: '127.0.0.1', host: '192.168.200.200',
user: 'root', user: 'root',
password: '', password: 'stephane1313',
database: 'university', database: 'university',
waitForConnections: true, waitForConnections: true,
connectionLimit: 10, connectionLimit: 10,

4
database/function/System.js

@ -287,13 +287,13 @@ async function updateNessesaryTable(id, multiplicateur) {
if (result.affectedRows === 0) { if (result.affectedRows === 0) {
return { return {
success: false, success: false,
message: 'Année Scolaire non trouvé.' message: 'Année universitaire non trouvé.'
} }
} }
return { return {
success: true, success: true,
message: 'Année Scolaire supprimé avec succès.' message: 'Année universitaire supprimé avec succès.'
} }
} catch (error) { } catch (error) {
return error return error

8
src/renderer/src/components/AddAnneeScolaire.jsx

@ -98,7 +98,7 @@ const AddAnneeScolaire = () => {
{status === 200 ? ( {status === 200 ? (
<Typography style={{ display: 'flex', flexDirection: 'column', alignItems: 'center' }}> <Typography style={{ display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
<img src={svgSuccess} alt="" width={50} height={50} />{' '} <img src={svgSuccess} alt="" width={50} height={50} />{' '}
<span>Année Scolaire insérer avec succes</span> <span>Année Univesitaire insérer avec succes</span>
</Typography> </Typography>
) : ( ) : (
<Typography style={{ display: 'flex', flexDirection: 'column', alignItems: 'center' }}> <Typography style={{ display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
@ -136,7 +136,7 @@ const AddAnneeScolaire = () => {
<div className={classe.h1style}> <div className={classe.h1style}>
<div className={classeHome.blockTitle}> <div className={classeHome.blockTitle}>
<h1 style={{ display: 'flex', alignItems: 'center', gap: '10px' }}> <h1 style={{ display: 'flex', alignItems: 'center', gap: '10px' }}>
<FaCalendarPlus /> Ajout Année Scolaire <FaCalendarPlus /> Ajout Année Univesitaire
</h1> </h1>
<Link to={'#'} onClick={() => window.history.back()}> <Link to={'#'} onClick={() => window.history.back()}>
<Button color="warning" variant="contained"> <Button color="warning" variant="contained">
@ -170,12 +170,12 @@ const AddAnneeScolaire = () => {
}} }}
> >
<h4 style={{ textAlign: 'center', padding: '0 0 3% 0' }}> <h4 style={{ textAlign: 'center', padding: '0 0 3% 0' }}>
Creation de nouvelle Année Scolaire Creation de nouvelle Année Univesitaire
</h4> </h4>
<Grid container spacing={2}> <Grid container spacing={2}>
<Grid item xs={12} sm={6}> <Grid item xs={12} sm={6}>
<TextField <TextField
label={'Année Scolaire'} label={'Année Univesitaire'}
name={'code'} name={'code'}
placeholder="2024-2025" placeholder="2024-2025"
color="warning" color="warning"

8
src/renderer/src/components/AddStudent.jsx

@ -409,7 +409,7 @@ const AddStudent = () => {
</Grid> </Grid>
<Grid item xs={12} sm={6}> <Grid item xs={12} sm={6}>
<TextField <TextField
label="Prenom" label="Prénom"
name="prenom" name="prenom"
fullWidth fullWidth
size="small" size="small"
@ -503,13 +503,13 @@ const AddStudent = () => {
variant="outlined" variant="outlined"
> >
<InputLabel id="demo-select-small-label" color="warning"> <InputLabel id="demo-select-small-label" color="warning">
Année Scolaire Année Univesitaire
</InputLabel> </InputLabel>
<Select <Select
labelId="demo-select-small-label" labelId="demo-select-small-label"
id="demo-select-small" id="demo-select-small"
value={formData.annee_scolaire} value={formData.annee_scolaire}
label="Année Scolaire" label="Année Univesitaire"
color="warning" color="warning"
size="small" size="small"
onChange={handleInputChange} onChange={handleInputChange}
@ -521,7 +521,7 @@ const AddStudent = () => {
<FaCalendarAlt /> <FaCalendarAlt />
</InputAdornment> </InputAdornment>
} }
label="Année Scolaire" label="Année Univesitaire"
/> />
} }
sx={{ sx={{

4
src/renderer/src/components/AnneeScolaire.jsx

@ -48,7 +48,7 @@ const AnneeScolaire = () => {
const [ids, setIds] = useState(0) const [ids, setIds] = useState(0)
const column = [ const column = [
{ field: 'code', headerName: 'Année Scolaire', width: 130 }, { field: 'code', headerName: 'Année Univesitaire', width: 130 },
{ field: 'debut', headerName: 'Date de début', width: 130 }, { field: 'debut', headerName: 'Date de début', width: 130 },
{ field: 'fin', headerName: 'Date de fin', width: 130 }, { field: 'fin', headerName: 'Date de fin', width: 130 },
{ {
@ -259,7 +259,7 @@ const AnneeScolaire = () => {
<div className={classe.h1style}> <div className={classe.h1style}>
<div className={classeHome.blockTitle}> <div className={classeHome.blockTitle}>
<h1 style={{ display: 'flex', alignItems: 'center', gap: '10px' }}> <h1 style={{ display: 'flex', alignItems: 'center', gap: '10px' }}>
<BsCalendar2Date /> Année Scolaire <BsCalendar2Date /> Année Univesitaire
</h1> </h1>
<Link to={'/addanneescolaire'}> <Link to={'/addanneescolaire'}>
<Button color="warning" variant="contained"> <Button color="warning" variant="contained">

8
src/renderer/src/components/ExportEtudiants.jsx

@ -460,16 +460,16 @@ const ExportEtudiants = () => {
> >
<MenuItem value={col.headerName}>{col.headerName}</MenuItem> <MenuItem value={col.headerName}>{col.headerName}</MenuItem>
<MenuItem value={'nom'}>nom</MenuItem> <MenuItem value={'nom'}>nom</MenuItem>
<MenuItem value={'prenom'}>prenom</MenuItem> <MenuItem value={'prenom'}>prénom</MenuItem>
<MenuItem value={`niveau`}>niveau</MenuItem> <MenuItem value={`niveau`}>niveau</MenuItem>
<MenuItem value={`date_naissance`}>date de naissance</MenuItem> <MenuItem value={`date_naissance`}>date de naissance</MenuItem>
<MenuItem value={`annee_scolaire`}>année scolaire</MenuItem> <MenuItem value={`annee_scolaire`}>Année Univesitaire</MenuItem>
<MenuItem value={`mention`}>mention</MenuItem> <MenuItem value={`mention`}>mention</MenuItem>
<MenuItem value={`num_inscription`}>numéro d'inscription</MenuItem> <MenuItem value={`num_inscription`}>numéro d'inscription</MenuItem>
<MenuItem value={`nationalite`}>Nationaliter</MenuItem> <MenuItem value={`nationalite`}>Nationalité</MenuItem>
<MenuItem value={`sexe`}>Sexe</MenuItem> <MenuItem value={`sexe`}>Sexe</MenuItem>
<MenuItem value={`cin`}>CIN</MenuItem> <MenuItem value={`cin`}>CIN</MenuItem>
<MenuItem value={`date_de_livraison`}>Date de livraison</MenuItem> <MenuItem value={`date_de_livraison`}>Date de délivrance(CIN)</MenuItem>
<MenuItem value={`annee_baccalaureat`}>Année du baccalaureat</MenuItem> <MenuItem value={`annee_baccalaureat`}>Année du baccalaureat</MenuItem>
<MenuItem value={`serie`}>Série</MenuItem> <MenuItem value={`serie`}>Série</MenuItem>
<MenuItem value={`code_redoublement`}>Code redoublement</MenuItem> <MenuItem value={`code_redoublement`}>Code redoublement</MenuItem>

4
src/renderer/src/components/Home.jsx

@ -151,12 +151,12 @@ const Home = () => {
sx={{ color: 'black', fontSize: '15px', textTransform: 'capitalize' }} sx={{ color: 'black', fontSize: '15px', textTransform: 'capitalize' }}
color="warning" color="warning"
> >
Année Scolaire Année Univesitaire
</InputLabel> </InputLabel>
<Select <Select
labelId="demo-select-small-label" labelId="demo-select-small-label"
id="demo-select-small" id="demo-select-small"
label="Année Scolaire" label="Année Univesitaire"
color="warning" color="warning"
defaultValue={'general'} defaultValue={'general'}
onChange={FilterAnneeScolaire} onChange={FilterAnneeScolaire}

147
src/renderer/src/components/Login.jsx

@ -1,60 +1,113 @@
import { useRef, useState } from 'react' import { useRef, useState, useEffect } from 'react'
// import { Container, Row, Col, Form, Button, Card, InputGroup } from 'react-bootstrap';
import { Container, Grid, Card, Typography, TextField, Button, InputAdornment } from '@mui/material' import { Container, Grid, Card, Typography, TextField, Button, InputAdornment } from '@mui/material'
import { FaUserCircle, FaLock, FaUser } from 'react-icons/fa' import { FaUserCircle, FaLock, FaUser } from 'react-icons/fa'
import classe from '../assets/Login.module.css' import classe from '../assets/Login.module.css'
import { useAuthContext } from '../contexts/AuthContext' import { useAuthContext } from '../contexts/AuthContext'
import { Link } from 'react-router-dom' import { Link, useNavigate } from 'react-router-dom'
import { ValidationLogin, invalidCredential } from './validation/Login' import { ValidationLogin, invalidCredential } from './validation/Login'
const Login = () => { const Login = () => {
/** const { token, setToken, setUser, isAuthenticated, isLoading } = useAuthContext()
* token from the AuthContext in the context folder const navigate = useNavigate()
*/
const { setToken } = useAuthContext() const [username, setUsername] = useState('')
const [password, setPassword] = useState('')
/** const [isSubmitting, setIsSubmitting] = useState(false)
* hook to store our data from the input element
*/
const [username, setUsername] = useState()
const [password, setPassword] = useState()
/**
* ref for our username and password input and the error span
*/
const userNameRef = useRef() const userNameRef = useRef()
const passwordRef = useRef() const passwordRef = useRef()
const userNameError = useRef() const userNameError = useRef()
const passwordError = useRef() const passwordError = useRef()
/** // Redirection si déjà authentifié
* function to send the data to the IPCRender useEffect(() => {
* and make login if (!isLoading && isAuthenticated) {
* console.log('Utilisateur déjà authentifié, redirection vers home')
* @param {any} e navigate('/', { replace: true })
*/ }
}, [isAuthenticated, isLoading, navigate])
const formLogin = async (e) => { const formLogin = async (e) => {
e.preventDefault() e.preventDefault()
let validate = ValidationLogin( if (isSubmitting) return
userNameRef.current, setIsSubmitting(true)
passwordRef.current,
userNameError.current, try {
passwordError.current const validate = ValidationLogin(
) userNameRef.current,
passwordRef.current,
userNameError.current,
passwordError.current
)
if (!validate) {
setIsSubmitting(false)
return
}
console.log('Tentative de connexion pour:', username)
if (validate) {
const response = await window.allUser.login({ username, password }) const response = await window.allUser.login({ username, password })
console.log('Réponse login:', response)
if (response.success) { if (response.success) {
// Redirect to main window // Extraire le token et les données utilisateur
setToken(JSON.stringify(response.user)) const userData = response.user
// Essayer plusieurs sources pour le token
const userToken = response.user.token || response.token || response.user.access_token || response.access_token
console.log('Connexion réussie:', { userData, userToken })
console.log('Structure complète de response:', response)
if (!userToken) {
console.error('Aucun token trouvé dans la réponse!')
// Générer un token temporaire ou utiliser l'ID utilisateur
const tempToken = `temp_token_${userData.id}_${Date.now()}`
console.log('Utilisation d\'un token temporaire:', tempToken)
setUser(userData)
setToken(tempToken)
} else {
// Sauvegarder les données
setUser(userData)
setToken(userToken)
}
console.log('Redirection vers home...')
// Forcer la redirection avec un délai
setTimeout(() => {
navigate('/', { replace: true })
}, 100)
} else { } else {
invalidCredential(userNameError.current, response.error) console.error('Échec de la connexion:', response.error)
invalidCredential(userNameError.current, response.error || 'Erreur de connexion')
} }
} catch (error) {
console.error('Erreur login :', error)
invalidCredential(userNameError.current, 'Erreur de connexion')
} finally {
setIsSubmitting(false)
} }
} }
// Afficher un loader pendant la vérification initiale
if (isLoading) {
return (
<Container
maxWidth={false}
sx={{ minHeight: '100vh', display: 'flex', alignItems: 'center', justifyContent: 'center' }}
>
<Typography>Chargement...</Typography>
</Container>
)
}
// Ne pas afficher le formulaire si déjà authentifié
if (isAuthenticated) {
return null
}
return ( return (
<Container <Container
maxWidth={false} maxWidth={false}
@ -63,7 +116,7 @@ const Login = () => {
> >
<Grid container justifyContent="center"> <Grid container justifyContent="center">
<Grid item xs={12} md={6} lg={4}> <Grid item xs={12} md={6} lg={4}>
<Card className={`p-4 shadow ` + classe.cards} sx={{ padding: 4, boxShadow: 3 }}> <Card className={`p-4 shadow ${classe.cards}`} sx={{ padding: 4, boxShadow: 3 }}>
<div style={{ textAlign: 'center', marginBottom: '1rem' }}> <div style={{ textAlign: 'center', marginBottom: '1rem' }}>
<FaUserCircle size={60} color="dark" className="text-light" /> <FaUserCircle size={60} color="dark" className="text-light" />
</div> </div>
@ -78,6 +131,8 @@ const Login = () => {
fullWidth fullWidth
placeholder="Nom d'utilisateur" placeholder="Nom d'utilisateur"
margin="normal" margin="normal"
value={username}
disabled={isSubmitting}
InputProps={{ InputProps={{
startAdornment: ( startAdornment: (
<InputAdornment position="start"> <InputAdornment position="start">
@ -90,16 +145,13 @@ const Login = () => {
inputRef={userNameRef} inputRef={userNameRef}
sx={{ sx={{
'& .MuiOutlinedInput-root': { '& .MuiOutlinedInput-root': {
'& fieldset': { '& fieldset': { borderColor: 'white' },
borderColor: 'white' // Set the border color when not focused '&:hover fieldset': { borderColor: 'rgb(156, 39, 176)' }
},
'&:hover fieldset': {
borderColor: 'rgb(156, 39, 176)' // Set the border color on hover
}
} }
}} }}
/> />
<span className="text-danger" ref={userNameError}></span> <span className="text-danger" ref={userNameError}></span>
<TextField <TextField
label="Mot de passe" label="Mot de passe"
color="secondary" color="secondary"
@ -108,6 +160,8 @@ const Login = () => {
fullWidth fullWidth
placeholder="Mot de passe" placeholder="Mot de passe"
margin="normal" margin="normal"
value={password}
disabled={isSubmitting}
className={classe.input} className={classe.input}
InputProps={{ InputProps={{
startAdornment: ( startAdornment: (
@ -120,12 +174,8 @@ const Login = () => {
inputRef={passwordRef} inputRef={passwordRef}
sx={{ sx={{
'& .MuiOutlinedInput-root': { '& .MuiOutlinedInput-root': {
'& fieldset': { '& fieldset': { borderColor: 'white' },
borderColor: 'white' // Set the border color when not focused '&:hover fieldset': { borderColor: 'rgb(156, 39, 176)' }
},
'&:hover fieldset': {
borderColor: 'rgb(156, 39, 176)' // Set the border color on hover
}
} }
}} }}
/> />
@ -136,9 +186,10 @@ const Login = () => {
color="secondary" color="secondary"
type="submit" type="submit"
fullWidth fullWidth
sx={{ marginTop: 2 }} disabled={isSubmitting}
sx={{ mt: 2 }}
> >
Se connecter {isSubmitting ? 'Connexion...' : 'Se connecter'}
</Button> </Button>
<div style={{ display: 'flex', justifyContent: 'space-between', marginTop: '1rem' }}> <div style={{ display: 'flex', justifyContent: 'space-between', marginTop: '1rem' }}>

6
src/renderer/src/components/ModalAddEtudiants.jsx

@ -154,7 +154,7 @@ const ModalAddEtudiants = ({ open, handleClose }) => {
</Grid> </Grid>
<Grid item xs={12} sm={6}> <Grid item xs={12} sm={6}>
<TextField <TextField
label="Prenom" label="Prénom"
name="prenom" name="prenom"
fullWidth fullWidth
color="secondary" color="secondary"
@ -232,10 +232,10 @@ const ModalAddEtudiants = ({ open, handleClose }) => {
/> />
</Grid> </Grid>
{/* Année Scolaire and Numéro d'Inscription Fields */} {/* Année Univesitaire and Numéro d'Inscription Fields */}
<Grid item xs={12} sm={6}> <Grid item xs={12} sm={6}>
<TextField <TextField
label="Année Scolaire" label="Année Univesitaire"
name="annee_scolaire" name="annee_scolaire"
fullWidth fullWidth
color="secondary" color="secondary"

4
src/renderer/src/components/ModalAddProf.jsx

@ -95,10 +95,10 @@ const ModalAddProf = ({ open, onClose, matiere_id, onSubmitSuccess }) => {
margin="normal" margin="normal"
required required
name="prenom_enseignant" name="prenom_enseignant"
label="Prenom du professeur" label="Prénom du professeur"
type="text" type="text"
fullWidth fullWidth
placeholder="Prenom du professeur" placeholder="Prénom du professeur"
variant="outlined" variant="outlined"
value={formData.prenom_enseignant} value={formData.prenom_enseignant}
color="warning" color="warning"

6
src/renderer/src/components/ModalCertificate.jsx

@ -41,14 +41,14 @@ const ModalCertificate = ({ open, onClose, json }) => {
return ( return (
<Dialog open={open} onClose={onClose}> <Dialog open={open} onClose={onClose}>
<form action=""> <form action="">
<DialogTitle>Informations sur l'élève</DialogTitle> <DialogTitle>Informations sur l'étudiant</DialogTitle>
<DialogContent> <DialogContent>
<TextField <TextField
autoFocus autoFocus
margin="dense" margin="dense"
required required
name="pere" name="pere"
label="Père de l'élève" label="Père de l'étudiant"
type="text" type="text"
fullWidth fullWidth
variant="outlined" variant="outlined"
@ -60,7 +60,7 @@ const ModalCertificate = ({ open, onClose, json }) => {
margin="dense" margin="dense"
name="mere" name="mere"
required required
label="Mère de l'élève" label="Mère de l'étudiant"
type="text" type="text"
fullWidth fullWidth
variant="outlined" variant="outlined"

2
src/renderer/src/components/ModalExportFichr.jsx

@ -170,7 +170,7 @@ const ModalExportFichr = () => {
</tr> </tr>
<tr style={{ borderBottom: 'solid 1px gray' }}> <tr style={{ borderBottom: 'solid 1px gray' }}>
<th style={{ borderRight: 'solid 1px gray' }}>N°</th> <th style={{ borderRight: 'solid 1px gray' }}>N°</th>
<th style={{ borderRight: 'solid 1px gray' }}>Nom et Prenom</th> <th style={{ borderRight: 'solid 1px gray' }}>Nom et Prénom</th>
<th style={{ borderRight: 'solid 1px gray' }}>Mention</th> <th style={{ borderRight: 'solid 1px gray' }}>Mention</th>
<th>Emergement</th> <th>Emergement</th>
</tr> </tr>

2
src/renderer/src/components/ModalRecepice.jsx

@ -41,7 +41,7 @@ const ModalRecepice = ({ open, onClose, json }) => {
margin="dense" margin="dense"
required required
name="nom" name="nom"
label="Nom et prenom du chef de services" label="Nom et prénom du chef de services"
type="text" type="text"
fullWidth fullWidth
variant="outlined" variant="outlined"

2
src/renderer/src/components/ModalStage.jsx

@ -57,7 +57,7 @@ const ModalStage = ({ open, onClose }) => {
margin="dense" margin="dense"
name="prenom" name="prenom"
required required
label="Prenom du directeur" label="Prénom du directeur"
type="text" type="text"
fullWidth fullWidth
variant="outlined" variant="outlined"

107
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 { createTheme, ThemeProvider } from '@mui/material/styles'
import { IoNewspaperOutline } from 'react-icons/io5' import { IoNewspaperOutline } from 'react-icons/io5'
import { IoMdReturnRight } from 'react-icons/io' 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 { Tooltip } from 'react-tooltip'
import ReleverNotes from './ReleverNotes' import ReleverNotes from './ReleverNotes'
import { FaDownload } from 'react-icons/fa' import { FaDownload } from 'react-icons/fa'
@ -50,12 +50,23 @@ const Noteclasse = () => {
} }
function checkNull(params) { function checkNull(params) {
console.log(params);
if (params == null || params == undefined) { if (params == null || params == undefined) {
return null return null
} }
return params 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) { function compareSessionNotes(session1, session2) {
let notes let notes
if (session2) { if (session2) {
@ -94,10 +105,10 @@ const Noteclasse = () => {
modelJson.mention = etudiants[index][j].mention_id modelJson.mention = etudiants[index][j].mention_id
modelJson.anneescolaire = etudiants[index][j].annee_scolaire 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]) { if (session[index]) {
note += note +=
compareSessionNotes(etudiants[index][j].note, checkNull(session[index][j])) * compareSessionNotesForAverage(etudiants[index][j].note, checkNull(session[index][j])) *
etudiants[index][j].credit etudiants[index][j].credit
} else { } else {
note += etudiants[index][j].note * etudiants[index][j].credit note += etudiants[index][j].note * etudiants[index][j].credit
@ -113,15 +124,15 @@ const Noteclasse = () => {
} }
function checkNumberSession(id) { function checkNumberSession(id) {
let sessionNumber let sessionNumber = 1
for (let index = 0; index < session.length; index++) { for (let index = 0; index < session.length; index++) {
for (let j = 0; j < session[index].length; j++) { for (let j = 0; j < session[index].length; j++) {
if (session[index][j].etudiant_id == id) { if (session[index][j].etudiant_id == id) {
sessionNumber = 2 sessionNumber = 2
} else { break
sessionNumber = 1
} }
} }
if (sessionNumber === 2) break
} }
return sessionNumber return sessionNumber
} }
@ -147,9 +158,29 @@ const Noteclasse = () => {
const paginationModel = { page: 0, pageSize: 5 } 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 = [ const columns = [
{ field: 'nom', headerName: 'Nom', width: 170 }, { 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: 'session', headerName: 'Nombre de Session', width: 180 },
{ field: 'mention', headerName: 'Mention', width: 180 }, { field: 'mention', headerName: 'Mention', width: 180 },
{ field: 'moyenne', headerName: 'Moyenne Général', width: 160 }, { field: 'moyenne', headerName: 'Moyenne Général', width: 160 },
@ -171,19 +202,21 @@ const Noteclasse = () => {
flex: 1, flex: 1,
renderCell: (params) => ( renderCell: (params) => (
<div style={{ display: 'flex', gap: '10px' }}> <div style={{ display: 'flex', gap: '10px' }}>
<Link to={`#`} onClick={() => sendData(params.value)}> <Button
{/* <IoEyeSharp style={{fontSize:"20px", color:"white"}} /> */} color="warning"
<Button color="warning" variant="contained" className={`update${params.value}`}> variant="contained"
<IoNewspaperOutline style={{ fontSize: '20px', color: 'white' }} /> className={`update${params.value}`}
</Button> onClick={(event) => handleMenuClick(event, params.value)}
<Tooltip >
anchorSelect={`.update${params.value}`} <IoNewspaperOutline style={{ fontSize: '20px', color: 'white' }} />
style={{ fontSize: '13px', zIndex: 22 }} </Button>
place="bottom-end" <Tooltip
> anchorSelect={`.update${params.value}`}
Imprimer un relevé de notes style={{ fontSize: '13px', zIndex: 22 }}
</Tooltip> place="bottom-end"
</Link> >
Imprimer un relevé de notes
</Tooltip>
</div> </div>
) )
} }
@ -205,15 +238,18 @@ const Noteclasse = () => {
const [form, setForm] = useState({ const [form, setForm] = useState({
id: '', id: '',
niveau: '', niveau: '',
anneescolaire: '' anneescolaire: '',
sessionType: 'ensemble' // Par défaut
}) })
const [selectedId, setSelectedId] = useState(null) // Store id dynamically const [selectedId, setSelectedId] = useState(null) // Store id dynamically
const sendData = (id) => { const sendData = (id, sessionType = 'ensemble') => {
setSelectedId(id) setSelectedId(id)
// if (selectedId !== null) { setForm(prevForm => ({
setOpenCart(true) ...prevForm,
// } sessionType: sessionType
}))
setOpenCart(true)
} }
useEffect(() => { useEffect(() => {
@ -229,7 +265,9 @@ const Noteclasse = () => {
} }
} }
}, [openCard, selectedId]) }, [openCard, selectedId])
console.log(form) console.log(form)
const downloadButton = () => { const downloadButton = () => {
setBolll(true) setBolll(true)
} }
@ -265,6 +303,7 @@ const Noteclasse = () => {
id={form.id} id={form.id}
anneescolaire={scolaire} anneescolaire={scolaire}
niveau={form.niveau} niveau={form.niveau}
sessionType={form.sessionType}
refs={bolll} refs={bolll}
/> />
<Button <Button
@ -298,6 +337,24 @@ const Noteclasse = () => {
return ( return (
<div className={classe.mainHome}> <div className={classe.mainHome}>
{modalReleverNotes()} {modalReleverNotes()}
{/* Menu pour sélectionner le type de session */}
<Menu
anchorEl={anchorEl}
open={open}
onClose={handleMenuClose}
MenuListProps={{
'aria-labelledby': 'session-button',
}}
>
<MenuItem onClick={() => handleSessionTypeSelect('normale')}>
Session Normale
</MenuItem>
<MenuItem onClick={() => handleSessionTypeSelect('ensemble')}>
Session Rattrapage
</MenuItem>
</Menu>
<div className={classeHome.header}> <div className={classeHome.header}>
<div className={classe.h1style}> <div className={classe.h1style}>
<div className={classeHome.blockTitle}> <div className={classeHome.blockTitle}>

2
src/renderer/src/components/Notes.jsx

@ -34,7 +34,7 @@ const Notes = () => {
const columns = [ const columns = [
{ field: 'niveau', headerName: 'Niveau', width: 170 }, { field: 'niveau', headerName: 'Niveau', width: 170 },
{ field: 'annee_scolaire', headerName: 'Année scolaire', width: 160 }, { field: 'annee_scolaire', headerName: 'Année Univesitaire', width: 160 },
// { field:'moyenne', headerName:'Moyenne de classe', width:160}, // { field:'moyenne', headerName:'Moyenne de classe', width:160},
{ {
field: 'action', field: 'action',

208
src/renderer/src/components/Param.jsx

@ -1,33 +1,35 @@
import { useState } from 'react' import { useState } from 'react'
import { Box, Button, InputAdornment, TextField, Grid, Modal, Typography } from '@mui/material'
import { FaEnvelope, FaLock, FaUser } from 'react-icons/fa'
import { GrConfigure } from 'react-icons/gr'
import { Link } from 'react-router-dom'
import { useAuthContext } from '../contexts/AuthContext'
import IpConfig from './IpConfig'
import classe from '../assets/AllStyleComponents.module.css' import classe from '../assets/AllStyleComponents.module.css'
import img from '../assets/para.png'
import classeHome from '../assets/Home.module.css' import classeHome from '../assets/Home.module.css'
import { Box, Button, InputAdornment, TextField, Grid, Modal, Typography } from '@mui/material'
import classeAdd from '../assets/AddStudent.module.css' import classeAdd from '../assets/AddStudent.module.css'
import { useAuthContext } from '../contexts/AuthContext' import img from '../assets/para.png'
import { FaEnvelope, FaLock, FaUser } from 'react-icons/fa'
import svgSuccess from '../assets/success.svg' import svgSuccess from '../assets/success.svg'
import svgError from '../assets/error.svg' import svgError from '../assets/error.svg'
import { Link } from 'react-router-dom' import { useNavigate} from 'react-router-dom'
import { GrConfigure } from 'react-icons/gr'
import IpConfig from './IpConfig'
const Setting = () => { const Setting = () => {
const { token, setToken } = useAuthContext() const { user, setUser, token, setToken } = useAuthContext()
const userInfo = JSON.parse(token)
const navigate = useNavigate()
if (!user) {
navigate('/login');
return <div>Chargement...</div>
}
// Initialisation du formulaire avec les infos de l'utilisateur
const [formData, setFormData] = useState({ const [formData, setFormData] = useState({
username: userInfo.username, username: user.username,
email: userInfo.email, email: user.email,
password: '', password: '',
id: userInfo.id id: user.id
}) })
/** // Gestion des inputs
* function to set the data in state
* @param {*} e
*/
const handleInputChange = (e) => { const handleInputChange = (e) => {
const { name, value } = e.target const { name, value } = e.target
setFormData((prevData) => ({ setFormData((prevData) => ({
@ -36,49 +38,40 @@ const Setting = () => {
})) }))
} }
// Gestion de l'envoi du formulaire
const handleSubmit = async (e) => { const handleSubmit = async (e) => {
e.preventDefault() e.preventDefault()
// Handle form submission logic try {
const response = await window.allUser.updateUsers(formData) const response = await window.allUser.updateUsers(formData)
console.log(response) if (response.success) {
if (response.success) { setOpen(true)
setOpen(true) setCode(200)
setCode(200) setUser(response.user) // Mettre à jour user
setToken(JSON.stringify(response.users)) setToken(response.user.token) // Mettre à jour token si besoin
setFormData({ setFormData({
username: response.username, username: response.user.username,
email: response.email, email: response.user.email,
password: '', password: '',
id: userInfo.id id: response.user.id
}) })
} else { } else {
setCode(422) setCode(422)
setOpen(true)
}
} catch (error) {
console.error('Erreur lors de la mise à jour:', error)
setCode(500)
setOpen(true) setOpen(true)
} }
} }
/**
* hook to open modal // Modal
*/
const [open, setOpen] = useState(false) const [open, setOpen] = useState(false)
const [code, setCode] = useState(200) const [code, setCode] = useState(200)
/**
* function to close modal
*/
const handleClose = () => setOpen(false) const handleClose = () => setOpen(false)
/**
* function to return the view Modal
*
* @returns {JSX}
*/
const modals = () => ( const modals = () => (
<Modal <Modal open={open} onClose={handleClose} aria-labelledby="modal-title">
open={open}
onClose={handleClose}
aria-labelledby="modal-title"
aria-describedby="modal-description"
>
<Box <Box
sx={{ sx={{
position: 'absolute', position: 'absolute',
@ -91,30 +84,22 @@ const Setting = () => {
p: 4 p: 4
}} }}
> >
{code == 422 ? ( {code === 422 ? (
<Typography <Typography sx={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: '10px' }}>
style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: '10px' }} <img src={svgError} alt="Erreur" width={50} height={50} />
> <span>Email déjà pris</span>
<img src={svgError} alt="" width={50} height={50} />{' '} </Typography>
<span style={{ marginLeft: '10px' }}>Email déjà pris</span> ) : code === 500 ? (
<Typography sx={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: '10px' }}>
<span>Une erreur est survenue</span>
</Typography> </Typography>
) : ( ) : (
<Typography <Typography sx={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: '10px' }}>
style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: '10px' }} <img src={svgSuccess} alt="Succès" width={100} height={100} />
> <span>Modification effectuée avec succès</span>
<img src={svgSuccess} alt="" width={100} height={100} />{' '}
<span>Modification a été effectuée avec succès</span>
</Typography> </Typography>
)} )}
<Box <Box sx={{ mt: 2, display: 'flex', justifyContent: 'flex-end' }}>
sx={{
marginTop: '2%',
display: 'flex',
gap: '20px',
alignItems: 'end',
justifyContent: 'flex-end'
}}
>
<Button onClick={handleClose} color="warning" variant="contained"> <Button onClick={handleClose} color="warning" variant="contained">
OK OK
</Button> </Button>
@ -123,10 +108,10 @@ const Setting = () => {
</Modal> </Modal>
) )
const [openConfig, setOpenCOnfig] = useState(false) // IP Config
const onCloseConfig = () => setOpenCOnfig(false) const [openConfig, setOpenConfig] = useState(false)
const onCloseConfig = () => setOpenConfig(false)
const openCOnfigFunction = () => setOpenCOnfig(true) const openConfigFunction = () => setOpenConfig(true)
return ( return (
<div className={classe.mainHome}> <div className={classe.mainHome}>
@ -135,8 +120,8 @@ const Setting = () => {
<div className={classeHome.header}> <div className={classeHome.header}>
<div className={classe.h1style}> <div className={classe.h1style}>
<div className={classeHome.blockTitle}> <div className={classeHome.blockTitle}>
<h1>setting</h1> <h1>Settings</h1>
<Link to={'#'} onClick={openCOnfigFunction}> <Link to="#" onClick={openConfigFunction}>
<Button color="warning" variant="contained"> <Button color="warning" variant="contained">
<GrConfigure style={{ fontSize: '20px' }} /> IP configuration <GrConfigure style={{ fontSize: '20px' }} /> IP configuration
</Button> </Button>
@ -144,7 +129,7 @@ const Setting = () => {
</div> </div>
</div> </div>
</div> </div>
{/* contenu */}
<div className={classeHome.contenaire}> <div className={classeHome.contenaire}>
<div className={classeAdd.boxEtudiantsCard}> <div className={classeAdd.boxEtudiantsCard}>
<Box <Box
@ -162,22 +147,15 @@ const Setting = () => {
> >
<Box <Box
sx={{ sx={{
marginTop: '5%', mt: '5%',
display: 'flex', display: 'flex',
gap: '10px',
alignItems: 'start',
flexDirection: 'column', flexDirection: 'column',
fontSize: 16, alignItems: 'center',
fontFamily: 'sans-serif', gap: '10px'
justifyContent: 'flex-end'
}} }}
> >
<span style={{ display: 'flex', marginLeft: '40%' }}> <img src={img} alt="avatar" width={150} height={150} />
<img src={img} alt="" height={150} width={150} /> <form onSubmit={handleSubmit} style={{ width: '100%', marginTop: '5%' }}>
</span>
<form onSubmit={handleSubmit} style={{ marginTop: '5%' }}>
{/* */}
<Grid container spacing={2}> <Grid container spacing={2}>
<Grid item xs={12} sm={6}> <Grid item xs={12} sm={6}>
<TextField <TextField
@ -189,18 +167,7 @@ const Setting = () => {
onChange={handleInputChange} onChange={handleInputChange}
required required
InputProps={{ InputProps={{
startAdornment: ( startAdornment: <InputAdornment position="start"><FaUser /></InputAdornment>
<InputAdornment position="start">
<FaUser />
</InputAdornment>
)
}}
sx={{
'& .MuiOutlinedInput-root': {
'&:hover fieldset': {
borderColor: '#ff9800' // Set the border color on hover
}
}
}} }}
/> />
</Grid> </Grid>
@ -214,23 +181,11 @@ const Setting = () => {
value={formData.email} value={formData.email}
onChange={handleInputChange} onChange={handleInputChange}
InputProps={{ InputProps={{
startAdornment: ( startAdornment: <InputAdornment position="start"><FaEnvelope /></InputAdornment>
<InputAdornment position="start">
<FaEnvelope />
</InputAdornment>
)
}}
sx={{
'& .MuiOutlinedInput-root': {
'&:hover fieldset': {
borderColor: '#ff9800' // Set the border color on hover
}
}
}} }}
/> />
</Grid> </Grid>
{/* matieres Mecanique general */} <Grid item xs={12}>
<Grid item xs={12} sm={12}>
<TextField <TextField
label="Mot de passe" label="Mot de passe"
name="password" name="password"
@ -240,30 +195,13 @@ const Setting = () => {
value={formData.password} value={formData.password}
onChange={handleInputChange} onChange={handleInputChange}
InputProps={{ InputProps={{
startAdornment: ( startAdornment: <InputAdornment position="start"><FaLock /></InputAdornment>
<InputAdornment position="start">
<FaLock />
</InputAdornment>
)
}}
sx={{
'& .MuiOutlinedInput-root': {
'&:hover fieldset': {
borderColor: '#ff9800' // Set the border color on hover
}
}
}} }}
/> />
</Grid> </Grid>
{/* Matieres Resistance Materiaux */} <Grid item xs={12} sx={{ display: 'flex', justifyContent: 'flex-end' }}>
{/* Submit Button */}
<Grid
item
xs={12}
style={{ display: 'flex', gap: '30px', justifyContent: 'flex-end' }}
>
<Button type="submit" color="warning" variant="contained"> <Button type="submit" color="warning" variant="contained">
Enregister Enregistrer
</Button> </Button>
</Grid> </Grid>
</Grid> </Grid>

261
src/renderer/src/components/ReleverNotes.jsx

@ -10,11 +10,16 @@ import dayjs from 'dayjs'
import getSemestre from './function/GetSemestre' import getSemestre from './function/GetSemestre'
import { descisionJury, getmentionAfterNotes } from './function/FonctionRelever' 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 [etudiant, setEtudiant] = useState([])
const [matieres, setMatieres] = useState([]) const [matieres, setMatieres] = useState([])
const [notes, setNotes] = 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 handleDownloadPDF = async () => {
const input = Telever.current const input = Telever.current
@ -166,9 +171,19 @@ const ReleverNotes = ({ id, anneescolaire, niveau, refs }) => {
return acc return acc
}, {}) }, {})
const compareMoyenne = (normal, rattrapage) => { // MODIFICATION: Fonction compareMoyenne mise à jour
const note = Math.max(Number(normal), Number(rattrapage)) const compareMoyenne = (normal, rattrapage, sessionType) => {
return note >= 10 ? 'Admis' : 'Ajourné' 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 = () => { const TbodyContent = () => {
@ -219,7 +234,6 @@ const ReleverNotes = ({ id, anneescolaire, niveau, refs }) => {
fontWeight: 'bold', fontWeight: 'bold',
textAlign: 'center', textAlign: 'center',
borderRight: 'solid 1px black', borderRight: 'solid 1px black',
// borderBottom: 'solid 1px black',
borderTop: 'solid 1px black' borderTop: 'solid 1px black'
}} }}
> >
@ -231,18 +245,29 @@ const ReleverNotes = ({ id, anneescolaire, niveau, refs }) => {
<td style={{ borderRight: 'solid 1px black', borderTop: 'solid 1px black' }}> <td style={{ borderRight: 'solid 1px black', borderTop: 'solid 1px black' }}>
{matiere.nom} {matiere.nom}
</td> </td>
<td style={{ borderRight: 'solid 1px black', borderTop: 'solid 1px black' }}>
{matiere.credit} {/* Affichage conditionnel des colonnes selon le type de session */}
</td> {sessionType !== 'rattrapage' && (
<td style={{ borderRight: 'solid 1px black', borderTop: 'solid 1px black' }}> <>
{matiere.note} <td style={{ borderRight: 'solid 1px black', borderTop: 'solid 1px black' }}>
</td> {matiere.credit}
<td style={{ borderRight: 'solid 1px black', borderTop: 'solid 1px black' }}> </td>
{matiere.credit} <td style={{ borderRight: 'solid 1px black', borderTop: 'solid 1px black' }}>
</td> {matiere.note}
<td style={{ borderRight: 'solid 1px black', borderTop: 'solid 1px black' }}> </td>
{matiere.noterepech} </>
</td> )}
{sessionType !== 'normale' && (
<>
<td style={{ borderRight: 'solid 1px black', borderTop: 'solid 1px black' }}>
{matiere.credit}
</td>
<td style={{ borderRight: 'solid 1px black', borderTop: 'solid 1px black' }}>
{matiere.noterepech}
</td>
</>
)}
{/* Display the comparison value only once */} {/* Display the comparison value only once */}
{matiereIndex === 0 && ( {matiereIndex === 0 && (
@ -255,7 +280,6 @@ const ReleverNotes = ({ id, anneescolaire, niveau, refs }) => {
borderTop: 'solid 1px black' borderTop: 'solid 1px black'
}} }}
> >
{/* Replace 'hgh' with your logic for displaying the comparison */}
{compareMoyenne( {compareMoyenne(
( (
matieres.reduce((total, matiere) => total + matiere.note, 0) / 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.reduce((total, matiere) => total + matiere.noterepech, 0) /
matieres.length matieres.length
).toFixed(2) ).toFixed(2),
sessionType // MODIFICATION: Passer le sessionType
)} )}
</td> </td>
)} )}
@ -288,57 +313,65 @@ const ReleverNotes = ({ id, anneescolaire, niveau, refs }) => {
> >
Total de Credit et Moyenne des Notes Total de Credit et Moyenne des Notes
</td> </td>
<td
style={{ {sessionType !== 'rattrapage' && (
textAlign: 'center', <>
fontWeight: 'bold', <td
borderRight: 'solid 1px black', style={{
borderTop: 'solid 1px black' textAlign: 'center',
}} fontWeight: 'bold',
> borderRight: 'solid 1px black',
{/* Calculate Total de Credit */} borderTop: 'solid 1px black'
{matieres.reduce((total, matiere) => total + matiere.credit, 0)} }}
</td> >
<td {matieres.reduce((total, matiere) => total + matiere.credit, 0)}
style={{ </td>
textAlign: 'center', <td
fontWeight: 'bold', style={{
borderRight: 'solid 1px black', textAlign: 'center',
borderTop: 'solid 1px black' fontWeight: 'bold',
}} borderRight: 'solid 1px black',
className="moyenneNotes" borderTop: 'solid 1px black'
> }}
{/* Calculate Moyenne des Notes */} className="moyenneNotes"
{( >
matieres.reduce((total, matiere) => total + matiere.note, 0) / {(
matieres.length matieres.reduce((total, matiere) => total + matiere.note, 0) /
).toFixed(2)}{' '} matieres.length
{/* Format to 2 decimal places */} ).toFixed(2)}
</td> </td>
<td </>
style={{ )}
textAlign: 'center',
fontWeight: 'bold', {sessionType !== 'normale' && (
borderTop: 'solid 1px black', <>
borderRight: 'solid 1px black' <td
}} style={{
> textAlign: 'center',
{matieres.reduce((total, matiere) => total + matiere.credit, 0)} fontWeight: 'bold',
</td> borderTop: 'solid 1px black',
<td borderRight: 'solid 1px black'
style={{ }}
textAlign: 'center', >
fontWeight: 'bold', {matieres.reduce((total, matiere) => total + matiere.credit, 0)}
borderRight: 'solid 1px black', </td>
borderTop: 'solid 1px black' <td
}} style={{
className="moyenneNotesRattrapage" textAlign: 'center',
> fontWeight: 'bold',
{( borderRight: 'solid 1px black',
matieres.reduce((total, matiere) => total + matiere.noterepech, 0) / borderTop: 'solid 1px black'
matieres.length }}
).toFixed(2)} className="moyenneNotesRattrapage"
</td> >
{(
matieres.reduce((total, matiere) => total + matiere.noterepech, 0) /
matieres.length
).toFixed(2)}
</td>
</>
)}
<td <td
style={{ style={{
textAlign: 'center', textAlign: 'center',
@ -357,6 +390,7 @@ const ReleverNotes = ({ id, anneescolaire, niveau, refs }) => {
) )
} }
// MODIFICATION: Fonction totalNotes mise à jour pour tenir compte du sessionType
const totalNotes = () => { const totalNotes = () => {
let totalNotes = document.querySelectorAll('.moyenneNotes') let totalNotes = document.querySelectorAll('.moyenneNotes')
let totalNotesRepech = document.querySelectorAll('.moyenneNotesRattrapage') let totalNotesRepech = document.querySelectorAll('.moyenneNotesRattrapage')
@ -365,25 +399,29 @@ const ReleverNotes = ({ id, anneescolaire, niveau, refs }) => {
let TotalNoteNumberRepech = 0 let TotalNoteNumberRepech = 0
totalNotes.forEach((notes) => { totalNotes.forEach((notes) => {
TotalNoteNumber += Number(notes.textContent / totalNotes.length) TotalNoteNumber += Number(notes.textContent) / totalNotes.length
// console.log(notes.textContent);
}) })
totalNotesRepech.forEach((notes) => { totalNotesRepech.forEach((notes) => {
TotalNoteNumberRepech += Number(notes.textContent / totalNotes.length) TotalNoteNumberRepech += Number(notes.textContent) / totalNotesRepech.length
// console.log(notes.textContent);
}) })
let note = Math.max(TotalNoteNumber, TotalNoteNumberRepech) // Retourner la note selon le type de session
if (sessionType === 'normale') {
return note 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) const [note, setNote] = useState(0)
useEffect(() => { useEffect(() => {
setNote(totalNotes()) setNote(totalNotes())
}, [TbodyContent]) }, [TbodyContent, sessionType])
return ( return (
<div className={classe.mainHome}> <div className={classe.mainHome}>
@ -391,9 +429,8 @@ const ReleverNotes = ({ id, anneescolaire, niveau, refs }) => {
<div style={{ display: 'flex', justifyContent: 'center' }}> <div style={{ display: 'flex', justifyContent: 'center' }}>
<Paper <Paper
sx={{ sx={{
// width: "100%", height: 'auto',
height: 'auto', // Auto height to make the grid responsive minHeight: 500,
minHeight: 500, // Ensures a minimum height
display: 'flex', display: 'flex',
padding: '1%', padding: '1%',
width: '70%', width: '70%',
@ -425,7 +462,7 @@ const ReleverNotes = ({ id, anneescolaire, niveau, refs }) => {
</span> </span>
<br /> <br />
<span> <span>
<b>Prenom</b> <b>Prénom</b>
</span> </span>
<br /> <br />
<span> <span>
@ -480,7 +517,7 @@ const ReleverNotes = ({ id, anneescolaire, niveau, refs }) => {
<tr style={{ borderTop: 'solid 1px black', textAlign: 'center' }}> <tr style={{ borderTop: 'solid 1px black', textAlign: 'center' }}>
<th colSpan={3}></th> <th colSpan={3}></th>
<th <th
colSpan={4} colSpan={sessionType === 'ensemble' ? 4 : 2}
style={{ style={{
background: '#bdbcbc', background: '#bdbcbc',
borderLeft: 'solid 1px black', borderLeft: 'solid 1px black',
@ -495,18 +532,25 @@ const ReleverNotes = ({ id, anneescolaire, niveau, refs }) => {
<th style={{ borderLeft: 'solid 1px black' }}></th> <th style={{ borderLeft: 'solid 1px black' }}></th>
<th style={{ borderLeft: 'solid 1px black' }}></th> <th style={{ borderLeft: 'solid 1px black' }}></th>
<th style={{ borderLeft: 'solid 1px black' }}></th> <th style={{ borderLeft: 'solid 1px black' }}></th>
<th
colSpan={2} {sessionType !== 'rattrapage' && (
style={{ background: '#bdbcbc', borderLeft: 'solid 1px black' }} <th
> colSpan={shouldShowCredits() ? 2 : 1}
Normale style={{ background: '#bdbcbc', borderLeft: 'solid 1px black' }}
</th> >
<th Normale
colSpan={2} </th>
style={{ background: '#bdbcbc', borderLeft: 'solid 1px black' }} )}
>
Rattrapage {sessionType !== 'normale' && (
</th> <th
colSpan={shouldShowCredits() ? 2 : 1}
style={{ background: '#bdbcbc', borderLeft: 'solid 1px black' }}
>
Rattrapage
</th>
)}
<th <th
style={{ borderLeft: 'solid 1px black', borderRight: 'solid 1px black' }} style={{ borderLeft: 'solid 1px black', borderRight: 'solid 1px black' }}
></th> ></th>
@ -514,7 +558,6 @@ const ReleverNotes = ({ id, anneescolaire, niveau, refs }) => {
<tr <tr
style={{ style={{
borderTop: 'solid 1px black', borderTop: 'solid 1px black',
// borderBottom: 'solid 1px black',
background: '#bdbcbc', background: '#bdbcbc',
textAlign: 'center' textAlign: 'center'
}} }}
@ -524,10 +567,21 @@ const ReleverNotes = ({ id, anneescolaire, niveau, refs }) => {
</th> </th>
<th style={{ borderLeft: 'solid 1px black' }}>UE</th> <th style={{ borderLeft: 'solid 1px black' }}>UE</th>
<th style={{ borderLeft: 'solid 1px black' }}>EC</th> <th style={{ borderLeft: 'solid 1px black' }}>EC</th>
<th style={{ borderLeft: 'solid 1px black', padding: '0 5px' }}>crédit</th>
<th style={{ borderLeft: 'solid 1px black', padding: '0 5px' }}>Notes</th> {sessionType !== 'rattrapage' && (
<th style={{ borderLeft: 'solid 1px black', padding: '0 5px' }}>crédit</th> <>
<th style={{ borderLeft: 'solid 1px black', padding: '0 5px' }}>Notes</th> <th style={{ borderLeft: 'solid 1px black', padding: '0 5px' }}>crédit</th>
<th style={{ borderLeft: 'solid 1px black', padding: '0 5px' }}>Notes</th>
</>
)}
{sessionType !== 'normale' && (
<>
<th style={{ borderLeft: 'solid 1px black', padding: '0 5px' }}>crédit</th>
<th style={{ borderLeft: 'solid 1px black', padding: '0 5px' }}>Notes</th>
</>
)}
<th style={{ borderLeft: 'solid 1px black', borderRight: 'solid 1px black' }}> <th style={{ borderLeft: 'solid 1px black', borderRight: 'solid 1px black' }}>
Observation Observation
</th> </th>
@ -548,7 +602,7 @@ const ReleverNotes = ({ id, anneescolaire, niveau, refs }) => {
</td> </td>
<td style={{ borderRight: 'solid 1px black' }}>{note.toFixed(2)}</td> <td style={{ borderRight: 'solid 1px black' }}>{note.toFixed(2)}</td>
<td style={{ borderRight: 'solid 1px black' }}>/20</td> <td style={{ borderRight: 'solid 1px black' }}>/20</td>
<td colSpan={4}></td> <td colSpan={sessionType === 'ensemble' ? 3 : 2}></td>
</tr> </tr>
<tr style={{ border: 'solid 1px black' }}> <tr style={{ border: 'solid 1px black' }}>
<td <td
@ -562,11 +616,8 @@ const ReleverNotes = ({ id, anneescolaire, niveau, refs }) => {
Mention:{' '} Mention:{' '}
<span style={{ marginLeft: '3%' }}>{getmentionAfterNotes(note)}</span> <span style={{ marginLeft: '3%' }}>{getmentionAfterNotes(note)}</span>
</td> </td>
<td colSpan={5} style={{ textAlign: 'left', paddingLeft: '1%' }}> <td colSpan={sessionType === 'ensemble' ? 4 : 3} style={{ textAlign: 'left', paddingLeft: '1%' }}>
Décision du Jury:{' '} Décision du Jury:{' '}
<span style={{ marginLeft: '3%' }}>
{descisionJury(note, etudiant.niveau)}
</span>
</td> </td>
</tr> </tr>
</tbody> </tbody>

560
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 classe from '../assets/AllStyleComponents.module.css'
import classeHome from '../assets/Home.module.css' import classeHome from '../assets/Home.module.css'
import Paper from '@mui/material/Paper' 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 { IoMdReturnRight } from 'react-icons/io'
import jsPDF from 'jspdf' import jsPDF from 'jspdf'
import autoTable from 'jspdf-autotable' import autoTable from 'jspdf-autotable'
@ -20,10 +20,18 @@ const Resultat = () => {
const [etudiants, setEtudiants] = useState([]) const [etudiants, setEtudiants] = useState([])
const [mention, setMention] = useState([]) const [mention, setMention] = useState([])
const [session, setSession] = 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(() => { useEffect(() => {
window.notes.getMoyenne(formData).then((response) => { window.notes.getMoyenne(formData).then((response) => {
setEtudiants(response) setEtudiants(response)
extractMatieresAndUEs(response)
}) })
window.noteRepech.getMoyenneRepech(formData).then((response) => { window.noteRepech.getMoyenneRepech(formData).then((response) => {
setSession(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 = [] let dataToMap = []
function returnmention(id) { function returnmention(id) {
@ -45,6 +75,18 @@ const Resultat = () => {
return mentions 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) { function checkNull(params) {
if (params == null || params == undefined) { if (params == null || params == undefined) {
return null return null
@ -52,51 +94,6 @@ const Resultat = () => {
return params 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) { function compareSessionNotes(session1, session2) {
let notes let notes
if (session2) { if (session2) {
@ -111,12 +108,13 @@ const Resultat = () => {
return notes return notes
} }
// Traitement des données pour résultat définitif - INCLUANT TOUS LES ÉTUDIANTS
for (let index = 0; index < etudiants.length; index++) { for (let index = 0; index < etudiants.length; index++) {
let total = 0 let total = 0
let note = 0 let note = 0
let totalCredit = 0 let totalCredit = 0
let hasValidNotes = false
// Create a new object for each student
let modelJson = { let modelJson = {
id: '', id: '',
nom: '', nom: '',
@ -135,29 +133,389 @@ const Resultat = () => {
modelJson.mention = etudiants[index][j].mention_id modelJson.mention = etudiants[index][j].mention_id
modelJson.anneescolaire = etudiants[index][j].annee_scolaire modelJson.anneescolaire = etudiants[index][j].annee_scolaire
// console.log(checkNull(session[index][j])); let currentNote = etudiants[index][j].note
if (session[index]) { if (session[index]) {
note += currentNote = compareSessionNotes(etudiants[index][j].note, checkNull(session[index][j]))
compareSessionNotes(etudiants[index][j].note, checkNull(session[index][j])) * }
etudiants[index][j].credit
} else { // Vérifier si l'étudiant a des notes valides
note += etudiants[index][j].note * etudiants[index][j].credit if (currentNote != null && currentNote != undefined && !isNaN(currentNote)) {
note += currentNote * etudiants[index][j].credit
totalCredit += etudiants[index][j].credit
hasValidNotes = true
} }
totalCredit += etudiants[index][j].credit
} }
total = note / totalCredit // Calculer la moyenne même si certaines notes manquent
modelJson.moyenne = total.toFixed(2) if (hasValidNotes && totalCredit > 0) {
total = note / totalCredit
modelJson.moyenne = total.toFixed(2)
} else {
modelJson.moyenne = 'N/A'
}
// Add the new object to the array
dataToMap.push(modelJson) dataToMap.push(modelJson)
} }
const sortedStudents = dataToMap // Fonction pour obtenir les résultats par matière sélectionnée
.filter((student) => parseFloat(student.moyenne) >= 10) const getResultsByMatiere = () => {
.sort((a, b) => parseFloat(b.moyenne) - parseFloat(a.moyenne)) 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])
}
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)
console.log(sortedStudents) 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 = () => (
<div
style={{
display: 'flex',
alignItems: 'flex-start',
justifyContent: 'space-between',
marginBottom: '20px',
position: 'relative'
}}
>
<img src={logoRelerev2} alt="Logo gauche" width={90} height={90} />
<div
style={{
position: 'absolute',
left: '50%',
transform: 'translateX(-50%)',
textAlign: 'center',
fontSize: '10px',
lineHeight: '1.2'
}}
>
<div style={{ fontWeight: 'bold' }}>REPOBLIKAN'I MADAGASIKARA</div>
<div style={{ fontStyle: 'italic' }}>Fitiavana-Tanindrazana-Fandrosoana</div>
<div>********************</div>
<div style={{ fontWeight: 'bold' }}>MINISTÈRE DE L'ENSEIGNEMENT SUPÉRIEUR</div>
<div style={{ fontWeight: 'bold' }}>ET DE LA RECHERCHE SCIENTIFIQUE</div>
<div>********************</div>
<div style={{ fontWeight: 'bold' }}>UNIVERSITÉ DE TOAMASINA</div>
<div style={{ fontWeight: 'bold' }}>ÉCOLE SUPÉRIEURE POLYTECHNIQUE</div>
</div>
<img src={logoRelerev1} alt="Logo droite" width={110} height={90} />
</div>
)
const renderResultDefinitif = () => (
<table
className="table table-bordered table-striped text-center shadow-sm"
id="resultTable"
style={{ fontSize: '12px' }}
>
<thead className="table-secondary">
<tr>
<td colSpan={5} className="py-3" style={{ backgroundColor: '#f8f9fa' }}>
<h6 style={{ margin: 0, fontWeight: 'bold' }}>
Résultat Définitif : {niveau} admis en {niveau === 'L1' ? 'L2' : niveau === 'L2' ? 'L3' : 'Master'} par ordre de mérite
</h6>
</td>
</tr>
<tr style={{ backgroundColor: '#e9ecef' }}>
<th style={{ width: '10%', fontWeight: 'bold' }}>RANG</th>
<th style={{ width: '25%', fontWeight: 'bold' }}>NOMS</th>
<th style={{ width: '30%', fontWeight: 'bold' }}>PRÉNOMS</th>
<th style={{ width: '15%', fontWeight: 'bold' }}>Moyenne</th>
<th style={{ width: '20%', fontWeight: 'bold' }}>Mention</th>
</tr>
</thead>
<tbody>
{sortedStudents.map((sorted, index) => (
<tr key={sorted.id}>
<td style={{ fontWeight: 'bold' }}>{index + 1}.</td>
<td style={{ textAlign: 'left', paddingLeft: '10px', fontWeight: 'bold' }}>{sorted.nom}</td>
<td style={{ textAlign: 'left', paddingLeft: '10px' }}>{sorted.prenom}</td>
<td style={{ fontWeight: 'bold' }}>{sorted.moyenne}</td>
<td style={{ fontWeight: 'bold' }}>
{sorted.moyenne !== 'N/A' ? getMentionFromMoyenne(sorted.moyenne) : 'N/A'}
</td>
</tr>
))}
</tbody>
</table>
)
const renderResultParMatiere = () => {
const results = getResultsByMatiere()
return (
<>
<div style={{ marginBottom: '20px' }}>
<FormControl fullWidth>
<InputLabel>Sélectionner une matière</InputLabel>
<Select
value={selectedMatiere}
onChange={(e) => setSelectedMatiere(e.target.value)}
label="Sélectionner une matière"
>
{availableMatieres.map((matiere) => (
<MenuItem key={matiere} value={matiere}>
{matiere}
</MenuItem>
))}
</Select>
</FormControl>
</div>
<table
className="table table-bordered table-striped text-center shadow-sm"
id="subjectTable"
style={{ fontSize: '12px' }}
>
<thead className="table-secondary">
<tr>
<td colSpan={4} className="py-3" style={{ backgroundColor: '#f8f9fa' }}>
<h6 style={{ margin: 0, fontWeight: 'bold' }}>
Résultat pour la matière : {selectedMatiere}
</h6>
</td>
</tr>
<tr style={{ backgroundColor: '#e9ecef' }}>
<th style={{ width: '10%', fontWeight: 'bold' }}>RANG</th>
<th style={{ width: '30%', fontWeight: 'bold' }}>NOMS</th>
<th style={{ width: '40%', fontWeight: 'bold' }}>PRÉNOMS</th>
<th style={{ width: '20%', fontWeight: 'bold' }}>NOTE</th>
</tr>
</thead>
<tbody>
{results.map((item, index) => (
<tr key={item.id}>
<td style={{ fontWeight: 'bold' }}>{index + 1}.</td>
<td style={{ textAlign: 'left', paddingLeft: '10px', fontWeight: 'bold' }}>{item.nom}</td>
<td style={{ textAlign: 'left', paddingLeft: '10px' }}>{item.prenom}</td>
<td style={{ fontWeight: 'bold' }}>{item.note}</td>
</tr>
))}
</tbody>
</table>
</>
)
}
const renderResultParUE = () => {
const { students, matieres } = getResultsByUE()
return (
<>
<div style={{ marginBottom: '20px' }}>
<FormControl fullWidth>
<InputLabel>Sélectionner une UE</InputLabel>
<Select
value={selectedUE}
onChange={(e) => setSelectedUE(e.target.value)}
label="Sélectionner une UE"
>
{availableUEs.map((ue) => (
<MenuItem key={ue} value={ue}>
{ue}
</MenuItem>
))}
</Select>
</FormControl>
</div>
<table
className="table table-bordered table-striped text-center shadow-sm"
id="ueTable"
style={{ fontSize: '12px' }}
>
<thead className="table-secondary">
<tr>
<td colSpan={3 + matieres.length} className="py-3" style={{ backgroundColor: '#f8f9fa' }}>
<h6 style={{ margin: 0, fontWeight: 'bold' }}>
Résultat pour l'UE : {selectedUE}
</h6>
</td>
</tr>
<tr style={{ backgroundColor: '#e9ecef' }}>
<th style={{ fontWeight: 'bold' }}>RANG</th>
<th style={{ fontWeight: 'bold' }}>NOMS</th>
<th style={{ fontWeight: 'bold' }}>PRÉNOMS</th>
{matieres.map((matiere) => (
<th key={matiere} style={{ fontWeight: 'bold' }}>{matiere}</th>
))}
<th style={{ fontWeight: 'bold' }}>MOYENNE UE</th>
</tr>
</thead>
<tbody>
{students.map((student, index) => (
<tr key={student.id}>
<td style={{ fontWeight: 'bold' }}>{index + 1}.</td>
<td style={{ textAlign: 'left', paddingLeft: '10px', fontWeight: 'bold' }}>{student.nom}</td>
<td style={{ textAlign: 'left', paddingLeft: '10px' }}>{student.prenom}</td>
{matieres.map((matiere) => (
<td key={matiere} style={{ fontWeight: 'bold' }}>
{student.matieres[matiere] || 'N/A'}
</td>
))}
<td style={{ fontWeight: 'bold', backgroundColor: '#fff3cd' }}>{student.moyenneUE}</td>
</tr>
))}
</tbody>
</table>
</>
)
}
return ( return (
<div className={classe.mainHome}> <div className={classe.mainHome}>
@ -194,80 +552,28 @@ const Resultat = () => {
padding: '2%' padding: '2%'
}} }}
> >
{/* En-tête avec logos et texte */} {renderHeader()}
<div
style={{
display: 'flex',
alignItems: 'flex-start',
justifyContent: 'space-between',
marginBottom: '20px',
position: 'relative'
}}
>
<img src={logoRelerev1} alt="Logo gauche" width={70} />
{/* Texte centré entre les logos */}
<div
style={{
position: 'absolute',
left: '50%',
transform: 'translateX(-50%)',
textAlign: 'center',
fontSize: '10px',
lineHeight: '1.2'
}}
>
<div style={{ fontWeight: 'bold' }}>REPOBLIKAN'I MADAGASIKARA</div>
<div style={{ fontStyle: 'italic' }}>Fitiavana-Tanindrazana-Fandrosoana</div>
<div>********************</div>
<div style={{ fontWeight: 'bold' }}>MINISTÈRE DE L'ENSEIGNEMENT SUPÉRIEUR</div>
<div style={{ fontWeight: 'bold' }}>ET DE LA RECHERCHE SCIENTIFIQUE</div>
<div>********************</div>
<div style={{ fontWeight: 'bold' }}>UNIVERSITÉ DE TOAMASINA</div>
<div style={{ fontWeight: 'bold' }}>ÉCOLE SUPÉRIEURE POLYTECHNIQUE</div>
</div>
<img src={logoRelerev2} alt="Logo droite" width={90} height={90} />
</div>
{/* Informations du parcours */}
<div style={{ marginBottom: '15px', fontSize: '12px' }}> <div style={{ marginBottom: '15px', fontSize: '12px' }}>
<div><strong>Parcours :</strong> GC</div> <div><strong>Parcours :</strong> GC</div>
<div><strong>Niveau :</strong> {niveau}</div> <div><strong>Niveau :</strong> {niveau}</div>
<div><strong>Année Universitaire :</strong> {scolaire}</div> <div><strong>Année Universitaire :</strong> {scolaire}</div>
</div> </div>
<table <Tabs
className="table table-bordered table-striped text-center shadow-sm" value={tabValue}
id="myTable2" onChange={handleTabChange}
style={{ fontSize: '12px' }} centered
sx={{ marginBottom: '20px' }}
> >
<thead className="table-secondary"> <Tab label="Résultat Définitif" />
<tr> <Tab label="Par Matière" />
<td colSpan={4} className="py-3" style={{ backgroundColor: '#f8f9fa' }}> <Tab label="Par UE" />
<h6 style={{ margin: 0, fontWeight: 'bold' }}> </Tabs>
Résultat de la Deuxième Session : {niveau} admis en L3 par ordre de mérite
</h6> {tabValue === 0 && renderResultDefinitif()}
</td> {tabValue === 1 && renderResultParMatiere()}
</tr> {tabValue === 2 && renderResultParUE()}
<tr style={{ backgroundColor: '#e9ecef' }}>
<th style={{ width: '10%', fontWeight: 'bold' }}>RANG</th>
<th style={{ width: '30%', fontWeight: 'bold' }}>NOMS</th>
<th style={{ width: '40%', fontWeight: 'bold' }}>PRÉNOMS</th>
<th style={{ width: '20%', fontWeight: 'bold' }}>Moyenne</th>
</tr>
</thead>
<tbody>
{sortedStudents.map((sorted, index) => (
<tr key={sorted.id}>
<td style={{ fontWeight: 'bold' }}>{index + 1}.</td>
<td style={{ textAlign: 'left', paddingLeft: '10px', fontWeight: 'bold' }}>{sorted.nom}</td>
<td style={{ textAlign: 'left', paddingLeft: '10px' }}>{sorted.prenom}</td>
<td style={{ fontWeight: 'bold' }}>{sorted.moyenne}</td>
</tr>
))}
</tbody>
</table>
</Paper> </Paper>
</div> </div>
</div> </div>

82
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 classe from '../assets/Sidenav.module.css'
import { RiDashboardHorizontalFill } from 'react-icons/ri' import { RiDashboardHorizontalFill } from 'react-icons/ri'
import { PiStudentFill } from 'react-icons/pi' import { PiStudentFill } from 'react-icons/pi'
@ -21,8 +21,27 @@ import { FaClipboardList } from 'react-icons/fa6'
const Sidenav = () => { const Sidenav = () => {
const [anchorEl, setAnchorEl] = useState(null) const [anchorEl, setAnchorEl] = useState(null)
const [userRole, setUserRole] = useState(null)
const open = Boolean(anchorEl) const open = Boolean(anchorEl)
const { setToken } = useAuthContext() 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) => { const handleClick = (event) => {
setAnchorEl(event.currentTarget) setAnchorEl(event.currentTarget)
@ -40,6 +59,11 @@ const Sidenav = () => {
setToken(null) 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 ( return (
<nav className={classe.navbar}> <nav className={classe.navbar}>
<style> <style>
@ -82,21 +106,26 @@ const Sidenav = () => {
</Tooltip> </Tooltip>
</Link> </Link>
</li> </li>
<li>
<Link {/* Navigation Notes - Visible uniquement pour les admins */}
to={'/notes'} {isAdmin() && (
className={classe.nav_link} <li>
style={{ <Link
outline: 'none', to={'/notes'}
borderBottom: window.location.hash == '#/notes' ? '2px solid white' : 'none' className={classe.nav_link}
}} style={{
> outline: 'none',
<CgNotes className="notes" style={{ outline: 'none' }} /> borderBottom: window.location.hash == '#/notes' ? '2px solid white' : 'none'
<Tooltip anchorSelect=".notes" className="custom-tooltip" place="top"> }}
Notes >
</Tooltip> <CgNotes className="notes" style={{ outline: 'none' }} />
</Link> <Tooltip anchorSelect=".notes" className="custom-tooltip" place="top">
</li> Notes
</Tooltip>
</Link>
</li>
)}
<li> <li>
<Link <Link
to={'/mention'} to={'/mention'}
@ -153,7 +182,7 @@ const Sidenav = () => {
> >
<BsCalendar2Date className="anneescolaire" style={{ outline: 'none' }} /> <BsCalendar2Date className="anneescolaire" style={{ outline: 'none' }} />
<Tooltip anchorSelect=".anneescolaire" className="custom-tooltip" place="top"> <Tooltip anchorSelect=".anneescolaire" className="custom-tooltip" place="top">
Année Scolaire Année Univesitaire
</Tooltip> </Tooltip>
</Link> </Link>
</li> </li>
@ -187,17 +216,6 @@ const Sidenav = () => {
</Tooltip> </Tooltip>
</Link> </Link>
</li> </li>
{/* <li>
<Link to={'/manual'} className={classe.nav_link} style={{
outline: 'none',
borderBottom: window.location.hash == '#/manual' ? '2px solid white' : 'none'
}}>
<GrManual className='manual' style={{ outline: 'none' }} />
<Tooltip anchorSelect=".manual" className='custom-tooltip' place="top">
Manuel d'utilisation
</Tooltip>
</Link>
</li> */}
</ul> </ul>
<ul className={classe.liste2}> <ul className={classe.liste2}>
<li> <li>
@ -261,14 +279,6 @@ const Sidenav = () => {
</MenuItem> </MenuItem>
</Menu> </Menu>
</li> </li>
{/* <li>
<Link to={'/teste'}>
<SiVitest className='test' style={{outline:'none'}} />
<Tooltip anchorSelect=".test" className='custom-tooltip' place="top">
Teste
</Tooltip>
</Link>
</li> */}
<li> <li>
<LuLogOut className="logout" style={{ outline: 'none' }} onClick={logout} /> <LuLogOut className="logout" style={{ outline: 'none' }} onClick={logout} />
<Tooltip anchorSelect=".logout" className="custom-tooltip" place="top"> <Tooltip anchorSelect=".logout" className="custom-tooltip" place="top">

6
src/renderer/src/components/SingleAnneeScolaire.jsx

@ -121,7 +121,7 @@ const SingleAnneeScolaire = () => {
<div className={classeHome.blockTitle}> <div className={classeHome.blockTitle}>
<h1 style={{ display: 'flex', alignItems: 'center', gap: '10px' }}> <h1 style={{ display: 'flex', alignItems: 'center', gap: '10px' }}>
<BsCalendar2Date /> <BsCalendar2Date />
Mise a jour Année Scolaire Mise a jour Année Univesitaire
</h1> </h1>
<Link to={'#'} onClick={() => window.history.back()}> <Link to={'#'} onClick={() => window.history.back()}>
<Button color="warning" variant="contained"> <Button color="warning" variant="contained">
@ -155,12 +155,12 @@ const SingleAnneeScolaire = () => {
onSubmit={formSubmit} onSubmit={formSubmit}
> >
<h4 style={{ textAlign: 'center', padding: '0 0 3% 0' }}> <h4 style={{ textAlign: 'center', padding: '0 0 3% 0' }}>
mise a jour Année Scolaire mise a jour Année Univesitaire
</h4> </h4>
<Grid container spacing={2}> <Grid container spacing={2}>
<Grid item xs={12} sm={6}> <Grid item xs={12} sm={6}>
<TextField <TextField
label={'Année Scolaire'} label={'Année Univesitaire'}
name={'code'} name={'code'}
placeholder="2024-2025" placeholder="2024-2025"
color="warning" color="warning"

8
src/renderer/src/components/SingleEtudiant.jsx

@ -535,12 +535,12 @@ const SingleEtudiant = () => {
</Grid> </Grid>
</Grid> </Grid>
{/* Group Année Scolaire and Numero d'Inscription */} {/* Group Année Univesitaire and Numero d'Inscription */}
<Grid container spacing={2}> <Grid container spacing={2}>
<Grid item xs={6}> <Grid item xs={6}>
<TextField <TextField
fullWidth fullWidth
label="Année Scolaire" label="Année Univesitaire"
name="annee_scolaire" name="annee_scolaire"
color="warning" color="warning"
defaultValue={etudiant.annee_scolaire} // Controlled component value defaultValue={etudiant.annee_scolaire} // Controlled component value
@ -813,7 +813,7 @@ const SingleEtudiant = () => {
</Grid> </Grid>
</Grid> </Grid>
{/* Group Année Scolaire and Numero d'Inscription */} {/* Group Année Univesitaire and Numero d'Inscription */}
<Grid container spacing={2}> <Grid container spacing={2}>
<Grid item xs={6}> <Grid item xs={6}>
<TextField <TextField
@ -1111,7 +1111,7 @@ const SingleEtudiant = () => {
variant="h6" variant="h6"
style={{ display: 'flex', justifyContent: 'space-between' }} style={{ display: 'flex', justifyContent: 'space-between' }}
> >
<span>Année Scolaire:</span> {etudiant.annee_scolaire} <span>Année Univesitaire:</span> {etudiant.annee_scolaire}
</Typography> </Typography>
</Grid> </Grid>
<Grid item xs={12}> <Grid item xs={12}>

21
src/renderer/src/components/Student.jsx

@ -26,8 +26,18 @@ import { processPdf } from './function/PDFEditorV2'
import { MdVerified } from 'react-icons/md' import { MdVerified } from 'react-icons/md'
import warning from '../assets/warning.svg' import warning from '../assets/warning.svg'
import success from '../assets/success.svg' import success from '../assets/success.svg'
import { useAuthContext } from '../contexts/AuthContext' // Import du contexte d'authentification
const Student = () => { const Student = () => {
// Récupération de l'utilisateur connecté
const { user } = useAuthContext()
// Fonction pour vérifier si l'utilisateur est admin
const isAdmin = () => {
console.log('Rôle de l\'utilisateur dans Student:', user?.roles)
return user?.roles?.toLowerCase() === 'admin'
}
const theme = createTheme({ const theme = createTheme({
components: { components: {
MuiIconButton: { MuiIconButton: {
@ -251,7 +261,7 @@ const Student = () => {
*/ */
const columns = [ const columns = [
{ field: 'nom', headerName: 'Nom', width: 180 }, { field: 'nom', headerName: 'Nom', width: 180 },
{ field: 'prenom', headerName: 'Prenom', width: 180 }, { field: 'prenom', headerName: 'Prénom', width: 180 },
{ field: 'sexe', headerName: 'Sexe', width: 80 }, { field: 'sexe', headerName: 'Sexe', width: 80 },
{ field: 'cin', headerName: 'CIN', width: 180 }, { field: 'cin', headerName: 'CIN', width: 180 },
{ field: 'date_deli', headerName: 'Date de delivrance', width: 80 }, { field: 'date_deli', headerName: 'Date de delivrance', width: 80 },
@ -337,7 +347,9 @@ const Student = () => {
> >
{/* Groupe 1 : Certificat */} {/* Groupe 1 : Certificat */}
<Link style={{ display: 'flex', gap: '10px' }}> <Link style={{ display: 'flex', gap: '10px' }}>
<SeeNote params={params} /> {/* Affichage conditionnel de SeeNote - uniquement pour les admins */}
{isAdmin() && <SeeNote params={params} />}
<Link> <Link>
<Button <Button
onClick={() => handleOpen(params.value)} onClick={() => handleOpen(params.value)}
@ -435,8 +447,8 @@ const Student = () => {
if (etudiant) { if (etudiant) {
let data = { let data = {
f1: `${etudiant.nom} ${etudiant.prenom}`, f1: `${etudiant.nom} ${etudiant.prenom}`,
f2: `Naissances: ${dayjs(etudiant.date_de_naissances).format('DD-MM-YYYY')}`, f2: `Naissance: ${dayjs(etudiant.date_de_naissances).format('DD-MM-YYYY')}`,
f3: `Niveau: ${etudiant.niveau}`, f3: `Niveau: ${etudiant.niveau} ${etudiant.mentionUnite}`,
f4: `Année: ${etudiant.annee_scolaire}`, f4: `Année: ${etudiant.annee_scolaire}`,
f5: `Inscription: ${etudiant.num_inscription}`, f5: `Inscription: ${etudiant.num_inscription}`,
f8: etudiant.photos f8: etudiant.photos
@ -488,6 +500,7 @@ const Student = () => {
domaine: etudiant.domaine, domaine: etudiant.domaine,
contact: etudiant.contact, contact: etudiant.contact,
mention_id: etudiant.mention_id, mention_id: etudiant.mention_id,
mentionUnite: etudiant.mentionUnite,
action: etudiant.id // Ensure this is a valid URL for the image action: etudiant.id // Ensure this is a valid URL for the image
})) }))

8
src/renderer/src/components/SystemeNote.jsx

@ -221,8 +221,8 @@ const SystemeNote = () => {
<tr style={{ fontWeight: 'bold' }}> <tr style={{ fontWeight: 'bold' }}>
<td style={{ color: 'gray' }}>Status :</td> <td style={{ color: 'gray' }}>Status :</td>
<td style={{ color: 'gray' }}>Admis</td> <td style={{ color: 'gray' }}>Admis</td>
<td style={{ color: 'gray' }}>Redouble</td> <td style={{ color: 'gray' }}>Autorisé à redoubler</td>
<td style={{ color: 'gray' }}>Renvoyer</td> <td style={{ color: 'gray' }}>Remis à la famille</td>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@ -271,7 +271,7 @@ const SystemeNote = () => {
{/* <Grid container spacing={2}> */} {/* <Grid container spacing={2}> */}
<Grid item xs={12} sm={3}> <Grid item xs={12} sm={3}>
<TextField <TextField
label={'Notes pour redoubler'} label={'Notes pour autorisé à redoubler'}
name={'redouble'} name={'redouble'}
color="warning" color="warning"
fullWidth fullWidth
@ -310,7 +310,7 @@ const SystemeNote = () => {
{/* <Grid container spacing={2}> */} {/* <Grid container spacing={2}> */}
<Grid item xs={12} sm={3}> <Grid item xs={12} sm={3}>
<TextField <TextField
label={'Notes pour etre renvoyer'} label={'Notes pour etre remis à la famille'}
name={'renvoyer'} name={'renvoyer'}
color="warning" color="warning"
fullWidth fullWidth

4
src/renderer/src/components/TesteDatagrid.jsx

@ -248,11 +248,11 @@ const TesteDatagrid = ({ id, niveau, annee_scolaire, nomPrenom, inscription, ref
</div> </div>
</div> </div>
<div style={{ fontSize: '13px', margin: '1%' }}> <div style={{ fontSize: '13px', margin: '1%' }}>
<span>Nom & Prenoms: </span> <span>Nom & Prénoms: </span>
<span>{nomPrenom}</span> <span>{nomPrenom}</span>
<br /> <br />
<div style={{ display: 'flex', justifyContent: 'space-between' }}> <div style={{ display: 'flex', justifyContent: 'space-between' }}>
<span>Année scolaire: </span> <span>Année Univesitaire: </span>
<span>{annee_scolaire}</span> <span>{annee_scolaire}</span>
<span>Niveau: </span> <span>Niveau: </span>
<span>{niveau}</span> <span>{niveau}</span>

4
src/renderer/src/components/UpdateModalProf.jsx

@ -96,10 +96,10 @@ const UpdateModalProf = ({ open, onClose, matiere_id, onSubmitSuccess }) => {
margin="normal" margin="normal"
required required
name="prenom_enseignant" name="prenom_enseignant"
label="Prenom du professeur" label="Prénom du professeur"
type="text" type="text"
fullWidth fullWidth
placeholder="Prenom du professeur" placeholder="Prénom du professeur"
variant="outlined" variant="outlined"
value={formData.prenom_enseignant} value={formData.prenom_enseignant}
color="warning" color="warning"

6
src/renderer/src/components/function/PDFEditor.js

@ -21,7 +21,7 @@ const PDFEditor = async (data) => {
form.getTextField('name').setText(data.f1) form.getTextField('name').setText(data.f1)
form.getTextField('birthday').setText('Date de naissance: ' + data.f2) form.getTextField('birthday').setText('Date de naissance: ' + data.f2)
form.getTextField('niveau').setText('Niveau: ' + data.f3) form.getTextField('niveau').setText('Niveau: ' + data.f3)
form.getTextField('annee').setText('Année scolaire: ' + data.f4) form.getTextField('annee').setText('Année Univesitaire: ' + data.f4)
form.getTextField('num_inscription').setText("Numéro d'inscription: " + data.f5) form.getTextField('num_inscription').setText("Numéro d'inscription: " + data.f5)
form.flatten() form.flatten()
@ -73,10 +73,10 @@ const PDFEditor = async (data) => {
// ----------------------------------------------- carte arriere ------------------------------------------- // ----------------------------------------------- carte arriere -------------------------------------------
const paperContent = ` const paperContent = `
CUniversity CUniversity
Nom et prenom: ${data.f1} Nom et prénom: ${data.f1}
Date de naissance: ${data.f2} Date de naissance: ${data.f2}
Niveau: ${data.f3} Niveau: ${data.f3}
Année scolaire: ${data.f4} Année Univesitaire: ${data.f4}
Numéro d'inscription: ${data.f5} Numéro d'inscription: ${data.f5}
` `

69
src/renderer/src/components/function/PDFEditorV2.js

@ -14,28 +14,49 @@ async function fillPdfFields(jsonData) {
// Get the first page to draw text on // Get the first page to draw text on
const page = pdfDoc.getPage(0) const page = pdfDoc.getPage(0)
const form = pdfDoc.getForm()
const nameField = form.getTextField('name')
nameField.setText(jsonData.f1 || '')
const birthdayField = form.getTextField('birthday')
birthdayField.setText(jsonData.f2 || '')
const niveauField = form.getTextField('niveau')
niveauField.setText(jsonData.f3 || '')
const anneeField = form.getTextField('annee')
anneeField.setText(jsonData.f4 || '')
const num_inscriptionField = form.getTextField('num_inscription')
num_inscriptionField.setText(jsonData.f5 || '')
console.log('namefield:', nameField.getText())
console.log('namefield:', birthdayField.getText())
console.log('namefield:', niveauField.getText())
console.log('namefield:', anneeField.getText())
console.log('namefield:', num_inscriptionField.getText())
// Define positions for text (adjust these coordinates based on your red dots) // Define positions for text (adjust these coordinates based on your red dots)
const textPositions = [ // const textPositions = [
{ x: 45, y: 92, text: `${jsonData.f1 || ''}`, fontSize: 10 }, // Nom et prénom // { x: 45, y: 92, text: `${jsonData.f1 || ''}`, fontSize: 10 }, // Nom et prénom
{ x: 45, y: 75, text: `${jsonData.f2 || ''}`, fontSize: 10 }, // Date de naissance // { x: 45, y: 75, text: `${jsonData.f2 || ''}`, fontSize: 10 }, // Date de naissance
{ x: 45, y: 58, text: `${jsonData.f3 || ''}`, fontSize: 10 }, // Niveau // { x: 45, y: 58, text: `${jsonData.f3 || ''}`, fontSize: 10 }, // Niveau
{ x: 45, y: 38, text: `${jsonData.f4 || ''}`, fontSize: 10 }, // Année scolaire // { x: 45, y: 38, text: `${jsonData.f4 || ''}`, fontSize: 10 }, // Année Univesitaire
{ x: 60, y: 23, text: `${jsonData.f5 || ''}`, fontSize: 10 } // Numéro d'inscription // { x: 60, y: 23, text: `${jsonData.f5 || ''}`, fontSize: 10 } // Numéro d'inscription
] // ]
// Draw text at specified positions // Draw text at specified positions
textPositions.forEach((item, index) => { // textPositions.forEach((item, index) => {
if (item.text.trim()) { // if (item.text.trim()) {
page.drawText(item.text, { // page.drawText(item.text, {
x: item.x, // x: item.x,
y: item.y, // y: item.y,
size: item.fontSize - 2, // size: item.fontSize - 2,
color: rgb(1, 1, 1), // Black text // color: rgb(1, 1, 1), // Black text
}) // })
console.log(`Drawing text at position ${index + 1}: ${item.text} at (${item.x}, ${item.y})`) // console.log(`Drawing text at position ${index + 1}: ${item.text} at (${item.x}, ${item.y})`)
} // }
}) // })
// ---------------------------------calculate and paste the image in pdf-------------------------------------- // ---------------------------------calculate and paste the image in pdf--------------------------------------
if (jsonData.f8) { if (jsonData.f8) {
@ -79,12 +100,12 @@ async function fillPdfFields(jsonData) {
// -------------------------------------------paste the qrCode in the pdf-------------------------------------- // -------------------------------------------paste the qrCode in the pdf--------------------------------------
const paperContent = ` const paperContent = `
ECOLE POLYTECHNIQUE DE TOAMASINA ECOLE SUPERIEURE POLYTECHNIQUE DE TOAMASINA
Nom et prenom: ${jsonData.f1} ${jsonData.f1}
Date de naissance: ${jsonData.f2} ${jsonData.f2}
Niveau: ${jsonData.f3} ${jsonData.f3}
Année scolaire: ${jsonData.f4} ${jsonData.f4}
Numéro d'inscription: ${jsonData.f5} ${jsonData.f5}
` `
const qrCanvas = document.createElement('canvas') const qrCanvas = document.createElement('canvas')

2
src/renderer/src/components/validation/ValidationAddAnneeScolaire.js

@ -1,5 +1,5 @@
/** /**
* function validation année scolaire form * function validation Année Univesitaire form
* @param {*} code * @param {*} code
* @param {*} debut * @param {*} debut
* @param {*} fin * @param {*} fin

78
src/renderer/src/contexts/AuthContext.jsx

@ -1,35 +1,81 @@
import { createContext, useContext, useState } from 'react' import { createContext, useContext, useState, useEffect } from 'react'
const AuthContext = createContext({ const AuthContext = createContext({
user: null, user: null,
token: null, token: null,
setUser: () => {}, setUser: () => {},
setToken: () => {} setToken: () => {},
isAuthenticated: false
}) })
export const AuthContextProvider = ({ children }) => { export const AuthContextProvider = ({ children }) => {
const [user, setUser] = useState() // Initialiser avec null explicitement
const [token, _setToken] = useState(localStorage.getItem('ACCESS_TOKEN')) const [user, setUser] = useState(null)
const [token, _setToken] = useState(null)
const [isLoading, setIsLoading] = useState(true)
const setToken = (token) => { // Initialiser depuis localStorage au montage
_setToken(token) useEffect(() => {
const storedToken = localStorage.getItem('ACCESS_TOKEN')
const storedUser = localStorage.getItem('USER_DATA')
if (token) { if (storedToken) {
localStorage.setItem('ACCESS_TOKEN', token) _setToken(storedToken)
}
if (storedUser) {
try {
setUser(JSON.parse(storedUser))
} catch (error) {
console.error('Erreur parsing user data:', error)
localStorage.removeItem('USER_DATA')
}
}
setIsLoading(false)
}, [])
const setToken = (newToken) => {
_setToken(newToken)
if (newToken) {
localStorage.setItem('ACCESS_TOKEN', newToken)
} else { } else {
localStorage.removeItem('ACCESS_TOKEN') localStorage.removeItem('ACCESS_TOKEN')
localStorage.removeItem('USER_DATA') // Nettoyer aussi les données utilisateur
setUser(null) // Reset user state
}
}
const setUserData = (userData) => {
setUser(userData)
if (userData) {
localStorage.setItem('USER_DATA', JSON.stringify(userData))
} else {
localStorage.removeItem('USER_DATA')
} }
} }
const logout = () => {
setToken(null)
setUserData(null)
}
const isAuthenticated = !!(token && user)
const contextValue = {
user,
token,
setUser: setUserData,
setToken,
logout,
isAuthenticated,
isLoading
}
return ( return (
<AuthContext.Provider <AuthContext.Provider value={contextValue}>
value={{
user,
token,
setUser,
setToken
}}
>
{children} {children}
</AuthContext.Provider> </AuthContext.Provider>
) )

2
src/renderer/src/test/qr.html

@ -26,7 +26,7 @@
<p><b>Prenom</b> : Joseph Fabrice</p> <p><b>Prenom</b> : Joseph Fabrice</p>
<p><b>Date de naissance</b> : 11-12-2001</p> <p><b>Date de naissance</b> : 11-12-2001</p>
<p><b>Niveau</b> : L3</p> <p><b>Niveau</b> : L3</p>
<p><b>Année scolaire</b> : 2023-2024</p> <p><b>Année Univesitaire</b> : 2023-2024</p>
<p><b>Num inscription</b> : 12345678900</p> <p><b>Num inscription</b> : 12345678900</p>
</div> </div>
</div> </div>

2
src/renderer/src/test/relever.html

@ -21,7 +21,7 @@
<h3>RELEVÉE DE NOTE</h3> <h3>RELEVÉE DE NOTE</h3>
<p><strong>Nom & Prenoms :</strong> F3</p> <p><strong>Nom & Prenoms :</strong> F3</p>
<p> <p>
<strong>Niveau :</strong> L1 <span><strong>Année scolaire :</strong> 2022-2023</span> <strong>Niveau :</strong> L1 <span><strong>Année Univesitaire :</strong> 2022-2023</span>
</p> </p>
<p><strong>N° inscription :</strong> F42</p> <p><strong>N° inscription :</strong> F42</p>

2
text.txt

@ -248,7 +248,7 @@ const FileUploader = () => {
<th>Photos</th> <th>Photos</th>
<th>Date de Naissances</th> <th>Date de Naissances</th>
<th>Niveau</th> <th>Niveau</th>
<th>Année Scolaire</th> <th>Année Univesitaire</th>
<th>Num Inscription</th> <th>Num Inscription</th>
</tr> </tr>
</thead> </thead>

Loading…
Cancel
Save