derniere version
This commit is contained in:
parent
f4ad4ecf12
commit
08e11d0bf6
@ -23,7 +23,7 @@ async function createAnneeScolaire(code, debut, fin) {
|
||||
}
|
||||
|
||||
/**
|
||||
* function to get all année scolaire
|
||||
* function to get all Année Univesitaire
|
||||
* @returns promise
|
||||
*/
|
||||
async function getAnneeScolaire() {
|
||||
@ -71,13 +71,13 @@ async function deleteAnneeScolaire(id) {
|
||||
if (result.affectedRows === 0) {
|
||||
return {
|
||||
success: false,
|
||||
message: 'Année Scolaire non trouvé.'
|
||||
message: 'Année universitaire non trouvé.'
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: 'Année Scolaire supprimé avec succès.'
|
||||
message: 'Année universitaire supprimé avec succès.'
|
||||
}
|
||||
} catch (error) {
|
||||
return { success: false, error: 'Erreur veullez réeseyer' }
|
||||
@ -93,13 +93,13 @@ async function updateAnneeScolaire(id, code, debut, fin) {
|
||||
if (result.affectedRows === 0) {
|
||||
return {
|
||||
success: false,
|
||||
message: 'Année Scolaire non trouvé ou aucune modification effectuée.'
|
||||
message: 'Année universitaire non trouvé ou aucune modification effectuée.'
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: 'Année Scolaire mis à jour avec succès.'
|
||||
message: 'Année universitaire mis à jour avec succès.'
|
||||
}
|
||||
} catch (error) {
|
||||
return { success: false, error: 'Erreur veullez réeseyer' }
|
||||
|
||||
@ -191,7 +191,7 @@ async function updateEtudiant(
|
||||
async function getDataToDashboard() {
|
||||
const query = database.prepare('SELECT * FROM niveaus')
|
||||
const query2 = database.prepare('SELECT * FROM etudiants')
|
||||
const query3 = database.prepare('SELECT DISTINCT annee_scolaire FROM etudiants') // get all année scolaire sans doublan
|
||||
const query3 = database.prepare('SELECT DISTINCT annee_scolaire FROM etudiants') // get all Année Univesitaire sans doublan
|
||||
|
||||
try {
|
||||
let niveau = query.all()
|
||||
|
||||
@ -83,7 +83,7 @@ async function getAllEtudiants() {
|
||||
* @returns Promise
|
||||
*/
|
||||
async function getSingleEtudiant(id) {
|
||||
const sql = 'SELECT * FROM etudiants WHERE id = ?'
|
||||
const sql = 'SELECT e.*, m.uniter AS mentionUnite FROM etudiants e JOIN mentions m ON e.mention_id = m.id WHERE e.id = ?'
|
||||
|
||||
try {
|
||||
const [rows] = await pool.query(sql, [id])
|
||||
@ -176,13 +176,13 @@ async function updateEtudiant(
|
||||
if (result.affectedRows === 0) {
|
||||
return {
|
||||
success: false,
|
||||
message: 'Année Scolaire non trouvé.'
|
||||
message: 'Année Univesitaire non trouvé.'
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: 'Année Scolaire supprimé avec succès.'
|
||||
message: 'Année Univesitaire supprimé avec succès.'
|
||||
}
|
||||
} catch (error) {
|
||||
return error
|
||||
@ -197,7 +197,7 @@ async function updateEtudiant(
|
||||
async function getDataToDashboard() {
|
||||
const query = 'SELECT * FROM niveaus'
|
||||
const query2 = 'SELECT * FROM etudiants'
|
||||
const query3 = 'SELECT DISTINCT annee_scolaire FROM etudiants' // get all année scolaire sans doublan
|
||||
const query3 = 'SELECT DISTINCT annee_scolaire FROM etudiants' // get all Année Univesitaire sans doublan
|
||||
|
||||
try {
|
||||
let [rows] = await pool.query(query)
|
||||
@ -222,13 +222,13 @@ async function changePDP(photos, id) {
|
||||
if (result.affectedRows === 0) {
|
||||
return {
|
||||
success: false,
|
||||
message: 'Année Scolaire non trouvé.'
|
||||
message: 'Année Univesitaire non trouvé.'
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: 'Année Scolaire supprimé avec succès.'
|
||||
message: 'Année Univesitaire supprimé avec succès.'
|
||||
}
|
||||
} catch (error) {
|
||||
return error
|
||||
@ -244,13 +244,13 @@ async function updateParcours(parcours, id) {
|
||||
if (result.affectedRows === 0) {
|
||||
return {
|
||||
success: false,
|
||||
message: 'Année Scolaire non trouvé.'
|
||||
message: 'Année Univesitaire non trouvé.'
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: 'Année Scolaire supprimé avec succès.'
|
||||
message: 'Année Univesitaire supprimé avec succès.'
|
||||
}
|
||||
} catch (error) {
|
||||
return error
|
||||
@ -294,13 +294,13 @@ async function updateTranche(id, tranchename, montant) {
|
||||
if (result.affectedRows === 0) {
|
||||
return {
|
||||
success: false,
|
||||
message: 'Année Scolaire non trouvé.'
|
||||
message: 'Année Univesitaire non trouvé.'
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: 'Année Scolaire supprimé avec succès.'
|
||||
message: 'Année Univesitaire supprimé avec succès.'
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('resultat error:',error);
|
||||
@ -317,13 +317,13 @@ async function deleteTranche(id) {
|
||||
if (result.affectedRows === 0) {
|
||||
return {
|
||||
success: false,
|
||||
message: 'Année Scolaire non trouvé.'
|
||||
message: 'Année Univesitaire non trouvé.'
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: 'Année Scolaire supprimé avec succès.'
|
||||
message: 'Année Univesitaire supprimé avec succès.'
|
||||
}
|
||||
} catch (error) {
|
||||
return error
|
||||
|
||||
@ -125,13 +125,13 @@ async function updateMatiere(nom, id, credit, uniter, ue) {
|
||||
if (result.affectedRows === 0) {
|
||||
return {
|
||||
success: false,
|
||||
message: 'Année Scolaire non trouvé ou aucune modification effectuée.'
|
||||
message: 'Année Univesitaire non trouvé ou aucune modification effectuée.'
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: 'Année Scolaire mis à jour avec succès.'
|
||||
message: 'Année Univesitaire mis à jour avec succès.'
|
||||
}
|
||||
} catch (error) {
|
||||
return { success: false, error: 'Erreur veullez réeseyer' + error }
|
||||
@ -448,13 +448,13 @@ async function updateProf(matiere_id, nom, prenom, contact, date) {
|
||||
if (result.affectedRows === 0) {
|
||||
return {
|
||||
success: false,
|
||||
message: 'Année Scolaire non trouvé.'
|
||||
message: 'Année Univesitaire non trouvé.'
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: 'Année Scolaire supprimé avec succès.'
|
||||
message: 'Année Univesitaire supprimé avec succès.'
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
|
||||
@ -24,13 +24,13 @@ async function deleteMention(id) {
|
||||
if (result.affectedRows === 0) {
|
||||
return {
|
||||
success: false,
|
||||
message: 'Année Scolaire non trouvé.'
|
||||
message: 'Année Univesitaire non trouvé.'
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: 'Année Scolaire supprimé avec succès.'
|
||||
message: 'Année Univesitaire supprimé avec succès.'
|
||||
}
|
||||
} catch (error) {
|
||||
return { success: false, error: 'Erreur veullez réeseyer' + error }
|
||||
@ -70,13 +70,13 @@ async function updateMention(nom, uniter, id) {
|
||||
if (result.affectedRows === 0) {
|
||||
return {
|
||||
success: false,
|
||||
message: 'Année Scolaire non trouvé ou aucune modification effectuée.'
|
||||
message: 'Année Univesitaire non trouvé ou aucune modification effectuée.'
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: 'Année Scolaire mis à jour avec succès.'
|
||||
message: 'Année Univesitaire mis à jour avec succès.'
|
||||
}
|
||||
} catch (error) {
|
||||
return { success: false, error: 'Erreur veullez réeseyer' + error }
|
||||
|
||||
@ -33,13 +33,13 @@ async function updateSysteme(id, admis, redouble, renvoyer) {
|
||||
if (result.affectedRows === 0) {
|
||||
return {
|
||||
success: false,
|
||||
message: 'Année Scolaire non trouvé.'
|
||||
message: 'Année Univesitaire non trouvé.'
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: 'Année Scolaire supprimé avec succès.'
|
||||
message: 'Année Univesitaire supprimé avec succès.'
|
||||
}
|
||||
} catch (error) {
|
||||
return error
|
||||
|
||||
@ -64,13 +64,13 @@ async function deletes(id) {
|
||||
if (result.affectedRows === 0) {
|
||||
return {
|
||||
success: false,
|
||||
message: 'Année Scolaire non trouvé.'
|
||||
message: 'Année Univesitaire non trouvé.'
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: 'Année Scolaire supprimé avec succès.'
|
||||
message: 'Année Univesitaire supprimé avec succès.'
|
||||
}
|
||||
} catch (error) {
|
||||
return error
|
||||
@ -86,13 +86,13 @@ async function updateparcour(id, nom, uniter, mention_id) {
|
||||
if (result.affectedRows === 0) {
|
||||
return {
|
||||
success: false,
|
||||
message: 'Année Scolaire non trouvé ou aucune modification effectuée.'
|
||||
message: 'Année Univesitaire non trouvé ou aucune modification effectuée.'
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: 'Année Scolaire mis à jour avec succès.'
|
||||
message: 'Année Univesitaire mis à jour avec succès.'
|
||||
}
|
||||
} catch (error) {
|
||||
return error
|
||||
|
||||
@ -2,9 +2,9 @@ const mysql = require('mysql2/promise')
|
||||
const bcrypt = require('bcryptjs')
|
||||
|
||||
const pool = mysql.createPool({
|
||||
host: '127.0.0.1',
|
||||
host: '192.168.200.200',
|
||||
user: 'root',
|
||||
password: '',
|
||||
password: 'stephane1313',
|
||||
database: 'university',
|
||||
waitForConnections: true,
|
||||
connectionLimit: 10,
|
||||
|
||||
@ -2,9 +2,9 @@ const mysql = require('mysql2/promise')
|
||||
const bcrypt = require('bcryptjs')
|
||||
|
||||
const pool = mysql.createPool({
|
||||
host: '127.0.0.1',
|
||||
host: '192.168.200.200',
|
||||
user: 'root',
|
||||
password: '',
|
||||
password: 'stephane1313',
|
||||
database: 'university',
|
||||
waitForConnections: true,
|
||||
connectionLimit: 10,
|
||||
|
||||
@ -2,9 +2,9 @@ const mysql = require('mysql2/promise')
|
||||
const bcrypt = require('bcryptjs')
|
||||
|
||||
const pool = mysql.createPool({
|
||||
host: '127.0.0.1',
|
||||
host: '192.168.200.200',
|
||||
user: 'root',
|
||||
password: '',
|
||||
password: 'stephane1313',
|
||||
database: 'university',
|
||||
waitForConnections: true,
|
||||
connectionLimit: 10,
|
||||
|
||||
@ -287,13 +287,13 @@ async function updateNessesaryTable(id, multiplicateur) {
|
||||
if (result.affectedRows === 0) {
|
||||
return {
|
||||
success: false,
|
||||
message: 'Année Scolaire non trouvé.'
|
||||
message: 'Année universitaire non trouvé.'
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: 'Année Scolaire supprimé avec succès.'
|
||||
message: 'Année universitaire supprimé avec succès.'
|
||||
}
|
||||
} catch (error) {
|
||||
return error
|
||||
|
||||
@ -98,7 +98,7 @@ const AddAnneeScolaire = () => {
|
||||
{status === 200 ? (
|
||||
<Typography style={{ display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
|
||||
<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 style={{ display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
|
||||
@ -136,7 +136,7 @@ const AddAnneeScolaire = () => {
|
||||
<div className={classe.h1style}>
|
||||
<div className={classeHome.blockTitle}>
|
||||
<h1 style={{ display: 'flex', alignItems: 'center', gap: '10px' }}>
|
||||
<FaCalendarPlus /> Ajout Année Scolaire
|
||||
<FaCalendarPlus /> Ajout Année Univesitaire
|
||||
</h1>
|
||||
<Link to={'#'} onClick={() => window.history.back()}>
|
||||
<Button color="warning" variant="contained">
|
||||
@ -170,12 +170,12 @@ const AddAnneeScolaire = () => {
|
||||
}}
|
||||
>
|
||||
<h4 style={{ textAlign: 'center', padding: '0 0 3% 0' }}>
|
||||
Creation de nouvelle Année Scolaire
|
||||
Creation de nouvelle Année Univesitaire
|
||||
</h4>
|
||||
<Grid container spacing={2}>
|
||||
<Grid item xs={12} sm={6}>
|
||||
<TextField
|
||||
label={'Année Scolaire'}
|
||||
label={'Année Univesitaire'}
|
||||
name={'code'}
|
||||
placeholder="2024-2025"
|
||||
color="warning"
|
||||
|
||||
@ -409,7 +409,7 @@ const AddStudent = () => {
|
||||
</Grid>
|
||||
<Grid item xs={12} sm={6}>
|
||||
<TextField
|
||||
label="Prenom"
|
||||
label="Prénom"
|
||||
name="prenom"
|
||||
fullWidth
|
||||
size="small"
|
||||
@ -503,13 +503,13 @@ const AddStudent = () => {
|
||||
variant="outlined"
|
||||
>
|
||||
<InputLabel id="demo-select-small-label" color="warning">
|
||||
Année Scolaire
|
||||
Année Univesitaire
|
||||
</InputLabel>
|
||||
<Select
|
||||
labelId="demo-select-small-label"
|
||||
id="demo-select-small"
|
||||
value={formData.annee_scolaire}
|
||||
label="Année Scolaire"
|
||||
label="Année Univesitaire"
|
||||
color="warning"
|
||||
size="small"
|
||||
onChange={handleInputChange}
|
||||
@ -521,7 +521,7 @@ const AddStudent = () => {
|
||||
<FaCalendarAlt />
|
||||
</InputAdornment>
|
||||
}
|
||||
label="Année Scolaire"
|
||||
label="Année Univesitaire"
|
||||
/>
|
||||
}
|
||||
sx={{
|
||||
|
||||
@ -48,7 +48,7 @@ const AnneeScolaire = () => {
|
||||
const [ids, setIds] = useState(0)
|
||||
|
||||
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: 'fin', headerName: 'Date de fin', width: 130 },
|
||||
{
|
||||
@ -259,7 +259,7 @@ const AnneeScolaire = () => {
|
||||
<div className={classe.h1style}>
|
||||
<div className={classeHome.blockTitle}>
|
||||
<h1 style={{ display: 'flex', alignItems: 'center', gap: '10px' }}>
|
||||
<BsCalendar2Date /> Année Scolaire
|
||||
<BsCalendar2Date /> Année Univesitaire
|
||||
</h1>
|
||||
<Link to={'/addanneescolaire'}>
|
||||
<Button color="warning" variant="contained">
|
||||
|
||||
@ -460,16 +460,16 @@ const ExportEtudiants = () => {
|
||||
>
|
||||
<MenuItem value={col.headerName}>{col.headerName}</MenuItem>
|
||||
<MenuItem value={'nom'}>nom</MenuItem>
|
||||
<MenuItem value={'prenom'}>prenom</MenuItem>
|
||||
<MenuItem value={'prenom'}>prénom</MenuItem>
|
||||
<MenuItem value={`niveau`}>niveau</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={`num_inscription`}>numéro d'inscription</MenuItem>
|
||||
<MenuItem value={`nationalite`}>Nationaliter</MenuItem>
|
||||
<MenuItem value={`nationalite`}>Nationalité</MenuItem>
|
||||
<MenuItem value={`sexe`}>Sexe</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={`serie`}>Série</MenuItem>
|
||||
<MenuItem value={`code_redoublement`}>Code redoublement</MenuItem>
|
||||
|
||||
@ -151,12 +151,12 @@ const Home = () => {
|
||||
sx={{ color: 'black', fontSize: '15px', textTransform: 'capitalize' }}
|
||||
color="warning"
|
||||
>
|
||||
Année Scolaire
|
||||
Année Univesitaire
|
||||
</InputLabel>
|
||||
<Select
|
||||
labelId="demo-select-small-label"
|
||||
id="demo-select-small"
|
||||
label="Année Scolaire"
|
||||
label="Année Univesitaire"
|
||||
color="warning"
|
||||
defaultValue={'general'}
|
||||
onChange={FilterAnneeScolaire}
|
||||
|
||||
@ -1,60 +1,113 @@
|
||||
import { useRef, useState } from 'react'
|
||||
// import { Container, Row, Col, Form, Button, Card, InputGroup } from 'react-bootstrap';
|
||||
import { useRef, useState, useEffect } from 'react'
|
||||
import { Container, Grid, Card, Typography, TextField, Button, InputAdornment } from '@mui/material'
|
||||
import { FaUserCircle, FaLock, FaUser } from 'react-icons/fa'
|
||||
import classe from '../assets/Login.module.css'
|
||||
import { useAuthContext } from '../contexts/AuthContext'
|
||||
import { Link } from 'react-router-dom'
|
||||
import { Link, useNavigate } from 'react-router-dom'
|
||||
import { ValidationLogin, invalidCredential } from './validation/Login'
|
||||
|
||||
const Login = () => {
|
||||
/**
|
||||
* token from the AuthContext in the context folder
|
||||
*/
|
||||
const { setToken } = useAuthContext()
|
||||
const { token, setToken, setUser, isAuthenticated, isLoading } = useAuthContext()
|
||||
const navigate = useNavigate()
|
||||
|
||||
/**
|
||||
* hook to store our data from the input element
|
||||
*/
|
||||
const [username, setUsername] = useState()
|
||||
const [password, setPassword] = useState()
|
||||
const [username, setUsername] = useState('')
|
||||
const [password, setPassword] = useState('')
|
||||
const [isSubmitting, setIsSubmitting] = useState(false)
|
||||
|
||||
/**
|
||||
* ref for our username and password input and the error span
|
||||
*/
|
||||
const userNameRef = useRef()
|
||||
const passwordRef = useRef()
|
||||
const userNameError = useRef()
|
||||
const passwordError = useRef()
|
||||
|
||||
/**
|
||||
* function to send the data to the IPCRender
|
||||
* and make login
|
||||
*
|
||||
* @param {any} e
|
||||
*/
|
||||
// Redirection si déjà authentifié
|
||||
useEffect(() => {
|
||||
if (!isLoading && isAuthenticated) {
|
||||
console.log('Utilisateur déjà authentifié, redirection vers home')
|
||||
navigate('/', { replace: true })
|
||||
}
|
||||
}, [isAuthenticated, isLoading, navigate])
|
||||
|
||||
const formLogin = async (e) => {
|
||||
e.preventDefault()
|
||||
|
||||
if (isSubmitting) return
|
||||
setIsSubmitting(true)
|
||||
|
||||
let validate = ValidationLogin(
|
||||
userNameRef.current,
|
||||
passwordRef.current,
|
||||
userNameError.current,
|
||||
passwordError.current
|
||||
)
|
||||
try {
|
||||
const validate = ValidationLogin(
|
||||
userNameRef.current,
|
||||
passwordRef.current,
|
||||
userNameError.current,
|
||||
passwordError.current
|
||||
)
|
||||
|
||||
if (validate) {
|
||||
if (!validate) {
|
||||
setIsSubmitting(false)
|
||||
return
|
||||
}
|
||||
|
||||
console.log('Tentative de connexion pour:', username)
|
||||
|
||||
const response = await window.allUser.login({ username, password })
|
||||
console.log('Réponse login:', response)
|
||||
|
||||
if (response.success) {
|
||||
// Redirect to main window
|
||||
setToken(JSON.stringify(response.user))
|
||||
// Extraire le token et les données utilisateur
|
||||
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 {
|
||||
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 (
|
||||
<Container
|
||||
maxWidth={false}
|
||||
@ -63,7 +116,7 @@ const Login = () => {
|
||||
>
|
||||
<Grid container justifyContent="center">
|
||||
<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' }}>
|
||||
<FaUserCircle size={60} color="dark" className="text-light" />
|
||||
</div>
|
||||
@ -78,6 +131,8 @@ const Login = () => {
|
||||
fullWidth
|
||||
placeholder="Nom d'utilisateur"
|
||||
margin="normal"
|
||||
value={username}
|
||||
disabled={isSubmitting}
|
||||
InputProps={{
|
||||
startAdornment: (
|
||||
<InputAdornment position="start">
|
||||
@ -90,16 +145,13 @@ const Login = () => {
|
||||
inputRef={userNameRef}
|
||||
sx={{
|
||||
'& .MuiOutlinedInput-root': {
|
||||
'& fieldset': {
|
||||
borderColor: 'white' // Set the border color when not focused
|
||||
},
|
||||
'&:hover fieldset': {
|
||||
borderColor: 'rgb(156, 39, 176)' // Set the border color on hover
|
||||
}
|
||||
'& fieldset': { borderColor: 'white' },
|
||||
'&:hover fieldset': { borderColor: 'rgb(156, 39, 176)' }
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<span className="text-danger" ref={userNameError}></span>
|
||||
|
||||
<TextField
|
||||
label="Mot de passe"
|
||||
color="secondary"
|
||||
@ -108,6 +160,8 @@ const Login = () => {
|
||||
fullWidth
|
||||
placeholder="Mot de passe"
|
||||
margin="normal"
|
||||
value={password}
|
||||
disabled={isSubmitting}
|
||||
className={classe.input}
|
||||
InputProps={{
|
||||
startAdornment: (
|
||||
@ -120,25 +174,22 @@ const Login = () => {
|
||||
inputRef={passwordRef}
|
||||
sx={{
|
||||
'& .MuiOutlinedInput-root': {
|
||||
'& fieldset': {
|
||||
borderColor: 'white' // Set the border color when not focused
|
||||
},
|
||||
'&:hover fieldset': {
|
||||
borderColor: 'rgb(156, 39, 176)' // Set the border color on hover
|
||||
}
|
||||
'& fieldset': { borderColor: 'white' },
|
||||
'&:hover fieldset': { borderColor: 'rgb(156, 39, 176)' }
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<span ref={passwordError} className="text-danger"></span>
|
||||
|
||||
<Button
|
||||
variant="contained"
|
||||
color="secondary"
|
||||
type="submit"
|
||||
fullWidth
|
||||
sx={{ marginTop: 2 }}
|
||||
<Button
|
||||
variant="contained"
|
||||
color="secondary"
|
||||
type="submit"
|
||||
fullWidth
|
||||
disabled={isSubmitting}
|
||||
sx={{ mt: 2 }}
|
||||
>
|
||||
Se connecter
|
||||
{isSubmitting ? 'Connexion...' : 'Se connecter'}
|
||||
</Button>
|
||||
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between', marginTop: '1rem' }}>
|
||||
@ -154,4 +205,4 @@ const Login = () => {
|
||||
)
|
||||
}
|
||||
|
||||
export default Login
|
||||
export default Login
|
||||
@ -154,7 +154,7 @@ const ModalAddEtudiants = ({ open, handleClose }) => {
|
||||
</Grid>
|
||||
<Grid item xs={12} sm={6}>
|
||||
<TextField
|
||||
label="Prenom"
|
||||
label="Prénom"
|
||||
name="prenom"
|
||||
fullWidth
|
||||
color="secondary"
|
||||
@ -232,10 +232,10 @@ const ModalAddEtudiants = ({ open, handleClose }) => {
|
||||
/>
|
||||
</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}>
|
||||
<TextField
|
||||
label="Année Scolaire"
|
||||
label="Année Univesitaire"
|
||||
name="annee_scolaire"
|
||||
fullWidth
|
||||
color="secondary"
|
||||
|
||||
@ -95,10 +95,10 @@ const ModalAddProf = ({ open, onClose, matiere_id, onSubmitSuccess }) => {
|
||||
margin="normal"
|
||||
required
|
||||
name="prenom_enseignant"
|
||||
label="Prenom du professeur"
|
||||
label="Prénom du professeur"
|
||||
type="text"
|
||||
fullWidth
|
||||
placeholder="Prenom du professeur"
|
||||
placeholder="Prénom du professeur"
|
||||
variant="outlined"
|
||||
value={formData.prenom_enseignant}
|
||||
color="warning"
|
||||
|
||||
@ -41,14 +41,14 @@ const ModalCertificate = ({ open, onClose, json }) => {
|
||||
return (
|
||||
<Dialog open={open} onClose={onClose}>
|
||||
<form action="">
|
||||
<DialogTitle>Informations sur l'élève</DialogTitle>
|
||||
<DialogTitle>Informations sur l'étudiant</DialogTitle>
|
||||
<DialogContent>
|
||||
<TextField
|
||||
autoFocus
|
||||
margin="dense"
|
||||
required
|
||||
name="pere"
|
||||
label="Père de l'élève"
|
||||
label="Père de l'étudiant"
|
||||
type="text"
|
||||
fullWidth
|
||||
variant="outlined"
|
||||
@ -60,7 +60,7 @@ const ModalCertificate = ({ open, onClose, json }) => {
|
||||
margin="dense"
|
||||
name="mere"
|
||||
required
|
||||
label="Mère de l'élève"
|
||||
label="Mère de l'étudiant"
|
||||
type="text"
|
||||
fullWidth
|
||||
variant="outlined"
|
||||
|
||||
@ -170,7 +170,7 @@ const ModalExportFichr = () => {
|
||||
</tr>
|
||||
<tr style={{ borderBottom: 'solid 1px gray' }}>
|
||||
<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>Emergement</th>
|
||||
</tr>
|
||||
|
||||
@ -41,7 +41,7 @@ const ModalRecepice = ({ open, onClose, json }) => {
|
||||
margin="dense"
|
||||
required
|
||||
name="nom"
|
||||
label="Nom et prenom du chef de services"
|
||||
label="Nom et prénom du chef de services"
|
||||
type="text"
|
||||
fullWidth
|
||||
variant="outlined"
|
||||
|
||||
@ -57,7 +57,7 @@ const ModalStage = ({ open, onClose }) => {
|
||||
margin="dense"
|
||||
name="prenom"
|
||||
required
|
||||
label="Prenom du directeur"
|
||||
label="Prénom du directeur"
|
||||
type="text"
|
||||
fullWidth
|
||||
variant="outlined"
|
||||
|
||||
@ -8,7 +8,7 @@ import { frFR } from '@mui/x-data-grid/locales'
|
||||
import { createTheme, ThemeProvider } from '@mui/material/styles'
|
||||
import { IoNewspaperOutline } from 'react-icons/io5'
|
||||
import { IoMdReturnRight } from 'react-icons/io'
|
||||
import { Button, Modal, Box } from '@mui/material'
|
||||
import { Button, Modal, Box, Menu, MenuItem } from '@mui/material'
|
||||
import { Tooltip } from 'react-tooltip'
|
||||
import ReleverNotes from './ReleverNotes'
|
||||
import { FaDownload } from 'react-icons/fa'
|
||||
@ -50,12 +50,23 @@ const Noteclasse = () => {
|
||||
}
|
||||
|
||||
function checkNull(params) {
|
||||
console.log(params);
|
||||
if (params == null || params == undefined) {
|
||||
return null
|
||||
}
|
||||
return params
|
||||
}
|
||||
|
||||
// MODIFICATION: Nouvelle fonction pour calculer la moyenne avec rattrapage
|
||||
function compareSessionNotesForAverage(session1, session2) {
|
||||
// Si il y a une session de rattrapage, utiliser la meilleure note
|
||||
if (session2) {
|
||||
return Math.max(session1, session2.note)
|
||||
}
|
||||
// Sinon utiliser la note normale
|
||||
return session1
|
||||
}
|
||||
|
||||
function compareSessionNotes(session1, session2) {
|
||||
let notes
|
||||
if (session2) {
|
||||
@ -94,10 +105,10 @@ const Noteclasse = () => {
|
||||
modelJson.mention = etudiants[index][j].mention_id
|
||||
modelJson.anneescolaire = etudiants[index][j].annee_scolaire
|
||||
|
||||
// console.log(checkNull(session[index][j]));
|
||||
// MODIFICATION: Utiliser la meilleure note (rattrapage si existe) pour la moyenne générale
|
||||
if (session[index]) {
|
||||
note +=
|
||||
compareSessionNotes(etudiants[index][j].note, checkNull(session[index][j])) *
|
||||
compareSessionNotesForAverage(etudiants[index][j].note, checkNull(session[index][j])) *
|
||||
etudiants[index][j].credit
|
||||
} else {
|
||||
note += etudiants[index][j].note * etudiants[index][j].credit
|
||||
@ -113,15 +124,15 @@ const Noteclasse = () => {
|
||||
}
|
||||
|
||||
function checkNumberSession(id) {
|
||||
let sessionNumber
|
||||
let sessionNumber = 1
|
||||
for (let index = 0; index < session.length; index++) {
|
||||
for (let j = 0; j < session[index].length; j++) {
|
||||
if (session[index][j].etudiant_id == id) {
|
||||
sessionNumber = 2
|
||||
} else {
|
||||
sessionNumber = 1
|
||||
break
|
||||
}
|
||||
}
|
||||
if (sessionNumber === 2) break
|
||||
}
|
||||
return sessionNumber
|
||||
}
|
||||
@ -147,9 +158,29 @@ const Noteclasse = () => {
|
||||
|
||||
const paginationModel = { page: 0, pageSize: 5 }
|
||||
|
||||
// États pour le menu déroulant
|
||||
const [anchorEl, setAnchorEl] = useState(null)
|
||||
const [selectedStudentId, setSelectedStudentId] = useState(null)
|
||||
const open = Boolean(anchorEl)
|
||||
|
||||
const handleMenuClick = (event, studentId) => {
|
||||
setAnchorEl(event.currentTarget)
|
||||
setSelectedStudentId(studentId)
|
||||
}
|
||||
|
||||
const handleMenuClose = () => {
|
||||
setAnchorEl(null)
|
||||
setSelectedStudentId(null)
|
||||
}
|
||||
|
||||
const handleSessionTypeSelect = (sessionType) => {
|
||||
sendData(selectedStudentId, sessionType)
|
||||
handleMenuClose()
|
||||
}
|
||||
|
||||
const columns = [
|
||||
{ field: 'nom', headerName: 'Nom', width: 170 },
|
||||
{ field: 'prenom', headerName: 'Prenom', width: 160 },
|
||||
{ field: 'prenom', headerName: 'Prénom', width: 160 },
|
||||
{ field: 'session', headerName: 'Nombre de Session', width: 180 },
|
||||
{ field: 'mention', headerName: 'Mention', width: 180 },
|
||||
{ field: 'moyenne', headerName: 'Moyenne Général', width: 160 },
|
||||
@ -171,19 +202,21 @@ const Noteclasse = () => {
|
||||
flex: 1,
|
||||
renderCell: (params) => (
|
||||
<div style={{ display: 'flex', gap: '10px' }}>
|
||||
<Link to={`#`} onClick={() => sendData(params.value)}>
|
||||
{/* <IoEyeSharp style={{fontSize:"20px", color:"white"}} /> */}
|
||||
<Button color="warning" variant="contained" className={`update${params.value}`}>
|
||||
<IoNewspaperOutline style={{ fontSize: '20px', color: 'white' }} />
|
||||
</Button>
|
||||
<Tooltip
|
||||
anchorSelect={`.update${params.value}`}
|
||||
style={{ fontSize: '13px', zIndex: 22 }}
|
||||
place="bottom-end"
|
||||
>
|
||||
Imprimer un relevé de notes
|
||||
</Tooltip>
|
||||
</Link>
|
||||
<Button
|
||||
color="warning"
|
||||
variant="contained"
|
||||
className={`update${params.value}`}
|
||||
onClick={(event) => handleMenuClick(event, params.value)}
|
||||
>
|
||||
<IoNewspaperOutline style={{ fontSize: '20px', color: 'white' }} />
|
||||
</Button>
|
||||
<Tooltip
|
||||
anchorSelect={`.update${params.value}`}
|
||||
style={{ fontSize: '13px', zIndex: 22 }}
|
||||
place="bottom-end"
|
||||
>
|
||||
Imprimer un relevé de notes
|
||||
</Tooltip>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@ -205,15 +238,18 @@ const Noteclasse = () => {
|
||||
const [form, setForm] = useState({
|
||||
id: '',
|
||||
niveau: '',
|
||||
anneescolaire: ''
|
||||
anneescolaire: '',
|
||||
sessionType: 'ensemble' // Par défaut
|
||||
})
|
||||
const [selectedId, setSelectedId] = useState(null) // Store id dynamically
|
||||
|
||||
const sendData = (id) => {
|
||||
const sendData = (id, sessionType = 'ensemble') => {
|
||||
setSelectedId(id)
|
||||
// if (selectedId !== null) {
|
||||
setOpenCart(true)
|
||||
// }
|
||||
setForm(prevForm => ({
|
||||
...prevForm,
|
||||
sessionType: sessionType
|
||||
}))
|
||||
setOpenCart(true)
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
@ -229,7 +265,9 @@ const Noteclasse = () => {
|
||||
}
|
||||
}
|
||||
}, [openCard, selectedId])
|
||||
|
||||
console.log(form)
|
||||
|
||||
const downloadButton = () => {
|
||||
setBolll(true)
|
||||
}
|
||||
@ -265,6 +303,7 @@ const Noteclasse = () => {
|
||||
id={form.id}
|
||||
anneescolaire={scolaire}
|
||||
niveau={form.niveau}
|
||||
sessionType={form.sessionType}
|
||||
refs={bolll}
|
||||
/>
|
||||
<Button
|
||||
@ -298,6 +337,24 @@ const Noteclasse = () => {
|
||||
return (
|
||||
<div className={classe.mainHome}>
|
||||
{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={classe.h1style}>
|
||||
<div className={classeHome.blockTitle}>
|
||||
@ -369,4 +426,4 @@ const Noteclasse = () => {
|
||||
)
|
||||
}
|
||||
|
||||
export default Noteclasse
|
||||
export default Noteclasse
|
||||
@ -34,7 +34,7 @@ const Notes = () => {
|
||||
|
||||
const columns = [
|
||||
{ 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: 'action',
|
||||
|
||||
@ -1,33 +1,35 @@
|
||||
import { useState } from 'react'
|
||||
import classe from '../assets/AllStyleComponents.module.css'
|
||||
import img from '../assets/para.png'
|
||||
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 { useAuthContext } from '../contexts/AuthContext'
|
||||
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 classeHome from '../assets/Home.module.css'
|
||||
import classeAdd from '../assets/AddStudent.module.css'
|
||||
import img from '../assets/para.png'
|
||||
import svgSuccess from '../assets/success.svg'
|
||||
import svgError from '../assets/error.svg'
|
||||
import { Link } from 'react-router-dom'
|
||||
import { GrConfigure } from 'react-icons/gr'
|
||||
import IpConfig from './IpConfig'
|
||||
import { useNavigate} from 'react-router-dom'
|
||||
|
||||
const Setting = () => {
|
||||
const { token, setToken } = useAuthContext()
|
||||
|
||||
const userInfo = JSON.parse(token)
|
||||
const { user, setUser, token, setToken } = useAuthContext()
|
||||
|
||||
const navigate = useNavigate()
|
||||
if (!user) {
|
||||
navigate('/login');
|
||||
return <div>Chargement...</div>
|
||||
}
|
||||
// Initialisation du formulaire avec les infos de l'utilisateur
|
||||
const [formData, setFormData] = useState({
|
||||
username: userInfo.username,
|
||||
email: userInfo.email,
|
||||
username: user.username,
|
||||
email: user.email,
|
||||
password: '',
|
||||
id: userInfo.id
|
||||
id: user.id
|
||||
})
|
||||
|
||||
/**
|
||||
* function to set the data in state
|
||||
* @param {*} e
|
||||
*/
|
||||
// Gestion des inputs
|
||||
const handleInputChange = (e) => {
|
||||
const { name, value } = e.target
|
||||
setFormData((prevData) => ({
|
||||
@ -36,49 +38,40 @@ const Setting = () => {
|
||||
}))
|
||||
}
|
||||
|
||||
// Gestion de l'envoi du formulaire
|
||||
const handleSubmit = async (e) => {
|
||||
e.preventDefault()
|
||||
// Handle form submission logic
|
||||
const response = await window.allUser.updateUsers(formData)
|
||||
console.log(response)
|
||||
if (response.success) {
|
||||
setOpen(true)
|
||||
setCode(200)
|
||||
setToken(JSON.stringify(response.users))
|
||||
setFormData({
|
||||
username: response.username,
|
||||
email: response.email,
|
||||
password: '',
|
||||
id: userInfo.id
|
||||
})
|
||||
} else {
|
||||
setCode(422)
|
||||
try {
|
||||
const response = await window.allUser.updateUsers(formData)
|
||||
if (response.success) {
|
||||
setOpen(true)
|
||||
setCode(200)
|
||||
setUser(response.user) // Mettre à jour user
|
||||
setToken(response.user.token) // Mettre à jour token si besoin
|
||||
setFormData({
|
||||
username: response.user.username,
|
||||
email: response.user.email,
|
||||
password: '',
|
||||
id: response.user.id
|
||||
})
|
||||
} else {
|
||||
setCode(422)
|
||||
setOpen(true)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Erreur lors de la mise à jour:', error)
|
||||
setCode(500)
|
||||
setOpen(true)
|
||||
}
|
||||
}
|
||||
/**
|
||||
* hook to open modal
|
||||
*/
|
||||
|
||||
// Modal
|
||||
const [open, setOpen] = useState(false)
|
||||
const [code, setCode] = useState(200)
|
||||
|
||||
/**
|
||||
* function to close modal
|
||||
*/
|
||||
const handleClose = () => setOpen(false)
|
||||
|
||||
/**
|
||||
* function to return the view Modal
|
||||
*
|
||||
* @returns {JSX}
|
||||
*/
|
||||
const modals = () => (
|
||||
<Modal
|
||||
open={open}
|
||||
onClose={handleClose}
|
||||
aria-labelledby="modal-title"
|
||||
aria-describedby="modal-description"
|
||||
>
|
||||
<Modal open={open} onClose={handleClose} aria-labelledby="modal-title">
|
||||
<Box
|
||||
sx={{
|
||||
position: 'absolute',
|
||||
@ -91,30 +84,22 @@ const Setting = () => {
|
||||
p: 4
|
||||
}}
|
||||
>
|
||||
{code == 422 ? (
|
||||
<Typography
|
||||
style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: '10px' }}
|
||||
>
|
||||
<img src={svgError} alt="" width={50} height={50} />{' '}
|
||||
<span style={{ marginLeft: '10px' }}>Email déjà pris</span>
|
||||
{code === 422 ? (
|
||||
<Typography sx={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: '10px' }}>
|
||||
<img src={svgError} alt="Erreur" width={50} height={50} />
|
||||
<span>Email déjà pris</span>
|
||||
</Typography>
|
||||
) : code === 500 ? (
|
||||
<Typography sx={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: '10px' }}>
|
||||
<span>Une erreur est survenue</span>
|
||||
</Typography>
|
||||
) : (
|
||||
<Typography
|
||||
style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: '10px' }}
|
||||
>
|
||||
<img src={svgSuccess} alt="" width={100} height={100} />{' '}
|
||||
<span>Modification a été effectuée avec succès</span>
|
||||
<Typography sx={{ 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>
|
||||
</Typography>
|
||||
)}
|
||||
<Box
|
||||
sx={{
|
||||
marginTop: '2%',
|
||||
display: 'flex',
|
||||
gap: '20px',
|
||||
alignItems: 'end',
|
||||
justifyContent: 'flex-end'
|
||||
}}
|
||||
>
|
||||
<Box sx={{ mt: 2, display: 'flex', justifyContent: 'flex-end' }}>
|
||||
<Button onClick={handleClose} color="warning" variant="contained">
|
||||
OK
|
||||
</Button>
|
||||
@ -123,10 +108,10 @@ const Setting = () => {
|
||||
</Modal>
|
||||
)
|
||||
|
||||
const [openConfig, setOpenCOnfig] = useState(false)
|
||||
const onCloseConfig = () => setOpenCOnfig(false)
|
||||
|
||||
const openCOnfigFunction = () => setOpenCOnfig(true)
|
||||
// IP Config
|
||||
const [openConfig, setOpenConfig] = useState(false)
|
||||
const onCloseConfig = () => setOpenConfig(false)
|
||||
const openConfigFunction = () => setOpenConfig(true)
|
||||
|
||||
return (
|
||||
<div className={classe.mainHome}>
|
||||
@ -135,8 +120,8 @@ const Setting = () => {
|
||||
<div className={classeHome.header}>
|
||||
<div className={classe.h1style}>
|
||||
<div className={classeHome.blockTitle}>
|
||||
<h1>setting</h1>
|
||||
<Link to={'#'} onClick={openCOnfigFunction}>
|
||||
<h1>Settings</h1>
|
||||
<Link to="#" onClick={openConfigFunction}>
|
||||
<Button color="warning" variant="contained">
|
||||
<GrConfigure style={{ fontSize: '20px' }} /> IP configuration
|
||||
</Button>
|
||||
@ -144,7 +129,7 @@ const Setting = () => {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/* contenu */}
|
||||
|
||||
<div className={classeHome.contenaire}>
|
||||
<div className={classeAdd.boxEtudiantsCard}>
|
||||
<Box
|
||||
@ -162,22 +147,15 @@ const Setting = () => {
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
marginTop: '5%',
|
||||
mt: '5%',
|
||||
display: 'flex',
|
||||
gap: '10px',
|
||||
alignItems: 'start',
|
||||
flexDirection: 'column',
|
||||
fontSize: 16,
|
||||
fontFamily: 'sans-serif',
|
||||
justifyContent: 'flex-end'
|
||||
alignItems: 'center',
|
||||
gap: '10px'
|
||||
}}
|
||||
>
|
||||
<span style={{ display: 'flex', marginLeft: '40%' }}>
|
||||
<img src={img} alt="" height={150} width={150} />
|
||||
</span>
|
||||
|
||||
<form onSubmit={handleSubmit} style={{ marginTop: '5%' }}>
|
||||
{/* */}
|
||||
<img src={img} alt="avatar" width={150} height={150} />
|
||||
<form onSubmit={handleSubmit} style={{ width: '100%', marginTop: '5%' }}>
|
||||
<Grid container spacing={2}>
|
||||
<Grid item xs={12} sm={6}>
|
||||
<TextField
|
||||
@ -189,18 +167,7 @@ const Setting = () => {
|
||||
onChange={handleInputChange}
|
||||
required
|
||||
InputProps={{
|
||||
startAdornment: (
|
||||
<InputAdornment position="start">
|
||||
<FaUser />
|
||||
</InputAdornment>
|
||||
)
|
||||
}}
|
||||
sx={{
|
||||
'& .MuiOutlinedInput-root': {
|
||||
'&:hover fieldset': {
|
||||
borderColor: '#ff9800' // Set the border color on hover
|
||||
}
|
||||
}
|
||||
startAdornment: <InputAdornment position="start"><FaUser /></InputAdornment>
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
@ -214,23 +181,11 @@ const Setting = () => {
|
||||
value={formData.email}
|
||||
onChange={handleInputChange}
|
||||
InputProps={{
|
||||
startAdornment: (
|
||||
<InputAdornment position="start">
|
||||
<FaEnvelope />
|
||||
</InputAdornment>
|
||||
)
|
||||
}}
|
||||
sx={{
|
||||
'& .MuiOutlinedInput-root': {
|
||||
'&:hover fieldset': {
|
||||
borderColor: '#ff9800' // Set the border color on hover
|
||||
}
|
||||
}
|
||||
startAdornment: <InputAdornment position="start"><FaEnvelope /></InputAdornment>
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
{/* matieres Mecanique general */}
|
||||
<Grid item xs={12} sm={12}>
|
||||
<Grid item xs={12}>
|
||||
<TextField
|
||||
label="Mot de passe"
|
||||
name="password"
|
||||
@ -240,30 +195,13 @@ const Setting = () => {
|
||||
value={formData.password}
|
||||
onChange={handleInputChange}
|
||||
InputProps={{
|
||||
startAdornment: (
|
||||
<InputAdornment position="start">
|
||||
<FaLock />
|
||||
</InputAdornment>
|
||||
)
|
||||
}}
|
||||
sx={{
|
||||
'& .MuiOutlinedInput-root': {
|
||||
'&:hover fieldset': {
|
||||
borderColor: '#ff9800' // Set the border color on hover
|
||||
}
|
||||
}
|
||||
startAdornment: <InputAdornment position="start"><FaLock /></InputAdornment>
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
{/* Matieres Resistance Materiaux */}
|
||||
{/* Submit Button */}
|
||||
<Grid
|
||||
item
|
||||
xs={12}
|
||||
style={{ display: 'flex', gap: '30px', justifyContent: 'flex-end' }}
|
||||
>
|
||||
<Grid item xs={12} sx={{ display: 'flex', justifyContent: 'flex-end' }}>
|
||||
<Button type="submit" color="warning" variant="contained">
|
||||
Enregister
|
||||
Enregistrer
|
||||
</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
@ -10,11 +10,16 @@ import dayjs from 'dayjs'
|
||||
import getSemestre from './function/GetSemestre'
|
||||
import { descisionJury, getmentionAfterNotes } from './function/FonctionRelever'
|
||||
|
||||
const ReleverNotes = ({ id, anneescolaire, niveau, refs }) => {
|
||||
const ReleverNotes = ({ id, anneescolaire, niveau, sessionType = 'ensemble', refs }) => {
|
||||
const [etudiant, setEtudiant] = useState([])
|
||||
const [matieres, setMatieres] = useState([])
|
||||
const [notes, setNotes] = useState([])
|
||||
|
||||
// Fonction pour vérifier si les crédits doivent être affichés
|
||||
const shouldShowCredits = () => {
|
||||
return niveau !== 'L1' && niveau !== 'L2'
|
||||
}
|
||||
|
||||
const handleDownloadPDF = async () => {
|
||||
const input = Telever.current
|
||||
|
||||
@ -166,9 +171,19 @@ const ReleverNotes = ({ id, anneescolaire, niveau, refs }) => {
|
||||
return acc
|
||||
}, {})
|
||||
|
||||
const compareMoyenne = (normal, rattrapage) => {
|
||||
const note = Math.max(Number(normal), Number(rattrapage))
|
||||
return note >= 10 ? 'Admis' : 'Ajourné'
|
||||
// MODIFICATION: Fonction compareMoyenne mise à jour
|
||||
const compareMoyenne = (normal, rattrapage, sessionType) => {
|
||||
if (sessionType === 'normale') {
|
||||
// Pour session normale: toujours évaluer selon la note normale uniquement
|
||||
return Number(normal) >= 10 ? 'Admis' : 'Ajourné'
|
||||
} else if (sessionType === 'rattrapage') {
|
||||
// Pour session rattrapage: évaluer selon la note de rattrapage
|
||||
return Number(rattrapage) >= 10 ? 'Admis' : 'Ajourné'
|
||||
} else {
|
||||
// Pour session ensemble: prendre la meilleure des deux notes
|
||||
const bestNote = Math.max(Number(normal), Number(rattrapage))
|
||||
return bestNote >= 10 ? 'Admis' : 'Ajourné'
|
||||
}
|
||||
}
|
||||
|
||||
const TbodyContent = () => {
|
||||
@ -219,7 +234,6 @@ const ReleverNotes = ({ id, anneescolaire, niveau, refs }) => {
|
||||
fontWeight: 'bold',
|
||||
textAlign: 'center',
|
||||
borderRight: 'solid 1px black',
|
||||
// borderBottom: 'solid 1px black',
|
||||
borderTop: 'solid 1px black'
|
||||
}}
|
||||
>
|
||||
@ -231,18 +245,29 @@ const ReleverNotes = ({ id, anneescolaire, niveau, refs }) => {
|
||||
<td style={{ borderRight: 'solid 1px black', borderTop: 'solid 1px black' }}>
|
||||
{matiere.nom}
|
||||
</td>
|
||||
<td style={{ borderRight: 'solid 1px black', borderTop: 'solid 1px black' }}>
|
||||
{matiere.credit}
|
||||
</td>
|
||||
<td style={{ borderRight: 'solid 1px black', borderTop: 'solid 1px black' }}>
|
||||
{matiere.note}
|
||||
</td>
|
||||
<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>
|
||||
|
||||
{/* Affichage conditionnel des colonnes selon le type de session */}
|
||||
{sessionType !== 'rattrapage' && (
|
||||
<>
|
||||
<td style={{ borderRight: 'solid 1px black', borderTop: 'solid 1px black' }}>
|
||||
{matiere.credit}
|
||||
</td>
|
||||
<td style={{ borderRight: 'solid 1px black', borderTop: 'solid 1px black' }}>
|
||||
{matiere.note}
|
||||
</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 */}
|
||||
{matiereIndex === 0 && (
|
||||
@ -255,7 +280,6 @@ const ReleverNotes = ({ id, anneescolaire, niveau, refs }) => {
|
||||
borderTop: 'solid 1px black'
|
||||
}}
|
||||
>
|
||||
{/* Replace 'hgh' with your logic for displaying the comparison */}
|
||||
{compareMoyenne(
|
||||
(
|
||||
matieres.reduce((total, matiere) => total + matiere.note, 0) /
|
||||
@ -264,7 +288,8 @@ const ReleverNotes = ({ id, anneescolaire, niveau, refs }) => {
|
||||
(
|
||||
matieres.reduce((total, matiere) => total + matiere.noterepech, 0) /
|
||||
matieres.length
|
||||
).toFixed(2)
|
||||
).toFixed(2),
|
||||
sessionType // MODIFICATION: Passer le sessionType
|
||||
)}
|
||||
</td>
|
||||
)}
|
||||
@ -288,57 +313,65 @@ const ReleverNotes = ({ id, anneescolaire, niveau, refs }) => {
|
||||
>
|
||||
Total de Credit et Moyenne des Notes
|
||||
</td>
|
||||
<td
|
||||
style={{
|
||||
textAlign: 'center',
|
||||
fontWeight: 'bold',
|
||||
borderRight: 'solid 1px black',
|
||||
borderTop: 'solid 1px black'
|
||||
}}
|
||||
>
|
||||
{/* Calculate Total de Credit */}
|
||||
{matieres.reduce((total, matiere) => total + matiere.credit, 0)}
|
||||
</td>
|
||||
<td
|
||||
style={{
|
||||
textAlign: 'center',
|
||||
fontWeight: 'bold',
|
||||
borderRight: 'solid 1px black',
|
||||
borderTop: 'solid 1px black'
|
||||
}}
|
||||
className="moyenneNotes"
|
||||
>
|
||||
{/* Calculate Moyenne des Notes */}
|
||||
{(
|
||||
matieres.reduce((total, matiere) => total + matiere.note, 0) /
|
||||
matieres.length
|
||||
).toFixed(2)}{' '}
|
||||
{/* Format to 2 decimal places */}
|
||||
</td>
|
||||
<td
|
||||
style={{
|
||||
textAlign: 'center',
|
||||
fontWeight: 'bold',
|
||||
borderTop: 'solid 1px black',
|
||||
borderRight: 'solid 1px black'
|
||||
}}
|
||||
>
|
||||
{matieres.reduce((total, matiere) => total + matiere.credit, 0)}
|
||||
</td>
|
||||
<td
|
||||
style={{
|
||||
textAlign: 'center',
|
||||
fontWeight: 'bold',
|
||||
borderRight: 'solid 1px black',
|
||||
borderTop: 'solid 1px black'
|
||||
}}
|
||||
className="moyenneNotesRattrapage"
|
||||
>
|
||||
{(
|
||||
matieres.reduce((total, matiere) => total + matiere.noterepech, 0) /
|
||||
matieres.length
|
||||
).toFixed(2)}
|
||||
</td>
|
||||
|
||||
{sessionType !== 'rattrapage' && (
|
||||
<>
|
||||
<td
|
||||
style={{
|
||||
textAlign: 'center',
|
||||
fontWeight: 'bold',
|
||||
borderRight: 'solid 1px black',
|
||||
borderTop: 'solid 1px black'
|
||||
}}
|
||||
>
|
||||
{matieres.reduce((total, matiere) => total + matiere.credit, 0)}
|
||||
</td>
|
||||
<td
|
||||
style={{
|
||||
textAlign: 'center',
|
||||
fontWeight: 'bold',
|
||||
borderRight: 'solid 1px black',
|
||||
borderTop: 'solid 1px black'
|
||||
}}
|
||||
className="moyenneNotes"
|
||||
>
|
||||
{(
|
||||
matieres.reduce((total, matiere) => total + matiere.note, 0) /
|
||||
matieres.length
|
||||
).toFixed(2)}
|
||||
</td>
|
||||
</>
|
||||
)}
|
||||
|
||||
{sessionType !== 'normale' && (
|
||||
<>
|
||||
<td
|
||||
style={{
|
||||
textAlign: 'center',
|
||||
fontWeight: 'bold',
|
||||
borderTop: 'solid 1px black',
|
||||
borderRight: 'solid 1px black'
|
||||
}}
|
||||
>
|
||||
{matieres.reduce((total, matiere) => total + matiere.credit, 0)}
|
||||
</td>
|
||||
<td
|
||||
style={{
|
||||
textAlign: 'center',
|
||||
fontWeight: 'bold',
|
||||
borderRight: 'solid 1px black',
|
||||
borderTop: 'solid 1px black'
|
||||
}}
|
||||
className="moyenneNotesRattrapage"
|
||||
>
|
||||
{(
|
||||
matieres.reduce((total, matiere) => total + matiere.noterepech, 0) /
|
||||
matieres.length
|
||||
).toFixed(2)}
|
||||
</td>
|
||||
</>
|
||||
)}
|
||||
|
||||
<td
|
||||
style={{
|
||||
textAlign: 'center',
|
||||
@ -357,6 +390,7 @@ const ReleverNotes = ({ id, anneescolaire, niveau, refs }) => {
|
||||
)
|
||||
}
|
||||
|
||||
// MODIFICATION: Fonction totalNotes mise à jour pour tenir compte du sessionType
|
||||
const totalNotes = () => {
|
||||
let totalNotes = document.querySelectorAll('.moyenneNotes')
|
||||
let totalNotesRepech = document.querySelectorAll('.moyenneNotesRattrapage')
|
||||
@ -365,25 +399,29 @@ const ReleverNotes = ({ id, anneescolaire, niveau, refs }) => {
|
||||
let TotalNoteNumberRepech = 0
|
||||
|
||||
totalNotes.forEach((notes) => {
|
||||
TotalNoteNumber += Number(notes.textContent / totalNotes.length)
|
||||
// console.log(notes.textContent);
|
||||
TotalNoteNumber += Number(notes.textContent) / totalNotes.length
|
||||
})
|
||||
|
||||
totalNotesRepech.forEach((notes) => {
|
||||
TotalNoteNumberRepech += Number(notes.textContent / totalNotes.length)
|
||||
// console.log(notes.textContent);
|
||||
TotalNoteNumberRepech += Number(notes.textContent) / totalNotesRepech.length
|
||||
})
|
||||
|
||||
let note = Math.max(TotalNoteNumber, TotalNoteNumberRepech)
|
||||
|
||||
return note
|
||||
// Retourner la note selon le type de session
|
||||
if (sessionType === 'normale') {
|
||||
return TotalNoteNumber
|
||||
} else if (sessionType === 'rattrapage') {
|
||||
return TotalNoteNumberRepech
|
||||
} else {
|
||||
// Pour 'ensemble', prendre la meilleure note
|
||||
return Math.max(TotalNoteNumber, TotalNoteNumberRepech)
|
||||
}
|
||||
}
|
||||
|
||||
const [note, setNote] = useState(0)
|
||||
|
||||
useEffect(() => {
|
||||
setNote(totalNotes())
|
||||
}, [TbodyContent])
|
||||
}, [TbodyContent, sessionType])
|
||||
|
||||
return (
|
||||
<div className={classe.mainHome}>
|
||||
@ -391,9 +429,8 @@ const ReleverNotes = ({ id, anneescolaire, niveau, refs }) => {
|
||||
<div style={{ display: 'flex', justifyContent: 'center' }}>
|
||||
<Paper
|
||||
sx={{
|
||||
// width: "100%",
|
||||
height: 'auto', // Auto height to make the grid responsive
|
||||
minHeight: 500, // Ensures a minimum height
|
||||
height: 'auto',
|
||||
minHeight: 500,
|
||||
display: 'flex',
|
||||
padding: '1%',
|
||||
width: '70%',
|
||||
@ -425,7 +462,7 @@ const ReleverNotes = ({ id, anneescolaire, niveau, refs }) => {
|
||||
</span>
|
||||
<br />
|
||||
<span>
|
||||
<b>Prenom</b>
|
||||
<b>Prénom</b>
|
||||
</span>
|
||||
<br />
|
||||
<span>
|
||||
@ -480,7 +517,7 @@ const ReleverNotes = ({ id, anneescolaire, niveau, refs }) => {
|
||||
<tr style={{ borderTop: 'solid 1px black', textAlign: 'center' }}>
|
||||
<th colSpan={3}></th>
|
||||
<th
|
||||
colSpan={4}
|
||||
colSpan={sessionType === 'ensemble' ? 4 : 2}
|
||||
style={{
|
||||
background: '#bdbcbc',
|
||||
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
|
||||
colSpan={2}
|
||||
style={{ background: '#bdbcbc', borderLeft: 'solid 1px black' }}
|
||||
>
|
||||
Normale
|
||||
</th>
|
||||
<th
|
||||
colSpan={2}
|
||||
style={{ background: '#bdbcbc', borderLeft: 'solid 1px black' }}
|
||||
>
|
||||
Rattrapage
|
||||
</th>
|
||||
|
||||
{sessionType !== 'rattrapage' && (
|
||||
<th
|
||||
colSpan={shouldShowCredits() ? 2 : 1}
|
||||
style={{ background: '#bdbcbc', borderLeft: 'solid 1px black' }}
|
||||
>
|
||||
Normale
|
||||
</th>
|
||||
)}
|
||||
|
||||
{sessionType !== 'normale' && (
|
||||
<th
|
||||
colSpan={shouldShowCredits() ? 2 : 1}
|
||||
style={{ background: '#bdbcbc', borderLeft: 'solid 1px black' }}
|
||||
>
|
||||
Rattrapage
|
||||
</th>
|
||||
)}
|
||||
|
||||
<th
|
||||
style={{ borderLeft: 'solid 1px black', borderRight: 'solid 1px black' }}
|
||||
></th>
|
||||
@ -514,7 +558,6 @@ const ReleverNotes = ({ id, anneescolaire, niveau, refs }) => {
|
||||
<tr
|
||||
style={{
|
||||
borderTop: 'solid 1px black',
|
||||
// borderBottom: 'solid 1px black',
|
||||
background: '#bdbcbc',
|
||||
textAlign: 'center'
|
||||
}}
|
||||
@ -524,10 +567,21 @@ const ReleverNotes = ({ id, anneescolaire, niveau, refs }) => {
|
||||
</th>
|
||||
<th style={{ borderLeft: 'solid 1px black' }}>UE</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>
|
||||
<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>
|
||||
</>
|
||||
)}
|
||||
|
||||
{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' }}>
|
||||
Observation
|
||||
</th>
|
||||
@ -548,7 +602,7 @@ const ReleverNotes = ({ id, anneescolaire, niveau, refs }) => {
|
||||
</td>
|
||||
<td style={{ borderRight: 'solid 1px black' }}>{note.toFixed(2)}</td>
|
||||
<td style={{ borderRight: 'solid 1px black' }}>/20</td>
|
||||
<td colSpan={4}></td>
|
||||
<td colSpan={sessionType === 'ensemble' ? 3 : 2}></td>
|
||||
</tr>
|
||||
<tr style={{ border: 'solid 1px black' }}>
|
||||
<td
|
||||
@ -562,11 +616,8 @@ const ReleverNotes = ({ id, anneescolaire, niveau, refs }) => {
|
||||
Mention:{' '}
|
||||
<span style={{ marginLeft: '3%' }}>{getmentionAfterNotes(note)}</span>
|
||||
</td>
|
||||
<td colSpan={5} style={{ textAlign: 'left', paddingLeft: '1%' }}>
|
||||
<td colSpan={sessionType === 'ensemble' ? 4 : 3} style={{ textAlign: 'left', paddingLeft: '1%' }}>
|
||||
Décision du Jury:{' '}
|
||||
<span style={{ marginLeft: '3%' }}>
|
||||
{descisionJury(note, etudiant.niveau)}
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
@ -591,4 +642,4 @@ const ReleverNotes = ({ id, anneescolaire, niveau, refs }) => {
|
||||
)
|
||||
}
|
||||
|
||||
export default ReleverNotes
|
||||
export default ReleverNotes
|
||||
@ -3,7 +3,7 @@ import { useParams, Link } from 'react-router-dom'
|
||||
import classe from '../assets/AllStyleComponents.module.css'
|
||||
import classeHome from '../assets/Home.module.css'
|
||||
import Paper from '@mui/material/Paper'
|
||||
import { Button, Modal, Box } from '@mui/material'
|
||||
import { Button, Modal, Box, Tabs, Tab, Select, MenuItem, FormControl, InputLabel } from '@mui/material'
|
||||
import { IoMdReturnRight } from 'react-icons/io'
|
||||
import jsPDF from 'jspdf'
|
||||
import autoTable from 'jspdf-autotable'
|
||||
@ -20,10 +20,18 @@ const Resultat = () => {
|
||||
const [etudiants, setEtudiants] = useState([])
|
||||
const [mention, setMention] = useState([])
|
||||
const [session, setSession] = useState([])
|
||||
const [tabValue, setTabValue] = useState(0)
|
||||
|
||||
// États pour les sélections
|
||||
const [selectedMatiere, setSelectedMatiere] = useState('')
|
||||
const [selectedUE, setSelectedUE] = useState('')
|
||||
const [availableMatieres, setAvailableMatieres] = useState([])
|
||||
const [availableUEs, setAvailableUEs] = useState([])
|
||||
|
||||
useEffect(() => {
|
||||
window.notes.getMoyenne(formData).then((response) => {
|
||||
setEtudiants(response)
|
||||
extractMatieresAndUEs(response)
|
||||
})
|
||||
window.noteRepech.getMoyenneRepech(formData).then((response) => {
|
||||
setSession(response)
|
||||
@ -33,6 +41,28 @@ const Resultat = () => {
|
||||
})
|
||||
}, [])
|
||||
|
||||
// Fonction pour extraire les matières et UEs disponibles
|
||||
const extractMatieresAndUEs = (data) => {
|
||||
const matieres = new Set()
|
||||
const ues = new Set()
|
||||
|
||||
for (let index = 0; index < data.length; index++) {
|
||||
for (let j = 0; j < data[index].length; j++) {
|
||||
const matiere = data[index][j].matiere || `Matière ${j + 1}`
|
||||
const ue = data[index][j].ue || `UE${Math.floor(j / 2) + 1}`
|
||||
matieres.add(matiere)
|
||||
ues.add(ue)
|
||||
}
|
||||
}
|
||||
|
||||
setAvailableMatieres(Array.from(matieres))
|
||||
setAvailableUEs(Array.from(ues))
|
||||
|
||||
// Sélectionner la première matière et UE par défaut
|
||||
if (matieres.size > 0) setSelectedMatiere(Array.from(matieres)[0])
|
||||
if (ues.size > 0) setSelectedUE(Array.from(ues)[0])
|
||||
}
|
||||
|
||||
let dataToMap = []
|
||||
|
||||
function returnmention(id) {
|
||||
@ -45,6 +75,18 @@ const Resultat = () => {
|
||||
return mentions
|
||||
}
|
||||
|
||||
// Fonction pour déterminer la mention selon la moyenne
|
||||
function getMentionFromMoyenne(moyenne) {
|
||||
const moy = parseFloat(moyenne)
|
||||
if (moy >= 18) return 'Excellent'
|
||||
if (moy >= 16) return 'Très Bien'
|
||||
if (moy >= 14) return 'Bien'
|
||||
if (moy >= 12) return 'Assez Bien'
|
||||
if (moy >= 10) return 'Passable'
|
||||
if (moy >= 7) return 'Autorisé à redoubler'
|
||||
return 'Remise à la famille'
|
||||
}
|
||||
|
||||
function checkNull(params) {
|
||||
if (params == null || params == undefined) {
|
||||
return null
|
||||
@ -52,51 +94,6 @@ const Resultat = () => {
|
||||
return params
|
||||
}
|
||||
|
||||
const print = () => {
|
||||
const generatePDF = () => {
|
||||
try {
|
||||
const pdf = new jsPDF({
|
||||
orientation: 'portrait',
|
||||
unit: 'mm',
|
||||
format: 'a4'
|
||||
})
|
||||
|
||||
pdf.addImage(logoRelerev1, 'PNG', 10, 5, 40, 20)
|
||||
pdf.addImage(logoRelerev2, 'PNG', 175, 5, 30, 30)
|
||||
|
||||
// Ajouter le texte entre les logos
|
||||
pdf.setFontSize(10)
|
||||
pdf.text('REPOBLIKAN\'I MADAGASIKARA', 105, 10, { align: 'center' })
|
||||
pdf.text('Fitiavana-Tanindrazana-Fandrosoana', 105, 14, { align: 'center' })
|
||||
pdf.text('********************', 105, 18, { align: 'center' })
|
||||
pdf.text('MINISTÈRE DE L\'ENSEIGNEMENT SUPÉRIEUR', 105, 22, { align: 'center' })
|
||||
pdf.text('ET DE LA RECHERCHE SCIENTIFIQUE', 105, 26, { align: 'center' })
|
||||
pdf.text('********************', 105, 30, { align: 'center' })
|
||||
pdf.text('UNIVERSITÉ DE TOAMASINA', 105, 34, { align: 'center' })
|
||||
pdf.text('ÉCOLE SUPÉRIEURE POLYTECHNIQUE', 105, 38, { align: 'center' })
|
||||
|
||||
// Select the table
|
||||
autoTable(pdf, {
|
||||
html: '#myTable2',
|
||||
startY: 50, // décalé vers le bas pour laisser la place aux logos et texte
|
||||
theme: 'grid',
|
||||
headStyles: {
|
||||
fillColor: 'gray',
|
||||
halign: 'center',
|
||||
fontStyle: 'bold',
|
||||
textColor: 'black'
|
||||
},
|
||||
styles: { fontSize: 8, cellPadding: 2, halign: 'center' }
|
||||
})
|
||||
|
||||
pdf.save(`Resultat-${niveau}-${scolaire}.pdf`)
|
||||
} catch (error) {
|
||||
console.error('Error generating PDF:', error)
|
||||
}
|
||||
}
|
||||
generatePDF()
|
||||
}
|
||||
|
||||
function compareSessionNotes(session1, session2) {
|
||||
let notes
|
||||
if (session2) {
|
||||
@ -111,12 +108,13 @@ const Resultat = () => {
|
||||
return notes
|
||||
}
|
||||
|
||||
// Traitement des données pour résultat définitif - INCLUANT TOUS LES ÉTUDIANTS
|
||||
for (let index = 0; index < etudiants.length; index++) {
|
||||
let total = 0
|
||||
let note = 0
|
||||
let totalCredit = 0
|
||||
let hasValidNotes = false
|
||||
|
||||
// Create a new object for each student
|
||||
let modelJson = {
|
||||
id: '',
|
||||
nom: '',
|
||||
@ -135,29 +133,389 @@ const Resultat = () => {
|
||||
modelJson.mention = etudiants[index][j].mention_id
|
||||
modelJson.anneescolaire = etudiants[index][j].annee_scolaire
|
||||
|
||||
// console.log(checkNull(session[index][j]));
|
||||
let currentNote = etudiants[index][j].note
|
||||
if (session[index]) {
|
||||
note +=
|
||||
compareSessionNotes(etudiants[index][j].note, checkNull(session[index][j])) *
|
||||
etudiants[index][j].credit
|
||||
} else {
|
||||
note += etudiants[index][j].note * etudiants[index][j].credit
|
||||
currentNote = compareSessionNotes(etudiants[index][j].note, checkNull(session[index][j]))
|
||||
}
|
||||
|
||||
// Vérifier si l'étudiant a des notes valides
|
||||
if (currentNote != null && currentNote != undefined && !isNaN(currentNote)) {
|
||||
note += currentNote * etudiants[index][j].credit
|
||||
totalCredit += etudiants[index][j].credit
|
||||
hasValidNotes = true
|
||||
}
|
||||
totalCredit += etudiants[index][j].credit
|
||||
}
|
||||
|
||||
total = note / totalCredit
|
||||
modelJson.moyenne = total.toFixed(2)
|
||||
|
||||
// Add the new object to the array
|
||||
// Calculer la moyenne même si certaines notes manquent
|
||||
if (hasValidNotes && totalCredit > 0) {
|
||||
total = note / totalCredit
|
||||
modelJson.moyenne = total.toFixed(2)
|
||||
} else {
|
||||
modelJson.moyenne = 'N/A'
|
||||
}
|
||||
|
||||
dataToMap.push(modelJson)
|
||||
}
|
||||
|
||||
const sortedStudents = dataToMap
|
||||
.filter((student) => parseFloat(student.moyenne) >= 10)
|
||||
.sort((a, b) => parseFloat(b.moyenne) - parseFloat(a.moyenne))
|
||||
// Fonction pour obtenir les résultats par matière sélectionnée
|
||||
const getResultsByMatiere = () => {
|
||||
const results = []
|
||||
|
||||
for (let index = 0; index < etudiants.length; index++) {
|
||||
for (let j = 0; j < etudiants[index].length; j++) {
|
||||
const matiere = etudiants[index][j].matiere || `Matière ${j + 1}`
|
||||
|
||||
if (matiere === selectedMatiere) {
|
||||
let finalNote = etudiants[index][j].note
|
||||
if (session[index] && session[index][j]) {
|
||||
finalNote = compareSessionNotes(etudiants[index][j].note, session[index][j])
|
||||
}
|
||||
|
||||
console.log(sortedStudents)
|
||||
results.push({
|
||||
id: etudiants[index][j].etudiant_id,
|
||||
nom: etudiants[index][j].nom,
|
||||
prenom: etudiants[index][j].prenom,
|
||||
note: finalNote != null ? finalNote.toFixed(2) : 'N/A',
|
||||
credit: etudiants[index][j].credit,
|
||||
mention: returnmention(etudiants[index][j].mention_id)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return results.sort((a, b) => {
|
||||
const noteA = a.note === 'N/A' ? -1 : parseFloat(a.note)
|
||||
const noteB = b.note === 'N/A' ? -1 : parseFloat(b.note)
|
||||
return noteB - noteA
|
||||
})
|
||||
}
|
||||
|
||||
// Fonction pour obtenir les résultats par UE sélectionnée
|
||||
const getResultsByUE = () => {
|
||||
const groupedStudents = {}
|
||||
const matieresInUE = new Set()
|
||||
|
||||
// Grouper les étudiants et collecter les matières de l'UE
|
||||
for (let index = 0; index < etudiants.length; index++) {
|
||||
for (let j = 0; j < etudiants[index].length; j++) {
|
||||
const ue = etudiants[index][j].ue || `UE${Math.floor(j / 2) + 1}`
|
||||
const matiere = etudiants[index][j].matiere || `Matière ${j + 1}`
|
||||
|
||||
if (ue === selectedUE) {
|
||||
matieresInUE.add(matiere)
|
||||
const etudiantId = etudiants[index][j].etudiant_id
|
||||
|
||||
if (!groupedStudents[etudiantId]) {
|
||||
groupedStudents[etudiantId] = {
|
||||
id: etudiantId,
|
||||
nom: etudiants[index][j].nom,
|
||||
prenom: etudiants[index][j].prenom,
|
||||
matieres: {},
|
||||
totalNote: 0,
|
||||
totalCredit: 0,
|
||||
hasValidNotes: false
|
||||
}
|
||||
}
|
||||
|
||||
let finalNote = etudiants[index][j].note
|
||||
if (session[index] && session[index][j]) {
|
||||
finalNote = compareSessionNotes(etudiants[index][j].note, session[index][j])
|
||||
}
|
||||
|
||||
if (finalNote != null && finalNote != undefined && !isNaN(finalNote)) {
|
||||
groupedStudents[etudiantId].matieres[matiere] = finalNote.toFixed(2)
|
||||
groupedStudents[etudiantId].totalNote += finalNote * etudiants[index][j].credit
|
||||
groupedStudents[etudiantId].totalCredit += etudiants[index][j].credit
|
||||
groupedStudents[etudiantId].hasValidNotes = true
|
||||
} else {
|
||||
groupedStudents[etudiantId].matieres[matiere] = 'N/A'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const results = Object.values(groupedStudents).map(student => ({
|
||||
...student,
|
||||
moyenneUE: student.hasValidNotes && student.totalCredit > 0
|
||||
? (student.totalNote / student.totalCredit).toFixed(2)
|
||||
: 'N/A'
|
||||
}))
|
||||
|
||||
return {
|
||||
students: results.sort((a, b) => {
|
||||
const moyA = a.moyenneUE === 'N/A' ? -1 : parseFloat(a.moyenneUE)
|
||||
const moyB = b.moyenneUE === 'N/A' ? -1 : parseFloat(b.moyenneUE)
|
||||
return moyB - moyA
|
||||
}),
|
||||
matieres: Array.from(matieresInUE)
|
||||
}
|
||||
}
|
||||
|
||||
const sortedStudents = dataToMap.sort((a, b) => {
|
||||
const moyA = a.moyenne === 'N/A' ? -1 : parseFloat(a.moyenne)
|
||||
const moyB = b.moyenne === 'N/A' ? -1 : parseFloat(b.moyenne)
|
||||
return moyB - moyA
|
||||
})
|
||||
|
||||
const handleTabChange = (event, newValue) => {
|
||||
setTabValue(newValue)
|
||||
}
|
||||
|
||||
const print = () => {
|
||||
const generatePDF = () => {
|
||||
try {
|
||||
const pdf = new jsPDF({
|
||||
orientation: 'portrait',
|
||||
unit: 'mm',
|
||||
format: 'a4'
|
||||
})
|
||||
|
||||
pdf.addImage(logoRelerev1, 'PNG', 175, 5, 32, 30)
|
||||
pdf.addImage(logoRelerev2, 'PNG', 10, 5, 40, 30)
|
||||
|
||||
pdf.setFontSize(10)
|
||||
pdf.text('REPOBLIKAN\'I MADAGASIKARA', 105, 10, { align: 'center' })
|
||||
pdf.text('Fitiavana-Tanindrazana-Fandrosoana', 105, 14, { align: 'center' })
|
||||
pdf.text('********************', 105, 18, { align: 'center' })
|
||||
pdf.text('MINISTÈRE DE L\'ENSEIGNEMENT SUPÉRIEUR', 105, 22, { align: 'center' })
|
||||
pdf.text('ET DE LA RECHERCHE SCIENTIFIQUE', 105, 26, { align: 'center' })
|
||||
pdf.text('********************', 105, 30, { align: 'center' })
|
||||
pdf.text('UNIVERSITÉ DE TOAMASINA', 105, 34, { align: 'center' })
|
||||
pdf.text('ÉCOLE SUPÉRIEURE POLYTECHNIQUE', 105, 38, { align: 'center' })
|
||||
|
||||
const tableId = tabValue === 0 ? '#resultTable' : tabValue === 1 ? '#subjectTable' : '#ueTable'
|
||||
|
||||
autoTable(pdf, {
|
||||
html: tableId,
|
||||
startY: 50,
|
||||
theme: 'grid',
|
||||
headStyles: {
|
||||
fillColor: [255, 255, 255], // Fond blanc
|
||||
halign: 'center',
|
||||
fontStyle: 'bold',
|
||||
textColor: [0, 0, 0], // Texte noir
|
||||
lineColor: [0, 0, 0], // Bordure noire
|
||||
lineWidth: 0.5
|
||||
},
|
||||
styles: {
|
||||
fontSize: 8,
|
||||
cellPadding: 2,
|
||||
halign: 'center',
|
||||
lineColor: [0, 0, 0], // Bordure noire pour toutes les cellules
|
||||
lineWidth: 0.5
|
||||
},
|
||||
bodyStyles: {
|
||||
lineColor: [0, 0, 0], // Bordure noire pour le corps du tableau
|
||||
lineWidth: 0.5
|
||||
}
|
||||
})
|
||||
|
||||
const suffix = tabValue === 0 ? 'definitif' :
|
||||
tabValue === 1 ? `par-matiere-${selectedMatiere}` :
|
||||
`par-ue-${selectedUE}`
|
||||
pdf.save(`Resultat-${suffix}-${niveau}-${scolaire}.pdf`)
|
||||
} catch (error) {
|
||||
console.error('Error generating PDF:', error)
|
||||
}
|
||||
}
|
||||
generatePDF()
|
||||
}
|
||||
|
||||
const renderHeader = () => (
|
||||
<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 (
|
||||
<div className={classe.mainHome}>
|
||||
@ -194,80 +552,28 @@ const Resultat = () => {
|
||||
padding: '2%'
|
||||
}}
|
||||
>
|
||||
{/* En-tête avec logos et texte */}
|
||||
<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>
|
||||
{renderHeader()}
|
||||
|
||||
{/* Informations du parcours */}
|
||||
<div style={{ marginBottom: '15px', fontSize: '12px' }}>
|
||||
<div><strong>Parcours :</strong> GC</div>
|
||||
<div><strong>Niveau :</strong> {niveau}</div>
|
||||
<div><strong>Année Universitaire :</strong> {scolaire}</div>
|
||||
</div>
|
||||
|
||||
<table
|
||||
className="table table-bordered table-striped text-center shadow-sm"
|
||||
id="myTable2"
|
||||
style={{ fontSize: '12px' }}
|
||||
<Tabs
|
||||
value={tabValue}
|
||||
onChange={handleTabChange}
|
||||
centered
|
||||
sx={{ marginBottom: '20px' }}
|
||||
>
|
||||
<thead className="table-secondary">
|
||||
<tr>
|
||||
<td colSpan={4} className="py-3" style={{ backgroundColor: '#f8f9fa' }}>
|
||||
<h6 style={{ margin: 0, fontWeight: 'bold' }}>
|
||||
Résultat de la Deuxième Session : {niveau} admis en L3 par ordre de mérite
|
||||
</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' }}>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>
|
||||
<Tab label="Résultat Définitif" />
|
||||
<Tab label="Par Matière" />
|
||||
<Tab label="Par UE" />
|
||||
</Tabs>
|
||||
|
||||
{tabValue === 0 && renderResultDefinitif()}
|
||||
{tabValue === 1 && renderResultParMatiere()}
|
||||
{tabValue === 2 && renderResultParUE()}
|
||||
</Paper>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import React, { useState } from 'react'
|
||||
import React, { useState, useEffect } from 'react'
|
||||
import classe from '../assets/Sidenav.module.css'
|
||||
import { RiDashboardHorizontalFill } from 'react-icons/ri'
|
||||
import { PiStudentFill } from 'react-icons/pi'
|
||||
@ -21,8 +21,27 @@ import { FaClipboardList } from 'react-icons/fa6'
|
||||
|
||||
const Sidenav = () => {
|
||||
const [anchorEl, setAnchorEl] = useState(null)
|
||||
const [userRole, setUserRole] = useState(null)
|
||||
const open = Boolean(anchorEl)
|
||||
const { setToken } = useAuthContext()
|
||||
const { user } = useAuthContext()
|
||||
|
||||
// // Récupération du rôle utilisateur au montage du composant
|
||||
// useEffect(() => {
|
||||
// const fetchUserRole = async () => {
|
||||
// try {
|
||||
// // Supposant que vous avez une méthode getUser dans votre contexte ou API
|
||||
// const user = await window.allUser?.users(); // ou votre méthode d'API
|
||||
// console.log('Résultat de getAllUsers:', user)
|
||||
// setUserRole(user?.roles?.toLowerCase()) // Normaliser en minuscule
|
||||
// } catch (error) {
|
||||
// console.error('Erreur lors de la récupération du rôle utilisateur:', error)
|
||||
// setUserRole(null)
|
||||
// }
|
||||
// }
|
||||
|
||||
// fetchUserRole()
|
||||
// }, [])
|
||||
|
||||
const handleClick = (event) => {
|
||||
setAnchorEl(event.currentTarget)
|
||||
@ -40,6 +59,11 @@ const Sidenav = () => {
|
||||
setToken(null)
|
||||
}
|
||||
|
||||
// Fonction pour vérifier si l'utilisateur est admin
|
||||
const isAdmin = () => {
|
||||
console.log('Rôle de l’utilisateur:', user?.roles)
|
||||
return user?.roles?.toLowerCase() === 'admin'
|
||||
}
|
||||
return (
|
||||
<nav className={classe.navbar}>
|
||||
<style>
|
||||
@ -82,21 +106,26 @@ const Sidenav = () => {
|
||||
</Tooltip>
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link
|
||||
to={'/notes'}
|
||||
className={classe.nav_link}
|
||||
style={{
|
||||
outline: 'none',
|
||||
borderBottom: window.location.hash == '#/notes' ? '2px solid white' : 'none'
|
||||
}}
|
||||
>
|
||||
<CgNotes className="notes" style={{ outline: 'none' }} />
|
||||
<Tooltip anchorSelect=".notes" className="custom-tooltip" place="top">
|
||||
Notes
|
||||
</Tooltip>
|
||||
</Link>
|
||||
</li>
|
||||
|
||||
{/* Navigation Notes - Visible uniquement pour les admins */}
|
||||
{isAdmin() && (
|
||||
<li>
|
||||
<Link
|
||||
to={'/notes'}
|
||||
className={classe.nav_link}
|
||||
style={{
|
||||
outline: 'none',
|
||||
borderBottom: window.location.hash == '#/notes' ? '2px solid white' : 'none'
|
||||
}}
|
||||
>
|
||||
<CgNotes className="notes" style={{ outline: 'none' }} />
|
||||
<Tooltip anchorSelect=".notes" className="custom-tooltip" place="top">
|
||||
Notes
|
||||
</Tooltip>
|
||||
</Link>
|
||||
</li>
|
||||
)}
|
||||
|
||||
<li>
|
||||
<Link
|
||||
to={'/mention'}
|
||||
@ -153,7 +182,7 @@ const Sidenav = () => {
|
||||
>
|
||||
<BsCalendar2Date className="anneescolaire" style={{ outline: 'none' }} />
|
||||
<Tooltip anchorSelect=".anneescolaire" className="custom-tooltip" place="top">
|
||||
Année Scolaire
|
||||
Année Univesitaire
|
||||
</Tooltip>
|
||||
</Link>
|
||||
</li>
|
||||
@ -187,17 +216,6 @@ const Sidenav = () => {
|
||||
</Tooltip>
|
||||
</Link>
|
||||
</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 className={classe.liste2}>
|
||||
<li>
|
||||
@ -261,14 +279,6 @@ const Sidenav = () => {
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
</li>
|
||||
{/* <li>
|
||||
<Link to={'/teste'}>
|
||||
<SiVitest className='test' style={{outline:'none'}} />
|
||||
<Tooltip anchorSelect=".test" className='custom-tooltip' place="top">
|
||||
Teste
|
||||
</Tooltip>
|
||||
</Link>
|
||||
</li> */}
|
||||
<li>
|
||||
<LuLogOut className="logout" style={{ outline: 'none' }} onClick={logout} />
|
||||
<Tooltip anchorSelect=".logout" className="custom-tooltip" place="top">
|
||||
@ -280,4 +290,4 @@ const Sidenav = () => {
|
||||
)
|
||||
}
|
||||
|
||||
export default Sidenav
|
||||
export default Sidenav
|
||||
@ -121,7 +121,7 @@ const SingleAnneeScolaire = () => {
|
||||
<div className={classeHome.blockTitle}>
|
||||
<h1 style={{ display: 'flex', alignItems: 'center', gap: '10px' }}>
|
||||
<BsCalendar2Date />
|
||||
Mise a jour Année Scolaire
|
||||
Mise a jour Année Univesitaire
|
||||
</h1>
|
||||
<Link to={'#'} onClick={() => window.history.back()}>
|
||||
<Button color="warning" variant="contained">
|
||||
@ -155,12 +155,12 @@ const SingleAnneeScolaire = () => {
|
||||
onSubmit={formSubmit}
|
||||
>
|
||||
<h4 style={{ textAlign: 'center', padding: '0 0 3% 0' }}>
|
||||
mise a jour Année Scolaire
|
||||
mise a jour Année Univesitaire
|
||||
</h4>
|
||||
<Grid container spacing={2}>
|
||||
<Grid item xs={12} sm={6}>
|
||||
<TextField
|
||||
label={'Année Scolaire'}
|
||||
label={'Année Univesitaire'}
|
||||
name={'code'}
|
||||
placeholder="2024-2025"
|
||||
color="warning"
|
||||
|
||||
@ -535,12 +535,12 @@ const SingleEtudiant = () => {
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
{/* Group Année Scolaire and Numero d'Inscription */}
|
||||
{/* Group Année Univesitaire and Numero d'Inscription */}
|
||||
<Grid container spacing={2}>
|
||||
<Grid item xs={6}>
|
||||
<TextField
|
||||
fullWidth
|
||||
label="Année Scolaire"
|
||||
label="Année Univesitaire"
|
||||
name="annee_scolaire"
|
||||
color="warning"
|
||||
defaultValue={etudiant.annee_scolaire} // Controlled component value
|
||||
@ -813,7 +813,7 @@ const SingleEtudiant = () => {
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
{/* Group Année Scolaire and Numero d'Inscription */}
|
||||
{/* Group Année Univesitaire and Numero d'Inscription */}
|
||||
<Grid container spacing={2}>
|
||||
<Grid item xs={6}>
|
||||
<TextField
|
||||
@ -1111,7 +1111,7 @@ const SingleEtudiant = () => {
|
||||
variant="h6"
|
||||
style={{ display: 'flex', justifyContent: 'space-between' }}
|
||||
>
|
||||
<span>Année Scolaire:</span> {etudiant.annee_scolaire}
|
||||
<span>Année Univesitaire:</span> {etudiant.annee_scolaire}
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
|
||||
@ -26,8 +26,18 @@ import { processPdf } from './function/PDFEditorV2'
|
||||
import { MdVerified } from 'react-icons/md'
|
||||
import warning from '../assets/warning.svg'
|
||||
import success from '../assets/success.svg'
|
||||
import { useAuthContext } from '../contexts/AuthContext' // Import du contexte d'authentification
|
||||
|
||||
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({
|
||||
components: {
|
||||
MuiIconButton: {
|
||||
@ -251,7 +261,7 @@ const Student = () => {
|
||||
*/
|
||||
const columns = [
|
||||
{ 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: 'cin', headerName: 'CIN', width: 180 },
|
||||
{ field: 'date_deli', headerName: 'Date de delivrance', width: 80 },
|
||||
@ -337,7 +347,9 @@ const Student = () => {
|
||||
>
|
||||
{/* Groupe 1 : Certificat */}
|
||||
<Link style={{ display: 'flex', gap: '10px' }}>
|
||||
<SeeNote params={params} />
|
||||
{/* Affichage conditionnel de SeeNote - uniquement pour les admins */}
|
||||
{isAdmin() && <SeeNote params={params} />}
|
||||
|
||||
<Link>
|
||||
<Button
|
||||
onClick={() => handleOpen(params.value)}
|
||||
@ -435,8 +447,8 @@ const Student = () => {
|
||||
if (etudiant) {
|
||||
let data = {
|
||||
f1: `${etudiant.nom} ${etudiant.prenom}`,
|
||||
f2: `Naissances: ${dayjs(etudiant.date_de_naissances).format('DD-MM-YYYY')}`,
|
||||
f3: `Niveau: ${etudiant.niveau}`,
|
||||
f2: `Naissance: ${dayjs(etudiant.date_de_naissances).format('DD-MM-YYYY')}`,
|
||||
f3: `Niveau: ${etudiant.niveau} ${etudiant.mentionUnite}`,
|
||||
f4: `Année: ${etudiant.annee_scolaire}`,
|
||||
f5: `Inscription: ${etudiant.num_inscription}`,
|
||||
f8: etudiant.photos
|
||||
@ -488,6 +500,7 @@ const Student = () => {
|
||||
domaine: etudiant.domaine,
|
||||
contact: etudiant.contact,
|
||||
mention_id: etudiant.mention_id,
|
||||
mentionUnite: etudiant.mentionUnite,
|
||||
action: etudiant.id // Ensure this is a valid URL for the image
|
||||
}))
|
||||
|
||||
|
||||
@ -221,8 +221,8 @@ const SystemeNote = () => {
|
||||
<tr style={{ fontWeight: 'bold' }}>
|
||||
<td style={{ color: 'gray' }}>Status :</td>
|
||||
<td style={{ color: 'gray' }}>Admis</td>
|
||||
<td style={{ color: 'gray' }}>Redouble</td>
|
||||
<td style={{ color: 'gray' }}>Renvoyer</td>
|
||||
<td style={{ color: 'gray' }}>Autorisé à redoubler</td>
|
||||
<td style={{ color: 'gray' }}>Remis à la famille</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@ -271,7 +271,7 @@ const SystemeNote = () => {
|
||||
{/* <Grid container spacing={2}> */}
|
||||
<Grid item xs={12} sm={3}>
|
||||
<TextField
|
||||
label={'Notes pour redoubler'}
|
||||
label={'Notes pour autorisé à redoubler'}
|
||||
name={'redouble'}
|
||||
color="warning"
|
||||
fullWidth
|
||||
@ -310,7 +310,7 @@ const SystemeNote = () => {
|
||||
{/* <Grid container spacing={2}> */}
|
||||
<Grid item xs={12} sm={3}>
|
||||
<TextField
|
||||
label={'Notes pour etre renvoyer'}
|
||||
label={'Notes pour etre remis à la famille'}
|
||||
name={'renvoyer'}
|
||||
color="warning"
|
||||
fullWidth
|
||||
|
||||
@ -248,11 +248,11 @@ const TesteDatagrid = ({ id, niveau, annee_scolaire, nomPrenom, inscription, ref
|
||||
</div>
|
||||
</div>
|
||||
<div style={{ fontSize: '13px', margin: '1%' }}>
|
||||
<span>Nom & Prenoms: </span>
|
||||
<span>Nom & Prénoms: </span>
|
||||
<span>{nomPrenom}</span>
|
||||
<br />
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
|
||||
<span>Année scolaire: </span>
|
||||
<span>Année Univesitaire: </span>
|
||||
<span>{annee_scolaire}</span>
|
||||
<span>Niveau: </span>
|
||||
<span>{niveau}</span>
|
||||
|
||||
@ -96,10 +96,10 @@ const UpdateModalProf = ({ open, onClose, matiere_id, onSubmitSuccess }) => {
|
||||
margin="normal"
|
||||
required
|
||||
name="prenom_enseignant"
|
||||
label="Prenom du professeur"
|
||||
label="Prénom du professeur"
|
||||
type="text"
|
||||
fullWidth
|
||||
placeholder="Prenom du professeur"
|
||||
placeholder="Prénom du professeur"
|
||||
variant="outlined"
|
||||
value={formData.prenom_enseignant}
|
||||
color="warning"
|
||||
|
||||
@ -21,7 +21,7 @@ const PDFEditor = async (data) => {
|
||||
form.getTextField('name').setText(data.f1)
|
||||
form.getTextField('birthday').setText('Date de naissance: ' + data.f2)
|
||||
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.flatten()
|
||||
|
||||
@ -73,10 +73,10 @@ const PDFEditor = async (data) => {
|
||||
// ----------------------------------------------- carte arriere -------------------------------------------
|
||||
const paperContent = `
|
||||
CUniversity
|
||||
Nom et prenom: ${data.f1}
|
||||
Nom et prénom: ${data.f1}
|
||||
Date de naissance: ${data.f2}
|
||||
Niveau: ${data.f3}
|
||||
Année scolaire: ${data.f4}
|
||||
Année Univesitaire: ${data.f4}
|
||||
Numéro d'inscription: ${data.f5}
|
||||
`
|
||||
|
||||
|
||||
@ -14,28 +14,49 @@ async function fillPdfFields(jsonData) {
|
||||
|
||||
// Get the first page to draw text on
|
||||
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)
|
||||
const textPositions = [
|
||||
{ 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: 58, text: `${jsonData.f3 || ''}`, fontSize: 10 }, // Niveau
|
||||
{ x: 45, y: 38, text: `${jsonData.f4 || ''}`, fontSize: 10 }, // Année scolaire
|
||||
{ x: 60, y: 23, text: `${jsonData.f5 || ''}`, fontSize: 10 } // Numéro d'inscription
|
||||
]
|
||||
// const textPositions = [
|
||||
// { 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: 58, text: `${jsonData.f3 || ''}`, fontSize: 10 }, // Niveau
|
||||
// { 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
|
||||
// ]
|
||||
|
||||
// Draw text at specified positions
|
||||
textPositions.forEach((item, index) => {
|
||||
if (item.text.trim()) {
|
||||
page.drawText(item.text, {
|
||||
x: item.x,
|
||||
y: item.y,
|
||||
size: item.fontSize - 2,
|
||||
color: rgb(1, 1, 1), // Black text
|
||||
})
|
||||
console.log(`Drawing text at position ${index + 1}: ${item.text} at (${item.x}, ${item.y})`)
|
||||
}
|
||||
})
|
||||
// textPositions.forEach((item, index) => {
|
||||
// if (item.text.trim()) {
|
||||
// page.drawText(item.text, {
|
||||
// x: item.x,
|
||||
// y: item.y,
|
||||
// size: item.fontSize - 2,
|
||||
// color: rgb(1, 1, 1), // Black text
|
||||
// })
|
||||
// console.log(`Drawing text at position ${index + 1}: ${item.text} at (${item.x}, ${item.y})`)
|
||||
// }
|
||||
// })
|
||||
|
||||
// ---------------------------------calculate and paste the image in pdf--------------------------------------
|
||||
if (jsonData.f8) {
|
||||
@ -79,12 +100,12 @@ async function fillPdfFields(jsonData) {
|
||||
// -------------------------------------------paste the qrCode in the pdf--------------------------------------
|
||||
|
||||
const paperContent = `
|
||||
ECOLE POLYTECHNIQUE DE TOAMASINA
|
||||
Nom et prenom: ${jsonData.f1}
|
||||
Date de naissance: ${jsonData.f2}
|
||||
Niveau: ${jsonData.f3}
|
||||
Année scolaire: ${jsonData.f4}
|
||||
Numéro d'inscription: ${jsonData.f5}
|
||||
ECOLE SUPERIEURE POLYTECHNIQUE DE TOAMASINA
|
||||
${jsonData.f1}
|
||||
${jsonData.f2}
|
||||
${jsonData.f3}
|
||||
${jsonData.f4}
|
||||
${jsonData.f5}
|
||||
`
|
||||
|
||||
const qrCanvas = document.createElement('canvas')
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/**
|
||||
* function validation année scolaire form
|
||||
* function validation Année Univesitaire form
|
||||
* @param {*} code
|
||||
* @param {*} debut
|
||||
* @param {*} fin
|
||||
|
||||
@ -1,38 +1,84 @@
|
||||
import { createContext, useContext, useState } from 'react'
|
||||
import { createContext, useContext, useState, useEffect } from 'react'
|
||||
|
||||
const AuthContext = createContext({
|
||||
user: null,
|
||||
token: null,
|
||||
setUser: () => {},
|
||||
setToken: () => {}
|
||||
setToken: () => {},
|
||||
isAuthenticated: false
|
||||
})
|
||||
|
||||
export const AuthContextProvider = ({ children }) => {
|
||||
const [user, setUser] = useState()
|
||||
const [token, _setToken] = useState(localStorage.getItem('ACCESS_TOKEN'))
|
||||
// Initialiser avec null explicitement
|
||||
const [user, setUser] = useState(null)
|
||||
const [token, _setToken] = useState(null)
|
||||
const [isLoading, setIsLoading] = useState(true)
|
||||
|
||||
const setToken = (token) => {
|
||||
_setToken(token)
|
||||
// Initialiser depuis localStorage au montage
|
||||
useEffect(() => {
|
||||
const storedToken = localStorage.getItem('ACCESS_TOKEN')
|
||||
const storedUser = localStorage.getItem('USER_DATA')
|
||||
|
||||
if (storedToken) {
|
||||
_setToken(storedToken)
|
||||
}
|
||||
|
||||
if (storedUser) {
|
||||
try {
|
||||
setUser(JSON.parse(storedUser))
|
||||
} catch (error) {
|
||||
console.error('Erreur parsing user data:', error)
|
||||
localStorage.removeItem('USER_DATA')
|
||||
}
|
||||
}
|
||||
|
||||
setIsLoading(false)
|
||||
}, [])
|
||||
|
||||
if (token) {
|
||||
localStorage.setItem('ACCESS_TOKEN', token)
|
||||
const setToken = (newToken) => {
|
||||
_setToken(newToken)
|
||||
|
||||
if (newToken) {
|
||||
localStorage.setItem('ACCESS_TOKEN', newToken)
|
||||
} else {
|
||||
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 (
|
||||
<AuthContext.Provider
|
||||
value={{
|
||||
user,
|
||||
token,
|
||||
setUser,
|
||||
setToken
|
||||
}}
|
||||
>
|
||||
<AuthContext.Provider value={contextValue}>
|
||||
{children}
|
||||
</AuthContext.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
export const useAuthContext = () => useContext(AuthContext)
|
||||
export const useAuthContext = () => useContext(AuthContext)
|
||||
@ -26,7 +26,7 @@
|
||||
<p><b>Prenom</b> : Joseph Fabrice</p>
|
||||
<p><b>Date de naissance</b> : 11-12-2001</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>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -21,7 +21,7 @@
|
||||
<h3>RELEVÉE DE NOTE</h3>
|
||||
<p><strong>Nom & Prenoms :</strong> F3</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><strong>N° inscription :</strong> F42</p>
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user