This commit is contained in:
andrymodeste 2025-08-13 13:33:36 +02:00
parent e5b4933076
commit f1aefc3073
45 changed files with 1059 additions and 774 deletions

View File

@ -71,13 +71,13 @@ async function deleteAnneeScolaire(id) {
if (result.affectedRows === 0) { if (result.affectedRows === 0) {
return { return {
success: false, success: false,
message: 'Année universitaire non trouvé.' message: 'Année Scolaire non trouvé.'
} }
} }
return { return {
success: true, success: true,
message: 'Année universitaire supprimé avec succès.' message: 'Année Scolaire supprimé avec succès.'
} }
} catch (error) { } catch (error) {
return { success: false, error: 'Erreur veullez réeseyer' } return { success: false, error: 'Erreur veullez réeseyer' }
@ -93,13 +93,13 @@ async function updateAnneeScolaire(id, code, debut, fin) {
if (result.affectedRows === 0) { if (result.affectedRows === 0) {
return { return {
success: false, success: false,
message: 'Année universitaire non trouvé ou aucune modification effectuée.' message: 'Année Scolaire non trouvé ou aucune modification effectuée.'
} }
} }
return { return {
success: true, success: true,
message: 'Année universitaire mis à jour avec succès.' message: 'Année Scolaire mis à jour avec succès.'
} }
} catch (error) { } catch (error) {
return { success: false, error: 'Erreur veullez réeseyer' } return { success: false, error: 'Erreur veullez réeseyer' }

View File

@ -280,6 +280,18 @@ async function deleteTranche(id) {
} }
} }
async function deleteEtudiant(id) {
const query = database.prepare('DELETE FROM etudiants WHERE id = ?')
try {
let response = query.run(id)
return response
} catch (error) {
return error
}
}
async function getSingleTranche(id) { async function getSingleTranche(id) {
try { try {
return await database.prepare('SELECT * FROM trancheecolage WHERE id = ?').get(id) return await database.prepare('SELECT * FROM trancheecolage WHERE id = ?').get(id)
@ -301,5 +313,6 @@ module.exports = {
getTranche, getTranche,
updateTranche, updateTranche,
deleteTranche, deleteTranche,
deleteEtudiant,
getSingleTranche getSingleTranche
} }

View File

@ -176,13 +176,13 @@ async function updateEtudiant(
if (result.affectedRows === 0) { if (result.affectedRows === 0) {
return { return {
success: false, success: false,
message: 'Année universitaire non trouvé.' message: 'Année Scolaire non trouvé.'
} }
} }
return { return {
success: true, success: true,
message: 'Année universitaire supprimé avec succès.' message: 'Année Scolaire supprimé avec succès.'
} }
} catch (error) { } catch (error) {
return error return error
@ -222,13 +222,13 @@ async function changePDP(photos, id) {
if (result.affectedRows === 0) { if (result.affectedRows === 0) {
return { return {
success: false, success: false,
message: 'Année universitaire non trouvé.' message: 'Année Scolaire non trouvé.'
} }
} }
return { return {
success: true, success: true,
message: 'Année universitaire supprimé avec succès.' message: 'Année Scolaire supprimé avec succès.'
} }
} catch (error) { } catch (error) {
return error return error
@ -244,13 +244,13 @@ async function updateParcours(parcours, id) {
if (result.affectedRows === 0) { if (result.affectedRows === 0) {
return { return {
success: false, success: false,
message: 'Année universitaire non trouvé.' message: 'Année Scolaire non trouvé.'
} }
} }
return { return {
success: true, success: true,
message: 'Année universitaire supprimé avec succès.' message: 'Année Scolaire supprimé avec succès.'
} }
} catch (error) { } catch (error) {
return error return error
@ -289,19 +289,21 @@ async function updateTranche(id, tranchename, montant) {
try { try {
const [result] = await pool.query(sql, [tranchename, montant, id]) const [result] = await pool.query(sql, [tranchename, montant, id])
console.log('resultat tranche:',result);
if (result.affectedRows === 0) { if (result.affectedRows === 0) {
return { return {
success: false, success: false,
message: 'Année universitaire non trouvé.' message: 'Année Scolaire non trouvé.'
} }
} }
return { return {
success: true, success: true,
message: 'Année universitaire supprimé avec succès.' message: 'Année Scolaire supprimé avec succès.'
} }
} catch (error) { } catch (error) {
console.log('resultat error:',error);
return error return error
} }
} }
@ -315,19 +317,45 @@ async function deleteTranche(id) {
if (result.affectedRows === 0) { if (result.affectedRows === 0) {
return { return {
success: false, success: false,
message: 'Année universitaire non trouvé.' message: 'Année Scolaire non trouvé.'
} }
} }
return { return {
success: true, success: true,
message: 'Année universitaire supprimé avec succès.' message: 'Année Scolaire supprimé avec succès.'
} }
} catch (error) { } catch (error) {
return error return error
} }
} }
async function deleteEtudiant(id) {
console.log("id: ", id);
const sql = 'DELETE FROM etudiants WHERE id = ?';
try {
let [result] = await pool.query(sql, [id]);
console.log("Résultat DELETE:", result);
if (result.affectedRows === 0) {
return {
success: false,
message: 'Etudiant non trouvée.'
};
}
return {
success: true,
message: 'Matière supprimée avec succès.'
};
} catch (error) {
console.log("err: ",+ error)
return { success: false, error: 'Erreur, veuillez réessayer: ' + error };
}
}
async function getSingleTranche(id) { async function getSingleTranche(id) {
const sql = 'SELECT * FROM trancheecolage WHERE id = ?' const sql = 'SELECT * FROM trancheecolage WHERE id = ?'
try { try {
@ -351,5 +379,6 @@ module.exports = {
getTranche, getTranche,
updateTranche, updateTranche,
deleteTranche, deleteTranche,
deleteEtudiant,
getSingleTranche getSingleTranche
} }

View File

@ -29,7 +29,7 @@ async function createMatiere(nom, credit, uniter, ue) {
* @returns Promise * @returns Promise
*/ */
async function getMatiere() { async function getMatiere() {
const query = database.prepare('SELECT * FROM matieres ORDER BY id DESC') const query = database.prepare('SELECT m.*, n.nom AS niveau_nom FROM matieres m LEFT JOIN niveaus n ON m.niveau_id = n.id ORDER BY m.id DESC')
try { try {
let response = await query.all() let response = await query.all()
@ -141,6 +141,35 @@ async function updateMatiere(nom, id, credit, uniter, ue) {
} }
} }
async function updateMatiereNiveau(formData) {
console.log('formdata:', formData);
const { niveau_id, id } = formData;
const sql = 'UPDATE matieres SET niveau_id = ? WHERE id = ?';
try {
const [result] = await pool.query(sql, [niveau_id, id]);
if (result.affectedRows === 0) {
return {
success: false,
message: 'Matière non trouvée ou aucune modification effectuée.'
};
}
return {
success: true,
message: 'Niveau mis à jour avec succès.'
};
} catch (error) {
console.error(error);
return {
success: false,
error: 'Erreur lors de la mise à jour du niveau : ' + error.message
};
}
}
async function deleteMatiere(id) { async function deleteMatiere(id) {
const query = database.prepare('DELETE FROM matieres WHERE id = ?') const query = database.prepare('DELETE FROM matieres WHERE id = ?')
@ -340,6 +369,7 @@ module.exports = {
getMatiere, getMatiere,
getSingleMatiere, getSingleMatiere,
updateMatiere, updateMatiere,
updateMatiereNiveau,
displayMatiereFromForm, displayMatiereFromForm,
deleteMatiere, deleteMatiere,
asygnationToMention, asygnationToMention,

View File

@ -31,7 +31,7 @@ async function createMatiere(nom, credit, uniter, ue) {
* @returns Promise * @returns Promise
*/ */
async function getMatiere() { async function getMatiere() {
const sql = 'SELECT * FROM matieres ORDER BY id DESC' const sql = 'SELECT m.*, n.nom AS niveau_nom FROM matieres m LEFT JOIN niveaus n ON m.niveau_id = n.id ORDER BY m.id DESC'
try { try {
let [rows] = await pool.query(sql) let [rows] = await pool.query(sql)
@ -149,41 +149,71 @@ async function updateMatiere(nom, id, credit, uniter, ue) {
if (result.affectedRows === 0) { if (result.affectedRows === 0) {
return { return {
success: false, success: false,
message: 'Année universitaire non trouvé ou aucune modification effectuée.' message: 'Année Scolaire non trouvé ou aucune modification effectuée.'
} }
} }
return { return {
success: true, success: true,
message: 'Année universitaire mis à jour avec succès.' message: 'Année Scolaire mis à jour avec succès.'
} }
} catch (error) { } catch (error) {
return { success: false, error: 'Erreur veullez réeseyer' + error } return { success: false, error: 'Erreur veullez réeseyer' + error }
} }
} }
async function updateMatiereNiveau(formData) {
async function deleteMatiere(id) { const { niveau_id, id } = formData; // ici id sera bien défini
const sql = 'DELETE FROM matieres WHERE id = ?' const sql = 'UPDATE matieres SET niveau_id = ? WHERE id = ?';
try { try {
let [result] = await pool.query(sql, [id]) const [result] = await pool.query(sql, [niveau_id, id]);
if (result.affectedRows === 0) { if (result.affectedRows === 0) {
return { return {
success: false, success: false,
message: 'Année universitaire non trouvé.' message: `Matière avec id ${id} non trouvée ou niveau déjà attribué.`
} };
} }
return { return {
success: true, success: true,
message: 'Année universitaire supprimé avec succès.' message: `Niveau de la matière ${id} mis à jour avec succès.`
} };
} catch (error) { } catch (error) {
return { success: false, error: 'Erreur veullez réeseyer' + error } return {
success: false,
error: 'Erreur lors de la mise à jour : ' + error.message
};
} }
} }
async function deleteMatiere(id) {
console.log("id: ", id);
const sql = 'DELETE FROM matieres WHERE id = ?';
try {
let [result] = await pool.query(sql, [id]);
console.log("Résultat DELETE:", result);
if (result.affectedRows === 0) {
return {
success: false,
message: 'Matière non trouvée.'
};
}
return {
success: true,
message: 'Matière supprimée avec succès.'
};
} catch (error) {
console.log("err: ",+ error)
return { success: false, error: 'Erreur, veuillez réessayer: ' + error };
}
}
/** /**
* Assign mentions to a matiere * Assign mentions to a matiere
* @param {Object} formData - keys = mention_ids, values = true/false * @param {Object} formData - keys = mention_ids, values = true/false
@ -444,13 +474,13 @@ async function updateProf(matiere_id, nom, prenom, contact, date) {
if (result.affectedRows === 0) { if (result.affectedRows === 0) {
return { return {
success: false, success: false,
message: 'Année universitaire non trouvé.' message: 'Année Scolaire non trouvé.'
} }
} }
return { return {
success: true, success: true,
message: 'Année universitaire supprimé avec succès.' message: 'Année Scolaire supprimé avec succès.'
} }
} catch (error) { } catch (error) {
console.error(error) console.error(error)
@ -464,6 +494,7 @@ module.exports = {
getMatiere, getMatiere,
getSingleMatiere, getSingleMatiere,
updateMatiere, updateMatiere,
updateMatiereNiveau,
displayMatiereFromForm, displayMatiereFromForm,
deleteMatiere, deleteMatiere,
asygnationToMention, asygnationToMention,

View File

@ -24,13 +24,13 @@ async function deleteMention(id) {
if (result.affectedRows === 0) { if (result.affectedRows === 0) {
return { return {
success: false, success: false,
message: 'Année universitaire non trouvé.' message: 'Année Scolaire non trouvé.'
} }
} }
return { return {
success: true, success: true,
message: 'Année universitaire supprimé avec succès.' message: 'Année Scolaire supprimé avec succès.'
} }
} catch (error) { } catch (error) {
return { success: false, error: 'Erreur veullez réeseyer' + error } return { success: false, error: 'Erreur veullez réeseyer' + error }
@ -70,13 +70,13 @@ async function updateMention(nom, uniter, id) {
if (result.affectedRows === 0) { if (result.affectedRows === 0) {
return { return {
success: false, success: false,
message: 'Année universitaire non trouvé ou aucune modification effectuée.' message: 'Année Scolaire non trouvé ou aucune modification effectuée.'
} }
} }
return { return {
success: true, success: true,
message: 'Année universitaire mis à jour avec succès.' message: 'Année Scolaire mis à jour avec succès.'
} }
} catch (error) { } catch (error) {
return { success: false, error: 'Erreur veullez réeseyer' + error } return { success: false, error: 'Erreur veullez réeseyer' + error }

View File

@ -89,17 +89,18 @@ async function updateNiveau(nom, id) {
* function to get all niveau * function to get all niveau
*/ */
async function getNiveau() { async function getNiveau() {
const sql = 'SELECT * FROM niveaus' const sql = 'SELECT niveaus.*,niveaus.id AS niveau_id FROM niveaus'
try { try {
let [rows] = await pool.query(sql) let [rows] = await pool.query(sql)
console.log("maka niveau: ", rows);
return rows return rows
} catch (error) { } catch (error) {
return { success: false, error: 'Erreur veullez réeseyer' } return { success: false, error: 'Erreur veullez réeseyer' }
} }
} }
async function deleteNiveau(id) { async function deleteNiveau(id) {
const sql = 'DELETE FROM niveaus WHERE id = ?' const sql = 'DELETE FROM niveaus WHERE id = ?'
@ -130,5 +131,5 @@ module.exports = {
insertNiveau, insertNiveau,
getSingleNiveau, getSingleNiveau,
updateNiveau, updateNiveau,
deleteNiveau deleteNiveau,
} }

View File

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

View File

@ -30,7 +30,7 @@ async function getParcourMatiere(id) {
} }
async function getParcours() { async function getParcours() {
const sql = 'SELECT * FROM parcours ORDER BY id DESC' const sql = 'SELECT parcours.*, mentions.nom AS mention_nom FROM parcours LEFT JOIN mentions ON parcours.mention_id = mentions.id ORDER BY parcours.id DESC'
try { try {
let [rows] = await pool.query(sql) let [rows] = await pool.query(sql)
@ -62,13 +62,13 @@ async function deletes(id) {
if (result.affectedRows === 0) { if (result.affectedRows === 0) {
return { return {
success: false, success: false,
message: 'Année universitaire non trouvé.' message: 'Année Scolaire non trouvé.'
} }
} }
return { return {
success: true, success: true,
message: 'Année universitaire supprimé avec succès.' message: 'Année Scolaire supprimé avec succès.'
} }
} catch (error) { } catch (error) {
return error return error
@ -84,13 +84,13 @@ async function updateparcour(id, nom, uniter, mention_id) {
if (result.affectedRows === 0) { if (result.affectedRows === 0) {
return { return {
success: false, success: false,
message: 'Année universitaire non trouvé ou aucune modification effectuée.' message: 'Année Scolaire non trouvé ou aucune modification effectuée.'
} }
} }
return { return {
success: true, success: true,
message: 'Année universitaire mis à jour avec succès.' message: 'Année Scolaire mis à jour avec succès.'
} }
} catch (error) { } catch (error) {
return error return error

View File

@ -1,444 +1,307 @@
const sqlite = require('better-sqlite3') const mysql = require('mysql2/promise')
const bcrypt = require('bcryptjs') const bcrypt = require('bcryptjs')
const pool = mysql.createPool({
host: '127.0.0.1',
user: 'root',
password: '',
database: 'university',
waitForConnections: true,
connectionLimit: 10,
queueLimit: 0
})
// Construct the database path using the detected IP async function createTables() {
let dbPath = `./base/data.db`; const connection = await pool.getConnection()
// Connect to SQLite database with the initial path try {
let database = new sqlite(dbPath); // Users table
await connection.query(`
// Create the users table if it doesn't exist
const createUserTableQuery = `
CREATE TABLE IF NOT EXISTS users ( CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(200) NOT NULL, username VARCHAR(200) NOT NULL,
email VARCHAR(250) NOT NULL UNIQUE, email VARCHAR(250) NOT NULL UNIQUE,
password TEXT NOT NULL, password TEXT NOT NULL,
roles VARCHAR(250) NOT NULL, roles VARCHAR(250) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
); ) ENGINE=InnoDB;
` `)
database.prepare(createUserTableQuery).run()
// Insert a default admin user if not exists // Status table
const insertDefaultUserQuery = ` await connection.query(`
INSERT INTO users (username, email, password, roles)
SELECT 'admin', 'admin@example.com', ?, 'admin'
WHERE NOT EXISTS (SELECT 1 FROM users WHERE username = 'admin');
`
// Hash the password '1234' before storing
const hashedPassword = bcrypt.hashSync('123456789', 10)
database.prepare(insertDefaultUserQuery).run(hashedPassword)
// create table for note status
const createStatusTableQuery = `
CREATE TABLE IF NOT EXISTS status ( CREATE TABLE IF NOT EXISTS status (
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, id INT AUTO_INCREMENT PRIMARY KEY,
nom VARCHAR(200) NOT NULL, nom VARCHAR(200) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
); ) ENGINE=InnoDB;
` `)
database.prepare(createStatusTableQuery).run()
// create table for mention // Mentions table
const createMentionTableQuery = ` await connection.query(`
CREATE TABLE IF NOT EXISTS mentions ( CREATE TABLE IF NOT EXISTS mentions (
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, id INT AUTO_INCREMENT PRIMARY KEY,
nom VARCHAR(250) NOT NULL, nom VARCHAR(250) NOT NULL,
uniter VARCHAR(50) NOT NULL, -- Abréviation du nom uniter VARCHAR(50) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
); ) ENGINE=InnoDB;
` `)
database.prepare(createMentionTableQuery).run()
// Create the niveau table if it doesn't exist await connection.query(`
const createNiveauTableQuery = `
CREATE TABLE IF NOT EXISTS niveaus ( CREATE TABLE IF NOT EXISTS niveaus (
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, id INT AUTO_INCREMENT PRIMARY KEY,
nom VARCHAR(50) NOT NULL, -- Exemple: L1, L2, L3, etc. nom VARCHAR(50) UNIQUE NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
); ) ENGINE=InnoDB;
` `)
database.prepare(createNiveauTableQuery).run()
// Create the etudiants table if it doesn't exist await connection.query(`
const createEtudiantsTableQuery = `
CREATE TABLE IF NOT EXISTS etudiants ( CREATE TABLE IF NOT EXISTS etudiants (
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, id INT AUTO_INCREMENT PRIMARY KEY,
nom VARCHAR(250) DEFAULT NULL, nom VARCHAR(250) DEFAULT NULL,
prenom VARCHAR(250) DEFAULT NULL, prenom VARCHAR(250) DEFAULT NULL,
photos TEXT DEFAULT NULL, photos TEXT DEFAULT NULL,
date_de_naissances DATE DEFAULT NULL, date_de_naissances DATE DEFAULT NULL,
niveau VARCHAR(250) NOT NULL, -- Clé étrangère vers niveaus niveau VARCHAR(250) NOT NULL,
annee_scolaire VARCHAR(20) NOT NULL, annee_scolaire VARCHAR(20) NOT NULL,
status INTEGER DEFAULT NULL, status INT DEFAULT NULL,
mention_id INTEGER NOT NULL, -- Clé étrangère vers mentions mention_id INT NOT NULL,
num_inscription TEXT NOT NULL, num_inscription TEXT UNIQUE NOT NULL,
sexe VARCHAR(20) DEFAULT NULL, sexe VARCHAR(20) DEFAULT NULL,
cin VARCHAR(250) DEFAULT NULL, cin VARCHAR(250) DEFAULT NULL,
date_delivrance DEFAULT NULL, date_delivrance TEXT DEFAULT NULL,
nationalite DATE DEFAULT NULL, nationalite VARCHAR(250) DEFAULT NULL,
annee_bacc DATE DEFAULT NULL, annee_bacc TEXT DEFAULT NULL,
serie VARCHAR(20) DEFAULT NULL, serie VARCHAR(20) DEFAULT NULL,
boursier BOOLEAN DEFAULT FALSE, boursier VARCHAR(20) DEFAULT NULL,
domaine VARCHAR(250) DEFAULT NULL, domaine VARCHAR(250) DEFAULT NULL,
contact VARCHAR(20) DEFAULT NULL, contact VARCHAR(20) DEFAULT NULL,
parcours VARCHAR(250) DEFAULT NULL, parcours VARCHAR(250) DEFAULT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (status) REFERENCES status(id), FOREIGN KEY (status) REFERENCES status(id),
FOREIGN KEY (mention_id) REFERENCES mentions(id) FOREIGN KEY (mention_id) REFERENCES mentions(id)
); ) ENGINE=InnoDB;
` `)
database.prepare(createEtudiantsTableQuery).run()
// Create the notes table if it doesn't exist await connection.query(`
const createMatiereTableQuery = `
CREATE TABLE IF NOT EXISTS matieres ( CREATE TABLE IF NOT EXISTS matieres (
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, id INT AUTO_INCREMENT PRIMARY KEY,
nom VARCHAR(250) UNIQUE NOT NULL, nom VARCHAR(250) UNIQUE NOT NULL,
unite_enseignement VARCHAR(250) NOT NULL, unite_enseignement VARCHAR(250) NOT NULL,
credit INTEGER NOT NULL, credit INT NOT NULL,
heure INTEGER NOT NULL, heure INT NOT NULL,
ue VARCHAR(10) NOT NULL, ue VARCHAR(10) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
); ) ENGINE=InnoDB;
` `)
database.prepare(createMatiereTableQuery).run()
// Create the semestre table if it doesn't exist await connection.query(`
const createSemestreTableQuery = `
CREATE TABLE IF NOT EXISTS semestres ( CREATE TABLE IF NOT EXISTS semestres (
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, id INT AUTO_INCREMENT PRIMARY KEY,
nom VARCHAR(30) NOT NULL, -- Exemple: S1, S2, S3, etc. nom VARCHAR(30) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
); ) ENGINE=InnoDB;
` `)
database.prepare(createSemestreTableQuery).run()
// Create the semestre table if it doesn't exist await connection.query(`
const createMatiere_mentionTableQuery = `
CREATE TABLE IF NOT EXISTS matiere_mention ( CREATE TABLE IF NOT EXISTS matiere_mention (
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, id INT AUTO_INCREMENT PRIMARY KEY,
matiere_id INTEGER NOT NULL, -- Clé étrangère vers matieres matiere_id INT NOT NULL,
mention_id INTEGER NOT NULL, -- Clé étrangère vers mentions mention_id INT NOT NULL,
FOREIGN KEY (matiere_id) REFERENCES matieres(id), FOREIGN KEY (matiere_id) REFERENCES matieres(id),
FOREIGN KEY (mention_id) REFERENCES mentions(id) FOREIGN KEY (mention_id) REFERENCES mentions(id)
); ) ENGINE=InnoDB;
` `)
database.prepare(createMatiere_mentionTableQuery).run()
const createMatiere_semestreTableQuery = ` await connection.query(`
CREATE TABLE IF NOT EXISTS matiere_semestre ( CREATE TABLE IF NOT EXISTS matiere_semestre (
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, id INT AUTO_INCREMENT PRIMARY KEY,
matiere_id INTEGER NOT NULL, -- Clé étrangère vers matieres matiere_id INT NOT NULL,
semestre_id INTEGER NOT NULL, -- Clé étrangère vers semestres semestre_id INT NOT NULL,
mention_id INTEGER NOT NULL, -- Clé étrangère vers niveaus mention_id INT NOT NULL,
FOREIGN KEY (matiere_id) REFERENCES matieres(id), FOREIGN KEY (matiere_id) REFERENCES matieres(id),
FOREIGN KEY (semestre_id) REFERENCES semestres(id), FOREIGN KEY (semestre_id) REFERENCES semestres(id),
FOREIGN KEY (mention_id) REFERENCES mentions(id) FOREIGN KEY (mention_id) REFERENCES mentions(id)
); ) ENGINE=InnoDB;
` `)
database.prepare(createMatiere_semestreTableQuery).run()
// Create the notes table if it doesn't exist await connection.query(`
const createNoteTableQuery = `
CREATE TABLE IF NOT EXISTS notes ( CREATE TABLE IF NOT EXISTS notes (
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, id INT AUTO_INCREMENT PRIMARY KEY,
etudiant_id INTEGER NOT NULL, -- Clé étrangère vers etudiants etudiant_id INT NOT NULL,
matiere_id INTEGER NOT NULL, -- Clé étrangère vers matieres matiere_id INT NOT NULL,
etudiant_niveau VARCHAR(50) NOT NULL, etudiant_niveau VARCHAR(50) NOT NULL,
mention_id INTEGER NOT NULL, mention_id INT NOT NULL,
note FLOAT DEFAULT NULL, note FLOAT DEFAULT NULL,
annee_scolaire VARCHAR(50) NOT NULL, annee_scolaire VARCHAR(50) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (etudiant_id) REFERENCES etudiants(id), FOREIGN KEY (etudiant_id) REFERENCES etudiants(id),
FOREIGN KEY (matiere_id) REFERENCES matieres(id) FOREIGN KEY (matiere_id) REFERENCES matieres(id),
FOREIGN KEY (mention_id) REFERENCES mentions(id) FOREIGN KEY (mention_id) REFERENCES mentions(id)
); ) ENGINE=InnoDB;
` `)
database.prepare(createNoteTableQuery).run()
// Create the notes second session table if it doesn't exist await connection.query(`
const createNoteRepechTableQuery = `
CREATE TABLE IF NOT EXISTS notesrepech ( CREATE TABLE IF NOT EXISTS notesrepech (
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, id INT AUTO_INCREMENT PRIMARY KEY,
etudiant_id INTEGER NOT NULL, -- Clé étrangère vers etudiants etudiant_id INT NOT NULL,
matiere_id INTEGER NOT NULL, -- Clé étrangère vers matieres matiere_id INT NOT NULL,
etudiant_niveau VARCHAR(50) NOT NULL, etudiant_niveau VARCHAR(50) NOT NULL,
mention_id INTEGER NOT NULL, mention_id INT NOT NULL,
note FLOAT DEFAULT NULL, note FLOAT DEFAULT NULL,
annee_scolaire VARCHAR(50) NOT NULL, annee_scolaire VARCHAR(50) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (etudiant_id) REFERENCES etudiants(id), FOREIGN KEY (etudiant_id) REFERENCES etudiants(id),
FOREIGN KEY (matiere_id) REFERENCES matieres(id) FOREIGN KEY (matiere_id) REFERENCES matieres(id),
FOREIGN KEY (mention_id) REFERENCES mentions(id) FOREIGN KEY (mention_id) REFERENCES mentions(id)
); ) ENGINE=InnoDB;
` `)
database.prepare(createNoteRepechTableQuery).run()
// create table for note système await connection.query(`
const createNoteSystemeTableQuery = `
CREATE TABLE IF NOT EXISTS notesystems ( CREATE TABLE IF NOT EXISTS notesystems (
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, id INT AUTO_INCREMENT PRIMARY KEY,
admis FLOAT NOT NULL DEFAULT 10, admis FLOAT NOT NULL DEFAULT 10,
redouble FLOAT NOT NULL DEFAULT 9.99, redouble FLOAT NOT NULL DEFAULT 9.99,
renvoyer FLOAT NOT NULL DEFAULT 7.99, renvoyer FLOAT NOT NULL DEFAULT 7.99,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
); ) ENGINE=InnoDB;
` `)
database.prepare(createNoteSystemeTableQuery).run()
// create table année scolaire await connection.query(`
const createAnneeScolaireTableQuery = `
CREATE TABLE IF NOT EXISTS anneescolaire ( CREATE TABLE IF NOT EXISTS anneescolaire (
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, id INT AUTO_INCREMENT PRIMARY KEY,
code VARCHAR(30) NOT NULL, code VARCHAR(30) NOT NULL,
debut DATE NOT NULL, debut DATE NOT NULL,
fin DATE NOT NULL, fin DATE NOT NULL,
is_current INTEGER DEFAULT 0, is_current TINYINT(1) DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
); ) ENGINE=InnoDB;
` `)
database.prepare(createAnneeScolaireTableQuery).run()
// create traitement systeme await connection.query(`
const createTraitementSystemQuery = `
CREATE TABLE IF NOT EXISTS traitmentsystem ( CREATE TABLE IF NOT EXISTS traitmentsystem (
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, id INT AUTO_INCREMENT PRIMARY KEY,
code VARCHAR(30) NOT NULL, code VARCHAR(30) NOT NULL,
debut DATE NOT NULL, debut DATE NOT NULL,
fin DATE NOT NULL, fin DATE NOT NULL,
is_finished INTEGER DEFAULT 0, is_finished TINYINT(1) DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
); ) ENGINE=InnoDB;
` `)
database.prepare(createTraitementSystemQuery).run()
const createNecessaryParameterTableQuery = ` await connection.query(`
CREATE TABLE IF NOT EXISTS nessesaryTable ( CREATE TABLE IF NOT EXISTS nessesaryTable (
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, id INT AUTO_INCREMENT PRIMARY KEY,
uniter_heure INTEGER NOT NULL, uniter_heure INT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
); ) ENGINE=InnoDB;
` `)
database.prepare(createNecessaryParameterTableQuery).run()
const createMatiereEnseignantTableQuery = ` await connection.query(`
CREATE TABLE IF NOT EXISTS matiereEnseignants ( CREATE TABLE IF NOT EXISTS matiereEnseignants (
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, id INT AUTO_INCREMENT PRIMARY KEY,
matiere_id INTEGER NOT NULL, matiere_id INT NOT NULL,
nom_enseignant VARCHAR(250) NOT NULL, nom_enseignant VARCHAR(250) NOT NULL,
prenom_enseignant VARCHAR(250) NOT NULL, prenom_enseignant VARCHAR(250) NOT NULL,
contact VARCHAR(11) NOT NULL, contact VARCHAR(11) NOT NULL,
date DATE NOT NULL, date DATE NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (matiere_id) REFERENCES matieres(id) FOREIGN KEY (matiere_id) REFERENCES matieres(id)
); ) ENGINE=InnoDB;
` `)
database.prepare(createMatiereEnseignantTableQuery).run()
const createParcourTableQuery = ` await connection.query(`
CREATE TABLE IF NOT EXISTS parcours ( CREATE TABLE IF NOT EXISTS parcours (
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, id INT AUTO_INCREMENT PRIMARY KEY,
nom VARCHAR(250) NOT NULL, nom VARCHAR(250) NOT NULL,
uniter VARCHAR(250) NOT NULL, uniter VARCHAR(250) NOT NULL,
mention_id INTEGER DEFAULT NULL, -- Clé étrangère vers mentions mention_id INT DEFAULT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
); ) ENGINE=InnoDB;
` `)
database.prepare(createParcourTableQuery).run()
const createParcourSemestreTableQuery = ` await connection.query(`
CREATE TABLE IF NOT EXISTS parcoursmatiere ( CREATE TABLE IF NOT EXISTS parcoursmatiere (
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, id INT AUTO_INCREMENT PRIMARY KEY,
matiere_id INTEGER NOT NULL, matiere_id INT NOT NULL,
parcour_id INTEGER NOT NULL, parcour_id INT NOT NULL,
FOREIGN KEY (matiere_id) REFERENCES matieres(id), FOREIGN KEY (matiere_id) REFERENCES matieres(id),
FOREIGN KEY (parcour_id) REFERENCES parcours(id) FOREIGN KEY (parcour_id) REFERENCES parcours(id)
); ) ENGINE=InnoDB;
` `)
database.prepare(createParcourSemestreTableQuery).run()
const createTableEcolageQuery = ` await connection.query(`
CREATE TABLE IF NOT EXISTS trancheecolage ( CREATE TABLE IF NOT EXISTS trancheecolage (
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, id INT AUTO_INCREMENT PRIMARY KEY,
etudiant_id INTEGER NOT NULL, etudiant_id INT NOT NULL,
tranchename VARCHAR(255) NOT NULL, tranchename VARCHAR(255) NOT NULL,
montant DOUBLE NOT NULL montant DOUBLE NOT NULL
); ) ENGINE=InnoDB;
` `)
database.prepare(createTableEcolageQuery).run()
const createTableStoreIP = ` await connection.query(`
CREATE TABLE IF NOT EXISTS ipconfig ( CREATE TABLE IF NOT EXISTS ipconfig (
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, id INT AUTO_INCREMENT PRIMARY KEY,
ipname VARCHAR(255) NOT NULL ipname VARCHAR(255) NOT NULL
); ) ENGINE=InnoDB;
`; `)
database.prepare(createTableStoreIP).run() } finally {
connection.release()
}
}
// -------------------------------------- function pre-excuter -------------------------------------------- async function insertDefaultAdmin() {
const conn = await pool.getConnection()
try {
const [rows] = await conn.query(`SELECT COUNT(*) as count FROM users WHERE username = ?`, [
'admin'
])
if (rows[0].count === 0) {
const hashedPassword = bcrypt.hashSync('123456789', 10)
await conn.query(
`
INSERT INTO users (username, email, password, roles)
VALUES (?, ?, ?, ?)`,
['admin', 'admin@example.com', hashedPassword, 'admin']
)
}
} finally {
conn.release()
}
}
async function insertStatusesIfNotExist() { async function insertStatusesIfNotExist() {
// Préparation des requêtes const conn = await pool.getConnection()
const checkStatusQuery = database.prepare(`
SELECT COUNT(*) AS count FROM status WHERE nom = ?;
`)
const insertStatusQuery = database.prepare(`
INSERT INTO status (nom) VALUES (?);
`)
// Tableau des statuts à vérifier/insérer
const arrayStatus = ['Nouveau', 'Passant', 'Redoublant', 'Renvoyé', 'Ancien']
for (let index = 0; index < arrayStatus.length; index++) {
const statusName = arrayStatus[index]
// Vérification si le statut existe déjà
const result = checkStatusQuery.get(statusName)
// Si le statut n'existe pas, on l'insère
if (result.count === 0) {
insertStatusQuery.run(statusName)
}
}
}
// execute the function
insertStatusesIfNotExist()
async function insertDefaultNoteSystemIfNotExist() {
// Préparation de la requête pour vérifier si une entrée existe déjà
const checkNoteSystemQuery = database.prepare(`
SELECT COUNT(*) AS count FROM notesystems;
`)
// Préparation de la requête pour insérer une entrée par défaut
const insertNoteSystemQuery = database.prepare(`
INSERT INTO notesystems (admis, redouble, renvoyer)
VALUES (?, ?, ?);
`)
// Valeurs par défaut à insérer
const defaultValues = {
admis: 10.0,
redouble: 9.99,
renvoyer: 7.99
}
// Vérification si une entrée existe déjà
const result = checkNoteSystemQuery.get()
if (result.count === 0) {
// Insérer les valeurs par défaut si aucune entrée n'existe
insertNoteSystemQuery.run(defaultValues.admis, defaultValues.redouble, defaultValues.renvoyer)
}
}
insertDefaultNoteSystemIfNotExist()
async function semestreCreate() {
const query = database.prepare('INSERT INTO semestres (nom) VALUES (?)')
// Préparation de la requête pour vérifier si une entrée existe déjà
const checkSemestreQuery = database.prepare(`
SELECT COUNT(*) AS count FROM semestres;
`)
try { try {
let arraySemestre = [ const statuses = ['Nouveau', 'Passant', 'Redoublant', 'Renvoyé', 'Ancien']
'S1', for (let name of statuses) {
'S2', const [rows] = await conn.query(`SELECT COUNT(*) as count FROM status WHERE nom = ?`, [name])
'S3', if (rows[0].count === 0) {
'S4', await conn.query(`INSERT INTO status (nom) VALUES (?)`, [name])
'S5',
'S6',
'S7',
'S8',
'S9',
'S10',
'S11',
'S12',
'S13',
'S14',
'S14',
'S16'
]
// Vérification si une entrée existe déjà
const result = checkSemestreQuery.get()
if (result.count === 0) {
database.transaction(() => {
for (let index = 0; index < arraySemestre.length; index++) {
query.run(arraySemestre[index])
} }
})()
} }
} catch (error) { } finally {
console.log(error) conn.release()
} }
} }
const createNecessaryParameterTable = () => {
// Check if the table is empty
const rowCount = database.prepare(`SELECT COUNT(*) AS count FROM nessesaryTable`).get().count
// If the table is empty, insert the default value
if (rowCount === 0) {
const insertDefaultQuery = `
INSERT INTO nessesaryTable (uniter_heure) VALUES (15);
`
database.prepare(insertDefaultQuery).run()
}
}
// Call the function when the app runs
createNecessaryParameterTable()
semestreCreate()
// Function to get the IP from the database
function getIP() {
const data = database.prepare("SELECT * FROM ipconfig WHERE id = 1").get();
if (data) {
return data.ipname;
} else {
return null; // Explicitly return `null` if no data is found
}
}
// Get the new IP from the database
let newIP = getIP();
if (newIP) {
// Construct the database path using the new IP from the database
dbPath = `\\\\${newIP}\\base\\data.db`;
// Reconnect to SQLite database with the updated path
database = new sqlite(dbPath); // Re-initialize database connection with new path
console.log("now COnnect to the ", dbPath);
}
module.exports = { module.exports = {
database pool,
createTables,
insertDefaultAdmin,
insertStatusesIfNotExist
} }

View File

@ -1,7 +1,7 @@
const mysql = require('mysql2/promise') const mysql = require('mysql2/promise')
const bcrypt = require('bcryptjs') const bcrypt = require('bcryptjs')
const pool = mysql.createPool({ const pool = mysql.createPool({
host: '127.0.0.1', host: '127.0.0.1',
user: 'root', user: 'root',
password: '', password: '',

View File

@ -6,11 +6,12 @@ const pool = mysql.createPool({
user: 'root', user: 'root',
password: '', password: '',
database: 'university', database: 'university',
waitForConnections: true, waitForConnections: true,
connectionLimit: 10, connectionLimit: 10,
queueLimit: 0 queueLimit: 0
}) })
async function createTables() { async function createTables() {
const connection = await pool.getConnection() const connection = await pool.getConnection()

View File

@ -14,7 +14,7 @@ async function modifyPDF(filepath) {
const firstPage = pages[0] const firstPage = pages[0]
// Replace text based on your data object // Replace text based on your data object
const data = { f1: 'Nom', f2: 'Prénom', f3: 23 } const data = { f1: 'Nom', f2: 'Prenom', f3: 23 }
// Example of replacing placeholders // Example of replacing placeholders
firstPage.drawText(data.f1, { x: 120, y: 700, size: 12 }) firstPage.drawText(data.f1, { x: 120, y: 700, size: 12 })

View File

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

View File

@ -1,264 +1,316 @@
const fs = require('fs') const fs = require('fs');
const path = require('path') const path = require('path');
const XLSX = require('xlsx') const XLSX = require('xlsx');
const { getCompressedDefaultImage } = require('../function/GetImageDefaault') const { getCompressedDefaultImage } = require('../function/GetImageDefaault');
const { parse } = require('csv-parse/sync') const { parse } = require('csv-parse/sync');
const { pool } = require('../database') const { pool } = require('../database');
const dayjs = require('dayjs') const dayjs = require('dayjs');
// const { getStatusMention } = require('../function/Helper') const customParseFormat = require('dayjs/plugin/customParseFormat');
const customParseFormat = require('dayjs/plugin/customParseFormat') dayjs.extend(customParseFormat);
// const { log } = require('console')
// const customParseFormatt = require('dayjs/plu')
dayjs.extend(customParseFormat)
// Function to convert any date format to 'YYYY-MM-DD' // ✅ Fonction de correction d'encodage
function fixEncoding(str) {
if (typeof str !== 'string') return str;
return str
.replace(/├®/g, 'é')
.replace(/├à/g, 'à')
.replace(/├©/g, 'é')
.replace(/├ô/g, 'ô')
.replace(/├ù/g, 'ù')
.replace(/’/g, "'")
.replace(/â€/g, '…')
.replace(/â€/g, '-');
}
function convertToISODate(input) { function convertToISODate(input) {
// Try parsing the date with different formats if (!input) return null;
const formats = [
'DD/MM/YYYY',
'MM/DD/YYYY',
'YYYY-MM-DD',
'DD-MM-YYYY',
'MM-DD-YYYY',
'DD/MM/YY',
'MM/DD/YY',
'DD-MMM-YY'
]
const parsedDate = dayjs(input, formats, true) // Strict parsing to ensure formats are matched correctly
// If the date is valid, return it in the YYYY-MM-DD format console.log('🔍 Input original:', input, 'Type:', typeof input);
if (parsedDate.isValid()) {
return parsedDate.format('YYYY-MM-DD') // Si input est un objet Date valide
if (input instanceof Date && !isNaN(input)) {
const result = dayjs(input).format('YYYY-MM-DD');
console.log('📅 Date object convertie:', result);
return result;
} }
// Handle cases like "Vers 2000" // Si input est un nombre (numéro de série Excel)
const versMatch = typeof input === 'string' && input.match(/vers\s*(\d{4})/i); if (typeof input === 'number') {
// Formule Excel: (numéro - 25569) * 86400 * 1000
const excelDate = new Date((input - 25569) * 86400 * 1000);
const result = dayjs(excelDate).format('YYYY-MM-DD');
console.log('📊 Numéro Excel', input, 'converti en:', result);
return result;
}
// Si input est une chaîne
if (typeof input === 'string') {
const cleanInput = input.trim();
// Cas spécial "vers YYYY"
const versMatch = cleanInput.match(/vers\s*(\d{4})/i);
if (versMatch) { if (versMatch) {
return `${versMatch[1]}-01-01`; // Return in ISO format const result = `${versMatch[1]}-01-01`;
console.log('📝 "Vers" détecté:', result);
return result;
} }
function excelDateToJSDate(serial) { // Formats à tester dans l'ordre de priorité
const utc_days = Math.floor(serial - 25569); // days from Jan 1, 1970 const formats = [
const utc_value = utc_days * 86400; // seconds in a day 'DD/MM/YYYY', 'D/M/YYYY', // Format français prioritaire
return new Date(utc_value * 1000); // JS Date uses milliseconds 'YYYY-MM-DD', // Format ISO
'DD-MM-YYYY', 'D-M-YYYY', // Format français avec tirets
'MM/DD/YYYY', 'M/D/YYYY', // Format américain
'MM-DD-YYYY', 'M-D-YYYY', // Format américain avec tirets
'DD/MM/YY', 'D/M/YY', // Années courtes
'MM/DD/YY', 'M/D/YY',
'DD-MM-YY', 'D-M-YY',
'MM-DD-YY', 'M-D-YY'
];
// Test avec parsing strict pour éviter les interprétations erronées
for (const format of formats) {
const parsedDate = dayjs(cleanInput, format, true); // true = strict parsing
if (parsedDate.isValid()) {
const result = parsedDate.format('YYYY-MM-DD');
console.log(`✅ Format "${format}" réussi:`, cleanInput, '->', result);
// Vérification supplémentaire pour les dates invalides comme 29/02 en année non-bissextile
if (format.includes('DD/MM') || format.includes('D/M')) {
const day = parsedDate.date();
const month = parsedDate.month() + 1; // dayjs month is 0-indexed
const year = parsedDate.year();
// Vérifier si c'est le 29 février d'une année non-bissextile
if (month === 2 && day === 29 && !isLeapYear(year)) {
console.warn('⚠️ Date invalide détectée: 29 février en année non-bissextile');
return null; // ou retourner une date par défaut
}
} }
let jsDate = excelDateToJSDate(input); return result;
}
}
// If the input is not a valid date, return 'Invalid Date' // Si aucun format strict ne fonctionne, essayer le parsing libre en dernier recours
return jsDate const freeParseDate = dayjs(cleanInput);
if (freeParseDate.isValid()) {
const result = freeParseDate.format('YYYY-MM-DD');
console.log('🆓 Parsing libre réussi:', cleanInput, '->', result);
return result;
}
}
console.error('❌ Impossible de convertir:', input);
return null;
} }
// Fonction utilitaire pour vérifier les années bissextiles
function isLeapYear(year) {
return (year % 4 === 0 && year % 100 !== 0) || (year % 400 === 0);
}
// ✅ Mise à jour d'un étudiant existant
async function updateEtudiant(row) {
const sql = `
UPDATE etudiants SET
nom = ?,
prenom = ?,
photos = ?,
date_de_naissances = ?,
niveau = ?,
annee_scolaire = ?,
status = ?,
mention_id = ?,
num_inscription = ?,
sexe = ?,
date_delivrance = ?,
nationalite = ?,
annee_bacc = ?,
serie = ?,
boursier = ?,
domaine = ?,
contact = ?,
parcours = ?
WHERE cin = ? OR (LOWER(nom) = ? AND LOWER(prenom) = ?)
`;
const params = [
row.nom,
row.prenom,
getCompressedDefaultImage(),
convertToISODate(row.date_naissance),
row.niveau,
row.annee_scolaire,
row.code_redoublement,
row.mention,
row.num_inscription.toString(),
row.sexe,
convertToISODate(row.date_de_delivrance),
row.nationaliter,
parseInt(row.annee_baccalaureat, 10),
row.serie,
row.boursier,
fixEncoding(row.domaine),
row.contact,
null,
row.cin,
row.nom.toLowerCase().trim(),
row.prenom.toLowerCase().trim()
];
try {
const [result] = await pool.query(sql, params);
console.log(`Update effectué pour CIN ${row.cin} ou nom ${row.nom} ${row.prenom}, affectedRows=${result.affectedRows}`);
return { success: true, affectedRows: result.affectedRows };
} catch (error) {
console.error('❌ Erreur MySQL update :', error.message);
return { success: false, error: error.message };
}
}
// ✅ Insertion réelle multiple
async function insertMultipleEtudiants(etudiants) { async function insertMultipleEtudiants(etudiants) {
const sql = ` const sql = `
INSERT INTO etudiants ( INSERT INTO etudiants (
nom, prenom, photos, date_de_naissances, niveau, annee_scolaire, status, nom, prenom, photos, date_de_naissances, niveau, annee_scolaire, status,
mention_id, num_inscription, sexe, cin, date_delivrance, nationalite, mention_id, num_inscription, sexe, cin, date_delivrance, nationalite,
annee_bacc, serie, boursier, domaine, contact, parcours annee_bacc, serie, boursier, domaine, contact, parcours
) ) VALUES ?
VALUES ? `;
`
// Prepare values as array of arrays const values = etudiants.map(row => [
const values = etudiants.map((row) => [
row.nom, row.nom,
row.prenom, row.prenom,
getCompressedDefaultImage(), // photos (you can adjust this if needed) getCompressedDefaultImage(),
convertToISODate(row.date_naissance), convertToISODate(row.date_naissance),
row.niveau, row.niveau,
row.annee_scolaire, row.annee_scolaire,
row.code_redoublement, row.code_redoublement,
row.mention, row.mention,
row.num_inscription, row.num_inscription.toString(),
row.sexe, row.sexe,
row.cin, row.cin,
convertToISODate(row.date_de_delivrance), convertToISODate(row.date_de_delivrance),
row.nationaliter, row.nationaliter,
row.annee_baccalaureat, parseInt(row.annee_baccalaureat, 10),
row.serie, row.serie,
row.boursier, row.boursier,
row.domaine, fixEncoding(row.domaine),
row.contact, row.contact,
null // parcours null
]) ]);
try { try {
const [result] = await pool.query(sql, [values]) const [result] = await pool.query(sql, [values]);
return { return { success: true, affectedRows: result.affectedRows };
success: true,
affectedRows: result.affectedRows,
insertId: result.insertId
}
} catch (error) { } catch (error) {
return { success: false, error: error.message } console.error('❌ Erreur MySQL :', error.message);
return { success: false, error: error.message };
} }
} }
/** // ✅ Import fichier vers base
* Function to import data from XLSX or CSV file into SQLite database
* @param {string} filePath - Path to the file (either .xlsx or .csv)
*/
async function importFileToDatabase(filePath) { async function importFileToDatabase(filePath) {
const fileExtension = path.extname(filePath).toLowerCase() const fileExtension = path.extname(filePath).toLowerCase();
let records;
// Determine the file type and parse accordingly
let records
if (fileExtension === '.xlsx') { if (fileExtension === '.xlsx') {
// Read and parse XLSX file const workbook = XLSX.readFile(filePath);
const workbook = XLSX.readFile(filePath) const worksheet = workbook.Sheets[workbook.SheetNames[0]];
const worksheet = workbook.Sheets[workbook.SheetNames[0]] // Assuming data is in the first sheet // raw: true pour garder les valeurs brutes, surtout pour les dates
records = XLSX.utils.sheet_to_json(worksheet, { defval: '', raw: false }) records = XLSX.utils.sheet_to_json(worksheet, { defval: ''});
} else if (fileExtension === '.csv') { } else if (fileExtension === '.csv') {
// Read and parse CSV file const fileContent = fs.readFileSync(filePath, 'utf8');
const fileContent = fs.readFileSync(filePath, 'utf8') records = parse(fileContent, { columns: true, skip_empty_lines: true });
records = parse(fileContent, { }else {
columns: true, console.error('Unsupported file format.');
skip_empty_lines: true return { error: true, message: 'Format de fichier non supporté.' };
}) }
console.log(`📄 Nombre de lignes : ${records.length}`);
// Vérifier champs obligatoires
const requiredFields = [
'nom', 'date_naissance', 'niveau', 'annee_scolaire',
'mention', 'num_inscription', 'nationaliter', 'sexe',
'annee_baccalaureat', 'serie', 'code_redoublement',
'boursier', 'domaine'
];
for (const [i, row] of records.entries()) {
for (const field of requiredFields) {
if (!row[field]) {
const msg = `Le champ '${field}' est manquant à la ligne ${i + 2}`;
console.error(msg);
return { error: true, message: msg };
}
}
}
const [mentionRows] = await pool.query('SELECT * FROM mentions');
const [statusRows] = await pool.query('SELECT * FROM status');
const etudiantsToInsert = [];
const doublons = [];
console.log(records);
for (const row of records) {
// Mapping mention
console.log('Avant conversion date_naissance:', row.date_naissance);
row.date_naissance = convertToISODate(row.date_naissance);
console.log('Après conversion date_naissance:', row.date_naissance);
const matchedMention = mentionRows.find(
m => m.nom.toUpperCase() === row.mention.toUpperCase() ||
m.uniter.toUpperCase() === row.mention.toUpperCase()
);
if (matchedMention) row.mention = matchedMention.id;
// Gestion code_redoublement -> status id
if (row.code_redoublement) {
row.code_redoublement = row.code_redoublement.trim().substring(0, 1);
} else { } else {
console.error('Unsupported file format. Only .xlsx and .csv are allowed.') row.code_redoublement = 'N';
return }
const statusMatch = statusRows.find(
s => s.nom.toLowerCase().startsWith(row.code_redoublement.toLowerCase())
);
if (statusMatch) row.code_redoublement = statusMatch.id;
// Vérification doublons (extraction complet)
const nomComplet = (row.nom + ' ' + row.prenom).toLowerCase().trim();
const [existing] = await pool.query(
'SELECT * FROM etudiants WHERE LOWER(CONCAT(nom, " ", prenom)) = ? OR cin = ?',
[nomComplet, row.cin]
);
if (existing.length > 0) {
doublons.push({ nom: row.nom, prenom: row.prenom, cin: row.cin });
// Mise à jour
const updateResult = await updateEtudiant(row);
if (!updateResult.success) {
return { error: true, message: `Erreur lors de la mise à jour de ${row.nom} ${row.prenom} : ${updateResult.error}` };
}
continue;
} }
// ✅ Count number of data rows etudiantsToInsert.push(row);
const numberOfLines = records.length }
console.log(`Number of data rows: ${numberOfLines}`)
try { console.log(etudiantsToInsert);
let error = true
let message = ''
// Vérifier les données en une seule boucle // Insertion des nouveaux
let oldNum = '' let insertResult = { success: true, affectedRows: 0 };
for (const row of records) { if (etudiantsToInsert.length > 0) {
if ( insertResult = await insertMultipleEtudiants(etudiantsToInsert);
!row.nom || if (!insertResult.success) {
// !row.prenom || return { error: true, message: `Erreur lors de l'insertion : ${insertResult.error}` };
!row.date_naissance ||
!row.niveau ||
!row.annee_scolaire ||
!row.mention ||
!row.num_inscription ||
!row.nationaliter ||
!row.sexe ||
// !row.cin ||
// !row.date_de_delivrance ||
!row.annee_baccalaureat ||
!row.serie ||
!row.code_redoublement ||
!row.boursier ||
!row.domaine
// ||
// !row.contact
) {
if (!row.nom) {
message = "Le champ 'nom' est inconnu"
}
// else if (!row.prenom) {
// message = "Le champ 'prenom' est inconnu"
// }
else if (!row.date_naissance) {
message = "Le champ 'date_naissance' est inconnu"
} else if (!row.niveau) {
message = "Le champ 'niveau' est inconnu"
} else if (!row.annee_scolaire) {
message = "Le champ 'annee_scolaire' est inconnu"
} else if (!row.mention) {
message = "Le champ 'mention' est inconnu"
} else if (!row.num_inscription) {
message = "Le champ 'num_inscription' est inconnu"
} else if (!row.nationaliter) {
message = "Le champ 'nationaliter' est inconnu"
} else if (!row.sexe) {
message = "Le champ 'sexe' est inconnu"
}
// else if (!row.cin) {
// message = "Le champ 'cin' est inconnu"
// } else if (!row.date_de_delivrance) {
// message = "Le champ 'date_de_delivrance' est inconnu"
// }
else if (!row.annee_baccalaureat) {
message = "Le champ 'annee_baccalaureat' est inconnu"
} else if (!row.serie) {
message = "Le champ 'serie' est inconnu"
} else if (!row.code_redoublement) {
message = "Le champ 'code_redoublement' est inconnu"
} else if (!row.boursier) {
message = "Le champ 'boursier' est inconnu"
} else if (!row.domaine) {
message = "Le champ 'domaine' est inconnu"
}
// else if (!row.contact) {
// message = "Le champ 'contact' est inconnu"
// }
error = false
break
} }
} }
const query = 'SELECT * FROM mentions' let msg = `Importation réussie. ${etudiantsToInsert.length} nouvel(le)(s) étudiant(s) inséré(s). ${doublons.length} étudiant(s) mis à jour.`;
const [rows] = await pool.query(query) return { error: false, message: msg };
const MentionList = rows
console.log(MentionList)
if (error !== false) {
let newReccord = []
// Utiliser transaction pour éviter une latence si l'insertion dépasse 100
for (const row of records) {
// Convert row.mention to uppercase and compare with ListMention.nom and ListMention.uniter (also converted to uppercase)
const matchedMention = MentionList.find(
(mention) =>
mention.nom.toUpperCase() === row.mention.toUpperCase() ||
mention.uniter.toUpperCase() === row.mention.toUpperCase()
)
// If a match is found, update row.mention with ListMention.id
if (matchedMention) {
row.mention = matchedMention.id
}
const query = 'SELECT * FROM status'
let [rows] = await pool.query(query)
let response = rows
let statutCode
for (let index = 0; index < response.length; index++) {
let nom = response[index].nom
let nomLower = nom.toLowerCase() // Correct method
let find1 = row.code_redoublement.slice(0, 1)
let find2 = row.code_redoublement.slice(0, 3)
if (nomLower.slice(0, 1) == find1.toLowerCase()) {
statutCode = response[index].id
} else if (nomLower.slice(0, 3) == find2.toLowerCase()) {
statutCode = response[index].id
}
}
row.code_redoublement = statutCode
row.num_inscription = row.num_inscription.toString()
try {
let compare = row.num_inscription
if (compare == oldNum) {
row.num_inscription = String(row.num_inscription)
}
console.log(row.code_redoublement)
newReccord.push(row)
oldNum = compare
} catch (error) {
console.log(error)
}
}
console.log(insertMultipleEtudiants(newReccord))
}
return { error, message }
} catch (error) {
console.error('Error inserting record:', error)
return { error: 'error' }
}
} }
module.exports = { module.exports = { importFileToDatabase };
importFileToDatabase
}

View File

@ -0,0 +1,27 @@
// electron.vite.config.mjs
import { resolve } from "path";
import { defineConfig, externalizeDepsPlugin } from "electron-vite";
import react from "@vitejs/plugin-react";
var electron_vite_config_default = defineConfig({
main: {
plugins: [externalizeDepsPlugin()]
},
preload: {
plugins: [externalizeDepsPlugin()]
},
renderer: {
resolve: {
alias: {
"@renderer": resolve("src/renderer/src")
}
},
plugins: [react()]
},
worker: {
format: "es"
// Use ES module for worker (you can also use 'iife')
}
});
export {
electron_vite_config_default as default
};

View File

@ -25,6 +25,7 @@ const {
getTranche, getTranche,
updateTranche, updateTranche,
deleteTranche, deleteTranche,
deleteEtudiant,
getSingleTranche getSingleTranche
} = require('../../database/Models/Etudiants') } = require('../../database/Models/Etudiants')
const { const {
@ -45,6 +46,7 @@ const {
createMatiere, createMatiere,
getSingleMatiere, getSingleMatiere,
updateMatiere, updateMatiere,
updateMatiereNiveau,
displayMatiereFromForm, displayMatiereFromForm,
deleteMatiere, deleteMatiere,
asygnationToMention, asygnationToMention,
@ -537,6 +539,12 @@ ipcMain.handle('updateMatiere', async (event, credentials) => {
return update return update
}) })
ipcMain.handle('updateMatiereNiveau', async (event, credentials) => {
// credentials = { niveau_id, id }
const update = await updateMatiereNiveau(credentials) // ✅ on passe id + niveau_id
return update
})
// event for importExcel // event for importExcel
ipcMain.handle('importexcel', async (event, credentials) => { ipcMain.handle('importexcel', async (event, credentials) => {
const files = credentials const files = credentials
@ -672,12 +680,10 @@ ipcMain.handle('deleteNiveaus', async (event, credentials) => {
return get return get
}) })
ipcMain.handle('deleteMatiere', async (event, credentials) => { ipcMain.handle('deleteMatiere', async (event, id) => {
const { id } = credentials return await deleteMatiere(id);
});
const get = deleteMatiere(id)
return get
})
ipcMain.handle('asign', async (event, credentials) => { ipcMain.handle('asign', async (event, credentials) => {
const { formData, id } = credentials const { formData, id } = credentials
@ -887,6 +893,10 @@ ipcMain.handle('deleteTranche', async (event, credentials) => {
return get return get
}) })
ipcMain.handle('deleteEtudiant', async (event, id) => {
return await deleteEtudiant(id);
});
ipcMain.handle('getSingleTranche', async (event, credentials) => { ipcMain.handle('getSingleTranche', async (event, credentials) => {
const { id } = credentials const { id } = credentials
// console.log(formData, id); // console.log(formData, id);

View File

@ -45,8 +45,10 @@ const {
createMatiere, createMatiere,
getSingleMatiere, getSingleMatiere,
updateMatiere, updateMatiere,
updateMatiereNiveau,
displayMatiereFromForm, displayMatiereFromForm,
deleteMatiere, deleteMatiere,
deleteEtudiant,
asygnationToMention, asygnationToMention,
getMentionMatiere, getMentionMatiere,
getMentionMatiereChecked, getMentionMatiereChecked,
@ -520,6 +522,12 @@ ipcMain.handle('updateMatiere', async (event, credentials) => {
return update return update
}) })
ipcMain.handle('updateMatiereNiveau', async (event, credentials) => {
// credentials = { niveau_id, id }
const update = await updateMatiereNiveau(credentials) // ✅ on passe id + niveau_id
return update
})
// event for importExcel // event for importExcel
ipcMain.handle('importexcel', async (event, credentials) => { ipcMain.handle('importexcel', async (event, credentials) => {
const files = credentials const files = credentials
@ -654,13 +662,13 @@ ipcMain.handle('deleteNiveaus', async (event, credentials) => {
const get = deleteNiveau(id) const get = deleteNiveau(id)
return get return get
}) })
ipcMain.handle('deleteMatiere', async (event, id) => {
return await deleteMatiere(id);
});
ipcMain.handle('deleteEtudiant', async (event, id) => {
return await deleteEtudiant(id);
});
ipcMain.handle('deleteMatiere', async (event, credentials) => {
const { id } = credentials
const get = deleteMatiere(id)
return get
})
ipcMain.handle('asign', async (event, credentials) => { ipcMain.handle('asign', async (event, credentials) => {
const { formData, id } = credentials const { formData, id } = credentials

View File

@ -132,10 +132,12 @@ if (process.contextIsolated) {
createMatiere: (credentials) => ipcRenderer.invoke('createMatiere', credentials), createMatiere: (credentials) => ipcRenderer.invoke('createMatiere', credentials),
getMatiereByID: (credentials) => ipcRenderer.invoke('getMatiereByID', credentials), getMatiereByID: (credentials) => ipcRenderer.invoke('getMatiereByID', credentials),
updateMatiere: (credentials) => ipcRenderer.invoke('updateMatiere', credentials), updateMatiere: (credentials) => ipcRenderer.invoke('updateMatiere', credentials),
updateMatiereNiveau: (credentials) => ipcRenderer.invoke('updateMatiereNiveau', credentials),
importExcel: (credentials) => ipcRenderer.invoke('importExcelMatiere', credentials), importExcel: (credentials) => ipcRenderer.invoke('importExcelMatiere', credentials),
displayMatiereFromForm: (credentials) => displayMatiereFromForm: (credentials) =>
ipcRenderer.invoke('displayMatiereFromForm', credentials), ipcRenderer.invoke('displayMatiereFromForm', credentials),
deleteMatiere: (credentials) => ipcRenderer.invoke('deleteMatiere', credentials), deleteMatiere: (credentials) => ipcRenderer.invoke('deleteMatiere', credentials),
deleteEtudiant: (credentials) => ipcRenderer.invoke('deleteEtudiant', credentials),
asign: (credentials) => ipcRenderer.invoke('asign', credentials), asign: (credentials) => ipcRenderer.invoke('asign', credentials),
getAsign: (credentials) => ipcRenderer.invoke('getAsign', credentials), getAsign: (credentials) => ipcRenderer.invoke('getAsign', credentials),
asignSemestre: (credentials) => ipcRenderer.invoke('asignSemestre', credentials), asignSemestre: (credentials) => ipcRenderer.invoke('asignSemestre', credentials),

View File

@ -1,7 +1,6 @@
import { contextBridge, ipcRenderer } from 'electron' import { contextBridge, ipcRenderer } from 'electron'
import { electronAPI } from '@electron-toolkit/preload' import { electronAPI } from '@electron-toolkit/preload'
const { getNessesarytable } = require('../../database/function/System') const { getNessesarytable } = require('../../database/function/System')
const { getNiveau } = require('../../database/Models/Niveau')
const { getAllUsers } = require('../../database/Models/Users') const { getAllUsers } = require('../../database/Models/Users')
const { getAllEtudiants, getDataToDashboard } = require('../../database/Models/Etudiants') const { getAllEtudiants, getDataToDashboard } = require('../../database/Models/Etudiants')
const { verifyEtudiantIfHeHasNotes, blockShowMoyene } = require('../../database/Models/Notes') const { verifyEtudiantIfHeHasNotes, blockShowMoyene } = require('../../database/Models/Notes')
@ -12,6 +11,7 @@ const { getAnneeScolaire, getInterval } = require('../../database/Models/AnneeSc
const { getMentions } = require('../../database/Models/Mentions') const { getMentions } = require('../../database/Models/Mentions')
const { getAll } = require('../../database/api/Get') const { getAll } = require('../../database/api/Get')
const { getParcours } = require('../../database/Models/Parcours') const { getParcours } = require('../../database/Models/Parcours')
const { getNiveau } = require('../../database/Models/Niveau')
const { getIPConfig } = require('../../database/Models/IpConfig') const { getIPConfig } = require('../../database/Models/IpConfig')
// Custom APIs for renderer // Custom APIs for renderer
@ -128,10 +128,12 @@ if (process.contextIsolated) {
createMatiere: (credentials) => ipcRenderer.invoke('createMatiere', credentials), createMatiere: (credentials) => ipcRenderer.invoke('createMatiere', credentials),
getMatiereByID: (credentials) => ipcRenderer.invoke('getMatiereByID', credentials), getMatiereByID: (credentials) => ipcRenderer.invoke('getMatiereByID', credentials),
updateMatiere: (credentials) => ipcRenderer.invoke('updateMatiere', credentials), updateMatiere: (credentials) => ipcRenderer.invoke('updateMatiere', credentials),
updateMatiereNiveau: (credentials) => ipcRenderer.invoke('updateMatiereNiveau', credentials),
importExcel: (credentials) => ipcRenderer.invoke('importExcelMatiere', credentials), importExcel: (credentials) => ipcRenderer.invoke('importExcelMatiere', credentials),
displayMatiereFromForm: (credentials) => displayMatiereFromForm: (credentials) =>
ipcRenderer.invoke('displayMatiereFromForm', credentials), ipcRenderer.invoke('displayMatiereFromForm', credentials),
deleteMatiere: (credentials) => ipcRenderer.invoke('deleteMatiere', credentials), deleteMatiere: (id) => ipcRenderer.invoke('deleteMatiere', id),
deleteEtudiant: (id) => ipcRenderer.invoke('deleteEtudiant', id),
asign: (credentials) => ipcRenderer.invoke('asign', credentials), asign: (credentials) => ipcRenderer.invoke('asign', credentials),
getAsign: (credentials) => ipcRenderer.invoke('getAsign', credentials), getAsign: (credentials) => ipcRenderer.invoke('getAsign', credentials),
asignSemestre: (credentials) => ipcRenderer.invoke('asignSemestre', credentials), asignSemestre: (credentials) => ipcRenderer.invoke('asignSemestre', credentials),

View File

@ -1,5 +1,5 @@
.h1style { .h1style {
text-transform: uppercase; /* text-transform: uppercase; */
font-weight: 900; font-weight: 900;
/* 6636af4a 6636af ffae01 */ /* 6636af4a 6636af ffae01 */
border-left: 10px solid #ffff; border-left: 10px solid #ffff;

View File

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

View File

@ -52,6 +52,9 @@ const AddNotes = () => {
window.matieres.displayMatiereFromForm({ niveau, mention_id, parcours }).then((response) => { window.matieres.displayMatiereFromForm({ niveau, mention_id, parcours }).then((response) => {
setMatieres(response) setMatieres(response)
console.log("resulat teste:1", response);
console.log("resulat teste:2", mention_id);
console.log("resulat teste:3", parcours);
}) })
setIsSubmitted(false) setIsSubmitted(false)
} }
@ -109,6 +112,8 @@ const AddNotes = () => {
} }
} }
console.log('matiere: ',matieres);
const [statut, setStatut] = useState(200) const [statut, setStatut] = useState(200)
/** /**

View File

@ -503,13 +503,13 @@ const AddStudent = () => {
variant="outlined" variant="outlined"
> >
<InputLabel id="demo-select-small-label" color="warning"> <InputLabel id="demo-select-small-label" color="warning">
Année Universitaire Année Scolaire
</InputLabel> </InputLabel>
<Select <Select
labelId="demo-select-small-label" labelId="demo-select-small-label"
id="demo-select-small" id="demo-select-small"
value={formData.annee_scolaire} value={formData.annee_scolaire}
label="Année Universitaire" label="Année Scolaire"
color="warning" color="warning"
size="small" size="small"
onChange={handleInputChange} onChange={handleInputChange}
@ -521,7 +521,7 @@ const AddStudent = () => {
<FaCalendarAlt /> <FaCalendarAlt />
</InputAdornment> </InputAdornment>
} }
label="Année Universitaire" label="Année Scolaire"
/> />
} }
sx={{ sx={{

View File

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

View File

@ -47,7 +47,7 @@ const Apropos = () => {
<p style={{ color: 'black' }}> <p style={{ color: 'black' }}>
Nom du Logiciel: CUniversity <br /> Nom du Logiciel: CUniversity <br />
<br /> Description : logiciel de gestion d'universiter <br /> <br /> <br /> Description : logiciel de gestion d'espt <br /> <br />
Createur: CPAY COMPANY FOR MADAGASCAR <br /> Createur: CPAY COMPANY FOR MADAGASCAR <br />
<br /> Licence: A vie <br /> <br /> Licence: A vie <br />
<br /> Contact: 0348415301 <br /> Contact: 0348415301

View File

@ -142,8 +142,11 @@ const ExportEtudiants = () => {
* fonction qui envoye dans le back * fonction qui envoye dans le back
*/ */
const handleImport = async () => { const handleImport = async () => {
// Code to handle file import (can open a file dialog or call handleFileChange) if (!files) {
setError("Veuillez choisir un fichier d'abord.")
return
}
try {
let response = await window.etudiants.importExcel(files.path) let response = await window.etudiants.importExcel(files.path)
console.log(response) console.log(response)
@ -153,15 +156,22 @@ const ExportEtudiants = () => {
} }
if (response.error) { if (response.error) {
setIsinserted(false)
setOpen(true)
// Ne vide pas tableData, ça permet à l'utilisateur de corriger le fichier
} else {
setIsinserted(true) setIsinserted(true)
setOpen(true) setOpen(true)
setTableData([]) setTableData([]) // vider seulement si insertion réussie
} else { }
} catch (err) {
setMessage('Erreur inattendue lors de limport')
setIsinserted(false) setIsinserted(false)
setOpen(true) setOpen(true)
} }
} }
/** /**
* hook to open modal * hook to open modal
*/ */

View File

@ -28,9 +28,12 @@ import ParcourMatiere from './ParcourMatiere'
import UpdateModalProf from './UpdateModalProf' import UpdateModalProf from './UpdateModalProf'
import ModalProcessFichePresence from './ModalProcessFichePresence' import ModalProcessFichePresence from './ModalProcessFichePresence'
import ModalExportFichr from './ModalExportFichr' import ModalExportFichr from './ModalExportFichr'
import NiveauMatiere from './NiveauMatiere'
const Matieres = () => { const Matieres = () => {
const [matiere, setMatiere] = useState([]) const [matiere, setMatiere] = useState([])
const [openAssignNiveau, setOpenAssignNiveau] = useState(false)
const [matiereIdAssign, setMatiereIdAssign] = useState(null)
const [Enseignants, setEnseignants] = useState([]) const [Enseignants, setEnseignants] = useState([])
useEffect(() => { useEffect(() => {
@ -62,6 +65,29 @@ const Matieres = () => {
} }
}) })
const openAssignNiveauModal = (id) => {
setMatiereIdAssign(id)
setOpenAssignNiveau(true)
}
const closeAssignNiveauModal = () => {
setOpenAssignNiveau(false)
setMatiereIdAssign(null)
}
const handleNiveauAssignSuccess = (status) => {
if (status) {
// Rafraîchir les données des matières et enseignants
window.matieres.getMatiere().then((response) => {
setMatiere(response)
})
window.matieres.getENseignant().then((response) => {
setEnseignants(response)
})
}
}
const [isDeleted, setIsDeleted] = useState(false) const [isDeleted, setIsDeleted] = useState(false)
const [ids, setIds] = useState(0) const [ids, setIds] = useState(0)
@ -71,6 +97,7 @@ const Matieres = () => {
{ field: 'heure', headerName: 'Heure', width: 80 }, { field: 'heure', headerName: 'Heure', width: 80 },
{ field: 'uniter', headerName: "Unité d'enseignement", width: 180 }, { field: 'uniter', headerName: "Unité d'enseignement", width: 180 },
{ field: 'ue', headerName: 'UE', width: 80 }, { field: 'ue', headerName: 'UE', width: 80 },
{ field: 'niveau_id', headerName: 'Niveau', width: 80 },
{ field: 'enseignant', headerName: 'Professeur actuele', width: 230 }, { field: 'enseignant', headerName: 'Professeur actuele', width: 230 },
{ {
field: 'action', field: 'action',
@ -124,8 +151,32 @@ const Matieres = () => {
<FaS style={{ fontSize: '20px', color: 'white' }} /> <FaS style={{ fontSize: '20px', color: 'white' }} />
</Button> </Button>
</Link> </Link>
{/* ----------- BOUTON ASSIGNER NIVEAU ----------- */}
<Link <Link
to={`#`} to="#"
className={`niveau${params.value}`}
style={{ textDecoration: 'none' }}
onClick={(e) => {
e.preventDefault(); // empêche le # de provoquer un scroll
openAssignNiveauModal(params.value);
}}
>
<Tooltip
anchorSelect={`.niveau${params.value}`}
style={{ fontSize: '15px', zIndex: 9 }}
place="top"
>
Assigner à un niveau
</Tooltip>
<Button color="warning" variant="contained">
{/* Icône de ton choix, ici FaRegPlusSquare par exemple */}
<FaRegPlusSquare style={{ fontSize: '20px', color: 'white' }} />
</Button>
</Link>
<Link
to="#"
style={{ textDecoration: 'none' }} style={{ textDecoration: 'none' }}
className={`parcour${params.value}`} className={`parcour${params.value}`}
onClick={() => openParcoursFunction(params.value)} onClick={() => openParcoursFunction(params.value)}
@ -141,6 +192,7 @@ const Matieres = () => {
<FaP style={{ fontSize: '20px', color: 'white' }} /> <FaP style={{ fontSize: '20px', color: 'white' }} />
</Button> </Button>
</Link> </Link>
<Link to={`#`}> <Link to={`#`}>
<Button color="warning" variant="contained"> <Button color="warning" variant="contained">
<GiTeacher <GiTeacher
@ -253,13 +305,14 @@ const Matieres = () => {
heure: mat.heure, heure: mat.heure,
uniter: mat.unite_enseignement, uniter: mat.unite_enseignement,
ue: mat.ue, ue: mat.ue,
niveau_id: mat.niveau_nom ?? 'pas de niveau',
enseignant: enseignant:
compareMatieres(mat.id) != '' ? compareMatieres(mat.id) : 'Veuillez assigner un professeur', compareMatieres(mat.id) != '' ? compareMatieres(mat.id) : 'Veuillez assigner un professeur',
action: mat.id // Ensure this is a valid URL for the image action: mat.id // Ensure this is a valid URL for the image
})) }))
const deleteButton = async (id) => { const deleteButton = async (id) => {
let response = await window.matieres.deleteMatiere({ id }) let response = await window.matieres.deleteMatiere(id);
if (response.success) { if (response.success) {
const updatedMatieres = matiere.filter((matiere) => matiere.id !== id) const updatedMatieres = matiere.filter((matiere) => matiere.id !== id)
setMatiere(updatedMatieres) setMatiere(updatedMatieres)
@ -431,6 +484,15 @@ const Matieres = () => {
open={openUppdateProf} open={openUppdateProf}
/> />
<ModalProcessFichePresence matiere_id={matiereId} onClose={onCloseFiche} open={openFiche} /> <ModalProcessFichePresence matiere_id={matiereId} onClose={onCloseFiche} open={openFiche} />
{/* Modal NiveauMatiere */}
<NiveauMatiere
open={openAssignNiveau}
onClose={closeAssignNiveauModal}
matiere_id={matiereIdAssign}
onSubmitSuccess={handleNiveauAssignSuccess}
/>
<div className={classeAdd.header}> <div className={classeAdd.header}>
<div className={classe.h1style}> <div className={classe.h1style}>
<div className={classeHome.blockTitle}> <div className={classeHome.blockTitle}>

View File

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

View File

@ -0,0 +1,132 @@
import React, { useEffect, useState } from 'react';
import {
Dialog,
DialogActions,
DialogContent,
DialogTitle,
Button,
Box,
Grid,
FormControl,
InputLabel,
Select,
OutlinedInput,
MenuItem
} from '@mui/material'
const NiveauMatiere = ({ open, onClose, matiere_id }) => {
const [formData, setFormData] = useState({
niveau_id: '',
id: ''
})
const [niveaux, setNiveaux] = useState([])
const [niveauxMatiere, setNiveauxMatiere] = useState([])
console.log(niveaux);
useEffect(() => {
window.niveaus.getNiveau().then((response) => {
setNiveaux(response)
})
}, [])
useEffect(() => {
if (niveauxMatiere.length !== 0) {
const niveauIds = niveauxMatiere.map((item) => item.niveau_id)
setFormData((prevState) => ({
...prevState,
niveau_id: niveauIds
}))
}
}, [niveauxMatiere])
useEffect(() => {
if (matiere_id) {
setFormData(prev => ({
...prev,
id: matiere_id
}));
}
}, [matiere_id]);
const handleChange = (event) => {
const { name, value } = event.target
setFormData(prevState => ({
...prevState,
niveau_id: value // pas de tableau
}));
}
const formSubmit = async (e) => {
e.preventDefault();
console.log("Form envoyé côté front:", formData);
let response = await window.matieres.updateMatiereNiveau(formData);
console.log("Réponse backend:", response);
if (response.success) {
onClose();
}
};
return (
<Dialog open={open} onClose={onClose}>
<form action="" onSubmit={formSubmit}>
<DialogTitle>Assignation à des niveaux</DialogTitle>
<DialogContent>
<Box sx={{ flexGrow: 1 }}>
<Grid container spacing={2}>
<Grid item xs={12} sm={6}>
<FormControl sx={{ m: 1, width: 300 }}>
<InputLabel id="niveaux-select-label" color="warning">
Niveaux
</InputLabel>
<Select
labelId="niveaux-select-label"
id="niveaux-select"
name="niveau_id"
value={formData.niveau_id || ''}
onChange={handleChange}
color="warning"
size="small"
required
input={<OutlinedInput label="Niveaux" />}
MenuProps={{
PaperProps: {
style: {
maxHeight: 200,
width: 250
}
}
}}
>
{niveaux.map((niveau) => (
<MenuItem key={niveau.niveau_id} value={niveau.niveau_id}>
{niveau.nom}
</MenuItem>
))}
</Select>
</FormControl>
</Grid>
</Grid>
</Box>
</DialogContent>
<DialogActions>
<Button onClick={onClose} color="error">
Annuler
</Button>
<Button type="submit" color="warning">
Soumettre
</Button>
</DialogActions>
</form>
</Dialog>
)
}
export default NiveauMatiere

View File

@ -1,4 +1,4 @@
import React, { useEffect, useState } from 'react' import React, { useEffect, useState } from 'react';
import { import {
Dialog, Dialog,
DialogActions, DialogActions,

View File

@ -81,7 +81,7 @@ const Parcours = () => {
id: parc.id, id: parc.id,
nom: parc.nom, nom: parc.nom,
uniter: parc.uniter, uniter: parc.uniter,
mention: parc.mention_id, mention: parc.mention_nom || parc.mention || 'Mention non trouvée',
action: parc.id action: parc.id
})) }))

View File

@ -187,13 +187,13 @@ const Resultat = () => {
<tr> <tr>
<td colSpan={4} className="py-3"> <td colSpan={4} className="py-3">
<h6> <h6>
Niveau {niveau} | Année universitaire {scolaire} Niveau {niveau} | Année Scolaire {scolaire}
</h6> </h6>
</td> </td>
</tr> </tr>
<tr> <tr>
<th>Nom</th> <th>Nom</th>
<th>Prénom</th> <th>Prenom</th>
<th>Mention</th> <th>Mention</th>
<th>Moyenne</th> <th>Moyenne</th>
</tr> </tr>

View File

@ -153,7 +153,7 @@ const Sidenav = () => {
> >
<BsCalendar2Date className="anneescolaire" style={{ outline: 'none' }} /> <BsCalendar2Date className="anneescolaire" style={{ outline: 'none' }} />
<Tooltip anchorSelect=".anneescolaire" className="custom-tooltip" place="top"> <Tooltip anchorSelect=".anneescolaire" className="custom-tooltip" place="top">
Année Universitaire Année Scolaire
</Tooltip> </Tooltip>
</Link> </Link>
</li> </li>

View File

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

View File

@ -540,7 +540,7 @@ const SingleEtudiant = () => {
<Grid item xs={6}> <Grid item xs={6}>
<TextField <TextField
fullWidth fullWidth
label="Année Universitaire" label="Année Scolaire"
name="annee_scolaire" name="annee_scolaire"
color="warning" color="warning"
defaultValue={etudiant.annee_scolaire} // Controlled component value defaultValue={etudiant.annee_scolaire} // Controlled component value

View File

@ -309,16 +309,22 @@ const Student = () => {
} }
} }
// const paginationModel = { page: 0, pageSize: 20 } // PAGINATION CORRIGÉE - États pour la pagination complète
const [pageSize, setPageSize] = useState(20) const [paginationModel, setPaginationModel] = useState({
page: 0,
pageSize: 20
})
const [pageSizeOptions, setPageSizeOptions] = useState([20, 40, 60]) const [pageSizeOptions, setPageSizeOptions] = useState([20, 40, 60])
const handlePageSizeChange = (newPageSize) => { // Gestionnaire complet pour les changements de pagination (page ET pageSize)
setPageSize(newPageSize) const handlePaginationModelChange = (newModel) => {
console.log('📊 Pagination changed:', newModel) // Pour debug
// If the user picked the largest value, add next +20 setPaginationModel(newModel)
// Si l'utilisateur choisit la plus grande option, ajouter +20
const maxOption = Math.max(...pageSizeOptions) const maxOption = Math.max(...pageSizeOptions)
if (newPageSize === maxOption) { if (newModel.pageSize === maxOption) {
setPageSizeOptions((prev) => [...prev, maxOption + 20]) setPageSizeOptions((prev) => [...prev, maxOption + 20])
} }
} }
@ -360,16 +366,20 @@ const Student = () => {
} }
/** /**
* function to filter the data in dataGrid by Niveau * Fonction de filtrage avec reset de pagination
*/ */
const FilterData = async (e) => { const FilterData = async (e) => {
let niveau = e.target.value let niveau = e.target.value
if (niveau !== '') { if (niveau !== '') {
let data = await window.etudiants.FilterDataByNiveau({ niveau }) let data = await window.etudiants.FilterDataByNiveau({ niveau })
setEtudiants(data) setEtudiants(data)
// Reset vers la première page après filtrage
setPaginationModel(prev => ({ ...prev, page: 0 }))
} else { } else {
window.etudiants.getEtudiants().then((response) => { window.etudiants.getEtudiants().then((response) => {
setEtudiants(response) setEtudiants(response)
// Reset vers la première page
setPaginationModel(prev => ({ ...prev, page: 0 }))
}) })
} }
} }
@ -541,11 +551,9 @@ const Student = () => {
<DataGrid <DataGrid
rows={dataRow} rows={dataRow}
columns={columns} columns={columns}
// initialState={{ pagination: { paginationModel } }}
// pageSizeOptions={[20, 40, 60]}
pageSizeOptions={pageSizeOptions} pageSizeOptions={pageSizeOptions}
paginationModel={{ pageSize, page: 0 }} paginationModel={paginationModel} // Utilise l'état complet
onPaginationModelChange={(model) => handlePageSizeChange(model.pageSize)} onPaginationModelChange={handlePaginationModelChange} // Gère page ET pageSize
sx={{ sx={{
border: 0, border: 0,
width: 'auto', // Ensures the DataGrid takes full width width: 'auto', // Ensures the DataGrid takes full width

View File

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

View File

@ -47,7 +47,6 @@ const UpdateTranche = ({ open, onClose, onSubmitSuccess, id }) => {
const handleSubmit = async (e) => { const handleSubmit = async (e) => {
e.preventDefault() e.preventDefault()
console.log(formData)
let response = await window.etudiants.updateTranche(formData) let response = await window.etudiants.updateTranche(formData)
if (response.changes) { if (response.changes) {

View File

@ -40,7 +40,7 @@ export const generatePDF = async (students) => {
y -= 30 y -= 30
const headers = ['N°', 'Nom et Prénom', 'Mention', 'Émergement'] const headers = ['N°', 'Nom et Prenom', 'Mention', 'Émergement']
const columnWidths = [50, 200, 100, 100] const columnWidths = [50, 200, 100, 100]
const xPositions = [ const xPositions = [
margin, margin,

View File

@ -73,7 +73,7 @@ const PDFEditor = async (data) => {
// ----------------------------------------------- carte arriere ------------------------------------------- // ----------------------------------------------- carte arriere -------------------------------------------
const paperContent = ` const paperContent = `
CUniversity CUniversity
Nom et prénom: ${data.f1} Nom et prenom: ${data.f1}
Date de naissance: ${data.f2} Date de naissance: ${data.f2}
Niveau: ${data.f3} Niveau: ${data.f3}
Année scolaire: ${data.f4} Année scolaire: ${data.f4}

View File

@ -79,7 +79,7 @@ async function fillPdfFields(jsonData) {
const paperContent = ` const paperContent = `
C-University C-University
Nom et prénom: ${jsonData.f1} Nom et prenom: ${jsonData.f1}
Date de naissance: ${jsonData.f2} Date de naissance: ${jsonData.f2}
Niveau: ${jsonData.f3} Niveau: ${jsonData.f3}
Année scolaire: ${jsonData.f4} Année scolaire: ${jsonData.f4}

View File

@ -23,7 +23,7 @@
</div> </div>
<div class="cart-info"> <div class="cart-info">
<p><b>Nom</b> : BE</p> <p><b>Nom</b> : BE</p>
<p><b>Prénom</b> : Joseph Fabrice</p> <p><b>Prenom</b> : Joseph Fabrice</p>
<p><b>Date de naissance</b> : 11-12-2001</p> <p><b>Date de naissance</b> : 11-12-2001</p>
<p><b>Niveau</b> : L3</p> <p><b>Niveau</b> : L3</p>
<p><b>Année scolaire</b> : 2023-2024</p> <p><b>Année scolaire</b> : 2023-2024</p>

View File

@ -19,7 +19,7 @@
<div class="releve"> <div class="releve">
<h3>RELEVÉE DE NOTE</h3> <h3>RELEVÉE DE NOTE</h3>
<p><strong>Nom & Prénoms :</strong> F3</p> <p><strong>Nom & Prenoms :</strong> F3</p>
<p> <p>
<strong>Niveau :</strong> L1 <span><strong>Année scolaire :</strong> 2022-2023</span> <strong>Niveau :</strong> L1 <span><strong>Année scolaire :</strong> 2022-2023</span>
</p> </p>

View File

@ -244,7 +244,7 @@ const FileUploader = () => {
<thead> <thead>
<tr> <tr>
<th>Nom</th> <th>Nom</th>
<th>Prénom</th> <th>Prenom</th>
<th>Photos</th> <th>Photos</th>
<th>Date de Naissances</th> <th>Date de Naissances</th>
<th>Niveau</th> <th>Niveau</th>