diff --git a/database/Models/AnneeScolaire.js b/database/Models/AnneeScolaire.js index 3b4054e..1b89b53 100644 --- a/database/Models/AnneeScolaire.js +++ b/database/Models/AnneeScolaire.js @@ -71,13 +71,13 @@ async function deleteAnneeScolaire(id) { if (result.affectedRows === 0) { return { success: false, - message: 'Année universitaire non trouvé.' + message: 'Année Scolaire non trouvé.' } } return { success: true, - message: 'Année universitaire supprimé avec succès.' + message: 'Année Scolaire 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 universitaire non trouvé ou aucune modification effectuée.' + message: 'Année Scolaire non trouvé ou aucune modification effectuée.' } } return { success: true, - message: 'Année universitaire mis à jour avec succès.' + message: 'Année Scolaire mis à jour avec succès.' } } catch (error) { return { success: false, error: 'Erreur veullez réeseyer' } diff --git a/database/Models/Etudiants.backup.js b/database/Models/Etudiants.backup.js index 575fd4a..0d7c58d 100644 --- a/database/Models/Etudiants.backup.js +++ b/database/Models/Etudiants.backup.js @@ -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) { try { return await database.prepare('SELECT * FROM trancheecolage WHERE id = ?').get(id) @@ -301,5 +313,6 @@ module.exports = { getTranche, updateTranche, deleteTranche, + deleteEtudiant, getSingleTranche } diff --git a/database/Models/Etudiants.js b/database/Models/Etudiants.js index 59ed8e9..dacab4b 100644 --- a/database/Models/Etudiants.js +++ b/database/Models/Etudiants.js @@ -176,13 +176,13 @@ async function updateEtudiant( if (result.affectedRows === 0) { return { success: false, - message: 'Année universitaire non trouvé.' + message: 'Année Scolaire non trouvé.' } } return { success: true, - message: 'Année universitaire supprimé avec succès.' + message: 'Année Scolaire supprimé avec succès.' } } catch (error) { return error @@ -222,13 +222,13 @@ async function changePDP(photos, id) { if (result.affectedRows === 0) { return { success: false, - message: 'Année universitaire non trouvé.' + message: 'Année Scolaire non trouvé.' } } return { success: true, - message: 'Année universitaire supprimé avec succès.' + message: 'Année Scolaire 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 universitaire non trouvé.' + message: 'Année Scolaire non trouvé.' } } return { success: true, - message: 'Année universitaire supprimé avec succès.' + message: 'Année Scolaire supprimé avec succès.' } } catch (error) { return error @@ -289,19 +289,21 @@ async function updateTranche(id, tranchename, montant) { try { const [result] = await pool.query(sql, [tranchename, montant, id]) + console.log('resultat tranche:',result); if (result.affectedRows === 0) { return { success: false, - message: 'Année universitaire non trouvé.' + message: 'Année Scolaire non trouvé.' } } return { success: true, - message: 'Année universitaire supprimé avec succès.' + message: 'Année Scolaire supprimé avec succès.' } } catch (error) { + console.log('resultat error:',error); return error } } @@ -315,19 +317,45 @@ async function deleteTranche(id) { if (result.affectedRows === 0) { return { success: false, - message: 'Année universitaire non trouvé.' + message: 'Année Scolaire non trouvé.' } } return { success: true, - message: 'Année universitaire supprimé avec succès.' + message: 'Année Scolaire supprimé avec succès.' } } catch (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) { const sql = 'SELECT * FROM trancheecolage WHERE id = ?' try { @@ -351,5 +379,6 @@ module.exports = { getTranche, updateTranche, deleteTranche, + deleteEtudiant, getSingleTranche } diff --git a/database/Models/Matieres.backup.js b/database/Models/Matieres.backup.js index 8aaedde..528776c 100644 --- a/database/Models/Matieres.backup.js +++ b/database/Models/Matieres.backup.js @@ -29,7 +29,7 @@ async function createMatiere(nom, credit, uniter, ue) { * @returns Promise */ 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 { 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) { const query = database.prepare('DELETE FROM matieres WHERE id = ?') @@ -340,6 +369,7 @@ module.exports = { getMatiere, getSingleMatiere, updateMatiere, + updateMatiereNiveau, displayMatiereFromForm, deleteMatiere, asygnationToMention, diff --git a/database/Models/Matieres.js b/database/Models/Matieres.js index b5e4e8b..8614c39 100644 --- a/database/Models/Matieres.js +++ b/database/Models/Matieres.js @@ -31,7 +31,7 @@ async function createMatiere(nom, credit, uniter, ue) { * @returns Promise */ 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 { let [rows] = await pool.query(sql) @@ -149,41 +149,71 @@ async function updateMatiere(nom, id, credit, uniter, ue) { if (result.affectedRows === 0) { return { 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 { success: true, - message: 'Année universitaire mis à jour avec succès.' + message: 'Année Scolaire mis à jour avec succès.' } } catch (error) { return { success: false, error: 'Erreur veullez réeseyer' + error } } } +async function updateMatiereNiveau(formData) { + const { niveau_id, id } = formData; // ici id sera bien défini + 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 avec id ${id} non trouvée ou niveau déjà attribué.` + }; + } + + return { + success: true, + message: `Niveau de la matière ${id} mis à jour avec succès.` + }; + } catch (error) { + return { + success: false, + error: 'Erreur lors de la mise à jour : ' + error.message + }; + } +} async function deleteMatiere(id) { - const sql = 'DELETE FROM matieres WHERE id = ?' + console.log("id: ", id); + const sql = 'DELETE FROM matieres WHERE id = ?'; try { - let [result] = await pool.query(sql, [id]) + let [result] = await pool.query(sql, [id]); + console.log("Résultat DELETE:", result); if (result.affectedRows === 0) { return { success: false, - message: 'Année universitaire non trouvé.' - } + message: 'Matière non trouvée.' + }; } return { success: true, - message: 'Année universitaire supprimé avec succès.' - } + message: 'Matière supprimée avec succès.' + }; } catch (error) { - return { success: false, error: 'Erreur veullez réeseyer' + error } + console.log("err: ",+ error) + return { success: false, error: 'Erreur, veuillez réessayer: ' + error }; + } } + /** * Assign mentions to a matiere * @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) { return { success: false, - message: 'Année universitaire non trouvé.' + message: 'Année Scolaire non trouvé.' } } return { success: true, - message: 'Année universitaire supprimé avec succès.' + message: 'Année Scolaire supprimé avec succès.' } } catch (error) { console.error(error) @@ -464,6 +494,7 @@ module.exports = { getMatiere, getSingleMatiere, updateMatiere, + updateMatiereNiveau, displayMatiereFromForm, deleteMatiere, asygnationToMention, diff --git a/database/Models/Mentions.js b/database/Models/Mentions.js index 7c57aba..d907f15 100644 --- a/database/Models/Mentions.js +++ b/database/Models/Mentions.js @@ -24,13 +24,13 @@ async function deleteMention(id) { if (result.affectedRows === 0) { return { success: false, - message: 'Année universitaire non trouvé.' + message: 'Année Scolaire non trouvé.' } } return { success: true, - message: 'Année universitaire supprimé avec succès.' + message: 'Année Scolaire 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 universitaire non trouvé ou aucune modification effectuée.' + message: 'Année Scolaire non trouvé ou aucune modification effectuée.' } } return { success: true, - message: 'Année universitaire mis à jour avec succès.' + message: 'Année Scolaire mis à jour avec succès.' } } catch (error) { return { success: false, error: 'Erreur veullez réeseyer' + error } diff --git a/database/Models/Niveau.js b/database/Models/Niveau.js index 9651e5c..0e01c1d 100644 --- a/database/Models/Niveau.js +++ b/database/Models/Niveau.js @@ -89,17 +89,18 @@ async function updateNiveau(nom, id) { * function to get all niveau */ async function getNiveau() { - const sql = 'SELECT * FROM niveaus' + const sql = 'SELECT niveaus.*,niveaus.id AS niveau_id FROM niveaus' try { let [rows] = await pool.query(sql) - + console.log("maka niveau: ", rows); return rows } catch (error) { return { success: false, error: 'Erreur veullez réeseyer' } } } + async function deleteNiveau(id) { const sql = 'DELETE FROM niveaus WHERE id = ?' @@ -130,5 +131,5 @@ module.exports = { insertNiveau, getSingleNiveau, updateNiveau, - deleteNiveau + deleteNiveau, } diff --git a/database/Models/NoteSysrem.js b/database/Models/NoteSysrem.js index 1978ae4..5a8553f 100644 --- a/database/Models/NoteSysrem.js +++ b/database/Models/NoteSysrem.js @@ -33,13 +33,13 @@ async function updateSysteme(id, admis, redouble, renvoyer) { if (result.affectedRows === 0) { return { success: false, - message: 'Année universitaire non trouvé.' + message: 'Année Scolaire non trouvé.' } } return { success: true, - message: 'Année universitaire supprimé avec succès.' + message: 'Année Scolaire supprimé avec succès.' } } catch (error) { return error diff --git a/database/Models/Parcours.js b/database/Models/Parcours.js index 8b3d34e..ec9dd8e 100644 --- a/database/Models/Parcours.js +++ b/database/Models/Parcours.js @@ -30,7 +30,7 @@ async function getParcourMatiere(id) { } 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 { let [rows] = await pool.query(sql) @@ -62,13 +62,13 @@ async function deletes(id) { if (result.affectedRows === 0) { return { success: false, - message: 'Année universitaire non trouvé.' + message: 'Année Scolaire non trouvé.' } } return { success: true, - message: 'Année universitaire supprimé avec succès.' + message: 'Année Scolaire supprimé avec succès.' } } catch (error) { return error @@ -84,13 +84,13 @@ async function updateparcour(id, nom, uniter, mention_id) { if (result.affectedRows === 0) { return { 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 { success: true, - message: 'Année universitaire mis à jour avec succès.' + message: 'Année Scolaire mis à jour avec succès.' } } catch (error) { return error diff --git a/database/database.backup.js b/database/database.backup.js index 5f8be5f..7ea1c7f 100644 --- a/database/database.backup.js +++ b/database/database.backup.js @@ -1,444 +1,307 @@ -const sqlite = require('better-sqlite3') +const mysql = require('mysql2/promise') 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 -let dbPath = `./base/data.db`; +async function createTables() { + const connection = await pool.getConnection() -// Connect to SQLite database with the initial path -let database = new sqlite(dbPath); - - - - - -// Create the users table if it doesn't exist -const createUserTableQuery = ` - CREATE TABLE IF NOT EXISTS users ( - id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, - username VARCHAR(200) NOT NULL, - email VARCHAR(250) NOT NULL UNIQUE, - password TEXT NOT NULL, - roles VARCHAR(250) NOT NULL, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP - ); -` -database.prepare(createUserTableQuery).run() - -// Insert a default admin user if not exists -const insertDefaultUserQuery = ` - 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 ( - id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, - nom VARCHAR(200) NOT NULL, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP - ); -` -database.prepare(createStatusTableQuery).run() - -// create table for mention -const createMentionTableQuery = ` - CREATE TABLE IF NOT EXISTS mentions ( - id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, - nom VARCHAR(250) NOT NULL, - uniter VARCHAR(50) NOT NULL, -- Abréviation du nom - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP - ); -` -database.prepare(createMentionTableQuery).run() - -// Create the niveau table if it doesn't exist -const createNiveauTableQuery = ` - CREATE TABLE IF NOT EXISTS niveaus ( - id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, - nom VARCHAR(50) NOT NULL, -- Exemple: L1, L2, L3, etc. - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP - ); -` -database.prepare(createNiveauTableQuery).run() - -// Create the etudiants table if it doesn't exist -const createEtudiantsTableQuery = ` - CREATE TABLE IF NOT EXISTS etudiants ( - id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, - nom VARCHAR(250) DEFAULT NULL, - prenom VARCHAR(250) DEFAULT NULL, - photos TEXT DEFAULT NULL, - date_de_naissances DATE DEFAULT NULL, - niveau VARCHAR(250) NOT NULL, -- Clé étrangère vers niveaus - annee_scolaire VARCHAR(20) NOT NULL, - status INTEGER DEFAULT NULL, - mention_id INTEGER NOT NULL, -- Clé étrangère vers mentions - num_inscription TEXT NOT NULL, - sexe VARCHAR(20) DEFAULT NULL, - cin VARCHAR(250) DEFAULT NULL, - date_delivrance DEFAULT NULL, - nationalite DATE DEFAULT NULL, - annee_bacc DATE DEFAULT NULL, - serie VARCHAR(20) DEFAULT NULL, - boursier BOOLEAN DEFAULT FALSE, - domaine VARCHAR(250) DEFAULT NULL, - contact VARCHAR(20) DEFAULT NULL, - parcours VARCHAR(250) DEFAULT NULL, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - FOREIGN KEY (status) REFERENCES status(id), - FOREIGN KEY (mention_id) REFERENCES mentions(id) - ); -` -database.prepare(createEtudiantsTableQuery).run() - -// Create the notes table if it doesn't exist -const createMatiereTableQuery = ` - CREATE TABLE IF NOT EXISTS matieres ( - id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, - nom VARCHAR(250) UNIQUE NOT NULL, - unite_enseignement VARCHAR(250) NOT NULL, - credit INTEGER NOT NULL, - heure INTEGER NOT NULL, - ue VARCHAR(10) NOT NULL, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP - ); -` -database.prepare(createMatiereTableQuery).run() - -// Create the semestre table if it doesn't exist -const createSemestreTableQuery = ` - CREATE TABLE IF NOT EXISTS semestres ( - id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, - nom VARCHAR(30) NOT NULL, -- Exemple: S1, S2, S3, etc. - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP - ); -` -database.prepare(createSemestreTableQuery).run() - -// Create the semestre table if it doesn't exist -const createMatiere_mentionTableQuery = ` - CREATE TABLE IF NOT EXISTS matiere_mention ( - id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, - matiere_id INTEGER NOT NULL, -- Clé étrangère vers matieres - mention_id INTEGER NOT NULL, -- Clé étrangère vers mentions - FOREIGN KEY (matiere_id) REFERENCES matieres(id), - FOREIGN KEY (mention_id) REFERENCES mentions(id) - ); -` -database.prepare(createMatiere_mentionTableQuery).run() - -const createMatiere_semestreTableQuery = ` - CREATE TABLE IF NOT EXISTS matiere_semestre ( - id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, - matiere_id INTEGER NOT NULL, -- Clé étrangère vers matieres - semestre_id INTEGER NOT NULL, -- Clé étrangère vers semestres - mention_id INTEGER NOT NULL, -- Clé étrangère vers niveaus - FOREIGN KEY (matiere_id) REFERENCES matieres(id), - FOREIGN KEY (semestre_id) REFERENCES semestres(id), - FOREIGN KEY (mention_id) REFERENCES mentions(id) - ); -` -database.prepare(createMatiere_semestreTableQuery).run() - -// Create the notes table if it doesn't exist -const createNoteTableQuery = ` - CREATE TABLE IF NOT EXISTS notes ( - id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, - etudiant_id INTEGER NOT NULL, -- Clé étrangère vers etudiants - matiere_id INTEGER NOT NULL, -- Clé étrangère vers matieres - etudiant_niveau VARCHAR(50) NOT NULL, - mention_id INTEGER NOT NULL, - note FLOAT DEFAULT NULL, - annee_scolaire VARCHAR(50) NOT NULL, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - FOREIGN KEY (etudiant_id) REFERENCES etudiants(id), - FOREIGN KEY (matiere_id) REFERENCES matieres(id) - FOREIGN KEY (mention_id) REFERENCES mentions(id) - ); -` -database.prepare(createNoteTableQuery).run() - -// Create the notes second session table if it doesn't exist -const createNoteRepechTableQuery = ` - CREATE TABLE IF NOT EXISTS notesrepech ( - id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, - etudiant_id INTEGER NOT NULL, -- Clé étrangère vers etudiants - matiere_id INTEGER NOT NULL, -- Clé étrangère vers matieres - etudiant_niveau VARCHAR(50) NOT NULL, - mention_id INTEGER NOT NULL, - note FLOAT DEFAULT NULL, - annee_scolaire VARCHAR(50) NOT NULL, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - FOREIGN KEY (etudiant_id) REFERENCES etudiants(id), - FOREIGN KEY (matiere_id) REFERENCES matieres(id) - FOREIGN KEY (mention_id) REFERENCES mentions(id) - ); -` -database.prepare(createNoteRepechTableQuery).run() - -// create table for note système -const createNoteSystemeTableQuery = ` - CREATE TABLE IF NOT EXISTS notesystems ( - id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, - admis FLOAT NOT NULL DEFAULT 10, - redouble FLOAT NOT NULL DEFAULT 9.99, - renvoyer FLOAT NOT NULL DEFAULT 7.99, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP - ); -` -database.prepare(createNoteSystemeTableQuery).run() - -// create table année scolaire -const createAnneeScolaireTableQuery = ` - CREATE TABLE IF NOT EXISTS anneescolaire ( - id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, - code VARCHAR(30) NOT NULL, - debut DATE NOT NULL, - fin DATE NOT NULL, - is_current INTEGER DEFAULT 0, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP - ); -` -database.prepare(createAnneeScolaireTableQuery).run() - -// create traitement systeme -const createTraitementSystemQuery = ` - CREATE TABLE IF NOT EXISTS traitmentsystem ( - id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, - code VARCHAR(30) NOT NULL, - debut DATE NOT NULL, - fin DATE NOT NULL, - is_finished INTEGER DEFAULT 0, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP - ); -` -database.prepare(createTraitementSystemQuery).run() - -const createNecessaryParameterTableQuery = ` - CREATE TABLE IF NOT EXISTS nessesaryTable ( - id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, - uniter_heure INTEGER NOT NULL, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP - ); -` -database.prepare(createNecessaryParameterTableQuery).run() - -const createMatiereEnseignantTableQuery = ` - CREATE TABLE IF NOT EXISTS matiereEnseignants ( - id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, - matiere_id INTEGER NOT NULL, - nom_enseignant VARCHAR(250) NOT NULL, - prenom_enseignant VARCHAR(250) NOT NULL, - contact VARCHAR(11) NOT NULL, - date DATE NOT NULL, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - FOREIGN KEY (matiere_id) REFERENCES matieres(id) - ); -` -database.prepare(createMatiereEnseignantTableQuery).run() - -const createParcourTableQuery = ` - CREATE TABLE IF NOT EXISTS parcours ( - id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, - nom VARCHAR(250) NOT NULL, - uniter VARCHAR(250) NOT NULL, - mention_id INTEGER DEFAULT NULL, -- Clé étrangère vers mentions - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP - ); -` -database.prepare(createParcourTableQuery).run() - -const createParcourSemestreTableQuery = ` - CREATE TABLE IF NOT EXISTS parcoursmatiere ( - id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, - matiere_id INTEGER NOT NULL, - parcour_id INTEGER NOT NULL, - FOREIGN KEY (matiere_id) REFERENCES matieres(id), - FOREIGN KEY (parcour_id) REFERENCES parcours(id) - ); -` -database.prepare(createParcourSemestreTableQuery).run() - -const createTableEcolageQuery = ` - CREATE TABLE IF NOT EXISTS trancheecolage ( - id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, - etudiant_id INTEGER NOT NULL, - tranchename VARCHAR(255) NOT NULL, - montant DOUBLE NOT NULL - ); -` -database.prepare(createTableEcolageQuery).run() - -const createTableStoreIP = ` - CREATE TABLE IF NOT EXISTS ipconfig ( - id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, - ipname VARCHAR(255) NOT NULL - ); -`; -database.prepare(createTableStoreIP).run() - -// -------------------------------------- function pre-excuter -------------------------------------------- - -async function insertStatusesIfNotExist() { - // Préparation des requêtes - 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) + try { + // Users table + await connection.query(` + CREATE TABLE IF NOT EXISTS users ( + id INT AUTO_INCREMENT PRIMARY KEY, + username VARCHAR(200) NOT NULL, + email VARCHAR(250) NOT NULL UNIQUE, + password TEXT NOT NULL, + roles VARCHAR(250) NOT NULL, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP + ) ENGINE=InnoDB; + `) + + // Status table + await connection.query(` + CREATE TABLE IF NOT EXISTS status ( + id INT AUTO_INCREMENT PRIMARY KEY, + nom VARCHAR(200) NOT NULL, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP + ) ENGINE=InnoDB; + `) + + // Mentions table + await connection.query(` + CREATE TABLE IF NOT EXISTS mentions ( + id INT AUTO_INCREMENT PRIMARY KEY, + nom VARCHAR(250) NOT NULL, + uniter VARCHAR(50) NOT NULL, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP + ) ENGINE=InnoDB; + `) + + await connection.query(` + CREATE TABLE IF NOT EXISTS niveaus ( + id INT AUTO_INCREMENT PRIMARY KEY, + nom VARCHAR(50) UNIQUE NOT NULL, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP + ) ENGINE=InnoDB; + `) + + await connection.query(` + CREATE TABLE IF NOT EXISTS etudiants ( + id INT AUTO_INCREMENT PRIMARY KEY, + nom VARCHAR(250) DEFAULT NULL, + prenom VARCHAR(250) DEFAULT NULL, + photos TEXT DEFAULT NULL, + date_de_naissances DATE DEFAULT NULL, + niveau VARCHAR(250) NOT NULL, + annee_scolaire VARCHAR(20) NOT NULL, + status INT DEFAULT NULL, + mention_id INT NOT NULL, + num_inscription TEXT UNIQUE NOT NULL, + sexe VARCHAR(20) DEFAULT NULL, + cin VARCHAR(250) DEFAULT NULL, + date_delivrance TEXT DEFAULT NULL, + nationalite VARCHAR(250) DEFAULT NULL, + annee_bacc TEXT DEFAULT NULL, + serie VARCHAR(20) DEFAULT NULL, + boursier VARCHAR(20) DEFAULT NULL, + domaine VARCHAR(250) DEFAULT NULL, + contact VARCHAR(20) DEFAULT NULL, + parcours VARCHAR(250) DEFAULT NULL, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + FOREIGN KEY (status) REFERENCES status(id), + FOREIGN KEY (mention_id) REFERENCES mentions(id) + ) ENGINE=InnoDB; + `) + + await connection.query(` + CREATE TABLE IF NOT EXISTS matieres ( + id INT AUTO_INCREMENT PRIMARY KEY, + nom VARCHAR(250) UNIQUE NOT NULL, + unite_enseignement VARCHAR(250) NOT NULL, + credit INT NOT NULL, + heure INT NOT NULL, + ue VARCHAR(10) NOT NULL, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP + ) ENGINE=InnoDB; + `) + + await connection.query(` + CREATE TABLE IF NOT EXISTS semestres ( + id INT AUTO_INCREMENT PRIMARY KEY, + nom VARCHAR(30) NOT NULL, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP + ) ENGINE=InnoDB; + `) + + await connection.query(` + CREATE TABLE IF NOT EXISTS matiere_mention ( + id INT AUTO_INCREMENT PRIMARY KEY, + matiere_id INT NOT NULL, + mention_id INT NOT NULL, + FOREIGN KEY (matiere_id) REFERENCES matieres(id), + FOREIGN KEY (mention_id) REFERENCES mentions(id) + ) ENGINE=InnoDB; + `) + + await connection.query(` + CREATE TABLE IF NOT EXISTS matiere_semestre ( + id INT AUTO_INCREMENT PRIMARY KEY, + matiere_id INT NOT NULL, + semestre_id INT NOT NULL, + mention_id INT NOT NULL, + FOREIGN KEY (matiere_id) REFERENCES matieres(id), + FOREIGN KEY (semestre_id) REFERENCES semestres(id), + FOREIGN KEY (mention_id) REFERENCES mentions(id) + ) ENGINE=InnoDB; + `) + + await connection.query(` + CREATE TABLE IF NOT EXISTS notes ( + id INT AUTO_INCREMENT PRIMARY KEY, + etudiant_id INT NOT NULL, + matiere_id INT NOT NULL, + etudiant_niveau VARCHAR(50) NOT NULL, + mention_id INT NOT NULL, + note FLOAT DEFAULT NULL, + annee_scolaire VARCHAR(50) NOT NULL, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + FOREIGN KEY (etudiant_id) REFERENCES etudiants(id), + FOREIGN KEY (matiere_id) REFERENCES matieres(id), + FOREIGN KEY (mention_id) REFERENCES mentions(id) + ) ENGINE=InnoDB; + `) + + await connection.query(` + CREATE TABLE IF NOT EXISTS notesrepech ( + id INT AUTO_INCREMENT PRIMARY KEY, + etudiant_id INT NOT NULL, + matiere_id INT NOT NULL, + etudiant_niveau VARCHAR(50) NOT NULL, + mention_id INT NOT NULL, + note FLOAT DEFAULT NULL, + annee_scolaire VARCHAR(50) NOT NULL, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + FOREIGN KEY (etudiant_id) REFERENCES etudiants(id), + FOREIGN KEY (matiere_id) REFERENCES matieres(id), + FOREIGN KEY (mention_id) REFERENCES mentions(id) + ) ENGINE=InnoDB; + `) + + await connection.query(` + CREATE TABLE IF NOT EXISTS notesystems ( + id INT AUTO_INCREMENT PRIMARY KEY, + admis FLOAT NOT NULL DEFAULT 10, + redouble FLOAT NOT NULL DEFAULT 9.99, + renvoyer FLOAT NOT NULL DEFAULT 7.99, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP + ) ENGINE=InnoDB; + `) + + await connection.query(` + CREATE TABLE IF NOT EXISTS anneescolaire ( + id INT AUTO_INCREMENT PRIMARY KEY, + code VARCHAR(30) NOT NULL, + debut DATE NOT NULL, + fin DATE NOT NULL, + is_current TINYINT(1) DEFAULT 0, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP + ) ENGINE=InnoDB; + `) + + await connection.query(` + CREATE TABLE IF NOT EXISTS traitmentsystem ( + id INT AUTO_INCREMENT PRIMARY KEY, + code VARCHAR(30) NOT NULL, + debut DATE NOT NULL, + fin DATE NOT NULL, + is_finished TINYINT(1) DEFAULT 0, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP + ) ENGINE=InnoDB; + `) + + await connection.query(` + CREATE TABLE IF NOT EXISTS nessesaryTable ( + id INT AUTO_INCREMENT PRIMARY KEY, + uniter_heure INT NOT NULL, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP + ) ENGINE=InnoDB; + `) + + await connection.query(` + CREATE TABLE IF NOT EXISTS matiereEnseignants ( + id INT AUTO_INCREMENT PRIMARY KEY, + matiere_id INT NOT NULL, + nom_enseignant VARCHAR(250) NOT NULL, + prenom_enseignant VARCHAR(250) NOT NULL, + contact VARCHAR(11) NOT NULL, + date DATE NOT NULL, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + FOREIGN KEY (matiere_id) REFERENCES matieres(id) + ) ENGINE=InnoDB; + `) + + await connection.query(` + CREATE TABLE IF NOT EXISTS parcours ( + id INT AUTO_INCREMENT PRIMARY KEY, + nom VARCHAR(250) NOT NULL, + uniter VARCHAR(250) NOT NULL, + mention_id INT DEFAULT NULL, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP + ) ENGINE=InnoDB; + `) + + await connection.query(` + CREATE TABLE IF NOT EXISTS parcoursmatiere ( + id INT AUTO_INCREMENT PRIMARY KEY, + matiere_id INT NOT NULL, + parcour_id INT NOT NULL, + FOREIGN KEY (matiere_id) REFERENCES matieres(id), + FOREIGN KEY (parcour_id) REFERENCES parcours(id) + ) ENGINE=InnoDB; + `) + + await connection.query(` + CREATE TABLE IF NOT EXISTS trancheecolage ( + id INT AUTO_INCREMENT PRIMARY KEY, + etudiant_id INT NOT NULL, + tranchename VARCHAR(255) NOT NULL, + montant DOUBLE NOT NULL + ) ENGINE=InnoDB; + `) + + await connection.query(` + CREATE TABLE IF NOT EXISTS ipconfig ( + id INT AUTO_INCREMENT PRIMARY KEY, + ipname VARCHAR(255) NOT NULL + ) ENGINE=InnoDB; + `) + } finally { + connection.release() } } -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; - `) - +async function insertDefaultAdmin() { + const conn = await pool.getConnection() try { - let arraySemestre = [ - 'S1', - 'S2', - 'S3', - 'S4', - '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]) - } - })() + 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'] + ) } - } catch (error) { - console.log(error) - } -} - -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() + } finally { + conn.release() } } -// 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 +async function insertStatusesIfNotExist() { + const conn = await pool.getConnection() + try { + const statuses = ['Nouveau', 'Passant', 'Redoublant', 'Renvoyé', 'Ancien'] + for (let name of statuses) { + const [rows] = await conn.query(`SELECT COUNT(*) as count FROM status WHERE nom = ?`, [name]) + if (rows[0].count === 0) { + await conn.query(`INSERT INTO status (nom) VALUES (?)`, [name]) + } + } + } finally { + conn.release() } } -// 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 = { - database + pool, + createTables, + insertDefaultAdmin, + insertStatusesIfNotExist } diff --git a/database/database.js b/database/database.js index 1634e1b..b6c285f 100644 --- a/database/database.js +++ b/database/database.js @@ -1,11 +1,11 @@ const mysql = require('mysql2/promise') const bcrypt = require('bcryptjs') -const pool = mysql.createPool({ - host: '127.0.0.1', - user: 'root', - password: '', - database: 'university', + const pool = mysql.createPool({ + host: '127.0.0.1', + user: 'root', + password: '', + database: 'university', waitForConnections: true, connectionLimit: 10, queueLimit: 0 diff --git a/database/database2.js b/database/database2.js index 9a03a25..de8806f 100644 --- a/database/database2.js +++ b/database/database2.js @@ -6,11 +6,12 @@ const pool = mysql.createPool({ user: 'root', password: '', database: 'university', - waitForConnections: true, - connectionLimit: 10, - queueLimit: 0 +waitForConnections: true, +connectionLimit: 10, +queueLimit: 0 }) + async function createTables() { const connection = await pool.getConnection() diff --git a/database/function/DownloadReleverNote.js b/database/function/DownloadReleverNote.js index 4521564..cdfb715 100644 --- a/database/function/DownloadReleverNote.js +++ b/database/function/DownloadReleverNote.js @@ -14,7 +14,7 @@ async function modifyPDF(filepath) { const firstPage = pages[0] // 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 firstPage.drawText(data.f1, { x: 120, y: 700, size: 12 }) diff --git a/database/function/System.js b/database/function/System.js index c6b40fd..7356730 100644 --- a/database/function/System.js +++ b/database/function/System.js @@ -287,13 +287,13 @@ async function updateNessesaryTable(id, multiplicateur) { if (result.affectedRows === 0) { return { success: false, - message: 'Année universitaire non trouvé.' + message: 'Année Scolaire non trouvé.' } } return { success: true, - message: 'Année universitaire supprimé avec succès.' + message: 'Année Scolaire supprimé avec succès.' } } catch (error) { return error diff --git a/database/import/Etudiants.js b/database/import/Etudiants.js index 7dfbca1..d4a351c 100644 --- a/database/import/Etudiants.js +++ b/database/import/Etudiants.js @@ -1,264 +1,316 @@ -const fs = require('fs') -const path = require('path') -const XLSX = require('xlsx') -const { getCompressedDefaultImage } = require('../function/GetImageDefaault') -const { parse } = require('csv-parse/sync') -const { pool } = require('../database') -const dayjs = require('dayjs') -// const { getStatusMention } = require('../function/Helper') -const customParseFormat = require('dayjs/plugin/customParseFormat') -// const { log } = require('console') -// const customParseFormatt = require('dayjs/plu') -dayjs.extend(customParseFormat) - -// Function to convert any date format to 'YYYY-MM-DD' +const fs = require('fs'); +const path = require('path'); +const XLSX = require('xlsx'); +const { getCompressedDefaultImage } = require('../function/GetImageDefaault'); +const { parse } = require('csv-parse/sync'); +const { pool } = require('../database'); +const dayjs = require('dayjs'); +const customParseFormat = require('dayjs/plugin/customParseFormat'); +dayjs.extend(customParseFormat); + +// ✅ 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) { - // Try parsing the date with different formats - 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 - if (parsedDate.isValid()) { - return parsedDate.format('YYYY-MM-DD') + if (!input) return null; + + console.log('🔍 Input original:', input, 'Type:', typeof input); + + // 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" - const versMatch = typeof input === 'string' && input.match(/vers\s*(\d{4})/i); - if (versMatch) { - return `${versMatch[1]}-01-01`; // Return in ISO format + // Si input est un nombre (numéro de série Excel) + 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; } - function excelDateToJSDate(serial) { - const utc_days = Math.floor(serial - 25569); // days from Jan 1, 1970 - const utc_value = utc_days * 86400; // seconds in a day - return new Date(utc_value * 1000); // JS Date uses milliseconds + // 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) { + const result = `${versMatch[1]}-01-01`; + console.log('📝 "Vers" détecté:', result); + return result; + } + + // Formats à tester dans l'ordre de priorité + const formats = [ + 'DD/MM/YYYY', 'D/M/YYYY', // Format français prioritaire + '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 + } + } + + return result; + } + } + + // Si aucun format strict ne fonctionne, essayer le parsing libre en dernier recours + const freeParseDate = dayjs(cleanInput); + if (freeParseDate.isValid()) { + const result = freeParseDate.format('YYYY-MM-DD'); + console.log('🆓 Parsing libre réussi:', cleanInput, '->', result); + return result; + } } - let jsDate = excelDateToJSDate(input); + console.error('❌ Impossible de convertir:', input); + return null; +} - // If the input is not a valid date, return 'Invalid Date' - return jsDate +// 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) { const sql = ` INSERT INTO etudiants ( nom, prenom, photos, date_de_naissances, niveau, annee_scolaire, status, mention_id, num_inscription, sexe, cin, date_delivrance, nationalite, 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.prenom, - getCompressedDefaultImage(), // photos (you can adjust this if needed) + getCompressedDefaultImage(), convertToISODate(row.date_naissance), row.niveau, row.annee_scolaire, row.code_redoublement, row.mention, - row.num_inscription, + row.num_inscription.toString(), row.sexe, row.cin, convertToISODate(row.date_de_delivrance), row.nationaliter, - row.annee_baccalaureat, + parseInt(row.annee_baccalaureat, 10), row.serie, row.boursier, - row.domaine, + fixEncoding(row.domaine), row.contact, - null // parcours - ]) + null + ]); try { - const [result] = await pool.query(sql, [values]) - return { - success: true, - affectedRows: result.affectedRows, - insertId: result.insertId - } + const [result] = await pool.query(sql, [values]); + return { success: true, affectedRows: result.affectedRows }; } catch (error) { - return { success: false, error: error.message } + console.error('❌ Erreur MySQL :', error.message); + return { success: false, error: error.message }; } } -/** - * Function to import data from XLSX or CSV file into SQLite database - * @param {string} filePath - Path to the file (either .xlsx or .csv) - */ +// ✅ Import fichier vers base 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') { - // Read and parse XLSX file - const workbook = XLSX.readFile(filePath) - const worksheet = workbook.Sheets[workbook.SheetNames[0]] // Assuming data is in the first sheet - records = XLSX.utils.sheet_to_json(worksheet, { defval: '', raw: false }) + const workbook = XLSX.readFile(filePath); + const worksheet = workbook.Sheets[workbook.SheetNames[0]]; + // raw: true pour garder les valeurs brutes, surtout pour les dates + records = XLSX.utils.sheet_to_json(worksheet, { defval: ''}); } else if (fileExtension === '.csv') { - // Read and parse CSV file - const fileContent = fs.readFileSync(filePath, 'utf8') - records = parse(fileContent, { - columns: true, - skip_empty_lines: true - }) - } else { - console.error('Unsupported file format. Only .xlsx and .csv are allowed.') - return + const fileContent = fs.readFileSync(filePath, 'utf8'); + records = parse(fileContent, { columns: true, skip_empty_lines: true }); + }else { + console.error('Unsupported file format.'); + return { error: true, message: 'Format de fichier non supporté.' }; } - // ✅ Count number of data rows - const numberOfLines = records.length - console.log(`Number of data rows: ${numberOfLines}`) + console.log(`📄 Nombre de lignes : ${records.length}`); - try { - let error = true - let message = '' - - // Vérifier les données en une seule boucle - let oldNum = '' - for (const row of records) { - if ( - !row.nom || - // !row.prenom || - !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 + // 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 query = 'SELECT * FROM mentions' - const [rows] = await pool.query(query) - 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 [mentionRows] = await pool.query('SELECT * FROM mentions'); + const [statusRows] = await pool.query('SELECT * FROM status'); - 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 - } - } + const etudiantsToInsert = []; + const doublons = []; + console.log(records); - 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) - } + 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 { + row.code_redoublement = 'N'; + } + 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}` }; } - console.log(insertMultipleEtudiants(newReccord)) + continue; } - return { error, message } - } catch (error) { - console.error('Error inserting record:', error) - return { error: 'error' } + etudiantsToInsert.push(row); } -} -module.exports = { - importFileToDatabase + console.log(etudiantsToInsert); + + // Insertion des nouveaux + let insertResult = { success: true, affectedRows: 0 }; + if (etudiantsToInsert.length > 0) { + insertResult = await insertMultipleEtudiants(etudiantsToInsert); + if (!insertResult.success) { + return { error: true, message: `Erreur lors de l'insertion : ${insertResult.error}` }; + } + } + + let msg = `Importation réussie. ${etudiantsToInsert.length} nouvel(le)(s) étudiant(s) inséré(s). ${doublons.length} étudiant(s) mis à jour.`; + return { error: false, message: msg }; } + +module.exports = { importFileToDatabase }; diff --git a/resources/icon.png b/resources/icon.png deleted file mode 100644 index cf9e8b2..0000000 Binary files a/resources/icon.png and /dev/null differ diff --git a/resources/logo.ico b/resources/logo.ico deleted file mode 100644 index f592b3c..0000000 Binary files a/resources/logo.ico and /dev/null differ diff --git a/src/main/backup.js b/src/main/backup.js deleted file mode 100644 index 9cc4e0a..0000000 --- a/src/main/backup.js +++ /dev/null @@ -1,912 +0,0 @@ -import { app, shell, BrowserWindow, ipcMain, Tray, Menu } from 'electron' -import { join } from 'path' -const path = require('path') -import { electronApp, optimizer, is } from '@electron-toolkit/utils' -import icon from '../../resources/logo.ico?asset' // Your tray icon file -const database = require('../../database/database2') - -database - .createTables() - .then(() => database.insertDefaultAdmin()) - .then(() => database.insertStatusesIfNotExist()) - .catch(console.error) - -const { createConfigIp, updateIPConfig } = require('../../database/Models/IpConfig') -const { importFileToDatabase } = require('../../database/import/Etudiants') -const { loginUser, forgotPassword, insertUser, updateUser } = require('../../database/Models/Users') -const { - insertEtudiant, - getSingleEtudiant, - FilterDataByNiveau, - updateEtudiant, - changePDP, - updateParcours, - createTranche, - getTranche, - updateTranche, - deleteTranche, - getSingleTranche -} = require('../../database/Models/Etudiants') -const { - insertNiveau, - updateNiveau, - getSingleNiveau, - deleteNiveau -} = require('../../database/Models/Niveau') -const { - insertNote, - getNote, - updateNote, - showMoyen, - getMatiereAndNote, - getNotesWithRepechToDisplay -} = require('../../database/Models/Notes') -const { - createMatiere, - getSingleMatiere, - updateMatiere, - displayMatiereFromForm, - deleteMatiere, - asygnationToMention, - getMentionMatiere, - getMentionMatiereChecked, - getSemestreMatiere, - insertUpdateMentionSemestre, - insertNewProf, - getSIngleProf, - updateProf -} = require('../../database/Models/Matieres') -const { importFileToDatabaseMatiere } = require('../../database/import/Matieres') -const { importNiveau } = require('../../database/import/Niveau') -const { updateSysteme } = require('../../database/Models/NoteSysrem') -const { - createAnneeScolaire, - deleteAnneeScolaire, - getSingleAnneScolaire, - updateAnneeScolaire, - setCurrent -} = require('../../database/Models/AnneeScolaire') -const { - createMention, - deleteMention, - getSingleMention, - updateMention -} = require('../../database/Models/Mentions') -const { - getNoteRepech, - updateNoteRepech, - showMoyenRepech -} = require('../../database/Models/NoteRepechage') -const { - updateCurrentYears, - updateStudents, - updateNessesaryTable -} = require('../../database/function/System') -const { autoUpdater } = require('electron-updater') -const { URL } = require('../../database/api/Config') -const { - insertParcour, - getSingleParcours, - deletes, - updateparcour, - parcourMatiere, - extractFiche, - getParcourMatiere -} = require('../../database/Models/Parcours') - -// Declare mainWindow and tray in the global scope -let mainWindow -let tray = null -updateCurrentYears() -updateStudents() - -autoUpdater.setFeedURL({ - provider: 'generic', - url: `${URL}/latest` // Ensure this points to the folder containing latest.yml -}) - -function createWindow() { - // Create the browser window. - mainWindow = new BrowserWindow({ - width: 1375, - minWidth: 1375, - height: 740, - minHeight: 740, - show: false, - autoHideMenuBar: true, - fullscreen: false, - icon: path.join(__dirname, 'resources', 'logo.ico'), // Path to your icon, - ...(process.platform === 'linux' ? { icon } : {}), - webPreferences: { - preload: join(__dirname, '../preload/index.js'), - nodeIntegration: true, - contextIsolation: true, - sandbox: false - } - }) - - // Désactiver les raccourcis clavier - mainWindow.webContents.on('before-input-event', (event, input) => { - if (input.control || input.meta || input.alt || input.key === 'F11') { - event.preventDefault() - } - }) - - mainWindow.on('ready-to-show', () => { - mainWindow.maximize() // Maximiser la fenêtre - mainWindow.show() - }) - - mainWindow.webContents.setWindowOpenHandler((details) => { - shell.openExternal(details.url) - return { action: 'deny' } - }) - - // Load the appropriate URL based on environment - if (is.dev && process.env['ELECTRON_RENDERER_URL']) { - mainWindow.loadURL(process.env['ELECTRON_RENDERER_URL']) - } else { - mainWindow.loadFile(join(__dirname, '../renderer/index.html')) - } - - // Handle window close (hide instead of closing) - mainWindow.on('close', (event) => { - if (!app.isQuiting) { - event.preventDefault() - mainWindow.hide() // Minimize to tray instead of closing - } else { - // Destroy the tray when quitting - if (tray) tray.destroy() - } - }) -} - -// Function to create the system tray -function createTray() { - const iconPath = icon // Use your icon path here - tray = new Tray(iconPath) - - // Create a context menu for the tray - const contextMenu = Menu.buildFromTemplate([ - { - label: 'Ouvrir', - click: () => { - mainWindow.show() - mainWindow.webContents.send('navigateToRoute', '#/') // Send the route as a string - } - }, - { - label: 'A Propos', - click: () => { - mainWindow.show() - mainWindow.webContents.send('navigateToRoute', '#/apropos') // Send the route as a string - } - }, - { - label: 'Quit', - click: () => { - // Clear localStorage in the renderer process - mainWindow.webContents - .executeJavaScript('localStorage.removeItem("ACCESS_TOKEN");') - .then(() => { - console.log('localStorage cleared.') - // Ensure the app quits entirely - if (tray) { - app.quit() - tray.destroy() - // if (app.quit()) { - // tray.destroy() - // } - } // Quit the app - }) - .catch((err) => { - console.error('Error clearing localStorage:', err) - // Quit the app even if clearing fails - if (tray) { - app.quit() - tray.destroy() - // if (app.quit()) { - // tray.destroy() - // } - } - }) - } - } - ]) - - tray.setToolTip('My Electron App') - tray.setContextMenu(contextMenu) - - // Show the app when the tray icon is clicked - tray.on('click', () => { - mainWindow.show() - }) -} - -app.whenReady().then(() => { - electronApp.setAppUserModelId('com.electron') - autoUpdater.checkForUpdatesAndNotify() - - app.on('browser-window-created', (_, window) => { - optimizer.watchWindowShortcuts(window) - }) - - createWindow() - createTray() // Create the tray icon - - app.on('activate', function () { - if (BrowserWindow.getAllWindows().length === 0) createWindow() - }) -}) - -// When an update is available -autoUpdater.on('update-available', () => { - dialog.showMessageBox({ - type: 'info', - title: 'Mise à jour disponible', - message: 'Une nouvelle version est disponible. Téléchargement en cours...' - }) -}) - -// When the update is downloaded -autoUpdater.on('update-downloaded', (info) => { - dialog - .showMessageBox({ - type: 'info', - title: 'Mise à jour prête', - message: `La version ${info.version} a été téléchargée. Redémarrer maintenant ?`, - buttons: ['Redémarrer', 'Plus tard'] - }) - .then((result) => { - if (result.response === 0) { - autoUpdater.quitAndInstall() - } - }) -}) - -// If an error occurs -autoUpdater.on('error', (error) => { - dialog.showErrorBox('Update Error', error == null ? 'Unknown' : error.message) -}) - -// Quit the app when all windows are closed, except on macOS -app.on('window-all-closed', () => { - if (process.platform !== 'darwin') { - app.quit() - } -}) - -// In this file you can include the rest of your app"s specific main process -// code. You can also put them in separate files and require them here. - -// Event for handling login -ipcMain.handle('login', async (event, credentials) => { - const { username, password } = credentials - - const users = await loginUser(username, password) - - if (users) { - return { success: true, user: users } - } else { - return { success: false } - } -}) - -// Event for handling insert other user -ipcMain.handle('insertUser', async (event, credentials) => { - const { username, email, password, roles } = credentials - - const users = await insertUser(username, email, password, roles) - - return users -}) - -// event for handlign forgot password -ipcMain.handle('forgotPassword', async (event, credentials) => { - const { email, password, passwordConfirmation } = credentials - - const updated = await forgotPassword(email, password, passwordConfirmation) - - if (updated) { - return updated - } -}) - -// event for updating users -ipcMain.handle('updateUsers', async (event, credentials) => { - const { username, newUsername, email, newEmail, passwordVerif, password, id } = credentials - - const update = await updateUser(newUsername, newEmail, password, id) - - return update -}) - -// event for quit app -ipcMain.handle('quit', async () => { - app.quit() -}) - -// event for minimizing the app -ipcMain.handle('minimize', async () => { - if (mainWindow) { - mainWindow.minimize() - } -}) - -// event for insert etudiants -ipcMain.handle('insertEtudiant', async (event, credentials) => { - const { - nom, - prenom, - photos, - date_de_naissances, - niveau, - annee_scolaire, - status, - num_inscription, - mention_id, - sexe, - nationaliter, - cin, - date_delivrence, - annee_bacc, - serie, - boursier, - domaine, - contact, - parcours - } = credentials - - const insert = await insertEtudiant( - nom, - prenom, - photos, - date_de_naissances, - niveau, - annee_scolaire, - status, - num_inscription, - mention_id, - sexe, - nationaliter, - cin, - date_delivrence, - annee_bacc, - serie, - boursier, - domaine, - contact, - parcours - ) - - return insert -}) - -// event for fetching single -ipcMain.handle('getByNiveau', async (event, credentials) => { - const { niveau } = credentials - - const getSingle = await FilterDataByNiveau(niveau) - - return getSingle -}) - -// event for fetching single -ipcMain.handle('single', async (event, credentials) => { - const { id } = credentials - - const getSingle = await getSingleEtudiant(id) - - return getSingle -}) - -// event for inserting niveau -ipcMain.handle('insertNiveau', async (event, credentials) => { - const { nom } = credentials - - const insert = await insertNiveau(nom) - - return insert -}) - -// event for updating etudiants -ipcMain.handle('updateETudiants', async (event, credentials) => { - const { - nom, - prenom, - photos, - date_de_naissances, - niveau, - annee_scolaire, - status, - mention_id, - num_inscription, - id, - sexe, - nationalite, - cin, - date_delivrance, - annee_bacc, - serie, - boursier, - domaine, - contact, - parcours - } = credentials - - const updating = await updateEtudiant( - nom, - prenom, - photos, - date_de_naissances, - niveau, - annee_scolaire, - status, - mention_id, - num_inscription, - id, - sexe, - nationalite, - cin, - date_delivrance, - annee_bacc, - serie, - boursier, - domaine, - contact, - parcours - ) - - return updating -}) - -// event for updating etudiants pdp -ipcMain.handle('updateETudiantsPDP', async (event, credentials) => { - const { pdp, id } = credentials - - const updating = await changePDP(pdp, id) - - return updating -}) - -// event for adding notes -ipcMain.handle('insertNote', async (event, credentials) => { - const { etudiant_id, etudiant_niveau, mention_id, formData, annee_scolaire } = credentials - - const insert = await insertNote( - etudiant_id, - etudiant_niveau, - mention_id, - formData, - annee_scolaire - ) - - return insert -}) - -// event for get single note -ipcMain.handle('getSingleNote', async (event, credentials) => { - const { id, niveau, mention_id } = credentials - - const get = await getNote(id, niveau, mention_id) - - return get -}) - -// event for get single note repech -ipcMain.handle('getNotesRepech', async (event, credentials) => { - const { id, niveau, mention_id } = credentials - - const get = await getNoteRepech(id, niveau, mention_id) - - return get -}) - -// event for updating note -ipcMain.handle('updatetNote', async (event, credentials) => { - const { formData, niveau, id, mention_id, annee_scolaire } = credentials - - const update = await updateNote(formData, niveau, id, mention_id, annee_scolaire) - - return update -}) - -// event for updating note repech -ipcMain.handle('updatetNoteRepech', async (event, credentials) => { - const { formData2, niveau, id } = credentials - - const update = await updateNoteRepech(formData2, niveau, id) - - return update -}) - -// event to get single matiere -ipcMain.handle('getMatiereByID', async (event, credentials) => { - const { id } = credentials - - const matiere = await getSingleMatiere(id) - - return matiere -}) - -// event for updating matiere -ipcMain.handle('updateMatiere', async (event, credentials) => { - const { nom, credit, uniter, ue, id } = credentials - - const update = await updateMatiere(nom, id, credit, uniter, ue) - - return update -}) -// event for importExcel -ipcMain.handle('importexcel', async (event, credentials) => { - const files = credentials - console.log(files) - const insert = await importFileToDatabase(files) - - return insert -}) - -// event for udatign a single niveau -ipcMain.handle('updateSingleNiveau', async (event, credentials) => { - const { nom, id } = credentials - - const update = updateNiveau(nom, id) - - return update -}) - -// event to get single niveau -ipcMain.handle('singleNiveau', async (event, credentials) => { - const { id } = credentials - - const update = getSingleNiveau(id) - - return update -}) - -// event for creating matiere -ipcMain.handle('createMatiere', async (event, credentials) => { - const { nom, credit, uniter, ue } = credentials - - const create = createMatiere(nom, credit, uniter, ue) - - return create -}) - -// event for import excel matiere -ipcMain.handle('importExcelMatiere', async (event, credentials) => { - const files = credentials - console.log(files) - const insert = await importFileToDatabaseMatiere(files) - - return insert -}) - -// event for import excel niveau -ipcMain.handle('importNiveau', async (event, credentials) => { - const files = credentials - console.log(files) - const insert = await importNiveau(files) - - return insert -}) - -// event for updating note systeme -ipcMain.handle('updateNoteSysteme', async (event, credentials) => { - const { id, admis, redouble, renvoyer } = credentials - - const update = updateSysteme(id, admis, redouble, renvoyer) - return update -}) - -// event for updating note systeme -ipcMain.handle('createAnneeScolaire', async (event, credentials) => { - const { code, debut, fin } = credentials - - const create = createAnneeScolaire(code, debut, fin) - return create -}) - -ipcMain.handle('getMoyene', async (event, credentials) => { - const { niveau, scolaire } = credentials - console.log('index.js', niveau, scolaire) - - const create = showMoyen(niveau, scolaire) - return create -}) - -ipcMain.handle('getMoyenneRepech', async (event, credentials) => { - const { niveau, scolaire } = credentials - console.log('index.js', niveau, scolaire) - - const create = showMoyenRepech(niveau, scolaire) - return create -}) - -ipcMain.handle('noteMatiere', async (event, credentials) => { - const { id, niveau, annee_scolaire } = credentials - - const get = getMatiereAndNote(id, niveau, annee_scolaire) - return get -}) - -ipcMain.handle('displayMatiereFromForm', async (event, credentials) => { - const { niveau, mention_id, parcours } = credentials - - const get = displayMatiereFromForm(niveau, mention_id, parcours) - return get -}) - -ipcMain.handle('createMention', async (event, credentials) => { - const { nom, uniter } = credentials - - const get = createMention(nom, uniter) - return get -}) - -ipcMain.handle('getSingleMention', async (event, credentials) => { - const { id } = credentials - - const get = getSingleMention(id) - return get -}) - -ipcMain.handle('updateMention', async (event, credentials) => { - const { nom, uniter, id } = credentials - - const get = updateMention(nom, uniter, id) - return get -}) - -ipcMain.handle('deleteMention', async (event, credentials) => { - const { id } = credentials - - const get = deleteMention(id) - return get -}) - -ipcMain.handle('deleteNiveaus', async (event, credentials) => { - const { id } = credentials - - const get = deleteNiveau(id) - return get -}) - -ipcMain.handle('deleteMatiere', async (event, credentials) => { - const { id } = credentials - - const get = deleteMatiere(id) - return get -}) - -ipcMain.handle('asign', async (event, credentials) => { - const { formData, id } = credentials - // console.log(formData, id); - const get = asygnationToMention(formData, id) - - return get -}) - -ipcMain.handle('asignSemestre', async (event, credentials) => { - const { id } = credentials - - const get = getMentionMatiereChecked(id) - - return get -}) - -ipcMain.handle('getAsign', async (event, credentials) => { - const { id } = credentials - // console.log(formData, id); - const get = getMentionMatiere(id) - - return get -}) - -ipcMain.handle('deleteAnneeScolaire', async (event, credentials) => { - const { id } = credentials - // console.log(formData, id); - const get = deleteAnneeScolaire(id) - - return get -}) - -ipcMain.handle('getSemestreMatiere', async (event, credentials) => { - const { id } = credentials - // console.log(formData, id); - const get = getSemestreMatiere(id) - - return get -}) - -ipcMain.handle('insertUpdateMentionSemestre', async (event, credentials) => { - const { id, selectedSemestres } = credentials - // console.log(formData, id); - const get = insertUpdateMentionSemestre(id, selectedSemestres) - - return get -}) - -ipcMain.handle('getSingleAnneeScolaire', async (event, credentials) => { - const { id } = credentials - // console.log(formData, id); - const get = getSingleAnneScolaire(id) - - return get -}) - -ipcMain.handle('updateAnneeScolaire', async (event, credentials) => { - const { code, debut, fin, id } = credentials - // console.log(formData, id); - const get = updateAnneeScolaire(id, code, debut, fin) - - return get -}) - -ipcMain.handle('setCurrent', async (event, credentials) => { - const { id } = credentials - // console.log(formData, id); - const get = setCurrent(id) - - return get -}) - -ipcMain.handle('noteRelerer', async (event, credentials) => { - const { id, anneescolaire, niveau } = credentials - // console.log(formData, id); - const get = getNotesWithRepechToDisplay(id, anneescolaire, niveau) - - return get -}) - -ipcMain.handle('updateNessesary', async (event, credentials) => { - const { id, multiplicateur } = credentials - // console.log(formData, id); - const get = updateNessesaryTable(id, multiplicateur) - - return get -}) - -ipcMain.handle('insertProf', async (event, credentials) => { - const { nom_enseignant, prenom_enseignant, contact, date, matiere_id } = credentials - // console.log(formData, id); - const get = insertNewProf(matiere_id, nom_enseignant, prenom_enseignant, contact, date) - - return get -}) - -ipcMain.handle('insertParcours', async (event, credentials) => { - const { nom, uniter, mention_id } = credentials - // console.log(formData, id); - const get = insertParcour(nom, uniter, mention_id) - - return get -}) - -ipcMain.handle('getSingleParcours', async (event, credentials) => { - const { id } = credentials - // console.log(formData, id); - const get = getSingleParcours(id) - - return get -}) - -ipcMain.handle('deleteParcours', async (event, credentials) => { - const { id } = credentials - // console.log(formData, id); - const get = deletes(id) - - return get -}) - -ipcMain.handle('updateParcours', async (event, credentials) => { - const { nom, uniter, mention_id, id } = credentials - // console.log(formData, id); - const get = updateparcour(id, nom, uniter, mention_id) - - return get -}) - -ipcMain.handle('parcourMatiere', async (event, credentials) => { - const { matiere_id, parcour_id } = credentials - // console.log(formData, id); - const get = parcourMatiere(matiere_id, parcour_id) - - return get -}) - -ipcMain.handle('getSingleProf', async (event, credentials) => { - const { id } = credentials - // console.log(formData, id); - const get = getSIngleProf(id) - - return get -}) - -ipcMain.handle('updateProf', async (event, credentials) => { - const { nom_enseignant, prenom_enseignant, contact, date, matiere_id } = credentials - // console.log(formData, id); - const get = updateProf(matiere_id, nom_enseignant, prenom_enseignant, contact, date) - - return get -}) - -ipcMain.handle('extractFiches', async (event, credentials) => { - const { matiere_id } = credentials - // console.log(formData, id); - const get = extractFiche(matiere_id) - - return get -}) - -ipcMain.handle('getParcourMatiere', async (event, credentials) => { - const { matiere_id } = credentials - // console.log(formData, id); - const get = getParcourMatiere(matiere_id) - - return get -}) - -ipcMain.handle('changeParcours', async (event, credentials) => { - const { parcours, user_id } = credentials - // console.log(formData, id); - const get = updateParcours(parcours, user_id) - - return get -}) - -ipcMain.handle('createTranche', async (event, credentials) => { - const { etudiant_id, tranchename, montant } = credentials - // console.log(formData, id); - const get = createTranche(etudiant_id, tranchename, montant) - - return get -}) - -ipcMain.handle('getTranche', async (event, credentials) => { - const { id } = credentials - // console.log(formData, id); - const get = getTranche(id) - - return get -}) - -ipcMain.handle('updateTranche', async (event, credentials) => { - const { id, tranchename, montant } = credentials - // console.log(formData, id); - const get = updateTranche(id, tranchename, montant) - - return get -}) - -ipcMain.handle('deleteTranche', async (event, credentials) => { - const { id } = credentials - console.log(id) - const get = deleteTranche(id) - - return get -}) - -ipcMain.handle('getSingleTranche', async (event, credentials) => { - const { id } = credentials - // console.log(formData, id); - const get = getSingleTranche(id) - - return get -}) - -ipcMain.handle('createIPConfig', async (event, credentials) => { - const { ipname } = credentials - // console.log(formData, id); - const get = createConfigIp(ipname) - - return get -}) - -ipcMain.handle('updateIPConfig', async (event, credentials) => { - const { id, ipname } = credentials - // console.log(formData, id); - const get = updateIPConfig(id, ipname) - - return get -}) diff --git a/src/main/index.js b/src/main/index.js deleted file mode 100644 index b452894..0000000 --- a/src/main/index.js +++ /dev/null @@ -1,895 +0,0 @@ -import { app, shell, BrowserWindow, ipcMain, Tray, Menu } from 'electron' -import { join } from 'path' -const path = require('path') -import { electronApp, optimizer, is } from '@electron-toolkit/utils' -import icon from '../../resources/logo.ico?asset' // Your tray icon file -const database = require('../../database/database') - -database - .createTables() - .then(() => database.insertDefaultAdmin()) - .then(() => database.insertStatusesIfNotExist()) - .catch(console.error) - -const { loginUsers, insertUser, updateUser } = require('../../database/Models/Users') -const { createConfigIp, updateIPConfig } = require('../../database/Models/IpConfig') -const { importFileToDatabase } = require('../../database/import/Etudiants') -const { - insertEtudiant, - getSingleEtudiant, - FilterDataByNiveau, - updateEtudiant, - changePDP, - updateParcours, - createTranche, - getTranche, - updateTranche, - deleteTranche, - getSingleTranche -} = require('../../database/Models/Etudiants') -const { - insertNiveau, - updateNiveau, - getSingleNiveau, - deleteNiveau -} = require('../../database/Models/Niveau') -const { - insertNote, - getNote, - updateNote, - showMoyen, - getMatiereAndNote, - getNotesWithRepechToDisplay -} = require('../../database/Models/Notes') -const { - createMatiere, - getSingleMatiere, - updateMatiere, - displayMatiereFromForm, - deleteMatiere, - asygnationToMention, - getMentionMatiere, - getMentionMatiereChecked, - getSemestreMatiere, - insertUpdateMentionSemestre, - insertNewProf, - getSIngleProf, - updateProf -} = require('../../database/Models/Matieres') -const { importFileToDatabaseMatiere } = require('../../database/import/Matieres') -const { importNiveau } = require('../../database/import/Niveau') -const { updateSysteme } = require('../../database/Models/NoteSysrem') -const { - createAnneeScolaire, - deleteAnneeScolaire, - getSingleAnneScolaire, - updateAnneeScolaire, - setCurrent -} = require('../../database/Models/AnneeScolaire') -const { - createMention, - deleteMention, - getSingleMention, - updateMention -} = require('../../database/Models/Mentions') -const { - getNoteRepech, - updateNoteRepech, - showMoyenRepech -} = require('../../database/Models/NoteRepechage') -const { - updateCurrentYears, - updateStudents, - updateNessesaryTable -} = require('../../database/function/System') -const { autoUpdater } = require('electron-updater') -const { URL } = require('../../database/api/Config') -const { - insertParcour, - getSingleParcours, - deletes, - updateparcour, - parcourMatiere, - extractFiche, - getParcourMatiere -} = require('../../database/Models/Parcours') - -// Declare mainWindow and tray in the global scope -let mainWindow -let tray = null -updateCurrentYears() -updateStudents() - -autoUpdater.setFeedURL({ - provider: 'generic', - url: `${URL}/latest` // Ensure this points to the folder containing latest.yml -}) - -function createWindow() { - // Create the browser window. - mainWindow = new BrowserWindow({ - width: 1375, - minWidth: 1375, - height: 740, - minHeight: 740, - show: false, - autoHideMenuBar: true, - fullscreen: false, - icon: path.join(__dirname, 'resources', 'logo.ico'), // Path to your icon, - ...(process.platform === 'linux' ? { icon } : {}), - webPreferences: { - preload: join(__dirname, '../preload/index.js'), - nodeIntegration: true, - contextIsolation: true, - sandbox: false - } - }) - - // Désactiver les raccourcis clavier - mainWindow.webContents.on('before-input-event', (event, input) => { - if (input.control || input.meta || input.alt || input.key === 'F11') { - event.preventDefault() - } - }) - - mainWindow.on('ready-to-show', () => { - mainWindow.maximize() // Maximiser la fenêtre - mainWindow.show() - }) - - mainWindow.webContents.setWindowOpenHandler((details) => { - shell.openExternal(details.url) - return { action: 'deny' } - }) - - // Load the appropriate URL based on environment - if (is.dev && process.env['ELECTRON_RENDERER_URL']) { - mainWindow.loadURL(process.env['ELECTRON_RENDERER_URL']) - } else { - mainWindow.loadFile(join(__dirname, '../renderer/index.html')) - } - - // Handle window close (hide instead of closing) - mainWindow.on('close', (event) => { - if (!app.isQuiting) { - event.preventDefault() - mainWindow.hide() // Minimize to tray instead of closing - } else { - // Destroy the tray when quitting - if (tray) tray.destroy() - } - }) -} - -// Function to create the system tray -function createTray() { - const iconPath = icon // Use your icon path here - tray = new Tray(iconPath) - - // Create a context menu for the tray - const contextMenu = Menu.buildFromTemplate([ - { - label: 'Ouvrir', - click: () => { - mainWindow.show() - mainWindow.webContents.send('navigateToRoute', '#/') // Send the route as a string - } - }, - { - label: 'A Propos', - click: () => { - mainWindow.show() - mainWindow.webContents.send('navigateToRoute', '#/apropos') // Send the route as a string - } - }, - { - label: 'Quit', - click: () => { - // Clear localStorage in the renderer process - mainWindow.webContents - .executeJavaScript('localStorage.removeItem("ACCESS_TOKEN");') - .then(() => { - console.log('localStorage cleared.') - // Ensure the app quits entirely - if (tray) { - app.quit() - tray.destroy() - // if (app.quit()) { - // tray.destroy() - // } - } // Quit the app - }) - .catch((err) => { - console.error('Error clearing localStorage:', err) - // Quit the app even if clearing fails - if (tray) { - app.quit() - tray.destroy() - // if (app.quit()) { - // tray.destroy() - // } - } - }) - } - } - ]) - - tray.setToolTip('My Electron App') - tray.setContextMenu(contextMenu) - - // Show the app when the tray icon is clicked - tray.on('click', () => { - mainWindow.show() - }) -} - -app.whenReady().then(() => { - electronApp.setAppUserModelId('com.electron') - autoUpdater.checkForUpdatesAndNotify() - - app.on('browser-window-created', (_, window) => { - optimizer.watchWindowShortcuts(window) - }) - - createWindow() - createTray() // Create the tray icon - - app.on('activate', function () { - if (BrowserWindow.getAllWindows().length === 0) createWindow() - }) -}) - -// When an update is available -autoUpdater.on('update-available', () => { - dialog.showMessageBox({ - type: 'info', - title: 'Mise à jour disponible', - message: 'Une nouvelle version est disponible. Téléchargement en cours...' - }) -}) - -// When the update is downloaded -autoUpdater.on('update-downloaded', (info) => { - dialog - .showMessageBox({ - type: 'info', - title: 'Mise à jour prête', - message: `La version ${info.version} a été téléchargée. Redémarrer maintenant ?`, - buttons: ['Redémarrer', 'Plus tard'] - }) - .then((result) => { - if (result.response === 0) { - autoUpdater.quitAndInstall() - } - }) -}) - -// If an error occurs -autoUpdater.on('error', (error) => { - dialog.showErrorBox('Update Error', error == null ? 'Unknown' : error.message) -}) - -// Quit the app when all windows are closed, except on macOS -app.on('window-all-closed', () => { - if (process.platform !== 'darwin') { - app.quit() - } -}) - -// In this file you can include the rest of your app"s specific main process -// code. You can also put them in separate files and require them here. - -// event for quit app -ipcMain.handle('quit', async () => { - app.quit() -}) - -// event for minimizing the app -ipcMain.handle('minimize', async () => { - if (mainWindow) { - mainWindow.minimize() - } -}) - -ipcMain.handle('login', async (event, credentials) => { - const { username, password } = credentials - - // Pass username and password to loginUsers - let response = await loginUsers(username, password) - - return response -}) - -ipcMain.handle('insertUser', async (event, credentials) => { - const { username, email, password, roles } = credentials - - const users = await insertUser(username, email, password, roles) - - return users -}) - -ipcMain.handle('updateUsers', async (event, credentials) => { - const { username, email, password, id } = credentials - - const update = await updateUser(username, email, password, id) - - return update -}) - -// event for insert etudiants -ipcMain.handle('insertEtudiant', async (event, credentials) => { - const { - nom, - prenom, - photos, - date_de_naissances, - niveau, - annee_scolaire, - status, - num_inscription, - mention_id, - sexe, - nationaliter, - cin, - date_delivrence, - annee_bacc, - serie, - boursier, - domaine, - contact, - parcours - } = credentials - - const insert = await insertEtudiant( - nom, - prenom, - photos, - date_de_naissances, - niveau, - annee_scolaire, - status, - num_inscription, - mention_id, - sexe, - nationaliter, - cin, - date_delivrence, - annee_bacc, - serie, - boursier, - domaine, - contact, - parcours - ) - - return insert -}) - -// event for fetching single -ipcMain.handle('getByNiveau', async (event, credentials) => { - const { niveau } = credentials - - const getSingle = await FilterDataByNiveau(niveau) - - return getSingle -}) - -// event for fetching single -ipcMain.handle('single', async (event, credentials) => { - const { id } = credentials - - const getSingle = await getSingleEtudiant(id) - - return getSingle -}) - -// event for inserting niveau -ipcMain.handle('insertNiveau', async (event, credentials) => { - const { nom } = credentials - - const insert = await insertNiveau(nom) - - return insert -}) - -// event for updating etudiants -ipcMain.handle('updateETudiants', async (event, credentials) => { - const { - nom, - prenom, - photos, - date_de_naissances, - niveau, - annee_scolaire, - status, - mention_id, - num_inscription, - id, - sexe, - nationalite, - cin, - date_delivrance, - annee_bacc, - serie, - boursier, - domaine, - contact, - parcours - } = credentials - - const updating = await updateEtudiant( - nom, - prenom, - photos, - date_de_naissances, - niveau, - annee_scolaire, - status, - mention_id, - num_inscription, - id, - sexe, - nationalite, - cin, - date_delivrance, - annee_bacc, - serie, - boursier, - domaine, - contact, - parcours - ) - - return updating -}) - -// event for updating etudiants pdp -ipcMain.handle('updateETudiantsPDP', async (event, credentials) => { - const { pdp, id } = credentials - - const updating = await changePDP(pdp, id) - - return updating -}) - -// event for adding notes -ipcMain.handle('insertNote', async (event, credentials) => { - const { etudiant_id, etudiant_niveau, mention_id, formData, annee_scolaire } = credentials - - const insert = await insertNote( - etudiant_id, - etudiant_niveau, - mention_id, - formData, - annee_scolaire - ) - - return insert -}) - -// event for get single note -ipcMain.handle('getSingleNote', async (event, credentials) => { - const { id, niveau, mention_id } = credentials - - const get = await getNote(id, niveau, mention_id) - - return get -}) - -// event for get single note repech -ipcMain.handle('getNotesRepech', async (event, credentials) => { - const { id, niveau, mention_id } = credentials - - const get = await getNoteRepech(id, niveau, mention_id) - - return get -}) - -// event for updating note -ipcMain.handle('updatetNote', async (event, credentials) => { - const { formData, niveau, id, mention_id, annee_scolaire } = credentials - - const update = await updateNote(formData, niveau, id, mention_id, annee_scolaire) - - return update -}) - -// event for updating note repech -ipcMain.handle('updatetNoteRepech', async (event, credentials) => { - const { formData2, niveau, id } = credentials - - const update = await updateNoteRepech(formData2, niveau, id) - - return update -}) - -// event to get single matiere -ipcMain.handle('getMatiereByID', async (event, credentials) => { - const { id } = credentials - - const matiere = await getSingleMatiere(id) - - return matiere -}) - -// // event for updating matiere -ipcMain.handle('updateMatiere', async (event, credentials) => { - const { nom, credit, uniter, ue, id } = credentials - - const update = await updateMatiere(nom, id, credit, uniter, ue) - - return update -}) -// event for importExcel -ipcMain.handle('importexcel', async (event, credentials) => { - const files = credentials - console.log(files) - const insert = await importFileToDatabase(files) - - return insert -}) - -// event for udatign a single niveau -ipcMain.handle('updateSingleNiveau', async (event, credentials) => { - const { nom, id } = credentials - - const update = updateNiveau(nom, id) - - return update -}) - -// event to get single niveau -ipcMain.handle('singleNiveau', async (event, credentials) => { - const { id } = credentials - - const update = getSingleNiveau(id) - - return update -}) - -// event for creating matiere -ipcMain.handle('createMatiere', async (event, credentials) => { - const { nom, credit, uniter, ue } = credentials - - const create = createMatiere(nom, credit, uniter, ue) - - return create -}) - -// // event for import excel matiere -ipcMain.handle('importExcelMatiere', async (event, credentials) => { - const files = credentials - console.log(files) - const insert = await importFileToDatabaseMatiere(files) - - return insert -}) - -// event for import excel niveau -ipcMain.handle('importNiveau', async (event, credentials) => { - const files = credentials - console.log(files) - const insert = await importNiveau(files) - - return insert -}) - -// event for updating note systeme -ipcMain.handle('updateNoteSysteme', async (event, credentials) => { - const { id, admis, redouble, renvoyer } = credentials - - const update = updateSysteme(id, admis, redouble, renvoyer) - return update -}) - -// event for updating note systeme -ipcMain.handle('createAnneeScolaire', async (event, credentials) => { - const { code, debut, fin } = credentials - - const create = createAnneeScolaire(code, debut, fin) - return create -}) - -ipcMain.handle('getMoyene', async (event, credentials) => { - const { niveau, scolaire } = credentials - console.log('index.js', niveau, scolaire) - - const create = showMoyen(niveau, scolaire) - return create -}) - -ipcMain.handle('getMoyenneRepech', async (event, credentials) => { - const { niveau, scolaire } = credentials - console.log('index.js', niveau, scolaire) - - const create = showMoyenRepech(niveau, scolaire) - return create -}) - -ipcMain.handle('noteMatiere', async (event, credentials) => { - const { id, niveau, annee_scolaire } = credentials - - const get = getMatiereAndNote(id, niveau, annee_scolaire) - return get -}) - -ipcMain.handle('displayMatiereFromForm', async (event, credentials) => { - const { niveau, mention_id, parcours } = credentials - - const get = displayMatiereFromForm(niveau, mention_id, parcours) - return get -}) - -ipcMain.handle('createMention', async (event, credentials) => { - const { nom, uniter } = credentials - - const get = createMention(nom, uniter) - return get -}) - -ipcMain.handle('getSingleMention', async (event, credentials) => { - const { id } = credentials - - const get = getSingleMention(id) - return get -}) - -ipcMain.handle('updateMention', async (event, credentials) => { - const { nom, uniter, id } = credentials - - const get = updateMention(nom, uniter, id) - return get -}) - -ipcMain.handle('deleteMention', async (event, credentials) => { - const { id } = credentials - - const get = deleteMention(id) - return get -}) - -ipcMain.handle('deleteNiveaus', async (event, credentials) => { - const { id } = credentials - - const get = deleteNiveau(id) - return get -}) - -ipcMain.handle('deleteMatiere', async (event, credentials) => { - const { id } = credentials - - const get = deleteMatiere(id) - return get -}) - -ipcMain.handle('asign', async (event, credentials) => { - const { formData, id } = credentials - // console.log(formData, id); - const get = asygnationToMention(formData, id) - - return get -}) - -ipcMain.handle('asignSemestre', async (event, credentials) => { - const { id } = credentials - - const get = getMentionMatiereChecked(id) - - return get -}) - -ipcMain.handle('getAsign', async (event, credentials) => { - const { id } = credentials - // console.log(formData, id); - const get = getMentionMatiere(id) - - return get -}) - -ipcMain.handle('deleteAnneeScolaire', async (event, credentials) => { - const { id } = credentials - // console.log(formData, id); - const get = deleteAnneeScolaire(id) - - return get -}) - -ipcMain.handle('getSemestreMatiere', async (event, credentials) => { - const { id } = credentials - // console.log(formData, id); - const get = getSemestreMatiere(id) - - return get -}) - -ipcMain.handle('insertUpdateMentionSemestre', async (event, credentials) => { - const { id, selectedSemestres } = credentials - // console.log(formData, id); - const get = insertUpdateMentionSemestre(id, selectedSemestres) - - return get -}) - -ipcMain.handle('getSingleAnneeScolaire', async (event, credentials) => { - const { id } = credentials - // console.log(formData, id); - const get = getSingleAnneScolaire(id) - - return get -}) - -ipcMain.handle('updateAnneeScolaire', async (event, credentials) => { - const { code, debut, fin, id } = credentials - // console.log(formData, id); - const get = updateAnneeScolaire(id, code, debut, fin) - - return get -}) - -ipcMain.handle('setCurrent', async (event, credentials) => { - const { id } = credentials - // console.log(formData, id); - const get = setCurrent(id) - - return get -}) - -ipcMain.handle('noteRelerer', async (event, credentials) => { - const { id, anneescolaire, niveau } = credentials - // console.log(formData, id); - const get = getNotesWithRepechToDisplay(id, anneescolaire, niveau) - - return get -}) - -ipcMain.handle('updateNessesary', async (event, credentials) => { - const { id, multiplicateur } = credentials - // console.log(formData, id); - const get = updateNessesaryTable(id, multiplicateur) - - return get -}) - -ipcMain.handle('insertProf', async (event, credentials) => { - const { nom_enseignant, prenom_enseignant, contact, date, matiere_id } = credentials - // console.log(formData, id); - const get = insertNewProf(matiere_id, nom_enseignant, prenom_enseignant, contact, date) - - return get -}) - -ipcMain.handle('insertParcours', async (event, credentials) => { - const { nom, uniter, mention_id } = credentials - // console.log(formData, id); - const get = insertParcour(nom, uniter, mention_id) - - return get -}) - -ipcMain.handle('getSingleParcours', async (event, credentials) => { - const { id } = credentials - // console.log(formData, id); - const get = getSingleParcours(id) - - return get -}) - -ipcMain.handle('deleteParcours', async (event, credentials) => { - const { id } = credentials - // console.log(formData, id); - const get = deletes(id) - - return get -}) - -ipcMain.handle('updateParcours', async (event, credentials) => { - const { nom, uniter, mention_id, id } = credentials - // console.log(formData, id); - const get = updateparcour(id, nom, uniter, mention_id) - - return get -}) - -ipcMain.handle('parcourMatiere', async (event, credentials) => { - const { matiere_id, parcour_id } = credentials - // console.log(formData, id); - const get = parcourMatiere(matiere_id, parcour_id) - - return get -}) - -ipcMain.handle('getSingleProf', async (event, credentials) => { - const { id } = credentials - // console.log(formData, id); - const get = getSIngleProf(id) - - return get -}) - -ipcMain.handle('updateProf', async (event, credentials) => { - const { nom_enseignant, prenom_enseignant, contact, date, matiere_id } = credentials - // console.log(formData, id); - const get = updateProf(matiere_id, nom_enseignant, prenom_enseignant, contact, date) - - return get -}) - -ipcMain.handle('extractFiches', async (event, credentials) => { - const { matiere_id } = credentials - // console.log(formData, id); - const get = extractFiche(matiere_id) - - return get -}) - -ipcMain.handle('getParcourMatiere', async (event, credentials) => { - const { matiere_id } = credentials - // console.log(formData, id); - const get = getParcourMatiere(matiere_id) - - return get -}) - -ipcMain.handle('changeParcours', async (event, credentials) => { - const { parcours, user_id } = credentials - // console.log(formData, id); - const get = updateParcours(parcours, user_id) - - return get -}) - -ipcMain.handle('createTranche', async (event, credentials) => { - const { etudiant_id, tranchename, montant } = credentials - // console.log(formData, id); - const get = createTranche(etudiant_id, tranchename, montant) - - return get -}) - -ipcMain.handle('getTranche', async (event, credentials) => { - const { id } = credentials - // console.log(formData, id); - const get = getTranche(id) - - return get -}) - -ipcMain.handle('updateTranche', async (event, credentials) => { - const { id, tranchename, montant } = credentials - // console.log(formData, id); - const get = updateTranche(id, tranchename, montant) - - return get -}) - -ipcMain.handle('deleteTranche', async (event, credentials) => { - const { id } = credentials - console.log(id) - const get = deleteTranche(id) - - return get -}) - -ipcMain.handle('getSingleTranche', async (event, credentials) => { - const { id } = credentials - // console.log(formData, id); - const get = getSingleTranche(id) - - return get -}) - -ipcMain.handle('createIPConfig', async (event, credentials) => { - const { ipname } = credentials - // console.log(formData, id); - const get = createConfigIp(ipname) - - return get -}) - -ipcMain.handle('updateIPConfig', async (event, credentials) => { - const { id, ipname } = credentials - // console.log(formData, id); - const get = updateIPConfig(id, ipname) - - return get -}) diff --git a/src/main/test.js b/src/main/test.js deleted file mode 100644 index 53ce37c..0000000 --- a/src/main/test.js +++ /dev/null @@ -1,135 +0,0 @@ -import { app, shell, BrowserWindow, ipcMain } from 'electron' -import { join } from 'path' -import { electronApp, optimizer, is } from '@electron-toolkit/utils' -import icon from '../../resources/icon.png?asset' -const { loginUser, forgotPassword } = require('../../database/Models/Users') - -let splashWindow -let mainWindow - -// Create splash window -function createSplashScreen() { - splashWindow = new BrowserWindow({ - width: 400, - height: 300, - frame: false, - alwaysOnTop: true, - transparent: true, - resizable: false, - webPreferences: { - nodeIntegration: true, - contextIsolation: false - } - }) - - splashWindow.loadFile(join(__dirname, '../renderer/splash.html')) - - splashWindow.on('closed', () => { - splashWindow = null - }) -} - -// Create main application window -function createWindow() { - mainWindow = new BrowserWindow({ - width: 1000, - minWidth: 1000, - height: 670, - minHeight: 670, - show: false, - autoHideMenuBar: true, - fullscreen: true, - ...(process.platform === 'linux' ? { icon } : {}), - webPreferences: { - preload: join(__dirname, '../preload/index.js'), - nodeIntegration: true, - contextIsolation: true, - sandbox: false - } - }) - - mainWindow.on('ready-to-show', () => { - if (splashWindow) { - splashWindow.close() // Close splash screen when main window is ready - } - mainWindow.show() - }) - - mainWindow.webContents.setWindowOpenHandler((details) => { - shell.openExternal(details.url) - return { action: 'deny' } - }) - - // Load the initial content - if (is.dev && process.env['ELECTRON_RENDERER_URL']) { - mainWindow.loadURL(process.env['ELECTRON_RENDERER_URL']) - } else { - mainWindow.loadFile(join(__dirname, '../renderer/index.html')) - } -} - -// Function to load new content and show the splash screen -function loadNewContent(contentPath) { - createSplashScreen() // Show splash screen before loading new content - - mainWindow.loadFile(contentPath).then(() => { - if (splashWindow) { - splashWindow.close() // Close splash screen after loading content - } - mainWindow.show() // Show main window - }) -} - -// This method will be called when Electron has finished initialization -app.whenReady().then(() => { - // Set app user model id for Windows - electronApp.setAppUserModelId('com.electron') - - // Default open or close DevTools by F12 in development - app.on('browser-window-created', (_, window) => { - optimizer.watchWindowShortcuts(window) - }) - - // Create initial main window - createWindow() - - // IPC for loading new content - ipcMain.on('load-content', (event, contentPath) => { - loadNewContent(contentPath) - }) - - app.on('activate', function () { - if (BrowserWindow.getAllWindows().length === 0) createWindow() - }) -}) - -// Quit when all windows are closed, except on macOS -app.on('window-all-closed', () => { - if (process.platform !== 'darwin') { - app.quit() - } -}) - -// Event for handling login -ipcMain.handle('login', async (event, credentials) => { - const { username, password } = credentials - - const users = await loginUser(username, password) - - if (users) { - return { success: true, user: users } - } else { - return { success: false } - } -}) - -// Event for handling forgot password -ipcMain.handle('forgotPassword', async (event, credentials) => { - const { email, password, passwordConfirmation } = credentials - - const updated = await forgotPassword(email, password, passwordConfirmation) - - if (updated) { - return updated - } -}) diff --git a/src/preload/index.backup.js b/src/preload/index.backup.js deleted file mode 100644 index baa360e..0000000 --- a/src/preload/index.backup.js +++ /dev/null @@ -1,210 +0,0 @@ -import { contextBridge, ipcRenderer } from 'electron' -import { electronAPI } from '@electron-toolkit/preload' -const { getNessesarytable } = require('../../database/function/System') -const { getNiveau } = require('../../database/Models/Niveau') -const { getAllUsers } = require('../../database/Models/Users') -const { getAllEtudiants, getDataToDashboard } = require('../../database/Models/Etudiants') -const { verifyEtudiantIfHeHasNotes, blockShowMoyene } = require('../../database/Models/Notes') - -const { synchronizeData } = require('../../database/api/SyncronisationDataUsers') -const { synchronizeDataEtudiants } = require('../../database/api/SyncronisationDataEtudiants') -const { synchronizeDataNotes } = require('../../database/api/CheckUpdateNote') -const { getMatiere, getSemestre, getEnseignants } = require('../../database/Models/Matieres') -const { getSysteme } = require('../../database/Models/NoteSysrem') -const { getStatus } = require('../../database/Models/Status') -const { getAnneeScolaire, getInterval } = require('../../database/Models/AnneeScolaire') -const { getMentions } = require('../../database/Models/Mentions') -const { getAll } = require('../../database/api/Get') -const { getParcours } = require('../../database/Models/Parcours') -const { getIPConfig } = require('../../database/Models/IpConfig') - -// Custom APIs for renderer -const api = {} - -// Use `contextBridge` APIs to expose Electron APIs to -// renderer only if context isolation is enabled, otherwise -// just add to the DOM global. -if (process.contextIsolated) { - try { - contextBridge.exposeInMainWorld('electron', electronAPI) - contextBridge.exposeInMainWorld('api', api) - - /** - * contextBridge for Tray - */ - contextBridge.exposeInMainWorld('Tray', { - onNavigate: (callback) => { - ipcRenderer.on('navigateToRoute', (event, route) => { - callback(route) // Pass the route to the renderer callback - }) - } - }) - - /** - * contextBridge for users - */ - contextBridge.exposeInMainWorld('allUser', { - users: () => getAllUsers(), - login: (credentials) => ipcRenderer.invoke('login', credentials), - insertUsers: (credentials) => ipcRenderer.invoke('insertUser', credentials), - forgotPassword: (credentials) => ipcRenderer.invoke('forgotPassword', credentials), - quit: () => ipcRenderer.invoke('quit'), - minimize: () => ipcRenderer.invoke('minimize'), - updateUsers: (credentials) => ipcRenderer.invoke('updateUsers', credentials) - }) - - contextBridge.exposeInMainWorld('syncro', { - getall: () => getAll() - }) - - // syncronisation des donner - window.addEventListener('online', async () => { - if (navigator.onLine) { - // synchronizeData() - // synchronizeDataEtudiants() - // synchronizeDataNotes() - await getAll() - } - }) - // send data - getAll() - - /** - * contextBridge for etudiants - */ - contextBridge.exposeInMainWorld('etudiants', { - insertEtudiant: (credentials) => ipcRenderer.invoke('insertEtudiant', credentials), - getEtudiants: () => getAllEtudiants(), - FilterDataByNiveau: (credential) => ipcRenderer.invoke('getByNiveau', credential), - getSingle: (credential) => ipcRenderer.invoke('single', credential), - updateEtudiants: (credentials) => ipcRenderer.invoke('updateETudiants', credentials), - getDataToDashboards: () => getDataToDashboard(), - updateEtudiantsPDP: (credentials) => ipcRenderer.invoke('updateETudiantsPDP', credentials), - importExcel: (credentials) => ipcRenderer.invoke('importexcel', credentials), - changeParcours: (credentials) => ipcRenderer.invoke('changeParcours', credentials), - createTranche: (credentials) => ipcRenderer.invoke('createTranche', credentials), - getTranche: (credentials) => ipcRenderer.invoke('getTranche', credentials), - updateTranche: (credentials) => ipcRenderer.invoke('updateTranche', credentials), - deleteTranche: (credentials) => ipcRenderer.invoke('deleteTranche', credentials), - getSingleTranche: (credentials) => ipcRenderer.invoke('getSingleTranche', credentials) - }) - - /** - * cobtextBridge for niveaus - */ - contextBridge.exposeInMainWorld('niveaus', { - getNiveau: () => getNiveau(), - getSingleNiveau: (credential) => ipcRenderer.invoke('singleNiveau', credential), - insertNiveau: (credentials) => ipcRenderer.invoke('insertNiveau', credentials), - updateSingleNiveau: (credentials) => ipcRenderer.invoke('updateSingleNiveau', credentials), - importNiveau: (credentials) => ipcRenderer.invoke('importNiveau', credentials), - deleteNiveaus: (credentials) => ipcRenderer.invoke('deleteNiveaus', credentials) - }) - - /** - * contextBridge for notes - */ - contextBridge.exposeInMainWorld('notes', { - getNotes: (credentials) => ipcRenderer.invoke('getSingleNote', credentials), - insertNote: (credentials) => ipcRenderer.invoke('insertNote', credentials), - updateNote: (credentials) => ipcRenderer.invoke('updatetNote', credentials), - getMoyenne: (credentials) => ipcRenderer.invoke('getMoyene', credentials), - noteMatiere: (credentials) => ipcRenderer.invoke('noteMatiere', credentials), - noteRelerer: (credentials) => ipcRenderer.invoke('noteRelerer', credentials), - getMoyenneVerify: () => verifyEtudiantIfHeHasNotes(), - getblockNote: () => blockShowMoyene() - }) - - /** - * contextbridge for note repechage - */ - contextBridge.exposeInMainWorld('noteRepech', { - getNotesRepech: (credentials) => ipcRenderer.invoke('getNotesRepech', credentials), - updateNoteRepech: (credentials) => ipcRenderer.invoke('updatetNoteRepech', credentials), - getMoyenneRepech: (credentials) => ipcRenderer.invoke('getMoyenneRepech', credentials) - }) - - /** - * contextBridge for matieres - */ - contextBridge.exposeInMainWorld('matieres', { - getMatiere: () => getMatiere(), - createMatiere: (credentials) => ipcRenderer.invoke('createMatiere', credentials), - getMatiereByID: (credentials) => ipcRenderer.invoke('getMatiereByID', credentials), - updateMatiere: (credentials) => ipcRenderer.invoke('updateMatiere', credentials), - importExcel: (credentials) => ipcRenderer.invoke('importExcelMatiere', credentials), - displayMatiereFromForm: (credentials) => - ipcRenderer.invoke('displayMatiereFromForm', credentials), - deleteMatiere: (credentials) => ipcRenderer.invoke('deleteMatiere', credentials), - asign: (credentials) => ipcRenderer.invoke('asign', credentials), - getAsign: (credentials) => ipcRenderer.invoke('getAsign', credentials), - asignSemestre: (credentials) => ipcRenderer.invoke('asignSemestre', credentials), - getSemestreMatiere: (credentials) => ipcRenderer.invoke('getSemestreMatiere', credentials), - getSemestre: () => getSemestre(), - getNessesary: () => getNessesarytable(), - getENseignant: () => getEnseignants(), - insertUpdateMentionSemestre: (credentials) => - ipcRenderer.invoke('insertUpdateMentionSemestre', credentials), - updateNessesary: (credentials) => ipcRenderer.invoke('updateNessesary', credentials), - insertProf: (credentials) => ipcRenderer.invoke('insertProf', credentials), - getSingleProf: (credentials) => ipcRenderer.invoke('getSingleProf', credentials), - updateProf: (credentials) => ipcRenderer.invoke('updateProf', credentials) - }) - - /** - * contextBridge for note systeme - */ - contextBridge.exposeInMainWorld('notesysteme', { - getSyteme: () => getSysteme(), - updateNoteSysteme: (credentials) => ipcRenderer.invoke('updateNoteSysteme', credentials), - insertParcours: (credentials) => ipcRenderer.invoke('insertParcours', credentials), - getSingleParcours: (credentials) => ipcRenderer.invoke('getSingleParcours', credentials), - deleteParcours: (credentials) => ipcRenderer.invoke('deleteParcours', credentials), - updateParcours: (credentials) => ipcRenderer.invoke('updateParcours', credentials), - parcourMatiere: (credentials) => ipcRenderer.invoke('parcourMatiere', credentials), - getParcours: () => getParcours(), - extractFiches: (credentials) => ipcRenderer.invoke('extractFiches', credentials), - getParcourMatiere: (credentials) => ipcRenderer.invoke('getParcourMatiere', credentials), - createIPConfig: (credentials) => ipcRenderer.invoke('createIPConfig', credentials), - getIPConfig: () => getIPConfig(), - updateIPConfig: (credentials) => ipcRenderer.invoke('updateIPConfig', credentials) - }) - - /** - * contextbridge for status - */ - contextBridge.exposeInMainWorld('statuss', { - getStatus: () => getStatus() - }) - - /** - * contextbridge for annee scolaire - */ - contextBridge.exposeInMainWorld('anneescolaire', { - getAnneeScolaire: () => getAnneeScolaire(), - getInterval: () => getInterval(), - createAnneeScolaire: (credentials) => ipcRenderer.invoke('createAnneeScolaire', credentials), - deleteAnneeScolaire: (credentials) => ipcRenderer.invoke('deleteAnneeScolaire', credentials), - getSingleAnneeScolaire: (credentials) => - ipcRenderer.invoke('getSingleAnneeScolaire', credentials), - updateAnneeScolaire: (credentials) => ipcRenderer.invoke('updateAnneeScolaire', credentials), - setCurrent: (credentials) => ipcRenderer.invoke('setCurrent', credentials) - }) - - /** - * contextbridge for mention - */ - contextBridge.exposeInMainWorld('mention', { - createMention: (credentials) => ipcRenderer.invoke('createMention', credentials), - getMention: () => getMentions(), - getSingleMention: (credentials) => ipcRenderer.invoke('getSingleMention', credentials), - updateMention: (credentials) => ipcRenderer.invoke('updateMention', credentials), - deleteMention: (credentials) => ipcRenderer.invoke('deleteMention', credentials) - }) - } catch (error) { - console.error(error) - } -} else { - window.electron = electronAPI - window.api = api -} diff --git a/src/preload/index.js b/src/preload/index.js deleted file mode 100644 index 476fad3..0000000 --- a/src/preload/index.js +++ /dev/null @@ -1,206 +0,0 @@ -import { contextBridge, ipcRenderer } from 'electron' -import { electronAPI } from '@electron-toolkit/preload' -const { getNessesarytable } = require('../../database/function/System') -const { getNiveau } = require('../../database/Models/Niveau') -const { getAllUsers } = require('../../database/Models/Users') -const { getAllEtudiants, getDataToDashboard } = require('../../database/Models/Etudiants') -const { verifyEtudiantIfHeHasNotes, blockShowMoyene } = require('../../database/Models/Notes') -const { getMatiere, getSemestre, getEnseignants } = require('../../database/Models/Matieres') -const { getSysteme } = require('../../database/Models/NoteSysrem') -const { getStatus } = require('../../database/Models/Status') -const { getAnneeScolaire, getInterval } = require('../../database/Models/AnneeScolaire') -const { getMentions } = require('../../database/Models/Mentions') -const { getAll } = require('../../database/api/Get') -const { getParcours } = require('../../database/Models/Parcours') -const { getIPConfig } = require('../../database/Models/IpConfig') - -// Custom APIs for renderer -const api = {} - -// Use `contextBridge` APIs to expose Electron APIs to -// renderer only if context isolation is enabled, otherwise -// just add to the DOM global. -if (process.contextIsolated) { - try { - contextBridge.exposeInMainWorld('electron', electronAPI) - contextBridge.exposeInMainWorld('api', api) - - /** - * contextBridge for Tray - */ - contextBridge.exposeInMainWorld('Tray', { - onNavigate: (callback) => { - ipcRenderer.on('navigateToRoute', (event, route) => { - callback(route) // Pass the route to the renderer callback - }) - } - }) - - /** - * contextBridge for users - */ - contextBridge.exposeInMainWorld('allUser', { - users: () => getAllUsers(), - login: (credentials) => ipcRenderer.invoke('login', credentials), - insertUsers: (credentials) => ipcRenderer.invoke('insertUser', credentials), - forgotPassword: (credentials) => ipcRenderer.invoke('forgotPassword', credentials), - quit: () => ipcRenderer.invoke('quit'), - minimize: () => ipcRenderer.invoke('minimize'), - updateUsers: (credentials) => ipcRenderer.invoke('updateUsers', credentials) - }) - - contextBridge.exposeInMainWorld('syncro', { - getall: () => getAll() - }) - - // syncronisation des donner - window.addEventListener('online', async () => { - if (navigator.onLine) { - // synchronizeData() - // synchronizeDataEtudiants() - // synchronizeDataNotes() - await getAll() - } - }) - // send data - getAll() - - /** - * contextBridge for etudiants - */ - contextBridge.exposeInMainWorld('etudiants', { - insertEtudiant: (credentials) => ipcRenderer.invoke('insertEtudiant', credentials), - getEtudiants: () => getAllEtudiants(), - FilterDataByNiveau: (credential) => ipcRenderer.invoke('getByNiveau', credential), - getSingle: (credential) => ipcRenderer.invoke('single', credential), - updateEtudiants: (credentials) => ipcRenderer.invoke('updateETudiants', credentials), - getDataToDashboards: () => getDataToDashboard(), - updateEtudiantsPDP: (credentials) => ipcRenderer.invoke('updateETudiantsPDP', credentials), - importExcel: (credentials) => ipcRenderer.invoke('importexcel', credentials), - changeParcours: (credentials) => ipcRenderer.invoke('changeParcours', credentials), - createTranche: (credentials) => ipcRenderer.invoke('createTranche', credentials), - getTranche: (credentials) => ipcRenderer.invoke('getTranche', credentials), - updateTranche: (credentials) => ipcRenderer.invoke('updateTranche', credentials), - deleteTranche: (credentials) => ipcRenderer.invoke('deleteTranche', credentials), - getSingleTranche: (credentials) => ipcRenderer.invoke('getSingleTranche', credentials) - }) - - /** - * cobtextBridge for niveaus - */ - contextBridge.exposeInMainWorld('niveaus', { - getNiveau: () => getNiveau(), - getSingleNiveau: (credential) => ipcRenderer.invoke('singleNiveau', credential), - insertNiveau: (credentials) => ipcRenderer.invoke('insertNiveau', credentials), - updateSingleNiveau: (credentials) => ipcRenderer.invoke('updateSingleNiveau', credentials), - importNiveau: (credentials) => ipcRenderer.invoke('importNiveau', credentials), - deleteNiveaus: (credentials) => ipcRenderer.invoke('deleteNiveaus', credentials) - }) - - /** - * contextBridge for notes - */ - contextBridge.exposeInMainWorld('notes', { - getNotes: (credentials) => ipcRenderer.invoke('getSingleNote', credentials), - insertNote: (credentials) => ipcRenderer.invoke('insertNote', credentials), - updateNote: (credentials) => ipcRenderer.invoke('updatetNote', credentials), - getMoyenne: (credentials) => ipcRenderer.invoke('getMoyene', credentials), - noteMatiere: (credentials) => ipcRenderer.invoke('noteMatiere', credentials), - noteRelerer: (credentials) => ipcRenderer.invoke('noteRelerer', credentials), - getMoyenneVerify: () => verifyEtudiantIfHeHasNotes(), - getblockNote: () => blockShowMoyene() - }) - - /** - * contextbridge for note repechage - */ - contextBridge.exposeInMainWorld('noteRepech', { - getNotesRepech: (credentials) => ipcRenderer.invoke('getNotesRepech', credentials), - updateNoteRepech: (credentials) => ipcRenderer.invoke('updatetNoteRepech', credentials), - getMoyenneRepech: (credentials) => ipcRenderer.invoke('getMoyenneRepech', credentials) - }) - - /** - * contextBridge for matieres - */ - contextBridge.exposeInMainWorld('matieres', { - getMatiere: () => getMatiere(), - createMatiere: (credentials) => ipcRenderer.invoke('createMatiere', credentials), - getMatiereByID: (credentials) => ipcRenderer.invoke('getMatiereByID', credentials), - updateMatiere: (credentials) => ipcRenderer.invoke('updateMatiere', credentials), - importExcel: (credentials) => ipcRenderer.invoke('importExcelMatiere', credentials), - displayMatiereFromForm: (credentials) => - ipcRenderer.invoke('displayMatiereFromForm', credentials), - deleteMatiere: (credentials) => ipcRenderer.invoke('deleteMatiere', credentials), - asign: (credentials) => ipcRenderer.invoke('asign', credentials), - getAsign: (credentials) => ipcRenderer.invoke('getAsign', credentials), - asignSemestre: (credentials) => ipcRenderer.invoke('asignSemestre', credentials), - getSemestreMatiere: (credentials) => ipcRenderer.invoke('getSemestreMatiere', credentials), - getSemestre: () => getSemestre(), - getNessesary: () => getNessesarytable(), - getENseignant: () => getEnseignants(), - insertUpdateMentionSemestre: (credentials) => - ipcRenderer.invoke('insertUpdateMentionSemestre', credentials), - updateNessesary: (credentials) => ipcRenderer.invoke('updateNessesary', credentials), - insertProf: (credentials) => ipcRenderer.invoke('insertProf', credentials), - getSingleProf: (credentials) => ipcRenderer.invoke('getSingleProf', credentials), - updateProf: (credentials) => ipcRenderer.invoke('updateProf', credentials) - }) - - /** - * contextBridge for note systeme - */ - contextBridge.exposeInMainWorld('notesysteme', { - getSyteme: () => getSysteme(), - updateNoteSysteme: (credentials) => ipcRenderer.invoke('updateNoteSysteme', credentials), - insertParcours: (credentials) => ipcRenderer.invoke('insertParcours', credentials), - getSingleParcours: (credentials) => ipcRenderer.invoke('getSingleParcours', credentials), - deleteParcours: (credentials) => ipcRenderer.invoke('deleteParcours', credentials), - updateParcours: (credentials) => ipcRenderer.invoke('updateParcours', credentials), - parcourMatiere: (credentials) => ipcRenderer.invoke('parcourMatiere', credentials), - getParcours: () => getParcours(), - extractFiches: (credentials) => ipcRenderer.invoke('extractFiches', credentials), - getParcourMatiere: (credentials) => ipcRenderer.invoke('getParcourMatiere', credentials), - createIPConfig: (credentials) => ipcRenderer.invoke('createIPConfig', credentials), - getIPConfig: () => getIPConfig(), - updateIPConfig: (credentials) => ipcRenderer.invoke('updateIPConfig', credentials) - }) - - /** - * contextbridge for status - */ - contextBridge.exposeInMainWorld('statuss', { - getStatus: () => getStatus() - }) - - /** - * contextbridge for annee scolaire - */ - contextBridge.exposeInMainWorld('anneescolaire', { - getAnneeScolaire: () => getAnneeScolaire(), - getInterval: () => getInterval(), - createAnneeScolaire: (credentials) => ipcRenderer.invoke('createAnneeScolaire', credentials), - deleteAnneeScolaire: (credentials) => ipcRenderer.invoke('deleteAnneeScolaire', credentials), - getSingleAnneeScolaire: (credentials) => - ipcRenderer.invoke('getSingleAnneeScolaire', credentials), - updateAnneeScolaire: (credentials) => ipcRenderer.invoke('updateAnneeScolaire', credentials), - setCurrent: (credentials) => ipcRenderer.invoke('setCurrent', credentials) - }) - - /** - * contextbridge for mention - */ - contextBridge.exposeInMainWorld('mention', { - createMention: (credentials) => ipcRenderer.invoke('createMention', credentials), - getMention: () => getMentions(), - getSingleMention: (credentials) => ipcRenderer.invoke('getSingleMention', credentials), - updateMention: (credentials) => ipcRenderer.invoke('updateMention', credentials), - deleteMention: (credentials) => ipcRenderer.invoke('deleteMention', credentials) - }) - } catch (error) { - console.error(error) - } -} else { - window.electron = electronAPI - window.api = api -} diff --git a/src/renderer/index.html b/src/renderer/index.html deleted file mode 100644 index ae63b91..0000000 --- a/src/renderer/index.html +++ /dev/null @@ -1,18 +0,0 @@ - - - - - Université de Toamasina - - - - - - -
- - - diff --git a/src/renderer/src/App.jsx b/src/renderer/src/App.jsx deleted file mode 100644 index cb1b663..0000000 --- a/src/renderer/src/App.jsx +++ /dev/null @@ -1,63 +0,0 @@ -import React, { useEffect, useState } from 'react' -import { RouterProvider } from 'react-router-dom' -import Router from './Routes/Routes' -import { AuthContextProvider, useAuthContext } from './contexts/AuthContext' -import { ClipLoader } from 'react-spinners' // Import the loader -import preloader from './assets/preloader.jpg' -import { DataProvider } from './contexts/MoyenneDeClasseContext' - -const App = () => { - const [loading, setLoading] = useState(true) - const { setToken } = useAuthContext() - - // Simulate loading (e.g., fetching some initial data or assets) - useEffect(() => { - const timer = setTimeout(() => { - setLoading(false) // Set loading to false after the simulated loading time - }, 3000) // 3 seconds delay to simulate loading - - return () => clearTimeout(timer) // Cleanup the timer - }, []) - - // Show Preloader while loading, else show your content - if (loading) { - return ( -
- -
- ) - } - - /** - * condition usign with the Tray icon on the bottom - */ - if (window.Tray && typeof window.Tray.onNavigate === 'function') { - window.Tray.onNavigate((route) => { - if (route) { - window.location.hash = route // Navigate by updating the hash - } - }) - } - - return ( - - - - - - ) -} - -export default App diff --git a/src/renderer/src/Routes/Routes.jsx b/src/renderer/src/Routes/Routes.jsx deleted file mode 100644 index cafd33b..0000000 --- a/src/renderer/src/Routes/Routes.jsx +++ /dev/null @@ -1,207 +0,0 @@ -import { createHashRouter } from 'react-router-dom' -import DefaultLayout from '../layouts/DefaultLayout' -import Login from '../components/Login' -import LoginLayout from '../layouts/LoginLayout' -import NotFound from '../components/NotFound' -import ForgotPassword from '../components/ForgotPassword' -import Home from '../components/Home' -import Student from '../components/Student' -import Notes from '../components/Notes' -import AddStudent from '../components/AddStudent' -import SingleEtudiant from '../components/SingleEtudiant' -import AddNotes from '../components/AddNotes' -import Apropos from '../components/Apropos' -import Niveau from '../components/Niveau' -import AddNiveau from '../components/AddNiveau' -import Admin from '../components/Addadmin' -import Setting from '../components/Param' -import SingleNotes from '../components/SingleNotes' -import ExportEtudiants from '../components/ExportEtudiants' -import SingleNiveau from '../components/singleNiveau' -import Matieres from '../components/Matieres' -import AddMatiere from '../components/AddMatiere' -import ImportMatiere from '../components/ImportMatiere' -import SingleMatiere from '../components/SingleMatiere' -import ImportNiveau from '../components/ImportNiveau' -import SystemeNote from '../components/SystemeNote' -import AnneeScolaire from '../components/AnneeScolaire' -import AddAnneeScolaire from '../components/AddAnneeScolaire' -import Noteclasse from '../components/Noteclasse' -import TesteDatagrid from '../components/TesteDatagrid' -import Manuel from '../components/Manuel' -import Mentions from '../components/Mentions' -import AddMention from '../components/AddMention' -import SinleMention from '../components/SinleMention' -import AssignMatiereToMention from '../components/AssignMatiereToMention' -import AssingMatiereToSemestre from '../components/AssingMatiereToSemestre' -import SingleAnneeScolaire from '../components/SingleAnneeScolaire' -import Parcours from '../components/Parcours' -import ModalExportFichr from '../components/ModalExportFichr' -import Resultat from '../components/Resultat' -import TrancheEcolage from '../components/TrancheEcolage' - -// Use createHashRouter instead of createBrowserRouter because the desktop app is in local machine -const Router = createHashRouter([ - { - path: '/', - element: , - children: [ - { - path: '/', // This will now be accessed as #/ - element: - }, - { - path: '/student', - element: - }, - { - path: '/notes', - element: - }, - { - path: '/addstudent', - element: - }, - { - path: '/single/:id', - element: - }, - { - path: '/addnotes/:id/:niveau/:mention_id/:parcours', - element: - }, - { - path: '/anneescolaire/:id', - element: - }, - { - path: '/asignmatiere/:id', - element: - }, - { - path: '/asignmatieresemestre/:id', - element: - }, - { - path: '/manual', - element: - }, - { - path: '/mention', - element: - }, - { - path: '/addmention', - element: - }, - { - path: '/singlemention/:id', - element: - }, - { - path: '/apropos', - element: - }, - { - path: '/niveau', - element: - }, - { - path: '/addniveau', - element: - }, - { - path: '/para', - element: - }, - { - path: '/admin', - element: - }, - { - path: '/single/notes/:id/:niveau/:scolaire', - element: - }, - { - path: '/exportetudiant', - element: - }, - { - path: '/single/niveau/:id', - element: - }, - { - path: '/matiere', - element: - }, - { - path: '/addmatiere', - element: - }, - { - path: '/addmatiere/import', - element: - }, - { - path: '/singlematiere/:id', - element: - }, - { - path: '/importniveau', - element: - }, - { - path: '/systemenote', - element: - }, - { - path: '/anneescolaire', - element: - }, - { - path: '/addanneescolaire', - element: - }, - { - path: '/noteclass/:niveau/:scolaire', - element: - }, - { - path: '/parcours', - element: - }, - { - path: '/fiche/:matiere_id/:nom', - element: - }, - { - path: '/resultat/:niveau/:scolaire', - element: - }, - { - path: '/tranche/:id', - element: - } - ] - }, - { - path: '/', - element: , - children: [ - { - path: '/login', - element: - }, - { - path: '/forgotpassword', - element: - } - ] - }, - { - path: '/*', - element: - } -]) - -export default Router diff --git a/src/renderer/src/assets/AddNotes.module.css b/src/renderer/src/assets/AddNotes.module.css deleted file mode 100644 index b936f7e..0000000 --- a/src/renderer/src/assets/AddNotes.module.css +++ /dev/null @@ -1,12 +0,0 @@ -.blockTitle h1 { - font-size: 10px; - font-weight: bold; - color: white; - display: flex; - align-items: center; - gap: 10px; -} -.boxEtudiantsCard { - width: 10%; - padding: 1%; -} diff --git a/src/renderer/src/assets/AddStudent.module.css b/src/renderer/src/assets/AddStudent.module.css deleted file mode 100644 index ded8325..0000000 --- a/src/renderer/src/assets/AddStudent.module.css +++ /dev/null @@ -1,15 +0,0 @@ -.blockTitle h1 { - font-size: 20px; - font-weight: bold; - color: white; - display: flex; - align-items: center; - gap: 10px; -} -.boxEtudiantsCard { - width: 100%; - padding: 1%; - display: flex; - align-items: center; - justify-content: center; -} diff --git a/src/renderer/src/assets/AllStyleComponents.module.css b/src/renderer/src/assets/AllStyleComponents.module.css deleted file mode 100644 index c847c73..0000000 --- a/src/renderer/src/assets/AllStyleComponents.module.css +++ /dev/null @@ -1,17 +0,0 @@ -.h1style { - text-transform: uppercase; - font-weight: 900; - /* 6636af4a 6636af ffae01 */ - border-left: 10px solid #ffff; - padding-left: 10px; - margin-bottom: 30px; - background: linear-gradient(to right, #ffaf01b4, transparent); - color: white; - width: 100%; - padding-left: 45px; - font-size: 25px; -} -.mainHome { - padding: 1% 0 0 0; - width: 100%; -} diff --git a/src/renderer/src/assets/Capture.PNG b/src/renderer/src/assets/Capture.PNG deleted file mode 100644 index 289dc59..0000000 Binary files a/src/renderer/src/assets/Capture.PNG and /dev/null differ diff --git a/src/renderer/src/assets/CarteStudent.module.css b/src/renderer/src/assets/CarteStudent.module.css deleted file mode 100644 index 1b641b2..0000000 --- a/src/renderer/src/assets/CarteStudent.module.css +++ /dev/null @@ -1,86 +0,0 @@ -body { - margin: 0; - padding: 0; -} -.container { - display: flex; - align-items: center; - justify-content: center; - height: 100vh; - gap: 20px; -} -.cart { - width: 33%; - /* height: 35%; */ - border: solid 1px rgba(0, 0, 0, 0.315); - box-shadow: 0 4px 8px rgba(0, 0, 0, 0.8); /* Adds a soft shadow */ - /* border-radius: 10px; */ - padding: 1px; - background-color: #ffded4; - position: relative; -} -.cart-footer { - position: absolute; - height: 40px; - width: 100%; - bottom: 0; - left: 0; - border-bottom-left-radius: 10px; - border-bottom-right-radius: 10px; - background-color: #ff5a27; -} -.title { - margin: 0; - padding: 0; - text-align: center; - text-transform: uppercase; - z-index: 1; -} -.title h1, -p { - margin: 0; - font-size: 15px; -} -.content { - z-index: 1; - height: 70%; - display: flex; - align-items: center; - justify-content: space-between; -} -.cart_photos { - width: 30%; - text-align: center; -} -.cart_photos img { - border-radius: 50px; - border: solid 2px #ff5a27; - width: 95px; - height: 100px; - object-fit: cover; -} -.cart_info { - width: 60%; - padding-left: 1%; -} -.cart_info p { - font-size: 16px; -} -.qrContent { - display: flex; - align-items: center; - justify-content: space-around; - padding: 2%; -} -.gauche h1, -.droite h1 { - font-size: 17px; - text-align: center; -} -.gauche img, -.droite img { - width: 150px; -} -.droite .qrcodeDroite { - width: 150px; -} diff --git a/src/renderer/src/assets/Dashboard.module.css b/src/renderer/src/assets/Dashboard.module.css deleted file mode 100644 index ba9e6c4..0000000 --- a/src/renderer/src/assets/Dashboard.module.css +++ /dev/null @@ -1,4 +0,0 @@ -.display { - background-color: rgba(255, 255, 255, 0.9); - /* margin-bottom: 2%; */ -} diff --git a/src/renderer/src/assets/DefaultLayout.module.css b/src/renderer/src/assets/DefaultLayout.module.css deleted file mode 100644 index a7a712f..0000000 --- a/src/renderer/src/assets/DefaultLayout.module.css +++ /dev/null @@ -1,20 +0,0 @@ -html, -body { - height: 100%; - margin: 0; - padding: 0; -} - -/* DefaultLayout.css */ -.default_layout { - /* height: 100%; Use full viewport height */ - min-height: 100vh; - overflow-y: auto; - background: url('../assets/background2.jpg') no-repeat center/cover; - /* background-color: #aad4e571; */ -} -.outlet { - padding-left: 55px; - margin-top: 0; - height: 100%; -} diff --git a/src/renderer/src/assets/ExportReleverNote.module.css b/src/renderer/src/assets/ExportReleverNote.module.css deleted file mode 100644 index 029e629..0000000 --- a/src/renderer/src/assets/ExportReleverNote.module.css +++ /dev/null @@ -1,78 +0,0 @@ -.header { - width: 100%; - display: flex; - align-items: start; - justify-content: space-between; -} -.headerCenter { - text-align: center; - color: black; - line-height: 15px; - width: 60%; -} -.headerCenter h5 { - text-transform: uppercase; - line-height: 12px; - font-size: 14px; -} -.headerCenter p { - font-style: italic; - font-weight: 400; - font-size: 14px; -} -.transition { - border: solid 1px gray; - width: 100%; - padding: 1% 2%; - font-weight: bold; -} -.transition h6 { - font-size: 12px; -} - -/* content */ -.content { - text-align: center; -} -.contentHeader { - color: black; - flex-direction: column; - display: flex; - align-items: center; - justify-content: center; - font-size: 13px; -} -.contentHeader h1 { - font-size: 28px; -} -.contentHeaderList { - font-weight: bold; - font-size: 13px; -} -.contentHeaderList p { - font-size: 13px; - display: flex; - gap: 30px; -} -.ContentTable { - display: flex; - align-items: center; - justify-content: center; -} -.ContentTable table { - border-color: black !important; - font-size: 13px; - margin: 0; -} -.contentFooter { - display: flex; - align-items: end; - flex-direction: column; - margin-top: 5px; -} -.signature { - width: 50%; - display: flex; - flex-direction: column; - gap: 30px; -} diff --git a/src/renderer/src/assets/Home.module.css b/src/renderer/src/assets/Home.module.css deleted file mode 100644 index 81a55c8..0000000 --- a/src/renderer/src/assets/Home.module.css +++ /dev/null @@ -1,78 +0,0 @@ -.boxEtudiantsCard { - width: 100%; - padding: 1%; - /* margin-top: 12%; */ -} -.cards { - /* width: 30%; */ - justify-content: space-between; - align-items: center; - padding: 0 1%; -} -.nomEtudiants { - font-weight: bold; -} -.header { - color: white; - /* backdrop-filter: blur(5px); */ - /* position: fixed; */ - width: 100%; - z-index: 9; -} -.container { - display: flex; - align-items: center; - justify-content: center; - padding: 1% 2%; - background: linear-gradient(to left, #ffaf01b4, transparent); -} -.blockTitle { - display: flex; - align-items: center; - justify-content: space-between; - padding: 0 3%; -} -.blockTitle h1 { - font-size: 20px; - font-weight: bold; - /* text-transform: uppercase; */ - color: white; -} -.blockTitle button { - font-size: 12px; - display: inline-flex; - gap: 10px; -} -.boxImg { - padding: 2%; - display: flex; - align-items: center; - justify-content: center; -} -.imagePDP { - object-fit: cover; - border: solid 2px rgb(156, 39, 176); -} -.mainHome { - border: solid 1px red; -} -.select:hover { - border-color: rgb(156, 39, 176) !important; -} -.details { - background-color: rgba(128, 128, 128, 0.4); - border-radius: 8px; - padding: 3% 1% 3% 4%; - text-align: left; -} -.details span { - display: block; - line-height: 25px; -} -.cardOverflow { - height: 450px; - transition: 1s ease; -} -.cardOverflow:hover { - transform: scale(1.03); -} diff --git a/src/renderer/src/assets/Login.module.css b/src/renderer/src/assets/Login.module.css deleted file mode 100644 index cafe5c3..0000000 --- a/src/renderer/src/assets/Login.module.css +++ /dev/null @@ -1,20 +0,0 @@ -/* .container{ - background: url(bg2.jpg) no-repeat fixed center/cover; - background-color: #08000e; -} */ -.cards { - background-color: #06000aa4 !important; - color: white !important; - box-shadow: 0px 4px 10px rgba(255, 255, 255, 0.2) !important; /* Light white shadow */ - border: solid 1px rgba(245, 245, 245, 0.692); -} -.formulaireLogin { - color: white !important; -} -.formulaireLogin label { - color: white; - font-size: 17px; -} -.formulaireLogin input { - color: white; -} diff --git a/src/renderer/src/assets/Navbar.module.css b/src/renderer/src/assets/Navbar.module.css deleted file mode 100644 index 9ae24bd..0000000 --- a/src/renderer/src/assets/Navbar.module.css +++ /dev/null @@ -1,25 +0,0 @@ -.navnar { - color: rgba(0, 0, 0, 0.7); - background-color: #2d2d2d; - display: flex; - align-items: center; - justify-content: space-between; - padding: 2px 15px; - position: fixed; - width: 100%; - top: 0; - border-bottom: solid 1px white; - color: white; - z-index: 99999; -} -.gauche { - width: 30%; - display: flex; - align-items: center; -} -.droite { - width: 4%; - display: flex; - align-items: center; - justify-content: space-between; -} diff --git a/src/renderer/src/assets/Sidenav.module.css b/src/renderer/src/assets/Sidenav.module.css deleted file mode 100644 index 407fca7..0000000 --- a/src/renderer/src/assets/Sidenav.module.css +++ /dev/null @@ -1,51 +0,0 @@ -.navbar { - background-color: #2d2d2d; - border-top: solid 1px white; - color: white; - width: 50px; - /* top: 28px; */ - position: fixed; - height: 100%; - /* bottom: 0; */ - display: flex; - align-items: center; - justify-content: space-between; - flex-direction: column; - padding: 0 0 5% 0; - margin: 0; - border-right: solid 1px white; - z-index: 99; -} -.liste1, -.liste2 { - list-style: none; - padding: 0; - margin: 0; - display: flex; - flex-direction: column; - gap: 20px; -} -.liste1 li, -.liste2 li { - font-size: 25px; - cursor: pointer; -} -.nav_link { - color: white; - position: relative; - transition: 0.8s ease; -} -.icon_label { - position: absolute; - top: 0; /* Below the icon */ - left: 60px; - transform: translateX(-50%); - background-color: black; - color: white; - padding: 5px; - border-radius: 4px; - white-space: nowrap; /* Keep the label on one line */ - font-size: 12px; - margin-top: 5px; /* Slight gap between icon and label */ - z-index: 1; -} diff --git a/src/renderer/src/assets/Template carte arriere.pdf b/src/renderer/src/assets/Template carte arriere.pdf deleted file mode 100644 index 53c244d..0000000 Binary files a/src/renderer/src/assets/Template carte arriere.pdf and /dev/null differ diff --git a/src/renderer/src/assets/Template carte frontal.pdf b/src/renderer/src/assets/Template carte frontal.pdf deleted file mode 100644 index c909b4b..0000000 Binary files a/src/renderer/src/assets/Template carte frontal.pdf and /dev/null differ diff --git a/src/renderer/src/assets/admin.png b/src/renderer/src/assets/admin.png deleted file mode 100644 index 5d58ebe..0000000 Binary files a/src/renderer/src/assets/admin.png and /dev/null differ diff --git a/src/renderer/src/assets/arriere.pdf b/src/renderer/src/assets/arriere.pdf deleted file mode 100644 index 2a04b58..0000000 Binary files a/src/renderer/src/assets/arriere.pdf and /dev/null differ diff --git a/src/renderer/src/assets/autorisationstage.pdf b/src/renderer/src/assets/autorisationstage.pdf deleted file mode 100644 index b86ba10..0000000 Binary files a/src/renderer/src/assets/autorisationstage.pdf and /dev/null differ diff --git a/src/renderer/src/assets/background.jpg b/src/renderer/src/assets/background.jpg deleted file mode 100644 index 442ce5a..0000000 Binary files a/src/renderer/src/assets/background.jpg and /dev/null differ diff --git a/src/renderer/src/assets/background2.jpg b/src/renderer/src/assets/background2.jpg deleted file mode 100644 index d6d518f..0000000 Binary files a/src/renderer/src/assets/background2.jpg and /dev/null differ diff --git a/src/renderer/src/assets/base.css b/src/renderer/src/assets/base.css deleted file mode 100644 index e497b00..0000000 --- a/src/renderer/src/assets/base.css +++ /dev/null @@ -1,97 +0,0 @@ -/* :root { - --ev-c-white: #ffffff; - --ev-c-white-soft: #f8f8f8; - --ev-c-white-mute: #f2f2f2; - - --ev-c-black: #1b1b1f; - --ev-c-black-soft: #222222; - --ev-c-black-mute: #282828; - - --ev-c-gray-1: #515c67; - --ev-c-gray-2: #414853; - --ev-c-gray-3: #32363f; - - --ev-c-text-1: rgba(255, 255, 245, 0.86); - --ev-c-text-2: rgba(235, 235, 245, 0.6); - --ev-c-text-3: rgba(235, 235, 245, 0.38); - - --ev-button-alt-border: transparent; - --ev-button-alt-text: var(--ev-c-text-1); - --ev-button-alt-bg: var(--ev-c-gray-3); - --ev-button-alt-hover-border: transparent; - --ev-button-alt-hover-text: var(--ev-c-text-1); - --ev-button-alt-hover-bg: var(--ev-c-gray-2); -} - -:root { - --color-background: var(--ev-c-black); - --color-background-soft: var(--ev-c-black-soft); - --color-background-mute: var(--ev-c-black-mute); - - --color-text: var(--ev-c-text-1); -} - -*, -*::before, -*::after { - box-sizing: border-box; - margin: 0; - font-weight: normal; -} - -ul { - list-style: none; -} - -body { - min-height: 100vh; - color: var(--color-text); - background: var(--color-background); - line-height: 1.6; - font-family: - Inter, - -apple-system, - BlinkMacSystemFont, - 'Segoe UI', - Roboto, - Oxygen, - Ubuntu, - Cantarell, - 'Fira Sans', - 'Droid Sans', - 'Helvetica Neue', - sans-serif; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} */ -.form-control:focus { - outline: none; - box-shadow: none; - border-color: initial; /* Optional: restore the default border color */ -} -table { - border-collapse: collapse; /* Ensure there is no space between table cells */ - width: 100%; /* Adjust width as needed */ - margin: 0; - padding: 0; -} - -td, -th { - padding: 0; /* Remove padding from table cells */ - margin: 0; /* Ensure no margin inside cells */ - border: 1px solid black; /* Optional: Add border if needed */ - text-align: center; /* Center text horizontally */ - vertical-align: middle; /* Center text vertically */ -} - -tr { - margin: 0; - padding: 0; -} - -tbody { - margin: 0; - padding: 0; -} diff --git a/src/renderer/src/assets/bg1-min.jpg b/src/renderer/src/assets/bg1-min.jpg deleted file mode 100644 index 19699ea..0000000 Binary files a/src/renderer/src/assets/bg1-min.jpg and /dev/null differ diff --git a/src/renderer/src/assets/bg1.jpg b/src/renderer/src/assets/bg1.jpg deleted file mode 100644 index 72c8c7d..0000000 Binary files a/src/renderer/src/assets/bg1.jpg and /dev/null differ diff --git a/src/renderer/src/assets/bg2-min.jpg b/src/renderer/src/assets/bg2-min.jpg deleted file mode 100644 index f5c0690..0000000 Binary files a/src/renderer/src/assets/bg2-min.jpg and /dev/null differ diff --git a/src/renderer/src/assets/bg2.jpg b/src/renderer/src/assets/bg2.jpg deleted file mode 100644 index f393c60..0000000 Binary files a/src/renderer/src/assets/bg2.jpg and /dev/null differ diff --git a/src/renderer/src/assets/business_card_template_001.pdf b/src/renderer/src/assets/business_card_template_001.pdf deleted file mode 100644 index a83845f..0000000 Binary files a/src/renderer/src/assets/business_card_template_001.pdf and /dev/null differ diff --git a/src/renderer/src/assets/business_card_template_001_form.pdf b/src/renderer/src/assets/business_card_template_001_form.pdf deleted file mode 100644 index a83845f..0000000 Binary files a/src/renderer/src/assets/business_card_template_001_form.pdf and /dev/null differ diff --git a/src/renderer/src/assets/business_card_template_002.pdf b/src/renderer/src/assets/business_card_template_002.pdf deleted file mode 100644 index 7581bf1..0000000 Binary files a/src/renderer/src/assets/business_card_template_002.pdf and /dev/null differ diff --git a/src/renderer/src/assets/carte_etudiant.odg b/src/renderer/src/assets/carte_etudiant.odg deleted file mode 100644 index 15bdd1a..0000000 Binary files a/src/renderer/src/assets/carte_etudiant.odg and /dev/null differ diff --git a/src/renderer/src/assets/carte_etudiant.pdf b/src/renderer/src/assets/carte_etudiant.pdf deleted file mode 100644 index ab1983b..0000000 Binary files a/src/renderer/src/assets/carte_etudiant.pdf and /dev/null differ diff --git a/src/renderer/src/assets/certificat scolariter.pdf b/src/renderer/src/assets/certificat scolariter.pdf deleted file mode 100644 index 754bcbe..0000000 Binary files a/src/renderer/src/assets/certificat scolariter.pdf and /dev/null differ diff --git a/src/renderer/src/assets/electron.svg b/src/renderer/src/assets/electron.svg deleted file mode 100644 index 45ef09c..0000000 --- a/src/renderer/src/assets/electron.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/src/renderer/src/assets/enteterelever.png b/src/renderer/src/assets/enteterelever.png deleted file mode 100644 index 6876bef..0000000 Binary files a/src/renderer/src/assets/enteterelever.png and /dev/null differ diff --git a/src/renderer/src/assets/error.svg b/src/renderer/src/assets/error.svg deleted file mode 100644 index 7888679..0000000 --- a/src/renderer/src/assets/error.svg +++ /dev/null @@ -1,52 +0,0 @@ - - - - - diff --git a/src/renderer/src/assets/exemplecarte.png b/src/renderer/src/assets/exemplecarte.png deleted file mode 100644 index 517d61c..0000000 Binary files a/src/renderer/src/assets/exemplecarte.png and /dev/null differ diff --git a/src/renderer/src/assets/logo or.png b/src/renderer/src/assets/logo or.png deleted file mode 100644 index 1602696..0000000 Binary files a/src/renderer/src/assets/logo or.png and /dev/null differ diff --git a/src/renderer/src/assets/logo.PNG b/src/renderer/src/assets/logo.PNG deleted file mode 100644 index 203f31c..0000000 Binary files a/src/renderer/src/assets/logo.PNG and /dev/null differ diff --git a/src/renderer/src/assets/logo.ico b/src/renderer/src/assets/logo.ico deleted file mode 100644 index f592b3c..0000000 Binary files a/src/renderer/src/assets/logo.ico and /dev/null differ diff --git a/src/renderer/src/assets/logo.webp b/src/renderer/src/assets/logo.webp deleted file mode 100644 index 2fe582e..0000000 Binary files a/src/renderer/src/assets/logo.webp and /dev/null differ diff --git a/src/renderer/src/assets/logo_uni-removebg-preview.webp b/src/renderer/src/assets/logo_uni-removebg-preview.webp deleted file mode 100644 index 87cadb5..0000000 Binary files a/src/renderer/src/assets/logo_uni-removebg-preview.webp and /dev/null differ diff --git a/src/renderer/src/assets/logorelever.png b/src/renderer/src/assets/logorelever.png deleted file mode 100644 index 952d3a2..0000000 Binary files a/src/renderer/src/assets/logorelever.png and /dev/null differ diff --git a/src/renderer/src/assets/logorelever2.png b/src/renderer/src/assets/logorelever2.png deleted file mode 100644 index 8c5cc64..0000000 Binary files a/src/renderer/src/assets/logorelever2.png and /dev/null differ diff --git a/src/renderer/src/assets/main.css b/src/renderer/src/assets/main.css deleted file mode 100644 index 445130c..0000000 --- a/src/renderer/src/assets/main.css +++ /dev/null @@ -1,163 +0,0 @@ -@import './base.css'; - -body { - display: flex; - align-items: center; - justify-content: center; - overflow: hidden; - background-image: url('./wavy-lines.svg'); - background-size: cover; - user-select: none; -} - -code { - font-weight: 600; - padding: 3px 5px; - border-radius: 2px; - background-color: var(--color-background-mute); - font-family: - ui-monospace, - SFMono-Regular, - SF Mono, - Menlo, - Consolas, - Liberation Mono, - monospace; - font-size: 85%; -} - -#root { - display: flex; - align-items: center; - justify-content: center; - flex-direction: column; - margin-bottom: 80px; -} - -.logo { - margin-bottom: 20px; - -webkit-user-drag: none; - height: 128px; - width: 128px; - will-change: filter; - transition: filter 300ms; -} - -.logo:hover { - filter: drop-shadow(0 0 1.2em #6988e6aa); -} - -.creator { - font-size: 14px; - line-height: 16px; - color: var(--ev-c-text-2); - font-weight: 600; - margin-bottom: 10px; -} - -.text { - font-size: 28px; - color: var(--ev-c-text-1); - font-weight: 700; - line-height: 32px; - text-align: center; - margin: 0 10px; - padding: 16px 0; -} - -.tip { - font-size: 16px; - line-height: 24px; - color: var(--ev-c-text-2); - font-weight: 600; -} - -.react { - background: -webkit-linear-gradient(315deg, #087ea4 55%, #7c93ee); - background-clip: text; - -webkit-background-clip: text; - -webkit-text-fill-color: transparent; - font-weight: 700; -} - -.actions { - display: flex; - padding-top: 32px; - margin: -6px; - flex-wrap: wrap; - justify-content: flex-start; -} - -.action { - flex-shrink: 0; - padding: 6px; -} - -.action a { - cursor: pointer; - text-decoration: none; - display: inline-block; - border: 1px solid transparent; - text-align: center; - font-weight: 600; - white-space: nowrap; - border-radius: 20px; - padding: 0 20px; - line-height: 38px; - font-size: 14px; - border-color: var(--ev-button-alt-border); - color: var(--ev-button-alt-text); - background-color: var(--ev-button-alt-bg); -} - -.action a:hover { - border-color: var(--ev-button-alt-hover-border); - color: var(--ev-button-alt-hover-text); - background-color: var(--ev-button-alt-hover-bg); -} - -.versions { - position: absolute; - bottom: 30px; - margin: 0 auto; - padding: 15px 0; - font-family: 'Menlo', 'Lucida Console', monospace; - display: inline-flex; - overflow: hidden; - align-items: center; - border-radius: 22px; - background-color: #202127; - backdrop-filter: blur(24px); -} - -.versions li { - display: block; - float: left; - border-right: 1px solid var(--ev-c-gray-1); - padding: 0 20px; - font-size: 14px; - line-height: 14px; - opacity: 0.8; - &:last-child { - border: none; - } -} - -@media (max-width: 720px) { - .text { - font-size: 20px; - } -} - -@media (max-width: 620px) { - .versions { - display: none; - } -} - -@media (max-width: 350px) { - .tip, - .actions { - display: none; - } -} diff --git a/src/renderer/src/assets/manuel.pdf b/src/renderer/src/assets/manuel.pdf deleted file mode 100644 index b624e57..0000000 Binary files a/src/renderer/src/assets/manuel.pdf and /dev/null differ diff --git a/src/renderer/src/assets/para.png b/src/renderer/src/assets/para.png deleted file mode 100644 index 94c9bd0..0000000 Binary files a/src/renderer/src/assets/para.png and /dev/null differ diff --git a/src/renderer/src/assets/preloader.jpg b/src/renderer/src/assets/preloader.jpg deleted file mode 100644 index 03edfaa..0000000 Binary files a/src/renderer/src/assets/preloader.jpg and /dev/null differ diff --git a/src/renderer/src/assets/recepice.pdf b/src/renderer/src/assets/recepice.pdf deleted file mode 100644 index c2e1cd4..0000000 Binary files a/src/renderer/src/assets/recepice.pdf and /dev/null differ diff --git a/src/renderer/src/assets/releves.pdf b/src/renderer/src/assets/releves.pdf deleted file mode 100644 index 46a9332..0000000 Binary files a/src/renderer/src/assets/releves.pdf and /dev/null differ diff --git a/src/renderer/src/assets/success.svg b/src/renderer/src/assets/success.svg deleted file mode 100644 index 5f4e178..0000000 --- a/src/renderer/src/assets/success.svg +++ /dev/null @@ -1,52 +0,0 @@ - - - - - diff --git a/src/renderer/src/assets/template.png b/src/renderer/src/assets/template.png deleted file mode 100644 index 4729a9a..0000000 Binary files a/src/renderer/src/assets/template.png and /dev/null differ diff --git a/src/renderer/src/assets/template2.png b/src/renderer/src/assets/template2.png deleted file mode 100644 index bd39be7..0000000 Binary files a/src/renderer/src/assets/template2.png and /dev/null differ diff --git a/src/renderer/src/assets/teste.pdf b/src/renderer/src/assets/teste.pdf deleted file mode 100644 index d407be6..0000000 Binary files a/src/renderer/src/assets/teste.pdf and /dev/null differ diff --git a/src/renderer/src/assets/warning.svg b/src/renderer/src/assets/warning.svg deleted file mode 100644 index 74afebf..0000000 --- a/src/renderer/src/assets/warning.svg +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - diff --git a/src/renderer/src/assets/wavy-lines.svg b/src/renderer/src/assets/wavy-lines.svg deleted file mode 100644 index f625247..0000000 --- a/src/renderer/src/assets/wavy-lines.svg +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/renderer/src/components/AddAnneeScolaire.jsx b/src/renderer/src/components/AddAnneeScolaire.jsx deleted file mode 100644 index 0f7b372..0000000 --- a/src/renderer/src/components/AddAnneeScolaire.jsx +++ /dev/null @@ -1,283 +0,0 @@ -import React, { useRef, useState } from 'react' -import classe from '../assets/AllStyleComponents.module.css' -import classeHome from '../assets/Home.module.css' -import Paper from '@mui/material/Paper' -import { Link, useNavigate } from 'react-router-dom' -import { IoMdReturnRight } from 'react-icons/io' -import { Modal, Box, Typography, Button, InputAdornment, TextField, Grid } from '@mui/material' -import { FaCalendarAlt, FaCalendarPlus } from 'react-icons/fa' -import validationAnneeScolaire from './validation/ValidationAddAnneeScolaire' -import svgError from '../assets/error.svg' -import svgSuccess from '../assets/success.svg' - -const AddAnneeScolaire = () => { - const [formData, setFormData] = useState({ - code: '', - debut: '', - fin: '' - }) - - const debutRef = useRef() - const codeRef = useRef() - const finRef = useRef() - - /** - * function to set the data in state - * @param {*} e - */ - const handleInputChange = (e) => { - const { name, value } = e.target - setFormData((prevData) => ({ - ...prevData, - [name]: value - })) - } - - const formSubmit = async (e) => { - e.preventDefault() - let isValid = validationAnneeScolaire(codeRef.current, debutRef.current, finRef.current) - - if (isValid) { - let response = await window.anneescolaire.createAnneeScolaire(formData) - console.log(response) - if (response.success) { - setStatus(200) - setOpen(true) - } else { - setStatus(400) - setOpen(true) - } - } else { - setStatus(400) - setOpen(true) - } - } - - const [status, setStatus] = useState(200) - - /** - * hook to open modal - */ - const [open, setOpen] = useState(false) - - /** - * function to close modal - */ - const handleClose = () => { - setOpen(false) - window.history.back() - } - const handleClose2 = () => { - setOpen(false) - } - - /** - * function to return the view Modal - * - * @returns {JSX} - */ - const modals = () => ( - - - {status === 200 ? ( - - {' '} - Année universitaire insérer avec succes - - ) : ( - - {' '} - Erreur, veuillez réessayer - - )} - - {status === 200 ? ( - - ) : ( - - )} - - - - ) - - return ( -
- {modals()} -
-
-
-

- Ajout Année universitaire -

- window.history.back()}> - - -
-
-
- -
- -
-

- Creation de nouvelle année universitaire -

- - - - - - ) - }} - onChange={handleInputChange} - inputRef={codeRef} - className="inputAddNote" - sx={{ - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800' // Set the border color on hover - } - }, - '& .MuiInputBase-input::placeholder': { - fontSize: '14px' // Set the placeholder font size - } - }} - /> - - - - - - ) - }} - className="inputAddNote" - sx={{ - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800' // Set the border color on hover - } - }, - '& .MuiInputBase-input::placeholder': { - fontSize: '11px' // Set the placeholder font size - } - }} - /> - - - - - - ) - }} - onChange={handleInputChange} - inputRef={finRef} - value={formData.fin} - className="inputAddNote" - sx={{ - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800' // Set the border color on hover - } - }, - '& .MuiInputBase-input::placeholder': { - fontSize: '11px' // Set the placeholder font size - } - }} - /> - - - - - -
-
-
-
- ) -} - -export default AddAnneeScolaire diff --git a/src/renderer/src/components/AddMatiere.jsx b/src/renderer/src/components/AddMatiere.jsx deleted file mode 100644 index 2a69918..0000000 --- a/src/renderer/src/components/AddMatiere.jsx +++ /dev/null @@ -1,413 +0,0 @@ -import React, { useEffect, useRef, useState } from 'react' -import classe from '../assets/AllStyleComponents.module.css' -import classeAdd from '../assets/AddStudent.module.css' -import classeHome from '../assets/Home.module.css' -import { Link, useNavigate } from 'react-router-dom' -import { IoMdReturnRight } from 'react-icons/io' -import { - Box, - Button, - InputAdornment, - Typography, - Modal, - TextField, - Grid, - Autocomplete -} from '@mui/material' -import { BsBookmarkPlusFill } from 'react-icons/bs' -import { FaBook, FaClipboardList, FaClock, FaFileExcel } from 'react-icons/fa' -import validationMatiereAdd from './validation/ValidationMatiereAdd' -import svgSuccess from '../assets/success.svg' -import ChangeCapitalize from './function/ChangeCapitalizeLetter' -import { MdOutlineNumbers } from 'react-icons/md' -import { IoBookmark } from 'react-icons/io5' -import ChangeCapital from './function/ChangeCapitalLetter' -import { CgPathUnite } from 'react-icons/cg' - -const AddMatiere = () => { - const [formData, setFormData] = useState({ - nom: '', - credit: '', - uniter: '', - ue: '' - }) - - const navigate = useNavigate() - - const [matieres, setMatieres] = useState([]) - const [mention, setMention] = useState([]) - - useEffect(() => { - window.matieres.getMatiere().then((response) => { - setMatieres(response) - }) - - window.mention.getMention().then((response) => { - setMention(Array.isArray(response) ? response : []) - }) - }, []) - - /** - * hook to open modal - */ - const [open, setOpen] = useState(false) - - /** - * function to close modal - */ - const handleClose = () => { - setOpen(false) - navigate('/matiere') - } - - /** - * function to set the data in state - * @param {*} e - */ - const handleInputChange = (e) => { - const { name, value } = e.target - setFormData((prevData) => ({ - ...prevData, - [name]: value - })) - } - - const nomRef = useRef() - const errorRef = useRef() - const creditRef = useRef() - const ueRef = useRef() - const uniterRef = useRef() - - const formSubmit = async (e) => { - e.preventDefault() - - let arrayMatiere = [] - - matieres.map((matiere) => { - arrayMatiere.push(matiere.nom) - }) - - let valid = validationMatiereAdd( - nomRef.current, - errorRef.current, - arrayMatiere, - creditRef.current - ) - console.log(formData, valid) - if (valid) { - let response = await window.matieres.createMatiere(formData) - console.log(response) - if (response.success) { - setOpen(true) - } - - if (response.code) { - errorRef.current.textContent = `${formData.nom} existe déjà` - } - } - } - - /** - * function to return the view Modal - * - * @returns {JSX} - */ - const modals = () => ( - - - - {' '} - Matière insérer avec succes - - - - - - - ) - - return ( -
- {modals()} -
-
-
-

- - Ajout Matière -

- - - -
-
-
- - {/* displaying the formulaire */} -
- -
- - Importer un fichier excel - -
-

- Ajout d'un Matière -

- -
- - - ChangeCapitalize(nomRef)} - InputProps={{ - startAdornment: ( - - - - ) - }} - inputRef={nomRef} - sx={{ - marginBottom: '5px', - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800' // Set the border color on hover - } - } - }} - /> - - - - - - ) - }} - inputProps={{ min: 1 }} - inputRef={creditRef} - sx={{ - marginBottom: '5px', - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800' // Set the border color on hover - } - } - }} - /> - - {/* - - - - ), - }} - inputProps={{ min: 1 }} - inputRef={semestreRef} - sx={{ - marginBottom:"5px", - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800', // Set the border color on hover - }, - }, - }} - /> - */} - - ChangeCapital(uniterRef)} - InputProps={{ - startAdornment: ( - - - - ) - }} - inputProps={{ min: 1 }} - inputRef={uniterRef} - sx={{ - marginBottom: '5px', - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800' // Set the border color on hover - } - } - }} - /> - - - ChangeCapital(ueRef)} - onChange={handleInputChange} - type="text" - InputProps={{ - startAdornment: ( - - - - ) - }} - inputProps={{ min: 1 }} - inputRef={ueRef} - sx={{ - marginBottom: '5px', - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800' // Set the border color on hover - } - } - }} - /> - - {/* - option.nom || ""} // Safely access `nom` - value={formData.mention_id.map(id => mention.find(item => item.id === id)) || []} // Bind selected values to form data - onChange={(event, newValue) => { - setFormData((prevData) => ({ - ...prevData, - mention_id: newValue.map((item) => item.id), // Store only the IDs of selected mentions - })); - }} - isOptionEqualToValue={(option, value) => option.id === value.id} // Ensure correct matching of options - renderInput={(params) => ( - - - - - {params.InputProps.startAdornment} - - ), - }} - sx={{ - marginBottom: "5px", - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800', // Set border color on hover - }, - }, - }} - /> - )} - /> - - */} - - -
- - - -
-
-
-
-
- ) -} - -export default AddMatiere diff --git a/src/renderer/src/components/AddMention.jsx b/src/renderer/src/components/AddMention.jsx deleted file mode 100644 index f299e92..0000000 --- a/src/renderer/src/components/AddMention.jsx +++ /dev/null @@ -1,257 +0,0 @@ -import React, { useEffect, useRef, useState } from 'react' -import classe from '../assets/AllStyleComponents.module.css' -import classeAdd from '../assets/AddStudent.module.css' -import classeHome from '../assets/Home.module.css' -import { Link, useNavigate } from 'react-router-dom' -import { IoMdReturnRight } from 'react-icons/io' -import { Box, Button, InputAdornment, Typography, Modal, TextField, Grid } from '@mui/material' -import { BsBookmarkPlusFill } from 'react-icons/bs' -import { FaClipboardList } from 'react-icons/fa6' -import ChangeCapital from './function/ChangeCapitalLetter' -import { IoBookmark } from 'react-icons/io5' -import svgSuccess from '../assets/success.svg' - -const AddMention = () => { - const [formData, setFormData] = useState({ - nom: '', - uniter: '' - }) - - const [errors, setErrors] = useState({ - nom: false, - uniter: false - }) - - const navigate = useNavigate() - - /** - * function to set the data in state - * @param {*} e - */ - const handleInputChange = (e) => { - const { name, value } = e.target - setFormData({ - ...formData, - [name]: value - }) - setErrors({ - ...errors, - [name]: false // Reset the error when user starts typing - }) - } - - const formSubmit = async (e) => { - e.preventDefault() - const newErrors = {} - let hasError = false - - // Check for empty fields - Object.keys(formData).forEach((key) => { - if (!formData[key].trim()) { - newErrors[key] = true // Set error for empty fields - hasError = true - } - }) - - setErrors(newErrors) - - if (!hasError) { - try { - let response = await window.mention.createMention(formData) - - if (response.success) { - setOpen(true) - } - } catch (error) { - console.log(error) - } - } - } - - /** - * hook to open modal - */ - const [open, setOpen] = useState(false) - - /** - * function to close modal - */ - const handleClose = () => { - setOpen(false) - navigate('/mention') - } - - /** - * function to return the view Modal - * - * @returns {JSX} - */ - const modals = () => ( - - - - {' '} - Mention insérer avec succes - - - - - - - ) - - // Helper function to get helperText dynamically - const getHelperText = (field) => (errors[field] ? 'Ce champ est requis.' : '') - - const nomRef = useRef() - const uniterRef = useRef() - return ( -
- {modals()} -
-
-
-

- - Ajout Mention -

- - - -
-
-
- - {/* displaying the formulaire */} -
- -

- Ajout d'un Mention -

- -
- - - ChangeCapital(nomRef)} - InputProps={{ - startAdornment: ( - - - - ) - }} - helperText={getHelperText('nom')} - inputRef={nomRef} - sx={{ - marginBottom: '5px', - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800' // Set the border color on hover - } - } - }} - /> - - - ChangeCapital(uniterRef)} - InputProps={{ - startAdornment: ( - - - - ) - }} - inputRef={uniterRef} - sx={{ - marginBottom: '5px', - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800' // Set the border color on hover - } - } - }} - /> - - - - - -
-
-
-
-
- ) -} - -export default AddMention diff --git a/src/renderer/src/components/AddNiveau.jsx b/src/renderer/src/components/AddNiveau.jsx deleted file mode 100644 index c876c6e..0000000 --- a/src/renderer/src/components/AddNiveau.jsx +++ /dev/null @@ -1,214 +0,0 @@ -import React, { useEffect, useRef, useState } from 'react' -import classe from '../assets/AllStyleComponents.module.css' -import classeAdd from '../assets/AddStudent.module.css' -import { Link, useNavigate } from 'react-router-dom' -import { IoMdPersonAdd, IoMdReturnRight } from 'react-icons/io' -import { FaFileExcel, FaUser } from 'react-icons/fa' -import { Box, Button, InputAdornment, TextField, Grid, Modal, Typography } from '@mui/material' -import classeHome from '../assets/Home.module.css' -import validationNote from './validation/AddNiveau' -import svgSuccess from '../assets/success.svg' - -const AddNiveau = () => { - const navigate = useNavigate() - /** - * hook for storing data in the input - */ - const [formData, setFormData] = useState({ - nom: '' - }) - const [niveau, setNiveau] = useState([]) - /** - * hook to open modal - */ - const [open, setOpen] = useState(false) - - /** - * function to close modal - */ - const handleClose = () => { - setOpen(false) - navigate('/niveau') - } - - useEffect(() => { - window.niveaus.getNiveau().then((response) => { - setNiveau(response) - }) - }, []) - - /** - * function to set the data in state - * @param {*} e - */ - const handleInputChange = (e) => { - const { name, value } = e.target - setFormData((prevData) => ({ - ...prevData, - [name]: value - })) - } - - const nomRef = useRef() - const nomError = useRef() - - /** - * function to return the view Modal - * - * @returns {JSX} - */ - const modals = () => ( - - - - {' '} - Insertion a été effectuée avec succès - - - - - - - ) - - const formSubmit = async (e) => { - e.preventDefault() - let niveauNom = [] - niveau.map((niv) => { - niveauNom.push(niv.nom) - }) - let validation = validationNote(nomRef.current, nomError.current, niveauNom) - - if (validation) { - let response = await window.niveaus.insertNiveau(formData) - - let responses = JSON.parse(response) - if (responses.changes == 1) { - setOpen(true) - setFormData({ - nom: '' - }) - } - } - } - - return ( -
- {modals()} -
-
-
-

- - Ajout niveau -

- - - -
-
-
- -
- -

- Ajout d'un niveau -

-
- - Importer un fichier excel - -
- -
- - - - ) - }} - inputRef={nomRef} - sx={{ - marginBottom: '5px', - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800' // Set the border color on hover - } - } - }} - /> - -
- {/* Submit Button */} - - - - -
-
-
-
- ) -} - -export default AddNiveau diff --git a/src/renderer/src/components/AddNotes.jsx b/src/renderer/src/components/AddNotes.jsx deleted file mode 100644 index f000a56..0000000 --- a/src/renderer/src/components/AddNotes.jsx +++ /dev/null @@ -1,312 +0,0 @@ -import React, { useEffect, useRef, useState } from 'react' -import classe from '../assets/AllStyleComponents.module.css' -import classeAdd from '../assets/AddNotes.module.css' -import classeHome from '../assets/Home.module.css' -import { Modal, Box, Typography, Button, InputAdornment, TextField, Grid } from '@mui/material' -import { CgNotes } from 'react-icons/cg' -import { IoMdReturnRight } from 'react-icons/io' -import { Link, useParams, useNavigate } from 'react-router-dom' -import svgSuccess from '../assets/success.svg' -import svgError from '../assets/error.svg' -import validateAddNote from './validation/AddNote' -import ModalUpdateParcoursEtudiant from './ModalUpdateParcoursEtudiant' - -const AddNotes = () => { - const { id, niveau, mention_id, parcours } = useParams() - const [matieres, setMatieres] = useState([]) - const [formData, setFormData] = useState({}) // Initialize with an empty object - const [etudiants, setEtudiants] = useState([]) - const navigate = useNavigate() - const [openModal1, setOpenModal1] = useState(false) - const oncloseModal1 = () => { - setOpenModal1(false) - } - - /** - * Fetching the matieres - */ - useEffect(() => { - window.matieres.displayMatiereFromForm({ niveau, mention_id, parcours }).then((response) => { - setMatieres(response) - }) - - window.etudiants.getSingle({ id }).then((response) => { - setEtudiants(response) - }) - - if (parcours == 'Pas de parcours' && niveau != 'L1') { - setOpenModal1(true) - } - }, []) - - const [isSubmitted, setIsSubmitted] = useState(false) - const [parcoursChange, setParcourChanges] = useState('') - const handleFormSubmit = (status, parcours) => { - setIsSubmitted(status) - setParcourChanges(parcours) - } - - useEffect(() => { - if (isSubmitted) { - let parcours = parcoursChange - - window.matieres.displayMatiereFromForm({ niveau, mention_id, parcours }).then((response) => { - setMatieres(response) - }) - setIsSubmitted(false) - } - }, [isSubmitted]) - - let niveauEtudiant = etudiants.niveau - let AnneeScolaireEtudiant = etudiants.annee_scolaire - - /** - * Update formData whenever matieres change - */ - useEffect(() => { - const initialFormData = matieres.reduce((acc, mat) => { - acc[mat.id] = '' // Initialize each key with an empty string - return acc - }, {}) - setFormData(initialFormData) - }, [matieres]) // Dependency array ensures this runs whenever `matieres` is updated - - const [disabled, setDisabled] = useState(false) - - /** - * Handle form submission - */ - const handleSubmit = async (e) => { - e.preventDefault() - const etudiant_id = id - const etudiant_niveau = niveauEtudiant - let valid = validateAddNote() - let annee_scolaire = AnneeScolaireEtudiant - let mention_id = etudiants.mention_id - - if (valid) { - let response = await window.notes.insertNote({ - etudiant_id, - etudiant_niveau, - mention_id, - formData, - annee_scolaire - }) - console.log(response) - if (response.success) { - setOpen(true) - setStatut(200) - setDisabled(true) - const resetFormData = matieres.reduce((acc, mat) => { - acc[mat.id] = '' // Reset each field to an empty string - return acc - }, {}) - setFormData(resetFormData) - } - } else { - setOpen(true) - setStatut(400) - } - } - - const [statut, setStatut] = useState(200) - - /** - * hook to open modal - */ - const [open, setOpen] = useState(false) - - /** - * function to close modal - */ - const handleClose = () => { - setOpen(false) - } - - const handleClose2 = () => { - navigate('/notes') - setOpen(false) - } - - /** - * function to return the view Modal - * - * @returns {JSX} - */ - const modals = () => ( - - - {statut === 200 ? ( - - {' '} - - Note de {etudiants.nom} {etudiants.prenom} en {etudiants.niveau} a été inserer avec - succès - - - ) : ( - - {' '} - Inserer au moin un champ - - )} - - {statut == 200 ? ( - - ) : ( - - )} - - - - ) - - return ( -
- {modals()} - -
-
-
-

- - Ajout note -

- - - -
-
- - {/* displaying */} -
- - -
-

- Ajout des notes :{' '} - - {etudiants.nom} {etudiants.prenom} en {etudiants.niveau} - -

- - {/* map the all matiere to the form */} - - {matieres.map((mat) => ( - - setFormData({ ...formData, [mat.id]: e.target.value }) // Update the specific key - } - InputProps={{ - startAdornment: ( - - - - ) - }} - className="inputAddNote" - sx={{ - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800' // Set the border color on hover - } - }, - '& .MuiInputBase-input::placeholder': { - fontSize: '11px' // Set the placeholder font size - } - }} - /> - - ))} - - - - -
-
-
-
-
-
- ) -} - -export default AddNotes diff --git a/src/renderer/src/components/AddParcours.jsx b/src/renderer/src/components/AddParcours.jsx deleted file mode 100644 index dba119e..0000000 --- a/src/renderer/src/components/AddParcours.jsx +++ /dev/null @@ -1,162 +0,0 @@ -import React, { useEffect, useRef, useState } from 'react' -import { - Dialog, - DialogActions, - DialogContent, - DialogTitle, - TextField, - Button, - Autocomplete, - InputAdornment, - Box, - Grid -} from '@mui/material' -import { MdRule } from 'react-icons/md' -import { FaClipboardList } from 'react-icons/fa' - -const AddParcours = ({ open, onClose, onSubmitSuccess }) => { - const [formData, setFormData] = useState({ - nom: '', - uniter: '', - mention_id: null - }) - - const [mention, setMention] = useState([]) - - useEffect(() => { - window.mention.getMention().then((response) => { - setMention(response) - }) - }, []) - - const handleChange = (e) => { - const { name, value } = e.target - setFormData({ ...formData, [name]: value }) - } - - const handleSubmit = async (e) => { - e.preventDefault() - let response = await window.notesysteme.insertParcours(formData) - console.log(response) - if (response.success) { - onSubmitSuccess(true) - onClose() // Close the modal after submission - setFormData({ - nom: '', - uniter: '', - mention_id: null - }) - } - } - - return ( - -
- Information sur le parcour - - - - - - - - ) - }} - /> - - - - - - ) - }} - /> - - - option.nom || ''} // Safely access `nom` - value={mention.find((item) => item.id === formData.mention_id) || null} // Bind selected value to form data - onChange={(event, newValue) => { - setFormData((prevData) => ({ - ...prevData, - mention_id: newValue ? newValue.id : null // Store the ID of the selected mention - })) - }} - isOptionEqualToValue={(option, value) => option.id === value.id} // Ensure correct matching of options - renderInput={(params) => ( - - - - - {params.InputProps.startAdornment} - - ) - }} - sx={{ - marginBottom: '5px', - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800' // Set border color on hover - } - } - }} - /> - )} - /> - - - - - - - - -
-
- ) -} - -export default AddParcours diff --git a/src/renderer/src/components/AddStudent.jsx b/src/renderer/src/components/AddStudent.jsx deleted file mode 100644 index 2ff0136..0000000 --- a/src/renderer/src/components/AddStudent.jsx +++ /dev/null @@ -1,1070 +0,0 @@ -import React, { useEffect, useRef, useState } from 'react' -import classe from '../assets/AllStyleComponents.module.css' -import classeAdd from '../assets/AddStudent.module.css' -import { IoMdMale, IoMdPersonAdd } from 'react-icons/io' -import { IoMdReturnRight } from 'react-icons/io' -import classeHome from '../assets/Home.module.css' -import { Link, useNavigate } from 'react-router-dom' -import { - Box, - Button, - InputAdornment, - Typography, - Modal, - TextField, - Grid, - Autocomplete, - IconButton -} from '@mui/material' -import { - FaUser, - FaIdBadge, - FaBirthdayCake, - FaGraduationCap, - FaCalendarAlt, - FaFileUpload, - FaFileExcel, - FaClipboardList, - FaPassport, - FaGlobeAfrica, - FaMoneyBillWave, - FaHome, - FaPhone -} from 'react-icons/fa' -import { styled } from '@mui/material/styles' -import InputLabel from '@mui/material/InputLabel' -import MenuItem from '@mui/material/MenuItem' -import FormControl from '@mui/material/FormControl' -import Select from '@mui/material/Select' -import { OutlinedInput } from '@mui/material' -import svgSuccess from '../assets/success.svg' -import svgError from '../assets/error.svg' -import ChangeCapital from './function/ChangeCapitalLetter' -import ChangeCapitalize from './function/ChangeCapitalizeLetter' -import { MdChangeCircle, MdGrade, MdRule } from 'react-icons/md' -import ModalRecepice from './ModalRecepice' -import { FaLeftLong, FaRightLong } from 'react-icons/fa6' -import { Tooltip } from 'react-tooltip' - -const AddStudent = () => { - const [niveaus, setNiveau] = useState([]) - const [status, setStatus] = useState([]) - const [scolaire, setScolaire] = useState([]) - const [mention, setMention] = useState([]) - const [parcours, setParcours] = useState([]) - - useEffect(() => { - window.niveaus.getNiveau().then((response) => { - setNiveau(response) - }) - - window.statuss.getStatus().then((response) => { - setStatus(response) - }) - - window.anneescolaire.getAnneeScolaire().then((response) => { - setScolaire(response) - }) - - window.mention.getMention().then((response) => { - setMention(response) - }) - - window.notesysteme.getParcours().then((response) => { - setParcours(response) - }) - }, []) - - const navigate = useNavigate() - - /** - * hook for storing data in the input - */ - const [formData, setFormData] = useState({ - nom: '', - prenom: '', - photos: null, - date_de_naissances: '', - niveau: '', - annee_scolaire: '', - status: '', - num_inscription: '', - mention_id: '', - sexe: 'Garçon', - nationaliter: '', - cin: '', - date_delivrence: '', - annee_bacc: '', - serie: '', - boursier: 'oui', - domaine: '', - contact: '', - parcours: '' - }) - - const [dataToSend, setDataToSend] = useState({}) - - useEffect(() => { - setDataToSend({ - mention: compareMention(formData.mention_id), - niveau: formData.niveau, - nomPrenom: formData.nom + ' ' + formData.prenom, - inscri: formData.num_inscription, - annee: formData.annee_scolaire - }) - }, [formData]) - - function compareMention(mentionID) { - let statusText - - mention.map((statu) => { - if (mentionID == statu.id) { - statusText = statu.nom - } - }) - - return statusText ? statusText.charAt(0).toUpperCase() + statusText.slice(1) : statusText - } - - /** - * ref for each input - */ - const nomRef = useRef() - const prenomRef = useRef() - const date_de_naissancesRef = useRef() - - /** - * function to set the data in state - * @param {*} e - */ - const handleInputChange = (e) => { - const { name, value } = e.target - setFormData((prevData) => ({ - ...prevData, - [name]: value - })) - } - - const imageVisual = useRef() - - const handleFileChange = (e) => { - let img_file = e.target.files[0] - const reader = new FileReader() - reader.readAsDataURL(img_file) - reader.onload = (ev) => { - const url = ev.target.result - // initialisation de nouvelle imageURL - const image = document.createElement('img') - image.src = url - - // create a new image - image.onload = (event) => { - let canvas = document.createElement('canvas') - let ratio = 250 / event.target.width - canvas.width = 250 - canvas.height = event.target.height * ratio - const context = canvas.getContext('2d') - context.drawImage(image, 0, 0, canvas.width, canvas.height) - - // new url - const new_URL = canvas.toDataURL('image/jpeg', 90) - imageVisual.current.style.display = 'block' - imageVisual.current.src = new_URL - // rendement de l'url a notre variable global - setFormData((prevData) => ({ - ...prevData, - photos: new_URL - })) - } - } - } - - const handleSubmit = async (e) => { - e.preventDefault() - // Handle form submission logic - const response = await window.etudiants.insertEtudiant(formData) - - console.log(response) - if (!response.success) { - setCode(422) - setOpen(true) - } - - if (response.success) { - imageVisual.current.style.display = 'none' - imageVisual.current.src = '' - setCode(200) - setOpen(true) - } - } - - const VisuallyHiddenInput = styled('input')({ - clip: 'rect(0 0 0 0)', - clipPath: 'inset(50%)', - height: 1, - overflow: 'hidden', - position: 'absolute', - bottom: 0, - left: 0, - whiteSpace: 'nowrap', - width: 1 - }) - - /** - * hook to open modal - */ - const [open, setOpen] = useState(false) - const [open2, setOpen2] = useState(false) - const [code, setCode] = useState(200) - - /** - * function to close modal - */ - const handleClose = () => { - setOpen2(false) - navigate('/student') - } - const handleOpen3 = () => { - setOpenModal3(true) - } - - const handleClose2 = () => { - setOpen(false) - } - - /** - * function to return the view Modal - * - * @returns {JSX} - */ - const modals = () => ( - - - {code == 422 ? ( - - {' '} - Vérifier les champs - - ) : ( - - {' '} - Insertion a été effectuée avec succès - - )} - - {code === 200 ? ( - - ) : ( - - )} - - - - ) - - const [openModal3, setOpenModal3] = useState(false) - - const handleClose3 = () => { - navigate('/student') - setOpenModal3(false) - } - - const [page1, setPage1] = useState(true) - const [page2, setPage2] = useState(false) - - const seePage1 = () => { - setPage2(false) - setPage1(true) - } - - const seePage2 = () => { - setPage1(false) - setPage2(true) - } - - return ( -
- {modals()} - -
-
-
-

- - Ajout étudiant -

- - - -
-
-
-
- -
- - Importer un fichier excel - -
- -
-
- -
- - {page1 == true && ( - - {/* Nom and Prenom Fields */} - - ChangeCapital(nomRef)} - InputProps={{ - startAdornment: ( - - - - ) - }} - inputRef={nomRef} - sx={{ - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800' // Set the border color on hover - } - } - }} - /> - - - ChangeCapitalize(prenomRef)} - InputProps={{ - startAdornment: ( - - - - ) - }} - inputRef={prenomRef} - sx={{ - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800' // Set the border color on hover - } - } - }} - /> - - - {/* Date de Naissance and Niveau Fields */} - - - - - ) - }} - inputRef={date_de_naissancesRef} - sx={{ - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800' // Set the border color on hover - } - } - }} - /> - - - - - - ) - }} - sx={{ - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800' // Set the border color on hover - } - } - }} - /> - - - - - Année Universitaire - - - - - - - - Niveau - - - - - - - - Status - - - - - - option.nom || ''} // Safely access `nom` - value={mention.find((item) => item.id === formData.mention_id) || null} // Bind selected value to form data - onChange={(event, newValue) => { - setFormData((prevData) => ({ - ...prevData, - mention_id: newValue ? newValue.id : null // Store the ID of the selected mention - })) - }} - size="small" // Make the Autocomplete small - isOptionEqualToValue={(option, value) => option.id === value.id} // Ensure correct matching of options - renderInput={(params) => ( - - - - - {params.InputProps.startAdornment} - - ) - }} - sx={{ - marginBottom: '5px', - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800' // Set border color on hover - } - } - }} - /> - )} - /> - - - {/* Photos Field */} - - - - - )} - {page2 && ( - - - - - - ) - }} - sx={{ - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800' // Set the border color on hover - } - } - }} - /> - - - - - - ) - }} - sx={{ - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800' // Set the border color on hover - } - } - }} - /> - - - - - Sexe - - - - - - - - - ) - }} - sx={{ - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800' // Set the border color on hover - } - } - }} - /> - - - - - - ) - }} - sx={{ - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800' // Set the border color on hover - } - } - }} - /> - - - - - - ) - }} - sx={{ - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800' // Set the border color on hover - } - } - }} - /> - - - - - Boursier - - - - - - - - - ) - }} - sx={{ - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800' // Set the border color on hover - } - } - }} - /> - - - - - - ) - }} - sx={{ - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800' // Set the border color on hover - } - } - }} - /> - - - option.nom || ''} // Display `nom` - value={parcours.find((item) => item.nom === formData.parcours) || null} // Find selected option based on `nom` - onChange={(event, newValue) => { - setFormData((prevData) => ({ - ...prevData, - parcours: newValue ? newValue.nom : '' // Store only `nom` - })) - }} - size="small" - isOptionEqualToValue={(option, value) => option.nom === value?.nom} // Ensure correct matching - renderInput={(params) => ( - - - - - {params.InputProps.startAdornment} - - ) - }} - sx={{ - marginBottom: '5px', - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800' // Set border color on hover - } - } - }} - /> - )} - /> - - - )} - {/* Submit Button */} - -
- - - - - Page précédents - - - - - - Page suivants - -
- -
-
-
-
-
-
-
- ) -} - -export default AddStudent diff --git a/src/renderer/src/components/Addadmin.jsx b/src/renderer/src/components/Addadmin.jsx deleted file mode 100644 index 8ed4bd3..0000000 --- a/src/renderer/src/components/Addadmin.jsx +++ /dev/null @@ -1,336 +0,0 @@ -import React, { useRef, useState } from 'react' -import classe from '../assets/AllStyleComponents.module.css' -import img from '../assets/admin.png' -import classeHome from '../assets/Home.module.css' -import { Box, Button, InputAdornment, TextField, Grid, Typography, Modal } from '@mui/material' -import classeAdd from '../assets/AddStudent.module.css' -import validationAddAdmin from './validation/AddAdmin' -import svgSuccess from '../assets/success.svg' -import svgError from '../assets/error.svg' -import { FaEnvelope, FaLock, FaUser } from 'react-icons/fa' - -const Admin = () => { - const [formData, setFormData] = useState({ - username: '', - email: '', - password: '', - roles: 'Enseignant' - }) - - const usernameRef = useRef() - const emailRef = useRef() - const passwordRef = useRef() - const rolesRef = useRef() - const errorUsername = useRef() - const errorEmail = useRef() - const errorPassword = useRef() - - /** - * function to set the data in state - * @param {*} e - */ - const handleInputChange = (e) => { - const { name, value } = e.target - setFormData((prevData) => ({ - ...prevData, - [name]: value - })) - } - - const handleSubmit = async (e) => { - e.preventDefault() - // Handle form submission logic - const valid = validationAddAdmin( - usernameRef.current, - emailRef.current, - passwordRef.current, - errorUsername.current, - errorEmail.current, - errorPassword.current - ) - console.log(formData) - console.log(valid) - - if (valid) { - const response = await window.allUser.insertUsers(formData) - console.log(response) - if (response.success) { - setOpen(true) - setFormData({ - username: '', - email: '', - password: '', - roles: 'Enseignant' - }) - } - - if (response.code) { - setCode(422) - setOpen(true) - } - } - } - - /** - * hook to open 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 = () => ( - - - {code == 422 ? ( - - {' '} - Email déjà pris - - ) : ( - - {' '} - Insertion a été effectuée avec succès - - )} - - - - - - ) - - const sendData = async () => { - await window.syncro.getall() - } - - return ( -
- {modals()} -
-
-
-

Ajout d'admin

-
- - -
-
-
-
- {/* contenu */} -
-
- - - - - - -
- - {/* matieres Algebre */} - - - - - ) - }} - inputRef={usernameRef} - sx={{ - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800' // Set the border color on hover - } - } - }} - /> - {/* error username */} - - - {/* matieres Analyse */} - - - - - ) - }} - inputRef={emailRef} - sx={{ - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800' // Set the border color on hover - } - } - }} - /> - {/* error email */} - - - {/* matieres Mecanique general */} - - - - - ) - }} - inputRef={passwordRef} - sx={{ - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800' // Set the border color on hover - } - } - }} - /> - {/* error password */} - - - {/* Matieres Resistance Materiaux */} - - - }} - inputRef={rolesRef} - sx={{ - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800' // Set the border color on hover - } - } - }} - /> - - {/* Submit Button */} - - - - -
-
-
-
-
-
- ) -} - -export default Admin diff --git a/src/renderer/src/components/AjoutTranche.jsx b/src/renderer/src/components/AjoutTranche.jsx deleted file mode 100644 index 5f66207..0000000 --- a/src/renderer/src/components/AjoutTranche.jsx +++ /dev/null @@ -1,112 +0,0 @@ -import React, { useState } from 'react' -import { - Dialog, - DialogActions, - DialogContent, - DialogTitle, - TextField, - Button, - Autocomplete, - InputAdornment, - Box, - Grid -} from '@mui/material' -import { MdLabelImportantOutline } from 'react-icons/md' - -const AjoutTranche = ({ open, onClose, onSubmitSuccess, id }) => { - const [formData, setFormData] = useState({ - etudiant_id: id, - tranchename: '', - montant: '' - }) - - const handleChange = (e) => { - const { name, value } = e.target - setFormData({ ...formData, [name]: value }) - } - - const handleSubmit = async (e) => { - e.preventDefault() - let response = await window.etudiants.createTranche(formData) - - if (response.success) { - onClose() - onSubmitSuccess(true) - setFormData({ - etudiant_id: id, - tranchename: '', - montant: '' - }) - } - } - - return ( - -
- Ajout tranche - - - - - - - - ) - }} - /> - - - - - - ) - }} - /> - - - - - - - - -
-
- ) -} - -export default AjoutTranche diff --git a/src/renderer/src/components/AnneeScolaire.jsx b/src/renderer/src/components/AnneeScolaire.jsx deleted file mode 100644 index e0773b7..0000000 --- a/src/renderer/src/components/AnneeScolaire.jsx +++ /dev/null @@ -1,319 +0,0 @@ -import React, { useEffect, useState } from 'react' -import classe from '../assets/AllStyleComponents.module.css' -import classeHome from '../assets/Home.module.css' -import Paper from '@mui/material/Paper' -import { Modal, Box, Typography, Button, InputAdornment, TextField, Grid } from '@mui/material' -import { FaCalendarAlt, FaCheck, FaCheckCircle, FaSquare } from 'react-icons/fa' -import { DataGrid, GridToolbar, GridToolbarFilterButton } from '@mui/x-data-grid' -import { createTheme, ThemeProvider } from '@mui/material/styles' -import { frFR } from '@mui/x-data-grid/locales' -import { FaCalendarPlus } from 'react-icons/fa' -import { Link } from 'react-router-dom' -import { FaPenToSquare, FaTrash } from 'react-icons/fa6' -import { Tooltip } from 'react-tooltip' -import dayjs from 'dayjs' -import warning from '../assets/warning.svg' -import success from '../assets/success.svg' -import { BsCalendar2Date } from 'react-icons/bs' - -const AnneeScolaire = () => { - const theme = createTheme({ - components: { - MuiIconButton: { - styleOverrides: { - root: { - color: 'gray' // Change the color of toolbar icons - } - } - }, - MuiButton: { - styleOverrides: { - root: { - color: '#121212' // Change the color of toolbar icons - } - } - } - } - }) - - const [anneeScolaire, setAnneeScolaire] = useState([]) - - useEffect(() => { - window.anneescolaire.getAnneeScolaire().then((response) => { - setAnneeScolaire(response) - }) - }, []) - - const [isDeleted, setIsDeleted] = useState(false) - const [ids, setIds] = useState(0) - - const column = [ - { field: 'code', headerName: 'Année universitaire', width: 130 }, - { field: 'debut', headerName: 'Date de début', width: 130 }, - { field: 'fin', headerName: 'Date de fin', width: 130 }, - { - field: 'action', - headerName: 'Action', - flex: 1, - renderCell: (params) => ( -
- - - - { - setIds(params.row.id) - setOpen(true) - }} - > - - -
- ) - }, - { - field: 'current', - headerName: 'Année en cours', - flex: 1, - renderCell: (params) => ( -
- - - - Année en cours - - -
- ) - } - ] - - const paginationModel = { page: 0, pageSize: 5 } - - let data = anneeScolaire.map((annee) => ({ - id: annee.id, - code: annee.code, - debut: dayjs(annee.debut).format('DD-MM-YYYY'), - fin: dayjs(annee.fin).format('DD-MM-YYYY'), - action: annee.id, - current: { current: annee.is_current, id: annee.id } - })) - - const setCurrent = async (id) => { - // let response = await window.anneescolaire.setCurrent({id}); - // console.log(response); - // if (response.changes) { - // window.anneescolaire.getAnneeScolaire().then((response) => { - // setAnneeScolaire(response); - // }); - // } - } - - const deleteButton = async (id) => { - let response = await window.anneescolaire.deleteAnneeScolaire({ id }) - if (response.success) { - const updatedAnneeScolaire = anneeScolaire.filter((anneeScolaire) => anneeScolaire.id !== id) - setAnneeScolaire(updatedAnneeScolaire) - setIsDeleted(true) - } - } - - const CustomToolbar = () => { - return ( -
- -
- ) - } - - /** - * hook to open modal - */ - const [open, setOpen] = useState(false) - - /** - * function to close modal - */ - const handleClose = () => { - setOpen(false) - setIsDeleted(false) - } - - /** - * function to return the view Modal - * - * @returns {JSX} - */ - const modals = () => ( - - - {isDeleted ? ( - - Suprimer avec succèss - - ) : ( - - {' '} - Voulez vous supprimer cette année ? - - )} - - {isDeleted ? ( - - ) : ( -
- - -
- )} -
-
-
- ) - - return ( -
- {modals()} -
-
-
-

- Année Universitaire -

- - - -
-
-
- -
- - -
- -
-
-
-
-
- ) -} - -export default AnneeScolaire diff --git a/src/renderer/src/components/Apropos.jsx b/src/renderer/src/components/Apropos.jsx deleted file mode 100644 index e8e80c6..0000000 --- a/src/renderer/src/components/Apropos.jsx +++ /dev/null @@ -1,68 +0,0 @@ -import React from 'react' -import classe from '../assets/AllStyleComponents.module.css' -import classeHome from '../assets/Home.module.css' -import logo from '../assets/logo or.png' -import { Box } from '@mui/material' -import classeAdd from '../assets/AddStudent.module.css' - -const Apropos = () => { - return ( -
-
-
-
-

A propos

- - {/* contenu */} -
-
- - - - - - -

- Nom du Logiciel: CUniversity
-
Description : logiciel de gestion d'universiter

- Createur: CPAY COMPANY FOR MADAGASCAR
-
Licence: A vie
-
Contact: 0348415301 -

- E-mail: director@c4m.mg -

-
-
-
-
-
-
-
-
- ) -} - -export default Apropos diff --git a/src/renderer/src/components/AssignMatiereToMention.jsx b/src/renderer/src/components/AssignMatiereToMention.jsx deleted file mode 100644 index dd1da32..0000000 --- a/src/renderer/src/components/AssignMatiereToMention.jsx +++ /dev/null @@ -1,203 +0,0 @@ -import React, { useEffect, useState } from 'react' -import { Link, useParams } from 'react-router-dom' -import { FaPlus } from 'react-icons/fa' -import { Button, Grid, Paper, Checkbox, Modal, Typography, Box } from '@mui/material' -import { IoMdReturnRight } from 'react-icons/io' -import classe from '../assets/AllStyleComponents.module.css' -import classeAdd from '../assets/AddStudent.module.css' -import classeHome from '../assets/Home.module.css' -import svgSuccess from '../assets/success.svg' - -const AssignMatiereToMention = () => { - let { id } = useParams() - - const [mention, setMention] = useState([]) - const [matiere, setMatiere] = useState({}) - const [matiereMention, setMatiereMention] = useState([]) - const [formData, setFormData] = useState({}) - - // Fetch data on component mount - useEffect(() => { - window.matieres.getAsign({ id }).then((response) => { - setMatiereMention(response) // Set matiereMention - }) - window.mention.getMention().then((response) => { - setMention(response) // Set mention - }) - window.matieres.getMatiereByID({ id }).then((response) => { - setMatiere(response) // Set matiere - }) - }, [id]) - - // Initialize formData based on mentions and matiereMention - useEffect(() => { - if (mention.length && matiereMention.length) { - const initialFormData = mention.reduce((acc, mens) => { - // Check if the current mention ID exists in matiereMention - const isChecked = matiereMention.some((item) => item.mention_id === mens.id) - acc[mens.id] = isChecked // Set true if matched, false otherwise - return acc - }, {}) - setFormData(initialFormData) // Update formData - } - }, [mention, matiereMention]) - - /** - * Handle form submission - */ - const formSubmit = async (e) => { - e.preventDefault() - - let response = await window.matieres.asign({ formData, id }) - console.log(response) - if (response.success) { - setOpen(true) - } - } - - /** - * Handle checkbox change - */ - const handleCheckboxChange = (id) => { - setFormData((prevData) => ({ - ...prevData, - [id]: !prevData[id] // Toggle the checkbox value - })) - } - - /** - * hook to open modal - */ - const [open, setOpen] = useState(false) - - /** - * function to close modal - */ - const handleClose = () => { - setOpen(false) - } - - /** - * function to return the view Modal - * - * @returns {JSX} - */ - const modals = () => ( - - - - {' '} - Changemet effectuée avec succès - - - - - - - ) - - return ( -
- {modals()} -
-
-
-

- Asignation -

- window.history.back()}> - - -
-
-
- - -
-
- Choisissez les mentions qui utilisent {matiere?.nom || 'la matière'} -
- - {mention.map((mens) => ( - - - - {mens.nom} - - - - handleCheckboxChange(mens.id)} // Handle change - color="success" - /> - - - ))} - - - - -
-
-
- ) -} - -export default AssignMatiereToMention diff --git a/src/renderer/src/components/AssingMatiereToSemestre.jsx b/src/renderer/src/components/AssingMatiereToSemestre.jsx deleted file mode 100644 index 898c292..0000000 --- a/src/renderer/src/components/AssingMatiereToSemestre.jsx +++ /dev/null @@ -1,259 +0,0 @@ -import React, { useEffect, useState } from 'react' -import classe from '../assets/AllStyleComponents.module.css' -import classeAdd from '../assets/AddStudent.module.css' -import classeHome from '../assets/Home.module.css' -import { Link, useParams } from 'react-router-dom' -import { Button, Grid, Paper, Modal, Typography, Box } from '@mui/material' -import { IoMdReturnRight } from 'react-icons/io' -import { FaPlus } from 'react-icons/fa' -import OutlinedInput from '@mui/material/OutlinedInput' -import InputLabel from '@mui/material/InputLabel' -import MenuItem from '@mui/material/MenuItem' -import FormControl from '@mui/material/FormControl' -import Select from '@mui/material/Select' -import svgSuccess from '../assets/success.svg' - -const AssingMatiereToSemestre = () => { - let { id } = useParams() - - const [mentions, setMentions] = useState([]) - const [matiereSemestre, setMatiereSemestre] = useState([]) - const [matiere, setMatiere] = useState({}) - const [semestre, setSemestre] = useState([]) - - useEffect(() => { - window.matieres.asignSemestre({ id }).then((response) => { - setMentions(response) - }) - - window.matieres.getMatiereByID({ id }).then((response) => { - setMatiere(response) // Set matiere - }) - - window.matieres.getSemestreMatiere({ id }).then((response) => { - setMatiereSemestre(response) // Set matiere - }) - - window.matieres.getSemestre().then((response) => { - setSemestre(response) // Set matiere - }) - }, [id]) - - // State to manage selected semestres for each mention - const [selectedSemestres, setSelectedSemestres] = useState({}) - - // Populate the initial state for selectedSemestres - useEffect(() => { - const initialSelectedSemestres = {} - matiereSemestre.forEach((item) => { - if (!initialSelectedSemestres[item.mention_id]) { - initialSelectedSemestres[item.mention_id] = [] - } - initialSelectedSemestres[item.mention_id].push(item.semestre_id) - }) - setSelectedSemestres(initialSelectedSemestres) - }, [matiereSemestre]) - - // Handle change in Select - const handleChange = (id) => (event) => { - const { - target: { value } - } = event - - // Update state for the specific mention ID - setSelectedSemestres((prevState) => ({ - ...prevState, - [id]: typeof value === 'string' ? value.split(',') : value - })) - } - - const formSubmit = async (e) => { - e.preventDefault() - - let response = await window.matieres.insertUpdateMentionSemestre({ id, selectedSemestres }) - - console.log(response) - if (response.success) { - setOpen(true) - } - } - - /** - * hook to open modal - */ - const [open, setOpen] = useState(false) - - /** - * function to close modal - */ - const handleClose = () => { - setOpen(false) - } - - /** - * function to return the view Modal - * - * @returns {JSX} - */ - const modals = () => ( - - - - {' '} - Changemet effectuée avec succès - - - - - - - ) - - console.log(matiereSemestre) - - // Step 1: Preprocess matiereSemestre to create a mapping - const preprocessSemestres = () => { - const mapping = {} - matiereSemestre.forEach((item) => { - if (item.matiere_id === id) { - // Filter by matiere_id if necessary - if (!mapping[item.mention_id]) { - mapping[item.mention_id] = [] - } - mapping[item.mention_id].push(item.semestre_id) - } - }) - return mapping - } - - return ( -
- {modals()} -
-
-
-

- Asignation Semestre -

- - - -
-
-
- -
-
- Choisissez les semestre dans la quelle on enseigne {matiere?.nom || 'la matière'} -
- - {mentions.map((mens) => ( - -
-
- - {mens.nom} - -
-
- - - Semestre - - - -
-
-
- ))} -
- - - -
-
-
- ) -} - -export default AssingMatiereToSemestre diff --git a/src/renderer/src/components/CustomBar.jsx b/src/renderer/src/components/CustomBar.jsx deleted file mode 100644 index 7d91015..0000000 --- a/src/renderer/src/components/CustomBar.jsx +++ /dev/null @@ -1,30 +0,0 @@ -import React from 'react' -import { - GridToolbarContainer, - GridToolbarFilterButton, - GridToolbarColumnsButton, - GridToolbarExport -} from '@mui/x-data-grid' -import { Button } from '@mui/material' -import { FaCloudUploadAlt } from 'react-icons/fa' - -const CustomBar = ({ onImport }) => { - return ( - - - - {/* Custom import button */} - - - - ) -} - -export default CustomBar diff --git a/src/renderer/src/components/DeleteTranche.jsx b/src/renderer/src/components/DeleteTranche.jsx deleted file mode 100644 index f6e949b..0000000 --- a/src/renderer/src/components/DeleteTranche.jsx +++ /dev/null @@ -1,52 +0,0 @@ -import React, { useEffect, useState } from 'react' -import { - Dialog, - DialogActions, - DialogContent, - DialogTitle, - Button, - Box, - Typography -} from '@mui/material' - -const DeleteTranche = ({ open, onClose, id, onSubmitSuccess }) => { - const [idDelete, setIdDelete] = useState(null) - - useEffect(() => { - setIdDelete(id) - }, [id]) - - console.log(idDelete) - - const deleteOption = async () => { - if (idDelete !== null) { - const id = idDelete - let response = await window.etudiants.deleteTranche({ id }) - if (response.success) { - onSubmitSuccess(true) - onClose() - } - } - } - - return ( - - Suppression - - - Voulez vous Supprimer ? - - - - - - - - ) -} - -export default DeleteTranche diff --git a/src/renderer/src/components/ExportEtudiants.jsx b/src/renderer/src/components/ExportEtudiants.jsx deleted file mode 100644 index 0f450ac..0000000 --- a/src/renderer/src/components/ExportEtudiants.jsx +++ /dev/null @@ -1,517 +0,0 @@ -import React, { useEffect, useState } from 'react' -import classe from '../assets/AllStyleComponents.module.css' -import classeAdd from '../assets/AddStudent.module.css' -import classeHome from '../assets/Home.module.css' -import { IoMdReturnRight } from 'react-icons/io' -import { Link } from 'react-router-dom' -import { FaFileExcel, FaCloudUploadAlt, FaCloudDownloadAlt } from 'react-icons/fa' -import { Box, Button, Typography, ThemeProvider, Modal } from '@mui/material' -import { styled, createTheme } from '@mui/material/styles' -import * as XLSX from 'xlsx' -import Papa from 'papaparse' -import { DataGrid, GridToolbarContainer, GridToolbarColumnsButton } from '@mui/x-data-grid' -import { frFR } from '@mui/x-data-grid/locales' -import dayjs from 'dayjs' -import CustomBar from './CustomBar' -import svgSuccess from '../assets/success.svg' -import svgError from '../assets/error.svg' -import { MenuItem, Select, FormControl, InputLabel } from '@mui/material' - -const ExportEtudiants = () => { - const [tableData, setTableData] = useState([]) - const [error, setError] = useState('') - const [isInserted, setIsinserted] = useState(true) - const [message, setMessage] = useState('') - - const theme = createTheme({ - components: { - MuiIconButton: { - styleOverrides: { - root: { - color: 'gray' // Toolbar icons color - } - } - }, - MuiButton: { - styleOverrides: { - root: { - color: '#121212' // Button text color - } - } - } - } - }) - - const [header, setHeader] = useState([]) - let field = [] - const [dynamicColumns, setColumns] = useState([]) - - for (let index = 0; index < header.length; index++) { - field.push(header[index].toLowerCase().replace(/\s+/g, '_')) - } - - useEffect(() => { - setColumns( - header.map((col, index) => ({ - field: field[index], // Converts the header text to field names (e.g., "Nom" -> "nom") - headerName: col, // Display the header as is - width: 150 // Adjust the width as needed - })) - ) - }, [header]) - - const paginationModel = { page: 0, pageSize: 5 } - - // Assuming `tableData` is an array where each entry corresponds to a student's data - const dataRow = tableData.map((etudiant, index) => { - // Dynamically create an object with fields from the header and data from `etudiant` - let row = { id: index + 1 } // Unique ID for each row - - field.forEach((fieldName, idx) => { - if (fieldName === 'date_de_naissance') { - row[fieldName] = dayjs(etudiant[idx]).format('DD-MM-YYYY') // Format date - } else { - row[fieldName] = etudiant[idx] // Assign value to field dynamically - } - }) - - return row - }) - - const VisuallyHiddenInput = styled('input')({ - clip: 'rect(0 0 0 0)', - clipPath: 'inset(50%)', - height: 1, - overflow: 'hidden', - position: 'absolute', - bottom: 0, - left: 0, - whiteSpace: 'nowrap', - width: 1 - }) - - const [files, setFiles] = useState() - - const handleFileChange = (event) => { - const file = event.target.files[0] - setFiles(event.target.files[0]) - if (!file) { - setError('No file selected') - return - } - - const fileExtension = file.name.split('.').pop().toLowerCase() - - if (fileExtension === 'xlsx') { - const reader = new FileReader() - reader.onload = (e) => { - const data = new Uint8Array(e.target.result) - const workbook = XLSX.read(data, { type: 'array' }) - - // Extract data from all sheets and combine - const allData = [] - workbook.SheetNames.forEach((sheetName) => { - const worksheet = workbook.Sheets[sheetName] - const rows = XLSX.utils.sheet_to_json(worksheet, { header: 1 }) - setHeader(rows[0]) // keep the header - allData.push(...rows.slice(1)) // Skip header row for each sheet - }) - setTableData(allData) - } - reader.readAsArrayBuffer(file) - } else if (fileExtension === 'csv') { - const reader = new FileReader() - reader.onload = (e) => { - Papa.parse(e.target.result, { - complete: (results) => { - setHeader(results.data[0]) // keep the header - console.log(results.data) - setTableData(results.data.slice(1)) // Skip header row - }, - header: false - }) - } - reader.readAsText(file) - } else { - setError('Unsupported file format. Please upload .xlsx or .csv file.') - setTableData([]) - } - } - - /** - * fonction qui envoye dans le back - */ - const handleImport = async () => { - // Code to handle file import (can open a file dialog or call handleFileChange) - - let response = await window.etudiants.importExcel(files.path) - - console.log(response) - - if (response.message) { - setMessage(response.message) - } - - if (response.error) { - setIsinserted(true) - setOpen(true) - setTableData([]) - } else { - setIsinserted(false) - setOpen(true) - } - } - - /** - * hook to open modal - */ - const [open, setOpen] = useState(false) - - /** - * function to close modal - */ - const handleClose = () => setOpen(false) - - /** - * function to return the view Modal - * - * @returns {JSX} - */ - const modals = () => ( - - - {isInserted ? ( - - {' '} - Importation a été effectuée avec succès - - ) : ( - - {' '} - - L'importation n'a pas été effectuée -
- {message} -
-
- )} - - - -
-
- ) - - const exemplaireFileExcel = [ - { - nom: 'nom2', - prenom: 'prenom2', - niveau: 'L1', - date_naissance: 'jj/mm/AAAA', - annee_scolaire: '2024-2025', - mention: 'INFO', - num_inscription: 'azertyuiop', - sexe: 'F', - cin: '1234567890987', - date_de_delivrance: 'JJ/MM/AAAA', - nationaliter: 'Malagasy', - annee_baccalaureat: 'AAAA', - serie: 'D', - code_redoublement: 'N si nouveau, P si passant, R si redoublant RM si renvoyer, A si ancient', - boursier: 'Non', - domaine: "(S) Science de l'ingénieur", - contact: '0387205654' - }, - { - nom: 'nom1', - prenom: 'prenom2', - niveau: 'L2', - date_naissance: 'jj/mm/AAAA', - annee_scolaire: '2024-2025', - mention: 'Informatique', - num_inscription: 'azertyuiop', - sexe: 'M', - cin: '1234567890987', - date_de_delivrance: 'JJ/MM/AAAA', - nationaliter: 'Malagasy', - annee_baccalaureat: 'AAAA', - serie: 'D', - code_redoublement: 'N si nouveau, P si passant, R si redoublant RM si renvoyer, A si ancient', - boursier: 'Non', - domaine: "(S) Science de l'ingénieur", - contact: '0387205654' - } - ] - - const convertToExcel = () => { - // convert json to sheet - const worksheet = XLSX.utils.json_to_sheet(exemplaireFileExcel) - - // Create a new workbook and append the worksheet - const workbook = XLSX.utils.book_new() - XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1') - - // Write the workbook to a Blob and create a download link - const excelBuffer = XLSX.write(workbook, { bookType: 'xlsx', type: 'array' }) - const data = new Blob([excelBuffer], { type: 'application/octet-stream' }) - const url = URL.createObjectURL(data) - - // Trigger a download - const link = document.createElement('a') - link.href = url - link.download = 'exemplaire_etudiant.xlsx' - link.click() - - // Clean up - URL.revokeObjectURL(url) - } - - const handleColumnVisibilityChange = (model) => { - // Get the currently visible columns - const visibleColumns = dynamicColumns.filter((column) => model[column.field] !== false) - - // Create a new Excel file with visible columns - createExcelFile(visibleColumns) - } - - const createExcelFile = (columns) => { - // Extract and set the header - const header = columns.reduce((acc, col) => { - acc[col.field] = col.headerName || col.field // Use headerName or field as default - return acc - }, {}) - - // Map the data rows to match the extracted headers - const worksheetData = dataRow.map((row) => { - const filteredRow = {} - columns.forEach((col) => { - const headerName = header[col.field] - filteredRow[headerName] = row[col.field] - }) - return filteredRow - }) - - // Create a worksheet from the data - const ws = XLSX.utils.json_to_sheet(worksheetData) - - // Create a workbook and add the worksheet to it - const wb = XLSX.utils.book_new() - XLSX.utils.book_append_sheet(wb, ws, 'Sheet1') - - // Generate the Excel file as binary data - const excelFile = XLSX.write(wb, { bookType: 'xlsx', type: 'array' }) - - // Create a Blob for the Excel data - const blob = new Blob([excelFile], { - type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' - }) - - // Create a link element to trigger the download - const url = URL.createObjectURL(blob) - const link = document.createElement('a') - link.href = url - link.download = 'original-file.xlsx' // Original file name or any desired name - document.body.appendChild(link) - link.click() - document.body.removeChild(link) - URL.revokeObjectURL(url) // Clean up - } - - // Handle header name change for a specific field and auto-export to Excel - const handleHeaderChange = (field, newHeaderName) => { - setColumns((prevColumns) => - prevColumns.map((col) => (col.field === field ? { ...col, headerName: newHeaderName } : col)) - ) - } - - return ( -
- {modals()} -
-
-
-

- Export -

- - - -
-
-
- - - -
- - -
- {error && ( - - {error} - - )} - {tableData.length > 0 && ( - -
- {/* Dropdowns for each column */} - {dynamicColumns.map((col) => ( - - {col.headerName} - - - ))} -
-
- -
-
- )} -
-
-
- ) -} - -export default ExportEtudiants diff --git a/src/renderer/src/components/ForgotPassword.jsx b/src/renderer/src/components/ForgotPassword.jsx deleted file mode 100644 index 16f22e7..0000000 --- a/src/renderer/src/components/ForgotPassword.jsx +++ /dev/null @@ -1,247 +0,0 @@ -import React, { useRef, useState } from 'react' -import classe from '../assets/Login.module.css' -import { FaEnvelope, FaLock, FaLockOpen } from 'react-icons/fa' -import { Link } from 'react-router-dom' -import { - Modal, - Box, - Container, - Grid, - Card, - Typography, - TextField, - Button, - InputAdornment -} from '@mui/material' -import { validationForgotPassword } from './validation/ForgotPassword' - -const ForgotPassword = () => { - /** - * hook to store data from the input field - */ - const [email, setEmail] = useState() - const [password, setPassword] = useState() - const [passwordConfirmation, setPasswordConfirmation] = useState() - - /** - * hook to open modal and set the sattus and message - */ - const [open, setOpen] = useState(false) - const [message, setMessage] = useState('') - const [status, setStatus] = useState(null) - - const handleClose = () => setOpen(false) - - /** - * ref for our email and password, confirm password input and the error span - */ - const emailRef = useRef() - const passwordRef = useRef() - const passwordConfirmationRef = useRef() - const emailError = useRef() - const passwordError = useRef() - const passwordConfirmationError = useRef() - - /** - * function to return the view Modal - * - * @returns {JSX} - */ - const modals = () => ( - - - - {status === 200 ? 'Success' : 'Error'} - - - {message} - - - - - ) - - /** - * function to send the email verification - * to change the password and redirect the user to login - * - * @param {any} e - */ - const verification = async (e) => { - e.preventDefault() - - let validation = validationForgotPassword( - emailRef.current, - passwordRef.current, - passwordConfirmationRef.current, - emailError.current, - passwordError.current, - passwordConfirmationError.current - ) - console.log(validation) - if (validation === true) { - const response = await window.allUser.forgotPassword({ - email, - password, - passwordConfirmation - }) - - if (response.status === 200) { - setMessage(response.message) - setStatus(200) - } else { - setMessage(response.message) - setStatus(response.status) - } - setOpen(true) - console.log(response) - } - } - - return ( - - {modals()} - - - - - Changer de mot de passe - -
- - - - ) - }} - 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 - } - } - }} - placeholder="Entrer email" - onChange={(e) => setEmail(e.target.value)} - inputRef={emailRef} - /> - - - - - - ) - }} - 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 - } - } - }} - placeholder="Mot de passe" - onChange={(e) => setPassword(e.target.value)} - 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 - } - } - }} - className={classe.input} - placeholder="Confirmation Mot de passe" - onChange={(e) => setPasswordConfirmation(e.target.value)} - inputRef={passwordConfirmationRef} - /> - - - - -
- - Se connecter - -
- -
-
-
-
- ) -} - -export default ForgotPassword diff --git a/src/renderer/src/components/Home.jsx b/src/renderer/src/components/Home.jsx deleted file mode 100644 index 5d42279..0000000 --- a/src/renderer/src/components/Home.jsx +++ /dev/null @@ -1,194 +0,0 @@ -import React, { useEffect, useState } from 'react' -import classe from '../assets/AllStyleComponents.module.css' -import { Bar } from 'react-chartjs-2' -import { - Chart as ChartJS, - CategoryScale, - LinearScale, - BarElement, - Title, - Tooltip, - Legend -} from 'chart.js' -import classeHome from '../assets/Home.module.css' -import dclass from '../assets/Dashboard.module.css' -import dayjs from 'dayjs' -import MenuItem from '@mui/material/MenuItem' -import FormControl from '@mui/material/FormControl' -import Select from '@mui/material/Select' -import InputLabel from '@mui/material/InputLabel' - -ChartJS.register(CategoryScale, LinearScale, BarElement, Title, Tooltip, Legend) - -const Home = () => { - const [etudiants, setEtudiants] = useState([]) - const [niveau, setNiveau] = useState([]) - const [annee_scolaire, setAnnee_scolaire] = useState([]) - const [originalEtudiants, setOriginalEtudiants] = useState([]) - // Get the current year - const currentYear = dayjs().year() - - useEffect(() => { - // Fetch data and update state - window.etudiants.getDataToDashboards().then((response) => { - setEtudiants(response.etudiants) - setOriginalEtudiants(response.etudiants) - setNiveau(response.niveau) - setAnnee_scolaire(response.anne_scolaire) - }) - }, []) - - // filter all data - - // ordre des colones de filtre - const desiredOrder = ['L1', 'L2', 'L3', 'M1', 'M2', 'D1', 'D2', 'D3'] - let allNiveau = niveau.map((item) => item.nom) - allNiveau.sort((a, b) => desiredOrder.indexOf(a) - desiredOrder.indexOf(b)) - - const studentGrades = {} - - // Loop through allNiveau and set the number of students for each key - allNiveau.forEach((niveauNom) => { - // Filter etudiants based on the matching niveau - const studentCount = etudiants.filter((etudiant) => etudiant.niveau === niveauNom).length - - // Assign the student count as the value for the corresponding key in studentGrades - studentGrades[niveauNom] = studentCount - }) - const studentCounts = Object.values(studentGrades) - - // Find the maximum value using Math.max - const maxStudentCount = Math.max(...studentCounts) - - const FilterAnneeScolaire = (e) => { - let annee_scolaire = e.target.value - const filteredEtudiants = originalEtudiants.filter( - (etudiant) => etudiant.annee_scolaire === annee_scolaire - ) - setEtudiants(filteredEtudiants) - if (annee_scolaire == 'general') { - setEtudiants(originalEtudiants) - } - } - // end filter all data - - // Calculate the number of classes - const numberOfClasses = Object.keys(studentGrades).length - - // Data for the Bar chart - const data = { - labels: Object.keys(studentGrades), // Class levels - datasets: [ - { - label: 'Nombre des étudiants', - data: Object.values(studentGrades), // Student counts - backgroundColor: [ - '#FF6384', - '#36A2EB', - '#FFCE56', - '#4BC0C0', - '#9966FF', - '#FF9F40', - '#C9CBCF', - '#00A36C' - ], // Colors for each bar - borderColor: [ - '#FF6384', - '#36A2EB', - '#FFCE56', - '#4BC0C0', - '#9966FF', - '#FF9F40', - '#C9CBCF', - '#00A36C' - ], - borderWidth: 1 - } - ] - } - - // Chart options - const options = { - responsive: true, - plugins: { - legend: { - position: 'top' - }, - title: { - display: true, - text: `Nombre des niveau (Total : ${numberOfClasses})` - } - }, - scales: { - y: { - beginAtZero: true, - max: maxStudentCount // Set max value for the Y axis - } - } - } - - return ( -
-
-
-
-

Dashboard

- - - Année Scolaire - - - -
-
-
- {/* display each bars */} -
- -
-
- ) -} - -export default Home diff --git a/src/renderer/src/components/ImportMatiere.jsx b/src/renderer/src/components/ImportMatiere.jsx deleted file mode 100644 index 3e956c6..0000000 --- a/src/renderer/src/components/ImportMatiere.jsx +++ /dev/null @@ -1,489 +0,0 @@ -import React, { useEffect, useState } from 'react' -import classe from '../assets/AllStyleComponents.module.css' -import classeAdd from '../assets/AddStudent.module.css' -import classeHome from '../assets/Home.module.css' -import { Box, Button, Typography, ThemeProvider, Modal } from '@mui/material' -import { Link } from 'react-router-dom' -import { FaCloudDownloadAlt, FaCloudUploadAlt, FaFileExcel } from 'react-icons/fa' -import { IoMdReturnRight } from 'react-icons/io' -import { styled, createTheme } from '@mui/material/styles' -import * as XLSX from 'xlsx' -import Papa from 'papaparse' -import { DataGrid, GridToolbarContainer, GridToolbarColumnsButton } from '@mui/x-data-grid' -import { frFR } from '@mui/x-data-grid/locales' -import CustomBar from './CustomBar' -import dayjs from 'dayjs' -import svgSuccess from '../assets/success.svg' -import svgError from '../assets/error.svg' -import { MenuItem, Select, FormControl, InputLabel } from '@mui/material' - -const ImportMatiere = () => { - const VisuallyHiddenInput = styled('input')({ - clip: 'rect(0 0 0 0)', - clipPath: 'inset(50%)', - height: 1, - overflow: 'hidden', - position: 'absolute', - bottom: 0, - left: 0, - whiteSpace: 'nowrap', - width: 1 - }) - - const [error, setError] = useState('') - const [isInserted, setIsinserted] = useState(true) - const [message, setMessage] = useState('') - const [tableData, setTableData] = useState([]) - const [files, setFiles] = useState() - const [header, setHeader] = useState([]) - let field = [] - const [dynamicColumns, setColumns] = useState([]) - - for (let index = 0; index < header.length; index++) { - field.push(header[index].toLowerCase().replace(/\s+/g, '_')) - } - - useEffect(() => { - setColumns( - header.map((col, index) => ({ - field: field[index], // Converts the header text to field names (e.g., "Nom" -> "nom") - headerName: col, // Display the header as is - width: 150 // Adjust the width as needed - })) - ) - }, [header]) - - const theme = createTheme({ - components: { - MuiIconButton: { - styleOverrides: { - root: { - color: 'gray' // Toolbar icons color - } - } - }, - MuiButton: { - styleOverrides: { - root: { - color: '#121212' // Button text color - } - } - } - } - }) - - const paginationModel = { page: 0, pageSize: 5 } - - // Assuming `tableData` is an array where each entry corresponds to a student's data - const dataRow = tableData.map((etudiant, index) => { - // Dynamically create an object with fields from the header and data from `etudiant` - let row = { id: index + 1 } // Unique ID for each row - - field.forEach((fieldName, idx) => { - if (fieldName === 'date_de_naissance') { - row[fieldName] = dayjs(etudiant[idx]).format('DD-MM-YYYY') // Format date - } else { - row[fieldName] = etudiant[idx] // Assign value to field dynamically - } - }) - - return row - }) - - const handleFileChange = (event) => { - const file = event.target.files[0] - setFiles(event.target.files[0]) - if (!file) { - setError('No file selected') - return - } - - const fileExtension = file.name.split('.').pop().toLowerCase() - - if (fileExtension === 'xlsx') { - const reader = new FileReader() - reader.onload = (e) => { - const data = new Uint8Array(e.target.result) - const workbook = XLSX.read(data, { type: 'array' }) - - // Extract data from all sheets and combine - const allData = [] - workbook.SheetNames.forEach((sheetName) => { - const worksheet = workbook.Sheets[sheetName] - const rows = XLSX.utils.sheet_to_json(worksheet, { header: 1 }) - setHeader(rows[0]) // keep the header - allData.push(...rows.slice(1)) // Skip header row for each sheet - }) - setTableData(allData) - } - reader.readAsArrayBuffer(file) - } else if (fileExtension === 'csv') { - const reader = new FileReader() - reader.onload = (e) => { - Papa.parse(e.target.result, { - complete: (results) => { - setHeader(results.data[0]) // keep the header - setTableData(results.data.slice(1)) // Skip header row - }, - header: false - }) - } - reader.readAsText(file) - } else { - setError('Unsupported file format. Please upload .xlsx or .csv file.') - setTableData([]) - } - } - - const exemplaireFileExcel = [ - { - nom: 'matiere 1', - credit: 5, - uniter: 'MUI', - heure: 39 - }, - { - nom: 'matiere 2', - credit: 5, - uniter: 'MUI', - heure: 39 - }, - { - nom: 'matiere 3', - credit: 5, - uniter: 'MUI', - heure: 39 - }, - { - nom: 'matiere 4', - credit: 5, - uniter: 'MUI', - heure: 39 - }, - { - nom: 'matiere 5', - credit: 5, - uniter: 'MUI', - heure: 39 - } - ] - - const convertToExcel = () => { - // convert json to sheet - const worksheet = XLSX.utils.json_to_sheet(exemplaireFileExcel) - - // Create a new workbook and append the worksheet - const workbook = XLSX.utils.book_new() - XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1') - - // Write the workbook to a Blob and create a download link - const excelBuffer = XLSX.write(workbook, { bookType: 'xlsx', type: 'array' }) - const data = new Blob([excelBuffer], { type: 'application/octet-stream' }) - const url = URL.createObjectURL(data) - - // Trigger a download - const link = document.createElement('a') - link.href = url - link.download = 'exemplaier_matiere.xlsx' - link.click() - - // Clean up - URL.revokeObjectURL(url) - } - - const handleColumnVisibilityChange = (model) => { - // Get the currently visible columns - const visibleColumns = dynamicColumns.filter((column) => model[column.field] !== false) - - // Create a new Excel file with visible columns - createExcelFile(visibleColumns) - } - - const createExcelFile = (columns) => { - // Extract and set the header - const header = columns.reduce((acc, col) => { - acc[col.field] = col.headerName || col.field // Use headerName or field as default - return acc - }, {}) - - // Map the data rows to match the extracted headers - const worksheetData = dataRow.map((row) => { - const filteredRow = {} - columns.forEach((col) => { - const headerName = header[col.field] - filteredRow[headerName] = row[col.field] - }) - return filteredRow - }) - - // Create a worksheet from the data - const ws = XLSX.utils.json_to_sheet(worksheetData) - - // Create a workbook and add the worksheet to it - const wb = XLSX.utils.book_new() - XLSX.utils.book_append_sheet(wb, ws, 'Sheet1') - - // Generate the Excel file as binary data - const excelFile = XLSX.write(wb, { bookType: 'xlsx', type: 'array' }) - - // Create a Blob for the Excel data - const blob = new Blob([excelFile], { - type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' - }) - - // Create a link element to trigger the download - const url = URL.createObjectURL(blob) - const link = document.createElement('a') - link.href = url - link.download = 'original-file.xlsx' // Original file name or any desired name - document.body.appendChild(link) - link.click() - document.body.removeChild(link) - URL.revokeObjectURL(url) // Clean up - } - - /** - * fonction qui envoye dans le back - */ - const handleImport = async () => { - // Code to handle file import (can open a file dialog or call handleFileChange) - - let response = await window.matieres.importExcel(files.path) - - console.log(response) - - if (response.message) { - setMessage(response.message) - } - - if (response.error) { - setIsinserted(true) - setOpen(true) - setTableData([]) - } else { - setIsinserted(false) - setOpen(true) - } - } - - /** - * hook to open modal - */ - const [open, setOpen] = useState(false) - - /** - * function to close modal - */ - const handleClose = () => setOpen(false) - - /** - * function to return the view Modal - * - * @returns {JSX} - */ - const modals = () => ( - - - {isInserted ? ( - - {' '} - Importation a été effectuée avec succès - - ) : ( - - {' '} - - L'importation n'a pas été effectuée -
- {message} -
-
- )} - - - -
-
- ) - - // Handle header name change for a specific field and auto-export to Excel - const handleHeaderChange = (field, newHeaderName) => { - setColumns((prevColumns) => - prevColumns.map((col) => (col.field === field ? { ...col, headerName: newHeaderName } : col)) - ) - } - - return ( -
- {modals()} -
-
-
-

- - Importation de données -

- - - -
-
-
- - {/* displaying */} - - -
- - -
- {error && ( - - {error} - - )} - {tableData.length > 0 && ( - -
- {/* Dropdowns for each column */} - {dynamicColumns.map((col) => ( - - {col.headerName} - - - ))} -
-
- -
-
- )} -
-
-
- ) -} - -export default ImportMatiere diff --git a/src/renderer/src/components/ImportNiveau.jsx b/src/renderer/src/components/ImportNiveau.jsx deleted file mode 100644 index 75221c1..0000000 --- a/src/renderer/src/components/ImportNiveau.jsx +++ /dev/null @@ -1,397 +0,0 @@ -import React, { useState } from 'react' -import classe from '../assets/AllStyleComponents.module.css' -import classeAdd from '../assets/AddStudent.module.css' -import classeHome from '../assets/Home.module.css' -import { Box, Button, Typography, ThemeProvider, Modal } from '@mui/material' -import { Link } from 'react-router-dom' -import { FaCloudDownloadAlt, FaCloudUploadAlt, FaFileExcel } from 'react-icons/fa' -import { IoMdReturnRight } from 'react-icons/io' -import { styled, createTheme } from '@mui/material/styles' -import * as XLSX from 'xlsx' -import Papa from 'papaparse' -import { DataGrid, GridToolbarContainer, GridToolbarColumnsButton } from '@mui/x-data-grid' -import { frFR } from '@mui/x-data-grid/locales' -import CustomBar from './CustomBar' -import dayjs from 'dayjs' -import svgSuccess from '../assets/success.svg' - -const ImportNiveau = () => { - const VisuallyHiddenInput = styled('input')({ - clip: 'rect(0 0 0 0)', - clipPath: 'inset(50%)', - height: 1, - overflow: 'hidden', - position: 'absolute', - bottom: 0, - left: 0, - whiteSpace: 'nowrap', - width: 1 - }) - - const [error, setError] = useState('') - const [tableData, setTableData] = useState([]) - const [files, setFiles] = useState() - const [header, setHeader] = useState([]) - let field = [] - - for (let index = 0; index < header.length; index++) { - field.push(header[index].toLowerCase().replace(/\s+/g, '_')) - } - - const dynamicColumns = header.map((col, index) => ({ - field: col.toLowerCase().replace(/\s+/g, '_'), // Converts the header text to field names (e.g., "Nom" -> "nom") - headerName: col, // Display the header as is - width: 150 // Adjust the width as needed - })) - - const theme = createTheme({ - components: { - MuiIconButton: { - styleOverrides: { - root: { - color: 'gray' // Toolbar icons color - } - } - }, - MuiButton: { - styleOverrides: { - root: { - color: '#121212' // Button text color - } - } - } - } - }) - - const paginationModel = { page: 0, pageSize: 5 } - - // Assuming `tableData` is an array where each entry corresponds to a student's data - const dataRow = tableData.map((etudiant, index) => { - // Dynamically create an object with fields from the header and data from `etudiant` - let row = { id: index + 1 } // Unique ID for each row - - field.forEach((fieldName, idx) => { - if (fieldName === 'date_de_naissance') { - row[fieldName] = dayjs(etudiant[idx]).format('DD-MM-YYYY') // Format date - } else { - row[fieldName] = etudiant[idx] // Assign value to field dynamically - } - }) - - return row - }) - - const handleFileChange = (event) => { - const file = event.target.files[0] - setFiles(event.target.files[0]) - if (!file) { - setError('No file selected') - return - } - - const fileExtension = file.name.split('.').pop().toLowerCase() - - if (fileExtension === 'xlsx') { - const reader = new FileReader() - reader.onload = (e) => { - const data = new Uint8Array(e.target.result) - const workbook = XLSX.read(data, { type: 'array' }) - - // Extract data from all sheets and combine - const allData = [] - workbook.SheetNames.forEach((sheetName) => { - const worksheet = workbook.Sheets[sheetName] - const rows = XLSX.utils.sheet_to_json(worksheet, { header: 1 }) - setHeader(rows[0]) // keep the header - allData.push(...rows.slice(1)) // Skip header row for each sheet - }) - setTableData(allData) - } - reader.readAsArrayBuffer(file) - } else if (fileExtension === 'csv') { - const reader = new FileReader() - reader.onload = (e) => { - Papa.parse(e.target.result, { - complete: (results) => { - setHeader(results.data[0]) // keep the header - setTableData(results.data.slice(1)) // Skip header row - }, - header: false - }) - } - reader.readAsText(file) - } else { - setError('Unsupported file format. Please upload .xlsx or .csv file.') - setTableData([]) - } - } - - const exemplaireFileExcel = [ - { - Nom: 'L1' - }, - { - Nom: 'L2' - }, - { - Nom: 'L3' - }, - { - Nom: 'M1' - }, - { - Nom: 'M2' - } - ] - - const convertToExcel = () => { - // convert json to sheet - const worksheet = XLSX.utils.json_to_sheet(exemplaireFileExcel) - - // Create a new workbook and append the worksheet - const workbook = XLSX.utils.book_new() - XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1') - - // Write the workbook to a Blob and create a download link - const excelBuffer = XLSX.write(workbook, { bookType: 'xlsx', type: 'array' }) - const data = new Blob([excelBuffer], { type: 'application/octet-stream' }) - const url = URL.createObjectURL(data) - - // Trigger a download - const link = document.createElement('a') - link.href = url - link.download = 'exemplaire_niveau.xlsx' - link.click() - - // Clean up - URL.revokeObjectURL(url) - } - - const handleColumnVisibilityChange = (model) => { - // Get the currently visible columns - const visibleColumns = dynamicColumns.filter((column) => model[column.field] !== false) - - // Create a new Excel file with visible columns - createExcelFile(visibleColumns) - } - - const createExcelFile = (columns) => { - // Extract and set the header - const header = columns.reduce((acc, col) => { - acc[col.field] = col.headerName || col.field // Use headerName or field as default - return acc - }, {}) - - // Map the data rows to match the extracted headers - const worksheetData = dataRow.map((row) => { - const filteredRow = {} - columns.forEach((col) => { - const headerName = header[col.field] - filteredRow[headerName] = row[col.field] - }) - return filteredRow - }) - - // Create a worksheet from the data - const ws = XLSX.utils.json_to_sheet(worksheetData) - - // Create a workbook and add the worksheet to it - const wb = XLSX.utils.book_new() - XLSX.utils.book_append_sheet(wb, ws, 'Sheet1') - - // Generate the Excel file as binary data - const excelFile = XLSX.write(wb, { bookType: 'xlsx', type: 'array' }) - - // Create a Blob for the Excel data - const blob = new Blob([excelFile], { - type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' - }) - - // Create a link element to trigger the download - const url = URL.createObjectURL(blob) - const link = document.createElement('a') - link.href = url - link.download = 'original-file.xlsx' // Original file name or any desired name - document.body.appendChild(link) - link.click() - document.body.removeChild(link) - URL.revokeObjectURL(url) // Clean up - } - - /** - * fonction qui envoye dans le back - */ - const handleImport = async () => { - // Code to handle file import (can open a file dialog or call handleFileChange) - - let response = await window.niveaus.importNiveau(files.path) - - console.log(response) - if (response.success) { - setOpen(true) - setTableData([]) - } - } - - /** - * hook to open modal - */ - const [open, setOpen] = useState(false) - - /** - * function to close modal - */ - const handleClose = () => setOpen(false) - - /** - * function to return the view Modal - * - * @returns {JSX} - */ - const modals = () => ( - - - - {' '} - Importation a été effectuée avec succès - - - - - - - ) - - return ( -
- {modals()} -
-
-
-

- - Importation de données -

- - - -
-
-
- - {/* displaying */} - - -
- - -
- {error && ( - - {error} - - )} - {tableData.length > 0 && ( - -
- -
-
- )} -
-
-
- ) -} - -export default ImportNiveau diff --git a/src/renderer/src/components/IpConfig.jsx b/src/renderer/src/components/IpConfig.jsx deleted file mode 100644 index a584651..0000000 --- a/src/renderer/src/components/IpConfig.jsx +++ /dev/null @@ -1,133 +0,0 @@ -import React, { useEffect, useState } from 'react' -import { - Dialog, - DialogActions, - DialogContent, - DialogTitle, - TextField, - Button, - InputAdornment, - Box, - Grid, - FormControl, - InputLabel, - Select, - OutlinedInput, - MenuItem -} from '@mui/material' - - -const IpConfig = ({ open, onClose }) => { - - const [localIp, setLocalIp] = useState(""); - const [formData, setFormData] = useState({ - ipname: "", - id: '', - }) - const [ip, setIp] = useState({}); - - useEffect(() => { - - window.notesysteme.getIPConfig().then((response) => { - setIp(response) - }) - - const getLocalIP = async () => { - const pc = new RTCPeerConnection(); - pc.createDataChannel(""); // Create a data channel - pc.createOffer().then((offer) => pc.setLocalDescription(offer)); - - pc.onicecandidate = (event) => { - if (event && event.candidate) { - const ipRegex = /([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})/; - const match = ipRegex.exec(event.candidate.candidate); - if (match) setLocalIp(match[1]); - pc.close(); - } - }; - }; - - getLocalIP(); - }, []); - - useEffect(() => { - if (ip) { - setFormData((prevData) => ({ - ...prevData, - ipname: ip.ipname, - id: ip.id - })) - } - - }, [ip]); - - const handleChange = (e) => { - const { name, value } = e.target - setFormData({ ...formData, [name]: value }) - } - - const formSubmit = async (e) => { - e.preventDefault() - - if (ip == undefined) { - let response = await window.notesysteme.createIPConfig(formData) - console.log('running the creation: ', response); - if (response.changes) { - window.notesysteme.getIPConfig().then((response) => { - setIp(response) - }) - onClose() - } - } else { - let response = await window.notesysteme.updateIPConfig(formData) - console.log('running the update: ', response); - if (response.changes) { - window.notesysteme.getIPConfig().then((response) => { - setIp(response) - }) - onClose() - } - } - - } - - return ( - -
- Configuration de l'adresse IP -
Votre Local IP: {localIp || "Detecting..."}
- - - - - - - - - - - - - -
-
- ) -} - -export default IpConfig diff --git a/src/renderer/src/components/Login.jsx b/src/renderer/src/components/Login.jsx deleted file mode 100644 index b8417d2..0000000 --- a/src/renderer/src/components/Login.jsx +++ /dev/null @@ -1,157 +0,0 @@ -import { useRef, useState } from 'react' -// import { Container, Row, Col, Form, Button, Card, InputGroup } from 'react-bootstrap'; -import { Container, Grid, Card, Typography, TextField, Button, InputAdornment } from '@mui/material' -import { 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 { ValidationLogin, invalidCredential } from './validation/Login' - -const Login = () => { - /** - * token from the AuthContext in the context folder - */ - const { setToken } = useAuthContext() - - /** - * hook to store our data from the input element - */ - const [username, setUsername] = useState() - const [password, setPassword] = useState() - - /** - * ref for our username and password input and the error span - */ - const userNameRef = useRef() - const passwordRef = useRef() - const userNameError = useRef() - const passwordError = useRef() - - /** - * function to send the data to the IPCRender - * and make login - * - * @param {any} e - */ - const formLogin = async (e) => { - e.preventDefault() - - let validate = ValidationLogin( - userNameRef.current, - passwordRef.current, - userNameError.current, - passwordError.current - ) - - if (validate) { - const response = await window.allUser.login({ username, password }) - - if (response.success) { - // Redirect to main window - setToken(JSON.stringify(response.user)) - } else { - invalidCredential(userNameError.current, response.error) - } - } - } - - return ( - - - - -
- -
- - Université de Toamasina - -
- - - - ) - }} - className={classe.input} - onChange={(e) => setUsername(e.target.value)} - 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 - } - } - }} - /> - - - - - ) - }} - onChange={(e) => setPassword(e.target.value)} - 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 - } - } - }} - /> - - - - -
- - Mot de passe oublié ? - -
- -
-
-
-
- ) -} - -export default Login diff --git a/src/renderer/src/components/Manuel.jsx b/src/renderer/src/components/Manuel.jsx deleted file mode 100644 index 3dff2f2..0000000 --- a/src/renderer/src/components/Manuel.jsx +++ /dev/null @@ -1,98 +0,0 @@ -import React, { useState } from 'react' -import { Box, Button, Typography, Grid, Paper } from '@mui/material' -import { GrManual } from 'react-icons/gr' -import { Document, Page } from 'react-pdf/dist/esm/entry.webpack5' -import { FaAngleDoubleLeft, FaAngleDoubleRight } from 'react-icons/fa' -import pdfUrl from '../assets/manuel.pdf' -import classe from '../assets/AllStyleComponents.module.css' -import classeAdd from '../assets/AddStudent.module.css' -import classeHome from '../assets/Home.module.css' - -const Manuel = () => { - const [numPages, setNumPages] = useState(null) // Use correct name - const [pageNumber, setPageNumber] = useState(1) - - // Fix the onDocumentSuccess function - function onDocumentSuccess({ numPages }) { - setNumPages(numPages) // Use the correct property - } - - const prevPage = () => { - if (pageNumber > 1) { - setPageNumber(pageNumber - 1) - } - } - - const nextPage = () => { - if (pageNumber < numPages) { - setPageNumber(pageNumber + 1) - } - } - - return ( -
-
-
-
-

- Manuel d'utilisation -

-
-
-
- - - - - - - - Page {pageNumber} sur {numPages} - - -
- Chargement du Manuel...
} - error={
Une erreur s'est produite lors du chargement du Manuel.
} - > - - -
- - - - - - - - ) -} - -export default Manuel diff --git a/src/renderer/src/components/Matieres.jsx b/src/renderer/src/components/Matieres.jsx deleted file mode 100644 index 340dff6..0000000 --- a/src/renderer/src/components/Matieres.jsx +++ /dev/null @@ -1,502 +0,0 @@ -import React, { useEffect, useRef, useState } from 'react' -import classe from '../assets/AllStyleComponents.module.css' -import classeAdd from '../assets/AddStudent.module.css' -import classeHome from '../assets/Home.module.css' -import { Link } from 'react-router-dom' -import { BsBookmarkPlusFill } from 'react-icons/bs' -import { - FaUserCircle, - FaBook, - FaUserCog, - FaTrash, - FaPlus, - FaRegPlusSquare, - FaNewspaper -} from 'react-icons/fa' -import { Box, Button, InputAdornment, Typography, Modal, TextField, Grid } from '@mui/material' -import Paper from '@mui/material/Paper' -import { createTheme, ThemeProvider } from '@mui/material/styles' -import { DataGrid, GridToolbar } from '@mui/x-data-grid' -import { frFR } from '@mui/x-data-grid/locales' -import { Fa1, Fa2, Fa3, FaM, FaP, FaPenToSquare, FaS } from 'react-icons/fa6' -import { Tooltip } from 'react-tooltip' -import warning from '../assets/warning.svg' -import success from '../assets/success.svg' -import { GiTeacher } from 'react-icons/gi' -import ModalAddProf from './ModalAddProf' -import ParcourMatiere from './ParcourMatiere' -import UpdateModalProf from './UpdateModalProf' -import ModalProcessFichePresence from './ModalProcessFichePresence' -import ModalExportFichr from './ModalExportFichr' - -const Matieres = () => { - const [matiere, setMatiere] = useState([]) - const [Enseignants, setEnseignants] = useState([]) - - useEffect(() => { - window.matieres.getMatiere().then((response) => { - setMatiere(response) - }) - - window.matieres.getENseignant().then((response) => { - setEnseignants(response) - }) - }, []) - - const theme = createTheme({ - components: { - MuiIconButton: { - styleOverrides: { - root: { - color: 'gray' // Change the color of toolbar icons - } - } - }, - MuiButton: { - styleOverrides: { - root: { - color: '#121212' // Change the color of toolbar icons - } - } - } - } - }) - - const [isDeleted, setIsDeleted] = useState(false) - const [ids, setIds] = useState(0) - - const columns = [ - { field: 'nom', headerName: 'Nom', width: 230 }, - { field: 'credit', headerName: 'Crédit', width: 80 }, - { field: 'heure', headerName: 'Heure', width: 80 }, - { field: 'uniter', headerName: "Unité d'enseignement", width: 180 }, - { field: 'ue', headerName: 'UE', width: 80 }, - { field: 'enseignant', headerName: 'Professeur actuele', width: 230 }, - { - field: 'action', - headerName: 'Action', - width: 600, - renderCell: (params) => ( -
- - - - - - - - - Assigner à un semestre - - - - openParcoursFunction(params.value)} - > - - Assigner à des parcours - - - - - - - - - - - - - Fiche de presence éxamen - - - - { - setIds(params.row.id) - setOpen(true) - }} - > - - -
- ) - } - ] - - const compareMatieres = (matiere_id) => { - let NomPrenom = '' - for (let index = 0; index < Enseignants.length; index++) { - if (Enseignants[index].matiere_id == matiere_id) { - NomPrenom = `${Enseignants[index].nom_enseignant} ${Enseignants[index].prenom_enseignant}` - } - } - - return NomPrenom - } - - const paginationModel = { page: 0, pageSize: 5 } - - let dataRow = matiere.map((mat) => ({ - id: mat.id, // Ensure this exists and is unique for each etudiant - nom: mat.nom, - credit: mat.credit, - heure: mat.heure, - uniter: mat.unite_enseignement, - ue: mat.ue, - enseignant: - compareMatieres(mat.id) != '' ? compareMatieres(mat.id) : 'Veuillez assigner un professeur', - action: mat.id // Ensure this is a valid URL for the image - })) - - const deleteButton = async (id) => { - let response = await window.matieres.deleteMatiere({ id }) - if (response.success) { - const updatedMatieres = matiere.filter((matiere) => matiere.id !== id) - setMatiere(updatedMatieres) - setIsDeleted(true) - } - } - - /** - * hook to open modal - */ - const [open, setOpen] = useState(false) - - /** - * function to close modal - */ - const handleClose = () => { - setOpen(false) - setIsDeleted(false) - } - - /** - * function to return the view Modal - * - * @returns {JSX} - */ - const modals = () => ( - - - {isDeleted ? ( - - Suprimer avec succèss - - ) : ( - - {' '} - Voulez vous supprimer ce matiere ? - - )} - - {isDeleted ? ( - - ) : ( -
- - -
- )} -
-
-
- ) - - const [openForm, setOpenForm] = useState(false) - const [matiereId, setMatiereId] = useState('') - const [isSubmitted, setIsSubmitted] = useState(false) - - // Callback function to receive the submission status - const handleFormSubmit = (status) => { - setIsSubmitted(status) - } - - useEffect(() => { - if (isSubmitted) { - window.matieres - .getMatiere() - .then((response) => { - setMatiere(response) - setIsSubmitted(false) // Reset isSubmitted after fetching data - }) - .catch((error) => { - console.error('Error fetching matiere:', error) - setIsSubmitted(false) // Ensure reset even on error - }) - - window.matieres.getENseignant().then((response) => { - setEnseignants(response) - }) - } - }, [isSubmitted]) - - const closeForm = () => { - setOpenForm(false) - } - - const openFormModal = (id) => { - setOpenForm(true) - setMatiereId(id) - } - - const [openParcours, setOpenParcours] = useState(false) - const onCloseParcours = () => setOpenParcours(false) - const [idToSend, setIdToSend] = useState(null) - const openParcoursFunction = (id) => { - setIdToSend(id) - setOpenParcours(true) - } - - const [openUppdateProf, setOpenUpdateProf] = useState(false) - const onCloseUpdateProf = () => setOpenUpdateProf(false) - const [idSends, setIdSend] = useState('') - const openUppdateProfFunction = (id) => { - setIdSend(id) - setOpenUpdateProf(true) - } - - const [openFiche, setOpenFiche] = useState(false) - const onCloseFiche = () => setOpenFiche(false) - const [dataFiche, setDataFiche] = useState(null) - const paperRef = useRef() - - // const extractFiche = async (matiere_id) => { - // let response = await - // setDataFiche(response) - // } - - return ( -
- {modals()} - - - - -
-
-
-

- - Matiere -

- - - -
-
-
- - {/* displaying data */} -
-
- - -
- -
-
-
-
-
-
- ) -} - -export default Matieres diff --git a/src/renderer/src/components/Mentions.jsx b/src/renderer/src/components/Mentions.jsx deleted file mode 100644 index 776f24f..0000000 --- a/src/renderer/src/components/Mentions.jsx +++ /dev/null @@ -1,261 +0,0 @@ -import React, { useEffect, useState } from 'react' -import classe from '../assets/AllStyleComponents.module.css' -import classeAdd from '../assets/AddStudent.module.css' -import classeHome from '../assets/Home.module.css' -import { Link } from 'react-router-dom' -import { Box, Button, InputAdornment, Typography, Modal, TextField, Grid } from '@mui/material' -import { BsBookmarkPlusFill } from 'react-icons/bs' -import { FaClipboardList, FaPenToSquare, FaTrash } from 'react-icons/fa6' -import Paper from '@mui/material/Paper' -import { createTheme, ThemeProvider } from '@mui/material/styles' -import { DataGrid, GridToolbar } from '@mui/x-data-grid' -import { frFR } from '@mui/x-data-grid/locales' -import { Tooltip } from 'react-tooltip' -import warning from '../assets/warning.svg' -import success from '../assets/success.svg' - -const Mentions = () => { - const theme = createTheme({ - components: { - MuiIconButton: { - styleOverrides: { - root: { - color: 'gray' // Change the color of toolbar icons - } - } - }, - MuiButton: { - styleOverrides: { - root: { - color: '#121212' // Change the color of toolbar icons - } - } - } - } - }) - - const [isDeleted, setIsDeleted] = useState(false) - const [ids, setIds] = useState(0) - - const [mentions, setMentions] = useState([]) - - useEffect(() => { - window.mention.getMention().then((response) => { - setMentions(response) - }) - }, []) - - const columns = [ - { field: 'nom', headerName: 'Nom', width: 350 }, - { field: 'uniter', headerName: 'Unité ', width: 180 }, - { - field: 'action', - headerName: 'Action', - flex: 1, - renderCell: (params) => ( -
- - - - { - setIds(params.row.id) - setOpen(true) - }} - > - - -
- ) - } - ] - - const paginationModel = { page: 0, pageSize: 5 } - - const dataRow = mentions.map((men) => ({ - id: men.id, // Ensure this exists and is unique for each etudiant - nom: men.nom, - uniter: men.uniter, - action: men.id // Ensure this is a valid URL for the image - })) - - const deleteButton = async (id) => { - let response = await window.mention.deleteMention({ id }) - if (response.success) { - const updatedMentions = mentions.filter((mention) => mention.id !== id) - setMentions(updatedMentions) - setIsDeleted(true) - } - } - - /** - * hook to open modal - */ - const [open, setOpen] = useState(false) - - /** - * function to close modal - */ - const handleClose = () => { - setOpen(false) - setIsDeleted(false) - } - - /** - * function to return the view Modal - * - * @returns {JSX} - */ - const modals = () => ( - - - {isDeleted ? ( - - Suprimer avec succèss - - ) : ( - - {' '} - Voulez vous supprimer ce mention ? - - )} - - {isDeleted ? ( - - ) : ( -
- - -
- )} -
-
-
- ) - - return ( -
- {modals()} -
-
-
-

- - Mentions -

- - - -
-
-
- - {/* displaying data */} -
-
- - - - - -
-
-
- ) -} - -export default Mentions diff --git a/src/renderer/src/components/ModalAddEtudiants.jsx b/src/renderer/src/components/ModalAddEtudiants.jsx deleted file mode 100644 index c4ce7bf..0000000 --- a/src/renderer/src/components/ModalAddEtudiants.jsx +++ /dev/null @@ -1,343 +0,0 @@ -import React, { useRef, useState } from 'react' -import { - Modal, - Box, - Typography, - Button, - InputAdornment, - TextField, - Card, - Grid, - Container -} from '@mui/material' -import { - FaUser, - FaIdBadge, - FaBirthdayCake, - FaGraduationCap, - FaCalendarAlt, - FaFileUpload -} from 'react-icons/fa' - -const ModalAddEtudiants = ({ open, handleClose }) => { - /** - * hook for storing data in the input - */ - const [formData, setFormData] = useState({ - nom: '', - prenom: '', - photos: null, - date_de_naissances: '', - niveau: '', - annee_scolaire: '', - num_inscription: '' - }) - - /** - * ref for each input - */ - const nomRef = useRef() - const prenomRef = useRef() - const date_de_naissancesRef = useRef() - const niveauRef = useRef() - const annee_scolaireRef = useRef() - const numero_inscriptionRef = useRef() - const photosRef = useRef() - - /** - * function to set the data in state - * @param {*} e - */ - const handleInputChange = (e) => { - const { name, value } = e.target - setFormData((prevData) => ({ - ...prevData, - [name]: value - })) - } - - const handleFileChange = (e) => { - let img_file = e.target.files[0] - const reader = new FileReader() - reader.readAsDataURL(img_file) - reader.onload = (ev) => { - const url = ev.target.result - // initialisation de nouvelle imageURL - const image = document.createElement('img') - image.src = url - - // create a new image - image.onload = (event) => { - let canvas = document.createElement('canvas') - let ratio = 250 / event.target.width - canvas.width = 250 - canvas.height = event.target.height * ratio - const context = canvas.getContext('2d') - context.drawImage(image, 0, 0, canvas.width, canvas.height) - - // new url - const new_URL = canvas.toDataURL('image/jpeg', 90) - // rendement de l'url a notre variable global - setFormData((prevData) => ({ - ...prevData, - photos: new_URL - })) - } - } - } - - const handleSubmit = async (e) => { - e.preventDefault() - // Handle form submission logic - const response = await window.etudiants.insertEtudiant(formData) - console.log(response) - } - - return ( - - - - Ajoutez un etudiants - - -
- - {/* Nom and Prenom Fields */} - - - - - ) - }} - inputRef={nomRef} - sx={{ - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: 'rgb(156, 39, 176)' // Set the border color on hover - } - } - }} - /> - - - - - - ) - }} - inputRef={prenomRef} - sx={{ - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: 'rgb(156, 39, 176)' // Set the border color on hover - } - } - }} - /> - - - {/* Date de Naissance and Niveau Fields */} - - - - - ) - }} - inputRef={date_de_naissancesRef} - sx={{ - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: 'rgb(156, 39, 176)' // Set the border color on hover - } - } - }} - /> - - - - - - ) - }} - inputRef={niveauRef} - sx={{ - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: 'rgb(156, 39, 176)' // Set the border color on hover - } - } - }} - /> - - - {/* Année Scolaire and Numéro d'Inscription Fields */} - - - - - ) - }} - inputRef={annee_scolaireRef} - sx={{ - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: 'rgb(156, 39, 176)' // Set the border color on hover - } - } - }} - /> - - - - - - ) - }} - inputRef={numero_inscriptionRef} - sx={{ - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: 'rgb(156, 39, 176)' // Set the border color on hover - } - } - }} - /> - - - {/* Photos Field */} - - - - - ) - }} - InputLabelProps={{ - shrink: true - }} - inputRef={photosRef} - sx={{ - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: 'rgb(156, 39, 176)' // Set the border color on hover - } - } - }} - /> - - - {/* Submit Button */} - - - - - -
-
-
-
- ) -} - -export default ModalAddEtudiants diff --git a/src/renderer/src/components/ModalAddProf.jsx b/src/renderer/src/components/ModalAddProf.jsx deleted file mode 100644 index 2a4c837..0000000 --- a/src/renderer/src/components/ModalAddProf.jsx +++ /dev/null @@ -1,178 +0,0 @@ -import React, { useEffect, useRef, useState } from 'react' -import { - Dialog, - DialogActions, - DialogContent, - DialogTitle, - TextField, - Button, - InputAdornment, - Box, - Grid -} from '@mui/material' -import ChangeCapital from './function/ChangeCapitalLetter' -import ChangeCapitalize from './function/ChangeCapitalizeLetter' -import { PiChalkboardTeacher } from 'react-icons/pi' -import { MdContactPhone, MdDateRange } from 'react-icons/md' - -const ModalAddProf = ({ open, onClose, matiere_id, onSubmitSuccess }) => { - const [formData, setFormData] = useState({ - nom_enseignant: '', - prenom_enseignant: '', - contact: '', - date: '', - matiere_id: '' - }) - - const nomRefs = useRef() - const prenomRefs = useRef() - - const handleChange = (e) => { - const { name, value } = e.target - setFormData({ ...formData, [name]: value }) - } - - useEffect(() => { - setFormData((prev) => ({ - ...prev, - matiere_id: matiere_id - })) - }, [matiere_id]) - - const handleSubmit = async (e) => { - e.preventDefault() - let response = await window.matieres.insertProf(formData) - console.log(response) - - if (response.success) { - onSubmitSuccess(true) - onClose() // Close the modal after submission - setFormData({ - nom_enseignant: '', - prenom_enseignant: '', - contact: '', - date: '', - matiere_id: '' - }) - } - } - - return ( - -
- Information sur enseignant - - - - - ChangeCapital(nomRefs)} - onChange={handleChange} - InputProps={{ - startAdornment: ( - - - - ) - }} - /> - - - ChangeCapitalize(prenomRefs)} - onChange={handleChange} - InputProps={{ - startAdornment: ( - - - - ) - }} - /> - - - - - - ) - }} - /> - - - - - - ) - }} - /> - - - - - - - - -
-
- ) -} - -export default ModalAddProf diff --git a/src/renderer/src/components/ModalCertificate.jsx b/src/renderer/src/components/ModalCertificate.jsx deleted file mode 100644 index d513be3..0000000 --- a/src/renderer/src/components/ModalCertificate.jsx +++ /dev/null @@ -1,97 +0,0 @@ -import React, { useState } from 'react' -import { Dialog, DialogActions, DialogContent, DialogTitle, TextField, Button } from '@mui/material' -import PDFEditorCertificat from './function/PDFEditorCertificate' - -const ModalCertificate = ({ open, onClose, json }) => { - const [formData, setFormData] = useState({ - pere: '', - mere: '', - chefService: '' - }) - - const handleChange = (e) => { - const { name, value } = e.target - setFormData({ ...formData, [name]: value }) - } - - const handleSubmit = (e) => { - e.preventDefault() - console.log('Form submitted:', formData, json) - let data = { - f1: json.nomPrenom, - f2: json.naissances, - f3: formData.pere, - f4: formData.mere, - f5: json.niveau, - f6: json.mention, - f7: json.inscri, - f8: json.annee, - f9: formData.chefService - } - // Handle the form submission (e.g., send to a server or process data) - PDFEditorCertificat(data) - setFormData({ - mere: '', - pere: '', - chefService: '' - }) - onClose() // Close the modal after submission - } - - return ( - -
- Informations sur l'élève - - - - - - - - - -
-
- ) -} - -export default ModalCertificate diff --git a/src/renderer/src/components/ModalExportFichr.jsx b/src/renderer/src/components/ModalExportFichr.jsx deleted file mode 100644 index f7f33aa..0000000 --- a/src/renderer/src/components/ModalExportFichr.jsx +++ /dev/null @@ -1,220 +0,0 @@ -import React, { useEffect, useRef, useState } from 'react' -import { Link, useParams } from 'react-router-dom' -import classe from '../assets/AllStyleComponents.module.css' -import classeAdd from '../assets/AddStudent.module.css' -import classeHome from '../assets/Home.module.css' -import { FaBook, FaDownload } from 'react-icons/fa' -import { IoMdReturnRight } from 'react-icons/io' -import { Box, Button, Typography, ThemeProvider, Modal } from '@mui/material' -import Paper from '@mui/material/Paper' -import html2cancas from 'html2canvas' -import jsPDF from 'jspdf' -import autoTable from 'jspdf-autotable' - -const ModalExportFichr = () => { - const [fiche, setFiche] = useState([]) - const [mentions, setMentions] = useState([]) - const PaperRef = useRef() - - let { matiere_id } = useParams() - let { nom } = useParams() - - useEffect(() => { - if (matiere_id !== null && matiere_id !== undefined) { - window.notesysteme.extractFiches({ matiere_id }).then((response) => { - setFiche(response) - }) - } - window.mention.getMention().then((response) => { - setMentions(response) - }) - }, [matiere_id]) - - // Sort by NomPrenom alphabetically - const sortedStudents = fiche.sort((a, b) => a.nom.localeCompare(b.nom)) - - function compareMention(id) { - let mentionText - mentions.map((ment) => { - if (id == ment.id) { - mentionText = ment.nom - } - }) - - return mentionText - } - - // const download = () => { - // const generatePDF = async () => { - // try { - // await new Promise((resolve) => setTimeout(resolve, 500)); - - // const canvas = await html2cancas(PaperRef.current, { - // scale: 2, - // useCORS: true, - // logging: false, - // backgroundColor: "#ffffff", - // imageTimeout: 0, // ⬅️ Prevent timeout errors - // }); - - // const imgData = canvas.toDataURL("image/jpeg", 0.8); // Use JPEG for smaller size - // const pdf = new jsPDF({ - // orientation: "portrait", - // unit: "mm", - // format: "a4", - // compress: true, - // }); - - // let imgWidth = 210; - // let imgHeight = (canvas.height * imgWidth) / canvas.width; - // let yPosition = 0; - - // // If image height is greater than A4 page height, add multiple pages - // while (yPosition < imgHeight) { - // pdf.addImage(imgData, "JPEG", 0, yPosition * -1, imgWidth, imgHeight); - // if (yPosition + 297 < imgHeight) pdf.addPage(); // A4 height = 297mm - // yPosition += 297; - // } - - // pdf.save("document.pdf"); - - // } catch (error) { - // console.error("Error generating PDF:", error); - // } - // }; - // generatePDF(); - // } - - const download = () => { - const generatePDF = () => { - try { - const pdf = new jsPDF({ - orientation: 'portrait', - unit: 'mm', - format: 'a4' - }) - - // Select the table - autoTable(pdf, { - html: '#myTable', // ID de la table - startY: 20, - theme: 'grid', - headStyles: { - fillColor: 'gray', - halign: 'center', - fontStyle: 'bold', - textColor: 'black' - }, // Supprimer la couleur et centrer - margin: { top: 10 }, - styles: { fontSize: 8, cellPadding: 2, halign: 'center' }, // Centrer le texte des cellules - didDrawPage: (data) => { - pdf.text('', 14, 10) - } - }) - - pdf.save('document.pdf') - } catch (error) { - console.error('Error generating PDF:', error) - } - } - generatePDF() - } - - return ( -
-
-
-
-

- - Matiere -

-
- - - - - - -
-
-
-
- -
- -
- - - - - - - - - - - - - - {sortedStudents.map((fi, index) => ( - - - - - - - ))} - -
{nom}
Nom et PrénomMentionEmergement
- {index + 1} - - {fi.nom} {fi.prenom} - - {compareMention(fi.mention_id)} -
-
-
-
-
- ) -} - -export default ModalExportFichr diff --git a/src/renderer/src/components/ModalFormMultiplicateur.jsx b/src/renderer/src/components/ModalFormMultiplicateur.jsx deleted file mode 100644 index d3bdd92..0000000 --- a/src/renderer/src/components/ModalFormMultiplicateur.jsx +++ /dev/null @@ -1,89 +0,0 @@ -import React, { useEffect, useState } from 'react' -import { - Dialog, - DialogActions, - DialogContent, - DialogTitle, - TextField, - Button, - InputAdornment -} from '@mui/material' -import { FaTimes } from 'react-icons/fa' - -const ModalFormMultiplicateur = ({ open, onClose }) => { - const [formData, setFormData] = useState({ - id: '', - multiplicateur: '' - }) - - const [Multiplicateur, setMultiplicateur] = useState(0) - - useEffect(() => { - window.matieres.getNessesary().then((response) => { - setMultiplicateur(response) - }) - }, []) - - useEffect(() => { - setFormData((prev) => ({ - ...prev, - id: Multiplicateur.id, - multiplicateur: Multiplicateur.uniter_heure - })) - }, [Multiplicateur]) - - const handleChange = (e) => { - const { name, value } = e.target - setFormData({ ...formData, [name]: value }) - } - - const handleSubmit = async (e) => { - e.preventDefault() - console.log(formData) - let response = await window.matieres.updateNessesary(formData) - - if (response.success) { - onClose() // Close the modal after submission - } - } - - return ( - -
- Changer le multiplicateur - - - - - ) - }} - /> - - - - - -
-
- ) -} - -export default ModalFormMultiplicateur diff --git a/src/renderer/src/components/ModalProcessFichePresence.jsx b/src/renderer/src/components/ModalProcessFichePresence.jsx deleted file mode 100644 index 5dd8285..0000000 --- a/src/renderer/src/components/ModalProcessFichePresence.jsx +++ /dev/null @@ -1,54 +0,0 @@ -import React, { useState } from 'react' -import { - Dialog, - DialogActions, - DialogContent, - DialogTitle, - TextField, - Button, - InputAdornment, - Box, - Grid -} from '@mui/material' -import { PiChalkboardTeacher } from 'react-icons/pi' - -const ModalProcessFichePresence = ({ open, onClose, matiere_id }) => { - const [formData, setFormData] = useState({ - matiere: '' - }) - return ( - - Option sur la la fiches - - - - - - - - ) - }} - /> - - - - - - ) -} - -export default ModalProcessFichePresence diff --git a/src/renderer/src/components/ModalRecepice.jsx b/src/renderer/src/components/ModalRecepice.jsx deleted file mode 100644 index 2f27cc0..0000000 --- a/src/renderer/src/components/ModalRecepice.jsx +++ /dev/null @@ -1,66 +0,0 @@ -import React, { useState } from 'react' -import { Dialog, DialogActions, DialogContent, DialogTitle, TextField, Button } from '@mui/material' -import PDFEditorRecepice from './function/PDFEditorRecepisse' - -const ModalRecepice = ({ open, onClose, json }) => { - const [formData, setFormData] = useState({ - nom: '' - }) - - const handleChange = (e) => { - const { name, value } = e.target - setFormData({ ...formData, [name]: value }) - } - - const handleSubmit = (e) => { - e.preventDefault() - console.log('Form submitted:', formData) - let data = { - f1: json.mention, - f2: json.niveau, - f3: json.nomPrenom, - f4: json.inscri, - f6: json.annee, - f7: formData.nom - } - // Handle the form submission (e.g., send to a server or process data) - PDFEditorRecepice(data) - setFormData({ - nom: '' - }) - onClose() // Close the modal after submission - } - - return ( - -
- Informations suplementaire - - - - - - - -
-
- ) -} - -export default ModalRecepice diff --git a/src/renderer/src/components/ModalStage.jsx b/src/renderer/src/components/ModalStage.jsx deleted file mode 100644 index 105fdc5..0000000 --- a/src/renderer/src/components/ModalStage.jsx +++ /dev/null @@ -1,84 +0,0 @@ -import React, { useRef, useState } from 'react' -import { Dialog, DialogActions, DialogContent, DialogTitle, TextField, Button } from '@mui/material' -import PDFEditorStage from './function/PDFEditorStage' -import ChangeCapital from './function/ChangeCapitalLetter' -import ChangeCapitalize from './function/ChangeCapitalizeLetter' - -const ModalStage = ({ open, onClose }) => { - const [formData, setFormData] = useState({ - nom: '', - prenom: '' - }) - - const handleChange = (e) => { - const { name, value } = e.target - setFormData({ ...formData, [name]: value }) - } - - const handleSubmit = (e) => { - e.preventDefault() - console.log('Form submitted:', formData) - let data = { - f1: formData.nom + ' ' + formData.prenom - } - // Handle the form submission (e.g., send to a server or process data) - PDFEditorStage(data) - setFormData({ - nom: '', - prenom: '' - }) - onClose() // Close the modal after submission - } - - const nomRef = useRef() - const prenomRef = useRef() - - return ( - -
- Informations suplementaire - - ChangeCapital(nomRef)} - color="warning" - onChange={handleChange} - /> - ChangeCapitalize(prenomRef)} - color="warning" - onChange={handleChange} - /> - - - - - -
-
- ) -} - -export default ModalStage diff --git a/src/renderer/src/components/ModalUpdateParcoursEtudiant.jsx b/src/renderer/src/components/ModalUpdateParcoursEtudiant.jsx deleted file mode 100644 index 642033a..0000000 --- a/src/renderer/src/components/ModalUpdateParcoursEtudiant.jsx +++ /dev/null @@ -1,107 +0,0 @@ -import React, { useEffect, useState } from 'react' -import { - Dialog, - DialogActions, - DialogContent, - DialogTitle, - TextField, - Button, - Autocomplete, - InputAdornment -} from '@mui/material' -import { MdRule } from 'react-icons/md' - -const ModalUpdateParcoursEtudiant = ({ open, onClose, user_id, onSubmit }) => { - const [formData, setFormData] = useState({ - parcours: '', - user_id: '' - }) - const [parcours, setParcours] = useState([]) - - useEffect(() => { - window.notesysteme.getParcours().then((response) => { - setParcours(response) - }) - }, []) - - useEffect(() => { - if (user_id) { - setFormData((prevData) => ({ - ...prevData, - user_id: user_id - })) - } - }, [user_id]) - - const handleSubmit = async (e) => { - e.preventDefault() - - let response = await window.etudiants.changeParcours(formData) - - if (response.changes) { - onSubmit(true, formData.parcours) - onClose() - } - } - - return ( - -
- Ajouter un parcours - - option.nom || ''} // Display `nom` - value={parcours.find((item) => item.nom === formData.parcours) || null} // Find selected option based on `nom` - onChange={(event, newValue) => { - setFormData((prevData) => ({ - ...prevData, - parcours: newValue ? newValue.nom : '' // Store only `nom` - })) - }} - size="small" - isOptionEqualToValue={(option, value) => option.nom === value?.nom} // Ensure correct matching - renderInput={(params) => ( - - - - - {params.InputProps.startAdornment} - - ) - }} - sx={{ - marginBottom: '5px', - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800' // Set border color on hover - } - } - }} - /> - )} - /> - - - - - -
-
- ) -} - -export default ModalUpdateParcoursEtudiant diff --git a/src/renderer/src/components/Navbar.jsx b/src/renderer/src/components/Navbar.jsx deleted file mode 100644 index f79aaea..0000000 --- a/src/renderer/src/components/Navbar.jsx +++ /dev/null @@ -1,140 +0,0 @@ -import React, { useState } from 'react' -import classe from '../assets/Navbar.module.css' -import icon from '../assets/logo.ico' -import { FaTimes, FaRegWindowMinimize } from 'react-icons/fa' -import { useAuthContext } from '../contexts/AuthContext' -import { Modal, Box, Typography, Button } from '@mui/material' -import { useNavigate } from 'react-router-dom' - -const Navbar = () => { - const { token, setToken } = useAuthContext() - const navigate = useNavigate() - - /** - * function to quit app - */ - const quitApp = () => { - if (token !== null) { - setOpen(true) - } else { - quit() - } - } - - /** - * function to minimize the app - * if the user try to open something - * in the desktop - */ - const minimize = async () => { - await window.allUser.minimize() - } - - /** - * hook to open modal - */ - const [open, setOpen] = useState(false) - - /** - * function to close modal - */ - const handleClose = () => setOpen(false) - - /** - * function to quit - */ - const quit = async () => { - await window.allUser.quit() - } - - /** - * function after user click yes button in the modal - */ - const logoutAndQuit = () => { - localStorage.removeItem('ACCESS_TOKEN') - setToken(null) - navigate('/login') - quit() - } - - /** - * function to return the view Modal - * - * @returns {JSX} - */ - const modals = () => ( - - - - Notification - - - Déconnecter et quitter ? - - - - - - - - ) - - return ( - <> -
- {modals()} -
- - Université de Toamasina -
-
- - -
-
- - ) -} - -export default Navbar diff --git a/src/renderer/src/components/Niveau.jsx b/src/renderer/src/components/Niveau.jsx deleted file mode 100644 index c43a1f1..0000000 --- a/src/renderer/src/components/Niveau.jsx +++ /dev/null @@ -1,264 +0,0 @@ -import React, { useEffect, useState } from 'react' -import { Link } from 'react-router-dom' -import { createTheme, ThemeProvider } from '@mui/material/styles' -import { DataGrid } from '@mui/x-data-grid' -import { frFR } from '@mui/x-data-grid/locales' -import Paper from '@mui/material/Paper' -import { Box, Button, InputAdornment, Typography, Modal, TextField, Grid } from '@mui/material' -import classe from '../assets/AllStyleComponents.module.css' -import classeHome from '../assets/Home.module.css' -import { GiUpgrade } from 'react-icons/gi' -import { FaPenToSquare, FaTrash } from 'react-icons/fa6' -import { Tooltip } from 'react-tooltip' -import warning from '../assets/warning.svg' -import success from '../assets/success.svg' - -const Niveau = () => { - const [niveaus, setNiveau] = useState([]) - - useEffect(() => { - window.niveaus.getNiveau().then((response) => { - setNiveau(response) - }) - }, []) - - const [isDeleted, setIsDeleted] = useState(false) - const [ids, setIds] = useState(0) - - const columns = [ - { field: 'nom', headerName: 'Nom', width: 200 }, - { - field: 'action', - headerName: 'Action', - flex: 1, - renderCell: (params) => ( -
- - - - { - setIds(params.row.id) - setOpen(true) - }} - > - - -
- ) - } - ] - - const paginationModel = { page: 0, pageSize: 5 } - - const dataRow = niveaus.map((niveau) => ({ - id: niveau.id, - nom: niveau.nom, - action: niveau.id - })) - - const theme = createTheme({ - components: { - MuiIconButton: { - styleOverrides: { - root: { - color: 'gray' // Change the color of toolbar icons - } - } - }, - MuiButton: { - styleOverrides: { - root: { - color: '#121212' // Change the color of toolbar icons - } - } - } - } - }) - - /** - * hook to open modal - */ - const [open, setOpen] = useState(false) - - /** - * function to close modal - */ - const handleClose = () => { - setOpen(false) - setIsDeleted(false) - } - - const deleteButton = async (id) => { - let response = await window.niveaus.deleteNiveaus({ id }) - console.log(response); - - if (response.success) { - const updatedNiveaus = niveaus.filter((niveau) => niveau.id !== id) - setNiveau(updatedNiveaus) - setIsDeleted(true) - } - } - - /** - * function to return the view Modal - * - * @returns {JSX} - */ - const modals = () => ( - - - {isDeleted ? ( - - Suprimer avec succèss - - ) : ( - - {' '} - Voulez vous supprimer ce niveau ? - - )} - - {isDeleted ? ( - - ) : ( -
- - -
- )} -
-
-
- ) - - return ( -
- {modals()} -
-
-
-

Niveau

- - - -
-
-
- - {/* display the data-grid niveau */} -
-
- - -
- -
-
-
-
-
-
- ) -} - -export default Niveau diff --git a/src/renderer/src/components/NotFound.jsx b/src/renderer/src/components/NotFound.jsx deleted file mode 100644 index 7d84918..0000000 --- a/src/renderer/src/components/NotFound.jsx +++ /dev/null @@ -1,11 +0,0 @@ -import React from 'react' - -const NotFound = () => { - return ( -
-

404 Not Found

-
- ) -} - -export default NotFound diff --git a/src/renderer/src/components/Noteclasse.jsx b/src/renderer/src/components/Noteclasse.jsx deleted file mode 100644 index 3a6d73f..0000000 --- a/src/renderer/src/components/Noteclasse.jsx +++ /dev/null @@ -1,372 +0,0 @@ -import React, { useEffect, useState } from 'react' -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 { DataGrid, GridToolbar } from '@mui/x-data-grid' -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 { Tooltip } from 'react-tooltip' -import ReleverNotes from './ReleverNotes' -import { FaDownload } from 'react-icons/fa' - -const Noteclasse = () => { - const { niveau, scolaire } = useParams() - - const [etudiants, setEtudiants] = useState([]) - const [mention, setMention] = useState([]) - const [session, setSession] = useState([]) - - const formData = { - niveau, - scolaire - } - - useEffect(() => { - window.notes.getMoyenne(formData).then((response) => { - setEtudiants(response) - }) - window.noteRepech.getMoyenneRepech(formData).then((response) => { - setSession(response) - }) - window.mention.getMention().then((response) => { - setMention(response) - }) - }, []) - - let dataToMap = [] - - function returnmention(id) { - let mentions - for (let index = 0; index < mention.length; index++) { - if (mention[index].id == id) { - mentions = mention[index].nom - } - } - return mentions - } - - function checkNull(params) { - if (params == null || params == undefined) { - return null - } - return params - } - - function compareSessionNotes(session1, session2) { - let notes - if (session2) { - if (session1 < session2.note) { - notes = session2.note - } else { - notes = session1 - } - } else { - notes = session1 - } - return notes - } - - for (let index = 0; index < etudiants.length; index++) { - let total = 0 - let note = 0 - let totalCredit = 0 - - // Create a new object for each student - let modelJson = { - id: '', - nom: '', - prenom: '', - photos: '', - moyenne: '', - mention: '', - anneescolaire: '' - } - - for (let j = 0; j < etudiants[index].length; j++) { - modelJson.id = etudiants[index][j].etudiant_id - modelJson.nom = etudiants[index][j].nom - modelJson.prenom = etudiants[index][j].prenom - modelJson.photos = etudiants[index][j].photos - modelJson.mention = etudiants[index][j].mention_id - modelJson.anneescolaire = etudiants[index][j].annee_scolaire - - // console.log(checkNull(session[index][j])); - 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 - } - totalCredit += etudiants[index][j].credit - } - - total = note / totalCredit - modelJson.moyenne = total.toFixed(2) - - // Add the new object to the array - dataToMap.push(modelJson) - } - - function checkNumberSession(id) { - let sessionNumber - 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 - } - } - } - return sessionNumber - } - - const theme = createTheme({ - components: { - MuiIconButton: { - styleOverrides: { - root: { - color: 'gray' // Change the color of toolbar icons - } - } - }, - MuiButton: { - styleOverrides: { - root: { - color: '#121212' // Change the color of toolbar icons - } - } - } - } - }) - - const paginationModel = { page: 0, pageSize: 5 } - - const columns = [ - { field: 'nom', headerName: 'Nom', width: 170 }, - { field: 'prenom', headerName: 'Prenom', 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 }, - { - field: 'photos', - headerName: 'Photos', - width: 100, - renderCell: (params) => ( - {'image - ) - }, - { - field: 'action', - headerName: 'Action', - flex: 1, - renderCell: (params) => ( -
- sendData(params.value)}> - {/* */} - - - Imprimer un relevé de notes - - -
- ) - } - ] - - const dataTable = dataToMap.map((data) => ({ - id: data.id, - nom: data.nom, - prenom: data.prenom, - photos: data.photos, - mention: returnmention(data.mention), - session: checkNumberSession(data.id), - moyenne: data.moyenne, - action: data.id - })) - - const [openCard, setOpenCart] = useState(false) - const [bolll, setBolll] = useState(false) - const [form, setForm] = useState({ - id: '', - niveau: '', - anneescolaire: '' - }) - const [selectedId, setSelectedId] = useState(null) // Store id dynamically - - const sendData = (id) => { - setSelectedId(id) - // if (selectedId !== null) { - setOpenCart(true) - // } - } - - useEffect(() => { - if (selectedId !== null) { - const foundData = dataToMap.find((item) => item.id === selectedId) - if (foundData) { - setForm((prevForm) => ({ - ...prevForm, - id: foundData.id, - anneescolaire: foundData.anneescolaire, - niveau: niveau - })) // Update form with the found object - } - } - }, [openCard, selectedId]) - console.log(form) - const downloadButton = () => { - setBolll(true) - } - - /** - * function to close modal - */ - const handleCloseCart = () => { - setBolll(false) - setOpenCart(false) - } - - const modalReleverNotes = () => { - return ( - - - - - - - - ) - } - - return ( -
- {modalReleverNotes()} -
-
-
-

- Notes des {niveau} en {scolaire} -

-
- - - - window.history.back()}> - - -
-
-
-
- -
-
- - -
- -
-
-
-
-
-
- ) -} - -export default Noteclasse diff --git a/src/renderer/src/components/Notes.jsx b/src/renderer/src/components/Notes.jsx deleted file mode 100644 index 173a2c9..0000000 --- a/src/renderer/src/components/Notes.jsx +++ /dev/null @@ -1,176 +0,0 @@ -import React, { useEffect, useState } from 'react' -import { Button } from '@mui/material' -import { createTheme, ThemeProvider } from '@mui/material/styles' -import { IoEyeSharp } from 'react-icons/io5' -import { frFR } from '@mui/x-data-grid/locales' -import { Tooltip } from 'react-tooltip' -import Paper from '@mui/material/Paper' -import { DataGrid, GridToolbar } from '@mui/x-data-grid' -import classe from '../assets/AllStyleComponents.module.css' -import classeHome from '../assets/Home.module.css' -import { Link } from 'react-router-dom' - -const Notes = () => { - const theme = createTheme({ - components: { - MuiIconButton: { - styleOverrides: { - root: { - color: 'gray' // Change the color of toolbar icons - } - } - }, - MuiButton: { - styleOverrides: { - root: { - color: '#121212' // Change the color of toolbar icons - } - } - } - } - }) - - const paginationModel = { page: 0, pageSize: 5 } - - const columns = [ - { field: 'niveau', headerName: 'Niveau', width: 170 }, - { field: 'annee_scolaire', headerName: 'Année scolaire', width: 160 }, - // { field:'moyenne', headerName:'Moyenne de classe', width:160}, - { - field: 'action', - headerName: 'Action', - flex: 1, - renderCell: (params) => ( -
- - - - Voir tous les etudiants dans ce niveau - - -
- ) - } - ] - - /** - * hook for dispplaying note - */ - const [blockNotes, SetBlockNotes] = useState([]) - - useEffect(() => { - window.notes.getblockNote().then((response) => { - SetBlockNotes(response) - }) - }, []) - - const calculMoyenneDeClasse = (L1, annee) => { - let data = blockNotes.allData - let note = 0 - let someId = [] - let total = 0 - let totalEtudiant = [] - let id = [] - let totalCredit = 0 - - if (data != undefined) { - for (let index = 0; index < data.length; index++) { - for (let j = 0; j < data[index].length; j++) { - if (data[index][j].niveau == L1 && data[index][j].annee_scolaire == annee) { - totalEtudiant.push(data[index][j]) - } - } - } - } - - for (let index = 0; index < totalEtudiant.length; index++) { - someId.push(totalEtudiant[index].etudiant_id) - id = [...new Set(someId)] - note += totalEtudiant[index].note * totalEtudiant[index].credit - totalCredit += totalEtudiant[index].credit - } - total = note / totalCredit - - return total.toFixed(2) - } - - let dataRow - if (blockNotes.response) { - dataRow = blockNotes.response.map((note, index) => ({ - id: index, - niveau: note.etudiant_niveau, - moyenne: calculMoyenneDeClasse(note.etudiant_niveau, note.annee_scolaire), - annee_scolaire: note.annee_scolaire, - action: note.niveau - })) - } else { - dataRow = [] - } - - return ( -
-
-
-
-

Notes

-
-
-
- - {/* display the data-grid students */} -
-
- - -
- -
-
-
-
-
-
- ) -} - -export default Notes diff --git a/src/renderer/src/components/Param.jsx b/src/renderer/src/components/Param.jsx deleted file mode 100644 index af91a41..0000000 --- a/src/renderer/src/components/Param.jsx +++ /dev/null @@ -1,279 +0,0 @@ -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 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' - -const Setting = () => { - const { token, setToken } = useAuthContext() - - const userInfo = JSON.parse(token) - - const [formData, setFormData] = useState({ - username: userInfo.username, - email: userInfo.email, - password: '', - id: userInfo.id - }) - - /** - * function to set the data in state - * @param {*} e - */ - const handleInputChange = (e) => { - const { name, value } = e.target - setFormData((prevData) => ({ - ...prevData, - [name]: value - })) - } - - 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) - setOpen(true) - } - } - /** - * hook to open 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 = () => ( - - - {code == 422 ? ( - - {' '} - Email déjà pris - - ) : ( - - {' '} - Modification a été effectuée avec succès - - )} - - - - - - ) - - const [openConfig, setOpenCOnfig] = useState(false) - const onCloseConfig = () => setOpenCOnfig(false) - - const openCOnfigFunction = () => setOpenCOnfig(true) - - return ( -
- {modals()} - -
-
-
-

setting

- - - -
-
-
- {/* contenu */} -
-
- - - - - - -
- {/* */} - - - - - - ) - }} - sx={{ - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800' // Set the border color on hover - } - } - }} - /> - - - - - - ) - }} - sx={{ - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800' // Set the border color on hover - } - } - }} - /> - - {/* matieres Mecanique general */} - - - - - ) - }} - sx={{ - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800' // Set the border color on hover - } - } - }} - /> - - {/* Matieres Resistance Materiaux */} - {/* Submit Button */} - - - - -
-
-
-
-
-
- ) -} - -export default Setting diff --git a/src/renderer/src/components/ParcourMatiere.jsx b/src/renderer/src/components/ParcourMatiere.jsx deleted file mode 100644 index df458fb..0000000 --- a/src/renderer/src/components/ParcourMatiere.jsx +++ /dev/null @@ -1,130 +0,0 @@ -import React, { useEffect, useState } from 'react' -import { - Dialog, - DialogActions, - DialogContent, - DialogTitle, - TextField, - Button, - InputAdornment, - Box, - Grid, - FormControl, - InputLabel, - Select, - OutlinedInput, - MenuItem -} from '@mui/material' - -const ParcourMatiere = ({ open, onClose, matiere_id }) => { - const [formData, setFormData] = useState({ - parcour_id: [], - matiere_id: '' - }) - - const [parcours, setParcours] = useState([]) - const [parcoursMatiere, setParcoursMatiere] = useState([]) - - useEffect(() => { - window.notesysteme.getParcours().then((response) => { - setParcours(response) - }) - }, []) - - useEffect(() => { - if (matiere_id) { - setFormData({ - matiere_id: matiere_id - }) - - window.notesysteme.getParcourMatiere({ matiere_id }).then((response) => { - setParcoursMatiere(response) - }) - } - }, [matiere_id]) - - useEffect(() => { - if (parcoursMatiere.length !== 0) { - const parcourIds = parcoursMatiere.map((item) => item.parcour_id) - - setFormData((prevState) => ({ - ...prevState, - parcour_id: parcourIds // Merge & remove duplicates - })) - } - }, [parcoursMatiere]) - - const handleChange = (event) => { - const { name, value } = event.target - - setFormData((prevState) => ({ - ...prevState, - [name]: value // Ensures multiple selection works correctly - })) - } - - const formSubmit = async (e) => { - e.preventDefault() - let response = await window.notesysteme.parcourMatiere(formData) - if (response.success) { - onClose() - } - } - - return ( - -
- Assignation à des parcours - - - - - - - Parcours - - - - - - - - - - - -
-
- ) -} - -export default ParcourMatiere diff --git a/src/renderer/src/components/Parcours.jsx b/src/renderer/src/components/Parcours.jsx deleted file mode 100644 index 6a160e4..0000000 --- a/src/renderer/src/components/Parcours.jsx +++ /dev/null @@ -1,199 +0,0 @@ -import React, { useEffect, useState } from 'react' -import classe from '../assets/AllStyleComponents.module.css' -import classeAdd from '../assets/AddStudent.module.css' -import classeHome from '../assets/Home.module.css' -import { Link } from 'react-router-dom' -import { MdRule } from 'react-icons/md' -import { FaPlus } from 'react-icons/fa' -import { Box, Button, InputAdornment, Typography, Modal, TextField, Grid } from '@mui/material' -import Paper from '@mui/material/Paper' -import { createTheme, ThemeProvider } from '@mui/material/styles' -import { DataGrid, GridToolbar } from '@mui/x-data-grid' -import { frFR } from '@mui/x-data-grid/locales' -import { Tooltip } from 'react-tooltip' -import warning from '../assets/warning.svg' -import success from '../assets/success.svg' -import AddParcours from './AddParcours' -import UpdateParcour from './UpdateParcour' -import { FaPenToSquare } from 'react-icons/fa6' - -const Parcours = () => { - const [parcours, setParcours] = useState([]) - - useEffect(() => { - window.notesysteme.getParcours().then((response) => { - setParcours(response) - }) - }, []) - - const theme = createTheme({ - components: { - MuiIconButton: { - styleOverrides: { - root: { - color: 'gray' // Change the color of toolbar icons - } - } - }, - MuiButton: { - styleOverrides: { - root: { - color: '#121212' // Change the color of toolbar icons - } - } - } - } - }) - - const columns = [ - { field: 'nom', headerName: 'Nom', width: 230 }, - { field: 'uniter', headerName: 'Uniter', width: 180 }, - { field: 'mention', headerName: 'Mention', width: 230 }, - { - field: 'action', - headerName: 'Action', - flex: 1, - renderCell: (params) => ( -
- openUpdate(params.value)}> - - -
- ) - } - ] - - const paginationModel = { page: 0, pageSize: 5 } - - const dataRow = parcours.map((parc) => ({ - id: parc.id, - nom: parc.nom, - uniter: parc.uniter, - mention: parc.mention_id, - action: parc.id - })) - - const [isSubmitted, setIsSubmitted] = useState(false) - const handleFormSubmit = (status) => { - setIsSubmitted(status) - } - - useEffect(() => { - if (isSubmitted) { - window.notesysteme.getParcours().then((response) => { - setParcours(response) - }) - setIsSubmitted(false) - } - }, [isSubmitted]) - - const [openModalAdd, setOpenModalAdd] = useState(false) - const [openModalUpdate, setOpenModalUpdate] = useState(false) - const [idToSend, setIdToSend] = useState(null) - - const closeUpdate = () => { - setOpenModalUpdate(false) - } - - const openUpdate = (id) => { - setIdToSend(id) - setOpenModalUpdate(true) - } - - const openModalAddFunction = () => { - setOpenModalAdd(true) - } - - const closeModalAdd = () => { - setOpenModalAdd(false) - } - - return ( -
- - -
-
-
-

- - Parcours -

- - - -
-
-
- -
-
- - -
- -
-
-
-
-
-
- ) -} - -export default Parcours diff --git a/src/renderer/src/components/ReleverNotes.jsx b/src/renderer/src/components/ReleverNotes.jsx deleted file mode 100644 index a09d4b1..0000000 --- a/src/renderer/src/components/ReleverNotes.jsx +++ /dev/null @@ -1,594 +0,0 @@ -import React, { useEffect, useRef, useState } from 'react' -import classe from '../assets/AllStyleComponents.module.css' -import classeHome from '../assets/Home.module.css' -import Paper from '@mui/material/Paper' -import jsPDF from 'jspdf' -import html2Canvas from 'html2canvas' -import logoRelerev1 from '../assets/logorelever.png' -import logoRelerev2 from '../assets/logorelever2.png' -import dayjs from 'dayjs' -import getSemestre from './function/GetSemestre' -import { descisionJury, getmentionAfterNotes } from './function/FonctionRelever' - -const ReleverNotes = ({ id, anneescolaire, niveau, refs }) => { - const [etudiant, setEtudiant] = useState([]) - const [matieres, setMatieres] = useState([]) - const [notes, setNotes] = useState([]) - - const handleDownloadPDF = async () => { - const input = Telever.current - - // Set a high scale for better quality - const scale = 3 - - html2Canvas(input, { - scale, // Increase resolution - useCORS: true, // Handle cross-origin images - allowTaint: true - }).then((canvas) => { - const imgData = canvas.toDataURL('image/png') - - // Create a PDF with dimensions matching the captured content - const pdf = new jsPDF({ - orientation: 'portrait', - unit: 'mm', - format: 'a4' - }) - - const imgWidth = 210 // A4 width in mm - const pageHeight = 297 // A4 height in mm - const imgHeight = (canvas.height * imgWidth) / canvas.width - - let position = 0 - - pdf.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight, '', 'FAST') - - // Handle multi-page case - while (position + imgHeight >= pageHeight) { - position -= pageHeight - pdf.addPage() - pdf.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight, '', 'FAST') - } - - pdf.save('document.pdf') - }) - } - - useEffect(() => { - if (!id) { - // id doesn't exist, you might want to retry, or do nothing - // For example, refetch later or show an error - return - } - window.etudiants.getSingle({ id }).then((response) => { - setEtudiant(response) - }) - - window.mention.getMention().then((response) => { - setMatieres(response) - }) - - window.notes.noteRelerer({ id, anneescolaire, niveau }).then((response) => { - setNotes(response) - }) - }, [id]) - - const Telever = useRef() - - useEffect(() => { - if (refs) { - handleDownloadPDF() - } - }, [refs]) - - const [matiereWithSemestre, setMatiereWithSemestre] = useState([]) - const [matiereWithSemestreRepech, setMatiereWithSemestreRepech] = useState([]) - - useEffect(() => { - if (!notes.noteNormal || !notes.semestre || !notes.noteRepech) return // Ensure data exists - - const updatedMatieres = notes.noteNormal.map((matiere) => { - // Get the semesters based on the student's niveau - const semesters = getSemestre(matiere.etudiant_niveau) - - // Find the matched semestre based on the conditions - const matchedSemestre = notes.semestre.find( - (sem) => - sem.matiere_id === matiere.matiere_id && - sem.mention_id === matiere.mention_id && - (sem.nom === semesters[0] || sem.nom === semesters[1]) // Check if the semester matches - ) - - return { - ...matiere, - semestre: matchedSemestre ? matchedSemestre.nom : null // Add 'semestre' or set null if no match - } - }) - - const updatedMatieresRepech = notes.noteRepech.map((matiere) => { - // Get the semesters based on the student's niveau - const semesters = getSemestre(matiere.etudiant_niveau) - - // Find the matched semestre based on the conditions - const matchedSemestre = notes.semestre.find( - (sem) => - sem.matiere_id === matiere.matiere_id && - sem.mention_id === matiere.mention_id && - (sem.nom === semesters[0] || sem.nom === semesters[1]) // Check if the semester matches - ) - - // Return the updated matiere with the matched semestre or null if no match - return { - ...matiere, - semestre: matchedSemestre ? matchedSemestre.nom : null // Add 'semestre' or set null if no match - } - }) - - setMatiereWithSemestre(updatedMatieres) - setMatiereWithSemestreRepech(updatedMatieresRepech) - }, [notes]) - - function compareMention(mentionID) { - let statusText - - matieres.map((statu) => { - if (mentionID == statu.id) { - statusText = statu.nom - } - }) - - return statusText ? statusText.charAt(0).toUpperCase() + statusText.slice(1) : statusText - } - - // data are finaly get and ready for the traitement below - - // Merging the arrays based on matiere_id - matiereWithSemestre.forEach((item1) => { - // Find the corresponding item in array2 based on matiere_id - let matchingItem = matiereWithSemestreRepech.find( - (item2) => item2.matiere_id === item1.matiere_id - ) - - // If there's a match, add noterepech from array2, otherwise use the note from array1 - item1.noterepech = matchingItem ? matchingItem.note : item1.note - }) - - // step 1 group all by semestre - const groupedDataBySemestre = matiereWithSemestre.reduce((acc, matiere) => { - const { semestre } = matiere - - if (!acc[semestre]) { - acc[semestre] = [] - } - - acc[semestre].push(matiere) - - return acc - }, {}) - - const compareMoyenne = (normal, rattrapage) => { - const note = Math.max(Number(normal), Number(rattrapage)) - return note >= 10 ? 'Admis' : 'Ajourné' - } - - const TbodyContent = () => { - return ( - <> - {Object.entries(groupedDataBySemestre).map(([semestre, matieres]) => { - // Group by unite_enseignement inside each semestre - const groupedByUnite = matieres.reduce((acc, matiere) => { - if (!acc[matiere.unite_enseignement]) { - acc[matiere.unite_enseignement] = [] - } - acc[matiere.unite_enseignement].push(matiere) - return acc - }, {}) - - return ( - - {Object.entries(groupedByUnite).map(([unite, matieres], uniteIndex) => ( - <> - {matieres.map((matiere, matiereIndex) => ( - - {/* Display 'semestre' only for the first row of the first unite_enseignement */} - {uniteIndex === 0 && matiereIndex === 0 && ( - - {semestre} - - )} - - {/* Display 'unite_enseignement' only for the first row of each group */} - {matiereIndex === 0 && ( - - {unite} - - )} - - {/* Matiere Data */} - - {matiere.nom} - - - {matiere.credit} - - - {matiere.note} - - - {matiere.credit} - - - {matiere.noterepech} - - - {/* Display the comparison value only once */} - {matiereIndex === 0 && ( - - {/* Replace 'hgh' with your logic for displaying the comparison */} - {compareMoyenne( - ( - matieres.reduce((total, matiere) => total + matiere.note, 0) / - matieres.length - ).toFixed(2), - ( - matieres.reduce((total, matiere) => total + matiere.noterepech, 0) / - matieres.length - ).toFixed(2) - )} - - )} - - ))} - - {/* Add Total Row for 'unite_enseignement' */} - - - Total de Credit et Moyenne des Notes - - - {/* Calculate Total de Credit */} - {matieres.reduce((total, matiere) => total + matiere.credit, 0)} - - - {/* Calculate Moyenne des Notes */} - {( - matieres.reduce((total, matiere) => total + matiere.note, 0) / - matieres.length - ).toFixed(2)}{' '} - {/* Format to 2 decimal places */} - - - {matieres.reduce((total, matiere) => total + matiere.credit, 0)} - - - {( - matieres.reduce((total, matiere) => total + matiere.noterepech, 0) / - matieres.length - ).toFixed(2)} - - - - - ))} - - ) - })} - - ) - } - - const totalNotes = () => { - let totalNotes = document.querySelectorAll('.moyenneNotes') - let totalNotesRepech = document.querySelectorAll('.moyenneNotesRattrapage') - - let TotalNoteNumber = 0 - let TotalNoteNumberRepech = 0 - - totalNotes.forEach((notes) => { - TotalNoteNumber += Number(notes.textContent / totalNotes.length) - // console.log(notes.textContent); - }) - - totalNotesRepech.forEach((notes) => { - TotalNoteNumberRepech += Number(notes.textContent / totalNotes.length) - // console.log(notes.textContent); - }) - - let note = Math.max(TotalNoteNumber, TotalNoteNumberRepech) - - return note - } - - const [note, setNote] = useState(0) - - useEffect(() => { - setNote(totalNotes()) - }, [TbodyContent]) - - return ( -
-
-
- -
-
- image en tete - image en tete -
-
-

- Releve de notes -

-
- {/* block info */} -
- {/* gauche */} -
- {/* gauche gauche */} -
- - Nom - -
- - Prenom - -
- - Date de naissance - -
- - Codage - -
- {/* gauche droite */} -
- : {etudiant.nom} -
- : {etudiant.prenom} -
- : {dayjs(etudiant.date_de_naissances).format('DD/MM/YYYY')} -
- : {etudiant.num_inscription} -
-
- {/* droite */} -
- {/* droite gauche */} -
- - Annee U - -
- - Niveau - -
- - Parcours - -
- {/* droite droite */} -
- : {etudiant.annee_scolaire} -
- : {etudiant.niveau} -
- : {compareMention(etudiant.mention_id)} -
-
-
- - {/* table */} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- Session -
- Normale - - Rattrapage -
- semestre - UEECcréditNotescréditNotes - Observation -
- Moyenne - {note.toFixed(2)}/20
- Mention:{' '} - {getmentionAfterNotes(note)} - - Décision du Jury:{' '} - - {descisionJury(note, etudiant.niveau)} - -
-
-

- Toamasine le -

- {/* texte hidden for place in signature */} -

- Lorem ipsum dolor sit amet consectetur adipisicing elit. Blanditiis delectus - perspiciatis nisi aliquid eos adipisci cumque amet ratione error voluptatum. - Expedita velit enim nulla nam? Vitae fuga enim et temporibus. Lorem ipsum dolor - sit amet, consectetur adipisicing elit. Mollitia, assumenda? -

-
-
-
-
-
-
- ) -} - -export default ReleverNotes diff --git a/src/renderer/src/components/Resultat.jsx b/src/renderer/src/components/Resultat.jsx deleted file mode 100644 index af9e808..0000000 --- a/src/renderer/src/components/Resultat.jsx +++ /dev/null @@ -1,218 +0,0 @@ -import React, { useEffect, useState } from 'react' -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 { IoMdReturnRight } from 'react-icons/io' -import jsPDF from 'jspdf' -import autoTable from 'jspdf-autotable' -import { FaDownload } from 'react-icons/fa' - -const Resultat = () => { - const { niveau, scolaire } = useParams() - const formData = { - niveau, - scolaire - } - const [etudiants, setEtudiants] = useState([]) - const [mention, setMention] = useState([]) - const [session, setSession] = useState([]) - - useEffect(() => { - window.notes.getMoyenne(formData).then((response) => { - setEtudiants(response) - }) - window.noteRepech.getMoyenneRepech(formData).then((response) => { - setSession(response) - }) - window.mention.getMention().then((response) => { - setMention(response) - }) - }, []) - - let dataToMap = [] - - function returnmention(id) { - let mentions - for (let index = 0; index < mention.length; index++) { - if (mention[index].id == id) { - mentions = mention[index].nom - } - } - return mentions - } - - function checkNull(params) { - if (params == null || params == undefined) { - return null - } - return params - } - - const print = () => { - const generatePDF = () => { - try { - const pdf = new jsPDF({ - orientation: 'portrait', - unit: 'mm', - format: 'a4' - }) - - // Select the table - autoTable(pdf, { - html: '#myTable2', // ID de la table - startY: 20, - theme: 'grid', - headStyles: { - fillColor: 'gray', - halign: 'center', - fontStyle: 'bold', - textColor: 'black' - }, // Supprimer la couleur et centrer - margin: { top: 10 }, - styles: { fontSize: 8, cellPadding: 2, halign: 'center' }, // Centrer le texte des cellules - didDrawPage: (data) => { - pdf.text('', 14, 10) - } - }) - - pdf.save(`Resultat-${niveau}-${scolaire}.pdf`) - } catch (error) { - console.error('Error generating PDF:', error) - } - } - generatePDF() - } - - function compareSessionNotes(session1, session2) { - let notes - if (session2) { - if (session1 < session2.note) { - notes = session2.note - } else { - notes = session1 - } - } else { - notes = session1 - } - return notes - } - - for (let index = 0; index < etudiants.length; index++) { - let total = 0 - let note = 0 - let totalCredit = 0 - - // Create a new object for each student - let modelJson = { - id: '', - nom: '', - prenom: '', - photos: '', - moyenne: '', - mention: '', - anneescolaire: '' - } - - for (let j = 0; j < etudiants[index].length; j++) { - modelJson.id = etudiants[index][j].etudiant_id - modelJson.nom = etudiants[index][j].nom - modelJson.prenom = etudiants[index][j].prenom - modelJson.photos = etudiants[index][j].photos - modelJson.mention = etudiants[index][j].mention_id - modelJson.anneescolaire = etudiants[index][j].annee_scolaire - - // console.log(checkNull(session[index][j])); - 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 - } - totalCredit += etudiants[index][j].credit - } - - total = note / totalCredit - modelJson.moyenne = total.toFixed(2) - - // Add the new object to the array - dataToMap.push(modelJson) - } - - const sortedStudents = dataToMap - .filter((student) => parseFloat(student.moyenne) >= 10) - .sort((a, b) => parseFloat(b.moyenne) - parseFloat(a.moyenne)) - - console.log(sortedStudents) - - return ( -
-
-
-
-

- Resultat des {niveau} en {scolaire} -

-
- - - - window.history.back()}> - - -
-
-
-
- -
- - - - - - - - - - - - - - - {sortedStudents.map((sorted) => ( - - - - - - - ))} - -
-
- Niveau {niveau} | Année universitaire {scolaire} -
-
NomPrénomMentionMoyenne
{sorted.nom}{sorted.prenom}{returnmention(sorted.mention)}{sorted.moyenne}
-
-
-
- ) -} - -export default Resultat diff --git a/src/renderer/src/components/Sidenav.jsx b/src/renderer/src/components/Sidenav.jsx deleted file mode 100644 index 28934ff..0000000 --- a/src/renderer/src/components/Sidenav.jsx +++ /dev/null @@ -1,283 +0,0 @@ -import React, { useState } from 'react' -import classe from '../assets/Sidenav.module.css' -import { RiDashboardHorizontalFill } from 'react-icons/ri' -import { PiStudentFill } from 'react-icons/pi' -import { IoMdHelpCircleOutline } from 'react-icons/io' -import { CgNotes } from 'react-icons/cg' -import { FaUserCircle, FaBook, FaUserCog } from 'react-icons/fa' -import { Link } from 'react-router-dom' -import { useLocation } from 'react-router-dom' -import { Tooltip } from 'react-tooltip' -import { LuLogOut } from 'react-icons/lu' -import { GiUpgrade } from 'react-icons/gi' -import Menu from '@mui/material/Menu' -import MenuItem from '@mui/material/MenuItem' -import { useAuthContext } from '../contexts/AuthContext' -import { MdAdminPanelSettings, MdRule } from 'react-icons/md' -import { BsCalendar2Date } from 'react-icons/bs' -import { SiVitest } from 'react-icons/si' -import { GrManual } from 'react-icons/gr' -import { FaClipboardList } from 'react-icons/fa6' - -const Sidenav = () => { - const [anchorEl, setAnchorEl] = useState(null) - const open = Boolean(anchorEl) - const { setToken } = useAuthContext() - - const handleClick = (event) => { - setAnchorEl(event.currentTarget) - } - - const handleClose = () => { - setAnchorEl(null) - } - - // don't touch it, i don't know why but the active button stop workin without this - const location = useLocation() - - const logout = () => { - localStorage.removeItem('ACCESS_TOKEN') - setToken(null) - } - - return ( - - ) -} - -export default Sidenav diff --git a/src/renderer/src/components/SingleAnneeScolaire.jsx b/src/renderer/src/components/SingleAnneeScolaire.jsx deleted file mode 100644 index 123d9fc..0000000 --- a/src/renderer/src/components/SingleAnneeScolaire.jsx +++ /dev/null @@ -1,268 +0,0 @@ -import { useEffect, useState } from 'react' -import classe from '../assets/AllStyleComponents.module.css' -import classeHome from '../assets/Home.module.css' -import Paper from '@mui/material/Paper' -import { Link, useParams } from 'react-router-dom' -import { IoMdReturnRight } from 'react-icons/io' -import { Modal, Box, Typography, Button, InputAdornment, TextField, Grid } from '@mui/material' -import { FaCalendarAlt } from 'react-icons/fa' -import svgError from '../assets/error.svg' -import svgSuccess from '../assets/success.svg' -import { BsCalendar2Date } from 'react-icons/bs' -import dayjs from 'dayjs' - -const SingleAnneeScolaire = () => { - const { id } = useParams() - const [formData, setFormData] = useState({ - code: '', - debut: '', - fin: '', - id: '' - }) - - const [scolaire, setScolaire] = useState([]) - const [status, setStatus] = useState(200) - const [open, setOpen] = useState(false) - - useEffect(() => { - window.anneescolaire.getSingleAnneeScolaire({ id }).then((response) => { - setScolaire(response) - }) - }, []) - - useEffect(() => { - setFormData((prev) => ({ - ...prev, - code: scolaire.code, - debut: dayjs(scolaire.debut).format('YYYY-MM-DD'), - fin: dayjs(scolaire.fin).format('YYYY-MM-DD'), - id: scolaire.id - })) - }, [scolaire]) - - /** - * function to set the data in state - * @param {*} e - */ - const handleInputChange = (e) => { - const { name, value } = e.target - setFormData((prevData) => ({ - ...prevData, - [name]: value - })) - } - - const formSubmit = async (e) => { - e.preventDefault() - - let response = await window.anneescolaire.updateAnneeScolaire(formData) - - if (response.success) { - setOpen(true) - setStatus(200) - } else { - setStatus(400) - setOpen(true) - } - } - - const handleClose = () => setOpen(false) - - const modals = () => ( - - - - - {status === 200 ? 'Mise à jour effectuée avec succès' : 'Erreur'} - - - - - - - ) - - return ( -
- {modals()} -
-
-
-

- - Mise a jour Année universitaire -

- window.history.back()}> - - -
-
-
- -
- -
-

- mise a jour année universitaire -

- - - - - - ) - }} - onChange={handleInputChange} - required - className="inputAddNote" - sx={{ - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800' // Set the border color on hover - } - }, - '& .MuiInputBase-input::placeholder': { - fontSize: '14px' // Set the placeholder font size - } - }} - /> - - - - - - ) - }} - className="inputAddNote" - sx={{ - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800' // Set the border color on hover - } - }, - '& .MuiInputBase-input::placeholder': { - fontSize: '11px' // Set the placeholder font size - } - }} - /> - - - - - - ) - }} - onChange={handleInputChange} - required - value={formData.fin} - className="inputAddNote" - sx={{ - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800' // Set the border color on hover - } - }, - '& .MuiInputBase-input::placeholder': { - fontSize: '11px' // Set the placeholder font size - } - }} - /> - - - - - -
-
-
-
- ) -} - -export default SingleAnneeScolaire diff --git a/src/renderer/src/components/SingleEtudiant.jsx b/src/renderer/src/components/SingleEtudiant.jsx deleted file mode 100644 index 6536e00..0000000 --- a/src/renderer/src/components/SingleEtudiant.jsx +++ /dev/null @@ -1,1156 +0,0 @@ -import React, { useEffect, useState } from 'react' -import { - TextField, - Button, - Grid, - Card, - CardContent, - Avatar, - Typography, - InputAdornment, - Modal, - Box, - Autocomplete, - IconButton -} from '@mui/material' -import { Tooltip } from 'react-tooltip' -import { FaClipboardList, FaEdit } from 'react-icons/fa' -import { AiOutlineUser, AiOutlineCalendar, AiOutlineNumber } from 'react-icons/ai' -import { Link, useParams } from 'react-router-dom' -import classe from '../assets/AllStyleComponents.module.css' -import { FaCamera } from 'react-icons/fa' -import { styled } from '@mui/material/styles' -import warning from '../assets/warning.svg' -import { FaRegTimesCircle } from 'react-icons/fa' -import MenuItem from '@mui/material/MenuItem' -import { MdGrade, MdRule } from 'react-icons/md' -import { FaLeftLong, FaRightLong } from 'react-icons/fa6' -import dayjs from 'dayjs' - -const SingleEtudiant = () => { - const { id } = useParams() - const [etudiant, setEtudiant] = useState({}) - const [niveaus, setNiveaus] = useState([]) - const [mention, setMention] = useState([]) - const [parcours, setParcours] = useState([]) - - const [editMode, setEditMode] = useState(false) - const [formData, setFormData] = useState({ - nom: '', - prenom: '', - photos: null, - date_de_naissances: '', - niveau: '', - annee_scolaire: '', - status: '', - mention_id: '', - num_inscription: '', - sexe: 'Garçon', - nationalite: '', - cin: '', - date_delivrance: '', - annee_bacc: '', - serie: '', - boursier: 'oui', - domaine: '', - contact: '', - parcours: '' - }) - const [status, setStatus] = useState([]) - const [scolaire, setScolaire] = useState([]) - - // Fetch the student data - useEffect(() => { - window.etudiants.getSingle({ id }).then((response) => { - setEtudiant(response) - }) - - window.niveaus.getNiveau().then((response) => { - setNiveaus(response) - }) - - window.statuss.getStatus().then((response) => { - setStatus(response) - }) - - window.anneescolaire.getAnneeScolaire().then((response) => { - setScolaire(response) - }) - - window.mention.getMention().then((response) => { - setMention(response) - }) - - window.notesysteme.getParcours().then((response) => { - setParcours(response) - }) - }, [id]) - - function comparestatut(statutID) { - let statusText - - status.map((statu) => { - if (statutID == statu.id) { - statusText = statu.nom - } - }) - return statusText - } - - function compareMention(mentionId) { - let mentionText - - mention.map((ment) => { - if (mentionId == ment.id) { - mentionText = ment.nom - } - }) - return mentionText - } - - // Populate formData with etudiant values when etudiant changes - useEffect(() => { - if (etudiant) { - setFormData({ - nom: etudiant.nom || '', - prenom: etudiant.prenom || '', - photos: etudiant.photos || null, - date_de_naissances: dayjs(etudiant.date_de_naissances).format('YYYY-MM-DD') || '', - niveau: etudiant.niveau || '', - annee_scolaire: etudiant.annee_scolaire || '', - status: etudiant.status || '', - mention_id: etudiant.mention_id || '', - num_inscription: etudiant.num_inscription || '', - id: etudiant.id || '', - sexe: etudiant.sexe, - nationalite: etudiant.nationalite, - cin: etudiant.cin, - date_delivrance: dayjs(etudiant.date_delivrance).format('YYYY-MM-DD'), - annee_bacc: dayjs(etudiant.annee_bacc).format('YYYY-MM-DD'), - serie: etudiant.serie, - boursier: etudiant.boursier, - domaine: etudiant.domaine, - contact: etudiant.contact, - parcours: etudiant.parcours - }) - } - }, [etudiant]) - - const handleChange = (e) => { - const { name, value } = e.target - setFormData({ - ...formData, - [name]: value - }) - } - - const handleSubmit = async () => { - const { - nom, - prenom, - date_de_naissances, - niveau, - annee_scolaire, - num_inscription, - sexe, - nationalite, - cin, - date_delivrance, - annee_bacc, - serie, - boursier, - domaine, - contact, - parcours - } = formData - - // Validation check: Ensure all required fields are filled - if ( - !nom || - !prenom || - !date_de_naissances || - !niveau || - !annee_scolaire || - !num_inscription || - !sexe || - !nationalite || - !cin || - !date_delivrance || - !annee_bacc || - !serie || - !boursier || - !domaine || - !contact - ) { - // setOpen(true) - alert('Veuillez remplir tous les champs obligatoires.') - console.log(formData); - - return // Prevent submission if validation fails - } - - // If validation passes, proceed with the submission - try { - let response = await window.etudiants.updateEtudiants(formData) - if (response.success) { - setEtudiant(formData) - } - - setEditMode(false) - } catch (error) { - console.error('Error updating student:', error) - } - } - - /** - * hook to open modal - */ - const [open, setOpen] = useState(false) - - /** - * function to close modal - */ - const handleClose = () => setOpen(false) - - /** - * function to return the view Modal - * - * @returns {JSX} - */ - const modals = () => ( - - - - {' '} - Voulez vous modifier la photos ? - - - - - - - - ) - - const [pdp, setPdp] = useState(null) - - const updatePDP = () => { - let avatar = document.getElementById('imagepdpdynamic') - let imgAvatar = avatar.querySelector('img') - - window.etudiants.updateEtudiantsPDP({ pdp, id }).then((responses) => { - console.log(responses); - - if (responses.success) { - if (imgAvatar === null) { - let image = document.createElement('img') - image.setAttribute('src', pdp) - image.style.width = '100%' - avatar.appendChild(image) - } else { - imgAvatar.removeAttribute('src') - imgAvatar.setAttribute('src', pdp) - } - setOpen(false) - } - }) - } - - const changePDP = () => { - document.getElementById('inputhiden').click() - } - - const handleFileChange = (e) => { - let img_file = e.target.files[0] - const reader = new FileReader() - reader.readAsDataURL(img_file) - reader.onload = (ev) => { - const url = ev.target.result - // initialisation de nouvelle imageURL - const image = document.createElement('img') - image.src = url - - // create a new image - image.onload = (event) => { - let canvas = document.createElement('canvas') - let ratio = 250 / event.target.width - canvas.width = 250 - canvas.height = event.target.height * ratio - const context = canvas.getContext('2d') - context.drawImage(image, 0, 0, canvas.width, canvas.height) - - // new url - const new_URL = canvas.toDataURL('image/jpeg', 90) - setPdp(new_URL) - setOpen(true) - } - } - } - - const VisuallyHiddenInput = styled('input')({ - clip: 'rect(0 0 0 0)', - clipPath: 'inset(50%)', - height: 1, - overflow: 'hidden', - position: 'absolute', - bottom: 0, - left: 0, - whiteSpace: 'nowrap', - width: 1 - }) - - const [page1, setPage1] = useState(true) - const [page2, setPage2] = useState(false) - const [page3, setPage3] = useState(false) - - const seePage1 = () => { - setPage2(false) - setPage3(false) - setPage1(true) - } - - const seePage2 = () => { - setPage1(false) - setPage3(false) - setPage2(true) - } - - const seePage3 = () => { - setPage1(false) - setPage2(false) - setPage3(true) - } - - return ( -
- {modals()} -
- - - - - - - - -
- - -
-
- {editMode ? ( - <> - {page1 && ( - - {/* Group Nom and Prenom */} - - - - - - ) - }} - sx={{ - marginBottom: 2, - padding: 1, - marginLeft: '4%', - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800' // Set the border color on hover - } - } - }} - /> - - - - - - ) - }} - sx={{ - marginBottom: 2, - padding: 1, - marginLeft: '4%', - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800' // Set the border color on hover - } - } - }} - /> - - - - {/* Group Niveau and Date de Naissance */} - - - - - - ) - }} - sx={{ - marginBottom: 2, - padding: 1, - marginLeft: '4%', - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800' // Couleur de la bordure au survol - } - } - }} - > - {/* Liste des options */} - {niveaus.map((niveau) => ( - - {niveau.nom} - - ))} - - - - - - - ) - }} - sx={{ - marginBottom: 2, - padding: 1, - marginLeft: '4%', - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800' // Set the border color on hover - } - } - }} - /> - - - - {/* Group Année Scolaire and Numero d'Inscription */} - - - - - - ) - }} - sx={{ - marginBottom: 2, - padding: 1, - marginLeft: '4%', - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800' // Set the border color on hover - } - } - }} - > - {scolaire.map((statu) => ( - - {statu.code} - - ))} - - - - - - - ) - }} - sx={{ - marginBottom: 2, - padding: 1, - marginLeft: '4%', - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800' // Set the border color on hover - } - } - }} - /> - - - - {/* Group status*/} - - - - - - ) - }} - sx={{ - marginBottom: 2, - padding: 1, - marginLeft: '4%', - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800' // Couleur de la bordure au survol - } - } - }} - > - {status.map((statu) => ( - - {statu.nom} - - ))} - - - - option.nom || ''} // Safely access `nom` - value={mention.find((item) => item.id === formData.mention_id) || null} // Bind selected value to form data - onChange={(event, newValue) => { - setFormData((prevData) => ({ - ...prevData, - mention_id: newValue ? newValue.id : null // Store the ID of the selected mention - })) - }} - // size="small" // Make the Autocomplete small - isOptionEqualToValue={(option, value) => option.id === value.id} // Ensure correct matching of options - renderInput={(params) => ( - - - - - {params.InputProps.startAdornment} - - ) - }} - sx={{ - marginBottom: 2, - padding: 1, - marginLeft: '4%', - // marginBottom: '5px', - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800' // Set border color on hover - } - } - }} - /> - )} - /> - - - - )} - - {page2 && ( - - {/* Group Nom and Prenom */} - - - - - - ) - }} - sx={{ - marginBottom: 2, - padding: 1, - marginLeft: '4%', - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800' // Set the border color on hover - } - } - }} - /> - - - - - - ) - }} - sx={{ - marginBottom: 2, - padding: 1, - marginLeft: '4%', - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800' // Set the border color on hover - } - } - }} - /> - - - - {/* Group Niveau and Date de Naissance */} - - - - - - ) - }} - sx={{ - marginBottom: 2, - padding: 1, - marginLeft: '4%', - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800' // Couleur de la bordure au survol - } - } - }} - > - {/* Liste des options */} - Garçon - Fille - - - - - - - ) - }} - sx={{ - marginBottom: 2, - padding: 1, - marginLeft: '4%', - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800' // Set the border color on hover - } - } - }} - /> - - - - {/* Group Année Scolaire and Numero d'Inscription */} - - - - - - ) - }} - sx={{ - marginBottom: 2, - padding: 1, - marginLeft: '4%', - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800' // Set the border color on hover - } - } - }} - > - - - - - - ) - }} - sx={{ - marginBottom: 2, - padding: 1, - marginLeft: '4%', - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800' // Set the border color on hover - } - } - }} - /> - - - - {/* Group status*/} - - - - - - ) - }} - sx={{ - marginBottom: 2, - padding: 1, - marginLeft: '4%', - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800' // Couleur de la bordure au survol - } - } - }} - > - Oui - Non - - - - option.nom || ''} // Display `nom` - value={parcours.find((item) => item.nom === etudiant.parcours) || null} // Find selected option based on `nom` - onChange={(event, newValue) => { - setFormData((prevData) => ({ - ...prevData, - parcours: newValue ? newValue.nom : '' // Store only `nom` - })) - }} - isOptionEqualToValue={(option, value) => option.nom === value?.nom} // Ensure correct matching - renderInput={(params) => ( - - - - - {params.InputProps.startAdornment} - - ) - }} - sx={{ - marginBottom: 2, - padding: 1, - marginLeft: '4%', - // marginBottom: '5px', - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800' // Set border color on hover - } - } - }} - /> - )} - /> - - - - )} - - {page3 && ( - - - - - - - ) - }} - sx={{ - marginBottom: 2, - padding: 1, - marginLeft: '4%', - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800' // Set the border color on hover - } - } - }} - /> - - - - - - ) - }} - sx={{ - marginBottom: 2, - padding: 1, - marginLeft: '4%', - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800' // Set the border color on hover - } - } - }} - /> - - - - )} - - {/* Submit Button */} - -
- - - - {/* - Page précédents - */} - - - - {/* - Page suivants - */} -
- -
- - ) : ( - <> -
-
- - - Nom: {etudiant.nom} - - - - - Prenom: {etudiant.prenom} - - - - - Niveau: {etudiant.niveau} - - - - - Status: {comparestatut(etudiant.status)} - - - - - Date de Naissance: {dayjs(etudiant.date_de_naissances).format('YYYY-MM-DD')} - - - - - Année Scolaire: {etudiant.annee_scolaire} - - - - - Numero d'Inscription: {etudiant.num_inscription} - - - - - Mention: {compareMention(etudiant.mention_id)} - - -
-
- - )} - - - - -
-
-
-
-
- ) -} - -export default SingleEtudiant diff --git a/src/renderer/src/components/SingleMatiere.jsx b/src/renderer/src/components/SingleMatiere.jsx deleted file mode 100644 index 9a8e42e..0000000 --- a/src/renderer/src/components/SingleMatiere.jsx +++ /dev/null @@ -1,383 +0,0 @@ -import React, { useEffect, useRef, useState } from 'react' -import { Link, useParams } from 'react-router-dom' -import { IoMdReturnRight } from 'react-icons/io' -import { - Box, - InputAdornment, - Typography, - Modal, - TextField, - Grid, - Button, - Autocomplete -} from '@mui/material' -import { BsBookmarkPlusFill } from 'react-icons/bs' -import svgSuccess from '../assets/success.svg' -import svgError from '../assets/error.svg' -import { MdOutlineNumbers } from 'react-icons/md' -import ChangeCapital from './function/ChangeCapitalLetter' -import { CiCalendar } from 'react-icons/ci' -import { IoBookmark } from 'react-icons/io5' -import { FaClipboardList, FaClock } from 'react-icons/fa' -import classe from '../assets/AllStyleComponents.module.css' -import classeHome from '../assets/Home.module.css' - -const SingleMatiere = () => { - const { id } = useParams() - const [matiere, setMatiere] = useState(null) - const [mentions, setMentions] = useState([]) - const [formData, setFormData] = useState({ - nom: '', - credit: '', - uniter: '', - ue: '', - id: id - }) - - const [message, setMessage] = useState('') - const [status, setStatus] = useState(200) - const [open, setOpen] = useState(false) - const uniterRef = useRef() - const ueRef = useRef() - - // Helper function to convert a string of IDs to an array - const stringToArray = (data) => (data ? data.split(',').map(Number) : []) - - useEffect(() => { - // Fetch single matiere data by ID - window.matieres.getMatiereByID({ id }).then((response) => { - setMatiere(response) - }) - - // Fetch mentions data - window.mention.getMention().then((response) => { - setMentions(Array.isArray(response) ? response : []) - }) - }, [id]) - - useEffect(() => { - if (matiere) { - setFormData((prev) => ({ - ...prev, - nom: matiere.nom || '', - credit: matiere.credit || '', - uniter: matiere.unite_enseignement || '', - ue: matiere.ue || '', - id: matiere.id || id - })) - } - }, [matiere, id]) - - const handleChange = (e) => { - const { name, value } = e.target - setFormData((prevData) => ({ - ...prevData, - [name]: value - })) - } - - const handleSubmit = async (e) => { - e.preventDefault() - const response = await window.matieres.updateMatiere(formData) - console.log(response) - if (response.success) { - setStatus(200) - setMessage('Modification a été effectuée avec succès') - } else { - setStatus(400) - setMessage('La matière existe déjà dans la base !') - } - setOpen(true) - } - - const handleClose = () => setOpen(false) - - const modals = () => ( - - - - - {message} - - - - - - - ) - - return ( -
- {modals()} -
-
-
-

Mise à jour des matières

-
- - - -
-
-
-
- -
- -
-

Mise à jour

- - - - - - ) - }} - sx={{ - marginBottom: '5px', - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800' // Set the border color on hover - } - } - }} - /> - - - - - - ) - }} - inputProps={{ min: 1 }} - // inputRef={creditRef} - sx={{ - marginBottom: '5px', - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800' // Set the border color on hover - } - } - }} - /> - - {/* - - - - ), - }} - inputProps={{ min: 1 }} - // inputRef={semestreRef} - sx={{ - marginBottom:"5px", - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800', // Set the border color on hover - }, - }, - }} - /> - */} - - ChangeCapital(uniterRef)} - required - inputRef={uniterRef} - InputProps={{ - startAdornment: ( - - - - ) - }} - inputProps={{ min: 1 }} - // inputRef={uniterRef} - sx={{ - marginBottom: '5px', - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800' // Set the border color on hover - } - } - }} - /> - - - ChangeCapital(ueRef)} - inputRef={ueRef} - type="text" - required - InputProps={{ - startAdornment: ( - - - - ) - }} - inputProps={{ min: 1 }} - // inputRef={uniterRef} - sx={{ - marginBottom: '5px', - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800' // Set the border color on hover - } - } - }} - /> - - {/* - option.nom || ''} - value={mentions.filter((mention) => - formData.mention_id.includes(mention.id) - )} - onChange={(event, newValue) => { - setFormData((prevData) => ({ - ...prevData, - mention_id: newValue.map((item) => item.id), - })); - }} - isOptionEqualToValue={(option, value) => - option.id === value.id - } - renderInput={(params) => ( - - - - - {params.InputProps.startAdornment} - - ), - }} - sx={{ - marginBottom: "5px", - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800', // Set border color on hover - }, - }, - }} - /> - )} - /> - */} - - - - -
-
-
-
- ) -} - -export default SingleMatiere diff --git a/src/renderer/src/components/SingleNiveau.jsx b/src/renderer/src/components/SingleNiveau.jsx deleted file mode 100644 index 21bc450..0000000 --- a/src/renderer/src/components/SingleNiveau.jsx +++ /dev/null @@ -1,223 +0,0 @@ -import React, { useEffect, useRef, useState } from 'react' -import classe from '../assets/AllStyleComponents.module.css' -import classeAdd from '../assets/AddStudent.module.css' -import classeHome from '../assets/Home.module.css' -import { FaPenToSquare } from 'react-icons/fa6' -import { IoMdReturnRight } from 'react-icons/io' -import { Link, useParams } from 'react-router-dom' -import { Box, Button, InputAdornment, Typography, Modal, TextField, Grid } from '@mui/material' -import validationSingleNiveau from './validation/SingleNiveau' -import svgSuccess from '../assets/success.svg' - -const SingleNiveau = () => { - const { id } = useParams() - - const [niveau, setNiveau] = useState([]) - const [allNiveau, setAllNiveau] = useState([]) - - useEffect(() => { - window.niveaus.getSingleNiveau({ id }).then((response) => { - setNiveau(response) - }) - - window.niveaus.getNiveau().then((response) => { - setAllNiveau(response) - }) - }, []) - - useEffect(() => { - if (niveau) { - setFormData({ - nom: niveau.nom || '', - id: niveau.id || id - }) - } - }, [niveau]) - - const [formData, setFormData] = useState({ - nom: '', - id: id - }) - - const handleChange = (e) => { - const { name, value } = e.target - setFormData({ - ...formData, - [name]: value - }) - } - - const handleSubmit = async (e) => { - e.preventDefault() - let niveauNom = [] - allNiveau.map((niv) => { - niveauNom.push(niv.nom) - }) - // let validation = validationSingleNiveau(nomRef.current, errorRef.current, niveauNom) - - // if (validation) { - let response = await window.niveaus.updateSingleNiveau(formData) - console.log(response) - - if (response.success) { - setOpen(true) - } - - if (!response.success) { - errorRef.current.textContent = `${formData.nom} existe déjà` - } - // } - } - - /** - * hook to open modal - */ - const [open, setOpen] = useState(false) - - /** - * function to close modal - */ - const handleClose = () => setOpen(false) - - /** - * function to return the view Modal - * - * @returns {JSX} - */ - const modals = () => ( - - - - {' '} - Modification a été effectuée avec succès - - - - - - - ) - - const nomRef = useRef() - const errorRef = useRef() - - return ( -
- {modals()} -
-
-
-

- - Mise à jour niveau -

- - - -
-
-
- -
- - -
-

modification niveau

- - {/* Nom Fields */} - - {/* */} - ) - }} - inputRef={nomRef} - sx={{ - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800' // Set the border color on hover - } - } - }} - /> - - - - {/* Submit Button */} - - - - -
-
-
-
-
- ) -} - -export default SingleNiveau diff --git a/src/renderer/src/components/SingleNotes.jsx b/src/renderer/src/components/SingleNotes.jsx deleted file mode 100644 index 07d0ce3..0000000 --- a/src/renderer/src/components/SingleNotes.jsx +++ /dev/null @@ -1,364 +0,0 @@ -import React, { useEffect, useRef, useState } from 'react' -import { useParams, Link } from 'react-router-dom' -import Paper from '@mui/material/Paper' -import classe from '../assets/AllStyleComponents.module.css' -import classeHome from '../assets/Home.module.css' -import { IoMdReturnRight } from 'react-icons/io' -import { Button } from '@mui/material' -import { Box, InputAdornment, Typography, Modal, TextField, Grid } from '@mui/material' -import { CgNotes } from 'react-icons/cg' -import svgSuccess from '../assets/success.svg' -import svgError from '../assets/error.svg' - -const SingleNotes = () => { - let { id, niveau, scolaire } = useParams() - const [notes, setNotes] = useState([]) - const [notesRepech, setNotesRepech] = useState([]) - const [formData, setFormData] = useState({}) - const [formData2, setFormData2] = useState({}) - const [etudiant, setEtudiant] = useState([]) - let annee_scolaire = scolaire - const [screenRattrapage, setScreenRattrapage] = useState(false) - - useEffect(() => { - window.etudiants.getSingle({ id }).then((response) => { - setEtudiant(response) - }) - }, []) - - useEffect(() => { - let mention_id = etudiant.mention_id - window.notes.getNotes({ id, niveau, mention_id }).then((response) => { - setNotes(response) - }) - - window.noteRepech.getNotesRepech({ id, niveau, mention_id }).then((response) => { - setNotesRepech(response) - }) - }, [etudiant]) - - console.log(notes) - /** - * Update formData whenever matieres change - */ - useEffect(() => { - const initialFormData = notes.reduce((acc, mat) => { - acc[mat.id] = mat.note // Initialize each key with an empty string - return acc - }, {}) - setFormData(initialFormData) - }, [notes]) // Dependency array ensures this runs whenever `matieres` is updated - - /** - * Update formData2 whenever matieres change - */ - useEffect(() => { - const initialFormData = notesRepech.reduce((acc, mat) => { - acc[mat.id] = mat.note // Initialize each key with an empty string - return acc - }, {}) - setFormData2(initialFormData) - }, [notesRepech]) // Dependency array ensures this runs whenever `matieres` is updated - - const submitForm = async (e) => { - e.preventDefault() - let mention_id = etudiant.mention_id - console.log('normal submited') - let annee_scolaire = etudiant.annee_scolaire - let response = await window.notes.updateNote({ - formData, - niveau, - id, - mention_id, - annee_scolaire - }) - - if (response.changes) { - setMessage('Modification des notes terminer avec succès') - setStatus(200) - setOpen(true) - window.noteRepech.getNotesRepech({ id, niveau, mention_id }).then((response) => { - setNotesRepech(response) - }) - - window.notes.getNotes({ id, niveau, mention_id }).then((response) => { - setNotes(response) - }) - } - } - - const submitForm2 = async (e) => { - e.preventDefault() - let mention_id = etudiant.mention_id - console.log('rattrapage submited') - let response = await window.noteRepech.updateNoteRepech({ formData2, niveau, id }) - - console.log(response) - if (response.changes) { - setMessage('Modification des notes terminer avec succès') - setStatus(200) - setOpen(true) - window.noteRepech.getNotesRepech({ id, niveau, mention_id }).then((response) => { - setNotesRepech(response) - }) - - window.notes.getNotes({ id, niveau, mention_id }).then((response) => { - setNotes(response) - }) - } - } - - const [status, setStatus] = useState(200) - const [message, setMessage] = useState('') - - /** - * hook to open modal - */ - const [open, setOpen] = useState(false) - - /** - * function to close modal - */ - const handleClose = () => setOpen(false) - - /** - * function to return the view Modal - * - * @returns {JSX} - */ - const modals = () => ( - - - {status === 200 ? ( - - {message} - - ) : ( - - {message} - - )} - - - - - - ) - - const nom = useRef() - - const changeScreen = () => { - setScreenRattrapage(!screenRattrapage) - } - - return ( -
- {modals()} -
-
-
-

Mise a jour des notes

-
- window.history.back()}> - - -
-
-
-
- - {/* displaying the form */} -
- - - {!screenRattrapage ? ( -
-

Mise a jour des notes

- {/* {/* map the all matiere and note to the form */} - - {notes.map((note) => ( - - setFormData({ ...formData, [note.id]: e.target.value }) // Update the specific key - } - InputProps={{ - startAdornment: ( - - - - ) - }} - inputRef={nom} - sx={{ - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800' // Set the border color on hover - } - }, - '& .MuiInputBase-input::placeholder': { - fontSize: '11px' // Set the placeholder font size - } - }} - /> - - ))} - - - - - -
- ) : ( -
-

Mise a jour des notes de Rattrapage

- {/* {/* map the all matiere and note to the form */} - - {notesRepech.length === 0 ? ( - // Show this message if notesRepech is empty - -

- L'étudiant a validé tous les crédits. -

-
- ) : ( - // Render form fields if notesRepech contains data - notesRepech.map((note) => ( - - setFormData2({ ...formData2, [note.id]: e.target.value }) // Update the specific key - } - InputProps={{ - startAdornment: ( - - - - ) - }} - inputRef={nom} - sx={{ - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800' // Set the border color on hover - } - }, - '& .MuiInputBase-input::placeholder': { - fontSize: '11px' // Set the placeholder font size - } - }} - /> - - )) - )} -
- - - - - -
- )} -
-
-
-
- ) -} - -export default SingleNotes diff --git a/src/renderer/src/components/SinleMention.jsx b/src/renderer/src/components/SinleMention.jsx deleted file mode 100644 index 6385ee1..0000000 --- a/src/renderer/src/components/SinleMention.jsx +++ /dev/null @@ -1,272 +0,0 @@ -import React, { useEffect, useRef, useState } from 'react' -import classe from '../assets/AllStyleComponents.module.css' -import classeHome from '../assets/Home.module.css' -import { Link, useParams } from 'react-router-dom' -import { IoMdReturnRight } from 'react-icons/io' -import { Box, InputAdornment, Typography, Modal, TextField, Grid, Button } from '@mui/material' -import ChangeCapital from './function/ChangeCapitalLetter' -import { FaClipboardList } from 'react-icons/fa6' -import { IoBookmark } from 'react-icons/io5' -import svgSuccess from '../assets/success.svg' - -const SinleMention = () => { - const { id } = useParams() - const [mentions, setMention] = useState([]) - const [formData, setFormData] = useState({ - nom: '', - uniter: '', - id: '' - }) - - const [errors, setErrors] = useState({ - nom: false, - uniter: false - }) - - useEffect(() => { - window.mention.getSingleMention({ id }).then((response) => { - setMention(response) - }) - }, []) - - useEffect(() => { - if (mentions) { - setFormData({ - nom: mentions.nom || '', - uniter: mentions.uniter || '', - id: mentions.id || id - }) - } - }, [mentions]) - - const nomRef = useRef() - const uniterRef = useRef() - - /** - * function to set the data in state - * @param {*} e - */ - const handleInputChange = (e) => { - const { name, value } = e.target - setFormData({ - ...formData, - [name]: value - }) - setErrors({ - ...errors, - [name]: false // Reset the error when user starts typing - }) - } - - // Helper function to get helperText dynamically - const getHelperText = (field) => (errors[field] ? 'Ce champ est requis.' : '') - - const formSubmit = async (e) => { - e.preventDefault() - const newErrors = {} - let hasError = false - - // Check for empty fields - Object.keys(formData).forEach((key) => { - const value = formData[key] - if (typeof value === 'string' && !value.trim()) { - newErrors[key] = true // Set error for empty fields - hasError = true - } - }) - - setErrors(newErrors) - - if (!hasError) { - try { - let response = await window.mention.updateMention(formData) - - if (response.success) { - setOpen(true) - } - } catch (error) { - console.log(error) - } - } - } - - /** - * hook to open modal - */ - const [open, setOpen] = useState(false) - - /** - * function to close modal - */ - const handleClose = () => { - setOpen(false) - } - - /** - * function to return the view Modal - * - * @returns {JSX} - */ - const modals = () => ( - - - - {' '} - Mention modifier avec succes - - - - - - - ) - - return ( -
- {modals()} -
-
-
-

Mise a jour mention

-
- - - -
-
-
-
- -
- - -
- - - ChangeCapital(nomRef)} - InputProps={{ - startAdornment: ( - - - - ) - }} - helperText={getHelperText('nom')} - inputRef={nomRef} - sx={{ - marginBottom: '5px', - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800' // Set the border color on hover - } - } - }} - /> - - - ChangeCapital(uniterRef)} - InputProps={{ - startAdornment: ( - - - - ) - }} - inputRef={uniterRef} - sx={{ - marginBottom: '5px', - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800' // Set the border color on hover - } - } - }} - /> - - - - - -
-
-
-
-
- ) -} - -export default SinleMention diff --git a/src/renderer/src/components/Student.jsx b/src/renderer/src/components/Student.jsx deleted file mode 100644 index ad42d3d..0000000 --- a/src/renderer/src/components/Student.jsx +++ /dev/null @@ -1,576 +0,0 @@ -import React, { useEffect, useRef, useState } from 'react' -import { Link, Navigate } 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, InputAdornment } from '@mui/material' -import { PiStudentFill } from 'react-icons/pi' -import { DataGrid, GridToolbar } from '@mui/x-data-grid' -import { frFR } from '@mui/x-data-grid/locales' -import dayjs from 'dayjs' -import { FaCertificate, FaGraduationCap, FaPlus, FaReceipt, FaToolbox } from 'react-icons/fa' -import { createTheme, ThemeProvider } from '@mui/material/styles' -import InputLabel from '@mui/material/InputLabel' -import MenuItem from '@mui/material/MenuItem' -import FormControl from '@mui/material/FormControl' -import Select from '@mui/material/Select' -import { Tooltip } from 'react-tooltip' -import { FaPenToSquare, FaFilePdf } from 'react-icons/fa6' -import { CgNotes } from 'react-icons/cg' -import { IoEyeSharp } from 'react-icons/io5' -import PDFEditor from './function/PDFEditor' -import ModalCertificate from './ModalCertificate' -import ModalStage from './ModalStage' -import ModalRecepice from './ModalRecepice' -import { processPdf } from './function/PDFEditorV2' -import { MdVerified } from 'react-icons/md' - -const Student = () => { - const theme = createTheme({ - components: { - MuiIconButton: { - styleOverrides: { - root: { - color: 'gray' // Change the color of toolbar icons - } - } - }, - MuiButton: { - styleOverrides: { - root: { - color: '#121212' // Change the color of toolbar icons - } - } - } - } - }) - - const [status, setStatus] = useState([]) - const [mention, setMention] = useState([]) - - /** - * hook for displaying the students - */ - const [etudiants, setEtudiants] = useState([]) - const [notes, setNotes] = useState([]) - - useEffect(() => { - window.etudiants.getEtudiants().then((response) => { - setEtudiants(response) - }) - - window.notes.getMoyenneVerify().then((response) => { - setNotes(response) - }) - }, []) - - const [niveaus, setNiveau] = useState([]) - - useEffect(() => { - window.niveaus.getNiveau().then((response) => { - setNiveau(response) - }) - - window.statuss.getStatus().then((response) => { - setStatus(response) - }) - - window.mention.getMention().then((response) => { - setMention(response) - }) - }, []) - - const SeeNote = ({ params }) => { - const matchingNote = notes.find( - (element) => - element.etudiant_niveau === params.row.niveau && element.etudiant_id === params.value - ) - - return ( -
- {matchingNote ? ( - - - - Voir les notes - - - ) : ( - - - - Ajouter un notes à cet étudiant - - - )} -
- ) - } - - /** - * function to return the date to local date string - * - * @param {string} dateString - * @returns string - */ - function formatDate(dateString) { - // Convert the string to a Date object - const dateObject = new Date(dateString) - - // Format the date using toLocaleDateString - const formattedDate = dateObject.toLocaleDateString('fr-FR', { - day: '2-digit', - month: 'long', - year: 'numeric' - }) - - return formattedDate - } - - /** - * data column, header of the grid - */ - const columns = [ - { field: 'nom', headerName: 'Nom', width: 180 }, - { field: 'prenom', headerName: 'Prenom', width: 180 }, - { field: 'sexe', headerName: 'Sexe', width: 80 }, - { field: 'cin', headerName: 'CIN', width: 180 }, - { field: 'date_deli', headerName: 'Date de delivrance', width: 80 }, - { field: 'nation', headerName: 'Natoinalité', width: 120 }, - { field: 'annee_bacc', headerName: 'Année du Baccalauréat', width: 80 }, - { field: 'serie', headerName: 'Série', width: 80 }, - { field: 'bourse', headerName: 'Boursier', width: 80 }, - { field: 'domaine', headerName: 'Domaine', width: 180 }, - { field: 'contact', headerName: 'Contact', width: 180 }, - { field: 'niveau', headerName: 'Niveau', width: 80 }, - { field: 'date_naissance', headerName: 'Date de naissance', width: 130 }, - { field: 'annee_scolaire', headerName: 'Année univarsitaire', width: 130 }, - { field: 'status', headerName: 'Status', width: 140 }, - { field: 'num_inscription', headerName: "Numéro d'inscription", width: 160 }, - { field: 'parcour', headerName: 'Parcours', width: 150 }, - { - field: 'photos', - headerName: 'Image', - width: 100, - renderCell: (params) => ( - {'image - ) - }, - { - field: 'action', - headerName: 'Action', - width: 300, - renderCell: (params) => ( -
- - - - - - - Verification Frais de Formation - - - Print(params.value)}> - - - Exporter carte d'etudiants - - - - - - {/* Groupe 1 : Certificat */} - - - - - - Télecharger le Certificat de scolariter - - - - - {/* Groupe 2 : Stage (affiché seulement pour L2) */} - - {params.row.niveau !== 'L1' && ( - - - - Télecharger l'autorisation de stage - - - )} - - - - Télecharger le recepissé d'inscription - - - - - -
- ) - } - ] - - const Print = async (id) => { - console.log(id) - let etudiant = await window.etudiants.getSingle({ id }) - - if (etudiant) { - let data = { - f1: `${etudiant.nom} ${etudiant.prenom}`, - f2: `Naissances: ${dayjs(etudiant.date_de_naissances).format('DD-MM-YYYY')}`, - f3: `Niveau: ${etudiant.niveau}`, - f4: `Année: ${etudiant.annee_scolaire}`, - f5: `Inscription: ${etudiant.num_inscription}`, - f8: etudiant.photos - } - processPdf(data) - // PDFEditor(data); - } - } - - // const paginationModel = { page: 0, pageSize: 20 } - const [pageSize, setPageSize] = useState(20) - const [pageSizeOptions, setPageSizeOptions] = useState([20, 40, 60]) - - const handlePageSizeChange = (newPageSize) => { - setPageSize(newPageSize) - - // If the user picked the largest value, add next +20 - const maxOption = Math.max(...pageSizeOptions) - if (newPageSize === maxOption) { - setPageSizeOptions((prev) => [...prev, maxOption + 20]) - } - } - - // Ensure that the array is flat (not wrapped in another array) - const dataRow = etudiants.map((etudiant) => ({ - id: etudiant.id, // Ensure this exists and is unique for each etudiant - nom: etudiant.nom, - prenom: etudiant.prenom, - niveau: etudiant.niveau, - date_naissance: dayjs(etudiant.date_de_naissances).format('DD-MM-YYYY'), - annee_scolaire: etudiant.annee_scolaire, - status: comparestatut(etudiant.status), - num_inscription: etudiant.num_inscription, - parcour: etudiant.parcours == null ? 'Pas de parcours' : etudiant.parcours, - photos: etudiant.photos, - sexe: etudiant.sexe, - cin: etudiant.cin, - date_deli: dayjs(etudiant.date_delivrance).format('DD-MM-YYYY'), - nation: etudiant.nationalite, - annee_bacc: etudiant.annee_bacc, - serie: etudiant.serie, - bourse: etudiant.boursier, - domaine: etudiant.domaine, - contact: etudiant.contact, - mention_id: etudiant.mention_id, - action: etudiant.id // Ensure this is a valid URL for the image - })) - - function comparestatut(statutID) { - let statusText - - status.map((statu) => { - if (statutID == statu.id) { - statusText = statu.nom - } - }) - return statusText - } - - /** - * function to filter the data in dataGrid by Niveau - */ - const FilterData = async (e) => { - let niveau = e.target.value - if (niveau !== '') { - let data = await window.etudiants.FilterDataByNiveau({ niveau }) - setEtudiants(data) - } else { - window.etudiants.getEtudiants().then((response) => { - setEtudiants(response) - }) - } - } - - const [openModal, setOpenModal] = useState(false) - const [openModal2, setOpenModal2] = useState(false) - const [openModal3, setOpenModal3] = useState(false) - const [json, setJson] = useState() - const [json2, setJson2] = useState() - const [nom, setNom] = useState([]) - const [nom2, setNom2] = useState([]) - - const handleOpen = (id) => { - window.etudiants.getSingle({ id }).then((response) => { - setNom(response) - }) - setOpenModal(true) - } - - const handleOpen3 = (id) => { - window.etudiants.getSingle({ id }).then((response) => { - setNom2(response) - }) - setOpenModal3(true) - } - - const handleOpen2 = () => { - setOpenModal2(true) - } - - function compareMention(mentionID) { - let statusText - - mention.map((statu) => { - if (mentionID == statu.id) { - statusText = statu.nom - } - }) - - return statusText ? statusText.charAt(0).toUpperCase() + statusText.slice(1) : statusText - } - - useEffect(() => { - setJson({ - nomPrenom: nom.nom + ' ' + nom.prenom, - naissances: nom.date_de_naissances, - mention: compareMention(nom.mention_id), - niveau: nom.niveau, - annee: nom.annee_scolaire, - inscri: nom.num_inscription - }) - }, [nom]) - - useEffect(() => { - setJson2({ - nomPrenom: nom.nom + ' ' + nom.prenom, - mention: compareMention(nom.mention_id), - niveau: nom.niveau, - annee: nom.annee_scolaire, - inscri: nom.num_inscription - }) - }, [nom2]) - - const handleClose = () => setOpenModal(false) - const handleClose2 = () => setOpenModal2(false) - const handleClose3 = () => setOpenModal3(false) - - return ( -
- -
-
-
-

Etudiants

- - - -
-
- {/* bare des filtre */} -
- {/* filtre par niveau */} -
- - - Niveau - - - -
-
-
- - {/* display the data-grid students */} -
-
- - -
- handlePageSizeChange(model.pageSize)} - sx={{ - border: 0, - width: 'auto', // Ensures the DataGrid takes full width - height: '50%', // Ensures it grows to fit content - minHeight: 400, // Minimum height for the DataGrid - display: 'flex', - justifyContent: 'center', - '@media (max-width: 600px)': { - width: '100%', // 100% width on small screens - height: 'auto' // Allow height to grow with content - } - }} - slots={{ toolbar: GridToolbar }} - localeText={frFR.components.MuiDataGrid.defaultProps.localeText} - /> -
-
-
- - - -
-
-
- ) -} - -export default Student diff --git a/src/renderer/src/components/SystemeNote.jsx b/src/renderer/src/components/SystemeNote.jsx deleted file mode 100644 index e3029f6..0000000 --- a/src/renderer/src/components/SystemeNote.jsx +++ /dev/null @@ -1,365 +0,0 @@ -import React, { useEffect, useRef, useState } from 'react' -import classe from '../assets/AllStyleComponents.module.css' -import classeAdd from '../assets/AddStudent.module.css' -import classeHome from '../assets/Home.module.css' -import { IoMdPersonAdd, IoMdReturnRight } from 'react-icons/io' -import { Link } from 'react-router-dom' -import { Box, Button, InputAdornment, Typography, Modal, TextField, Grid } from '@mui/material' -import { CgNotes } from 'react-icons/cg' -import { FaAngleDoubleUp, FaAngleDoubleDown, FaCog } from 'react-icons/fa' -import validateNOteSystem from './validation/NoteSystem' -import svgError from '../assets/error.svg' -import svgSuccess from '../assets/success.svg' -import { Tooltip } from 'react-tooltip' -import ModalFormMultiplicateur from './ModalFormMultiplicateur' - -const SystemeNote = () => { - const [formData, setFormData] = useState({ - id: '', - admis: '', - redouble: '', - renvoyer: '' - }) - - const [noteSy, setNoteSy] = useState([]) - const [status, setStatus] = useState(200) - - /** - * function to set the data in state - * @param {*} e - */ - const handleInputChange = (e) => { - const { name, value } = e.target - setFormData((prevData) => ({ - ...prevData, - [name]: value - })) - } - - useEffect(() => { - window.notesysteme.getSyteme().then((response) => { - setNoteSy(response) - }) - }, []) - - useEffect(() => { - if (noteSy) { - setFormData({ - id: noteSy.id, - admis: noteSy.admis || 0, - redouble: noteSy.redouble || 0, - renvoyer: noteSy.renvoyer || 0 - }) - } - }, [noteSy]) - - console.log(noteSy) - - const formSubmit = async (e) => { - e.preventDefault() - let valid = validateNOteSystem(admisRef.current, redoubleRef.current, renvoyerRef.current) - - if (valid) { - let response = await window.notesysteme.updateNoteSysteme(formData) - console.log(response) - if (response.success) { - setStatus(200) - setOpen(true) - } - } else { - setStatus(400) - setOpen(true) - } - } - - const admisRef = useRef() - const redoubleRef = useRef() - const renvoyerRef = useRef() - - /** - * hook to open modal - */ - const [open, setOpen] = useState(false) - - /** - * function to close modal - */ - const handleClose = () => setOpen(false) - - /** - * function to return the view Modal - * - * @returns {JSX} - */ - const modals = () => ( - - - {status === 200 ? ( - - {' '} - Modification des notes a été effectuée avec succès - - ) : ( - - {' '} - Vérifiez les champs vides ou les séparateurs (doivent être un point) - - )} - - - - - - ) - - const [openForm, setOpenForm] = useState(false) - - const closeForm = () => { - setOpenForm(false) - } - - const openThisForm = () => { - setOpenForm(true) - } - - return ( -
- - {modals()} - -
-
-
-

- - Système d'organisation des notes -

- - - - - Changer le multiplicateur (credit * M) - -
-
-
-
- - -
- - - - - - - - - - - - - - - - - -
Status :AdmisRedoubleRenvoyer
Notes : - {/* */} - - - - - ), - endAdornment: ( - - - - ) - }} - inputRef={admisRef} - sx={{ - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800' // Set the border color on hover - } - }, - '& .MuiInputBase-input::placeholder': { - fontSize: '11px' // Set the placeholder font size - } - }} - /> - - {/* */} - - {/* */} - - - - - ), - endAdornment: ( - - - - ) - }} - inputRef={redoubleRef} - sx={{ - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800' // Set the border color on hover - } - }, - '& .MuiInputBase-input::placeholder': { - fontSize: '11px' // Set the placeholder font size - } - }} - /> - - {/* */} - - {/* */} - - - - - ), - endAdornment: ( - - - - ) - }} - inputRef={renvoyerRef} - sx={{ - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800' // Set the border color on hover - } - }, - '& .MuiInputBase-input::placeholder': { - fontSize: '11px' // Set the placeholder font size - } - }} - /> - - {/* */} -
- - - -
-
-
-
-
- ) -} - -export default SystemeNote diff --git a/src/renderer/src/components/TesteDatagrid.jsx b/src/renderer/src/components/TesteDatagrid.jsx deleted file mode 100644 index 3ea96c7..0000000 --- a/src/renderer/src/components/TesteDatagrid.jsx +++ /dev/null @@ -1,458 +0,0 @@ -import React, { useEffect, useRef, useState } from 'react' -import classe from '../assets/AllStyleComponents.module.css' -import classeHome from '../assets/Home.module.css' -import Paper from '@mui/material/Paper' -import entete from '../assets/enteterelever.png' -import jsPDF from 'jspdf' -import html2Canvas from 'html2canvas' - -const TesteDatagrid = ({ id, niveau, annee_scolaire, nomPrenom, inscription, refs }) => { - const [print, setPrint] = useState(refs) - const paperRef = useRef() - - const [teste, setTeste] = useState([]) - useEffect(() => { - window.notes.noteMatiere({ id, niveau, annee_scolaire }).then((response) => { - setTeste(response) - }) - }, [id, niveau, annee_scolaire]) - - console.log(teste) - - useEffect(() => { - if (refs) { - let certificat = paperRef.current - html2Canvas(certificat, { scale: 3 }).then((canvas) => { - const URLimg = canvas.toDataURL() - const doc = new jsPDF('portrait', 'mm', 'a4') - const width = doc.internal.pageSize.getWidth() - const height = doc.internal.pageSize.getHeight() - doc.addImage(URLimg, 'PNG', 0, 0, width, height) - doc.save(`releve_${nomPrenom}.pdf`) - }) - } - }, [refs]) - - // Step 1: Group by semestre - const groupedBySemestre = teste.reduce((acc, item) => { - const { semestre, unite_enseignement } = item - - // Ensure a group exists for this `semestre` - if (!acc[semestre]) { - acc[semestre] = {} - } - - // Step 2: Further group by unite_enseignement - if (!acc[semestre][unite_enseignement]) { - acc[semestre][unite_enseignement] = [] - } - - acc[semestre][unite_enseignement].push(item) // Add the item to the appropriate group - return acc - }, {}) - console.log(groupedBySemestre) - - // Initialize semestre1 and semestre2 - let semestre1 = {} - let semestre2 = {} - - // Separate groupedBySemestre into semestre1 and semestre2 dynamically - Object.keys(groupedBySemestre).forEach((semestre) => { - // Check if the semester is odd or even - if (parseInt(semestre.replace('S', '')) % 2 !== 0) { - // Odd semesters (S1, S3, S5, ...) - semestre1[semestre] = groupedBySemestre[semestre] - } else { - // Even semesters (S2, S4, S6, ...) - semestre2[semestre] = groupedBySemestre[semestre] - } - }) - - // Function to count the total elements in the groupedData - function countTotalElements(data) { - let totalCount = 0 - - // Iterate through each key in the object - Object.keys(data).forEach((key) => { - // Add the length of the array at the current key to totalCount - totalCount += data[key].length - }) - - return totalCount - } - - function crontCredit() { - let total = 0 - let credit = document.querySelectorAll('.classCredit') - for (let index = 0; index < credit.length; index++) { - total += Number(credit[index].textContent) - } - return total - } - - function countMoyenneGeneral() { - let total = 0 - let moyenne = document.querySelectorAll('.classMoyenne') - for (let index = 0; index < moyenne.length; index++) { - total += Number(moyenne[index].textContent) - } - - return (total / moyenne.length).toFixed(2) - } - - // Combine both semesters into one object to handle them together - const combinedSemesters = { ...semestre1, ...semestre2 } - - // Function to generate the rows - const generateTableRows = (semesters) => { - const rows = [] - - // Iterate over each semester's keys (S1, S2, etc.) - Object.keys(semesters).forEach((semestreKey) => { - const units = semesters[semestreKey] - - // Iterate over each unite_enseignement - Object.keys(units).forEach((unitKey, idx) => { - const unitArray = units[unitKey] - const isFirstRow = idx === 0 // Check if it's the first row for this unit - - unitArray.forEach((item, itemIdx) => { - rows.push( - - {isFirstRow && itemIdx === 0 ? ( - - {semestreKey} - - ) : null} - - {itemIdx === 0 ? ( - - {unitKey} - - ) : null} - - - {item.nom} - - - {' '} - {item.credit} - - - {item.note} - - - {/* Ensure this renders only once for the unitArray */} - {itemIdx === 0 ? ( - - - {( - unitArray.reduce((sum, item) => sum + item.credit * item.note, 0) / - unitArray.reduce((sum, item) => sum + item.credit, 0) - ).toFixed(2)} - - - ) : null} - - ) - }) - }) - }) - return rows - } - - return ( -
-
-
- -
- image en tete -
-
- ECOLE SUPERIEURE POLYTECHNIQUE - REPOBLIKAN’I MADAGASIKARA - Fitiavana-Tanindrazana-Fandrosoana - ********************* -

RELEVÉE DE NOTE

-
-
-
- Nom & Prénoms: - {nomPrenom} -
-
- Année scolaire: - {annee_scolaire} - Niveau: - {niveau} - inscription: - {inscription} -
-
- - - - - - - - - - - - - {generateTableRows(combinedSemesters)} - - - - - - - - - - - - - - - - -
- Unités
d’Enseignement
(UE) -
- Eléments constitutifs - - Crédits - - Note - - Moyenne -
- {' '} - Total crédit: - - {crontCredit()} -
- Moyenne générale : - - {countMoyenneGeneral()} -
- Observation : - - -
-
-
- Décision de jury : - -
-

Le Directeur

-
-

RATSIMBAZAFY Christian Pierre

-
-
-
-
-
- ) -} - -export default TesteDatagrid diff --git a/src/renderer/src/components/TrancheEcolage.jsx b/src/renderer/src/components/TrancheEcolage.jsx deleted file mode 100644 index b209e57..0000000 --- a/src/renderer/src/components/TrancheEcolage.jsx +++ /dev/null @@ -1,194 +0,0 @@ -import React, { useEffect, useState } from 'react' -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 { IoMdReturnRight } from 'react-icons/io' -import AjoutTranche from './AjoutTranche' -import { Tooltip } from 'react-tooltip' -import { FaPenToSquare } from 'react-icons/fa6' -import { FaTrash } from 'react-icons/fa' -import UpdateTranche from './UpdateTranche' -import DeleteTranche from './DeleteTranche' - -const TrancheEcolage = () => { - const { id } = useParams() - const [tranche, setTranche] = useState([]) - const [etudiant, setEtudiant] = useState({}) - - useEffect(() => { - window.etudiants.getTranche({ id }).then((response) => { - setTranche(response) - }) - - window.etudiants.getSingle({ id }).then((response) => { - setEtudiant(response) - }) - }, []) - - const [openAdd, setOpenAdd] = useState(false) - const onCloseAdd = () => setOpenAdd(false) - - const openAddFunction = () => { - setOpenAdd(true) - } - - const [isSubmited, setIsSubmited] = useState(false) - const handleFormSubmit = (status) => { - setIsSubmited(status) - } - - const [openUpdate, setOpenUpdate] = useState(false) - const onCloseUpdate = () => setOpenUpdate(false) - const [idToSend, setIdToSend] = useState(null) - const [idToSend2, setIdToSend2] = useState(null) - - const openUpdateFunction = (id) => { - setOpenUpdate(true) - setIdToSend(id) - } - - const [openDelete, setOpenDelete] = useState(false) - const onCloseDelete = () => setOpenDelete(false) - const openDeleteFunction = (id) => { - setOpenDelete(true) - setIdToSend2(id) - } - - useEffect(() => { - if (isSubmited) { - window.etudiants.getTranche({ id }).then((response) => { - setTranche(response) - }) - setIsSubmited(false) - } - }, [isSubmited]) - - return ( -
- - - -
-
-
-

Tranche d'Ecolage

-
- - - - window.history.back()}> - - -
-
-
-
- -
- - - - - - - - - - - - - - - {tranche.map((tranch, index) => ( - - - - - - - ))} - -
-
- Evolution d'écolage de {etudiant.nom} {etudiant.prenom} -
-
Tranche N°DésignationMontantAction
{index + 1}{tranch.tranchename}{Number(tranch.montant).toLocaleString(0, 3)} - - -
-
-
-
- ) -} - -export default TrancheEcolage diff --git a/src/renderer/src/components/UpdateModalProf.jsx b/src/renderer/src/components/UpdateModalProf.jsx deleted file mode 100644 index ba8c3b7..0000000 --- a/src/renderer/src/components/UpdateModalProf.jsx +++ /dev/null @@ -1,179 +0,0 @@ -import React, { useEffect, useRef, useState } from 'react' -import { - Dialog, - DialogActions, - DialogContent, - DialogTitle, - TextField, - Button, - InputAdornment, - Box, - Grid -} from '@mui/material' -import ChangeCapital from './function/ChangeCapitalLetter' -import ChangeCapitalize from './function/ChangeCapitalizeLetter' -import { PiChalkboardTeacher } from 'react-icons/pi' -import { MdContactPhone, MdDateRange } from 'react-icons/md' - -const UpdateModalProf = ({ open, onClose, matiere_id, onSubmitSuccess }) => { - const [formData, setFormData] = useState({ - nom_enseignant: '', - prenom_enseignant: '', - contact: '', - date: '', - matiere_id: '' - }) - - const nomRefs = useRef() - const prenomRefs = useRef() - - const handleChange = (e) => { - const { name, value } = e.target - setFormData({ ...formData, [name]: value }) - } - - useEffect(() => { - let id = matiere_id - if (id !== '') { - window.matieres.getSingleProf({ id }).then((response) => { - setFormData((prev) => ({ - ...prev, - nom_enseignant: response.nom_enseignant, - prenom_enseignant: response.prenom_enseignant, - contact: response.contact, - date: response.date, - matiere_id: matiere_id - })) - }) - } - }, [matiere_id]) - - const handleSubmit = async (e) => { - e.preventDefault() - let response = await window.matieres.updateProf(formData) - - if (response.success) { - onSubmitSuccess(true) - onClose() // Close the modal after submission - } - } - - return ( - -
- mise à jour enseignant - - - - - ChangeCapital(nomRefs)} - onChange={handleChange} - InputProps={{ - startAdornment: ( - - - - ) - }} - /> - - - ChangeCapitalize(prenomRefs)} - onChange={handleChange} - InputProps={{ - startAdornment: ( - - - - ) - }} - /> - - - - - - ) - }} - /> - - - - - - ) - }} - /> - - - - - - - - -
-
- ) -} - -export default UpdateModalProf diff --git a/src/renderer/src/components/UpdateParcour.jsx b/src/renderer/src/components/UpdateParcour.jsx deleted file mode 100644 index 28bccf6..0000000 --- a/src/renderer/src/components/UpdateParcour.jsx +++ /dev/null @@ -1,178 +0,0 @@ -import React, { useEffect, useRef, useState } from 'react' -import { - Dialog, - DialogActions, - DialogContent, - DialogTitle, - TextField, - Button, - Autocomplete, - InputAdornment, - Box, - Grid -} from '@mui/material' -import { MdRule } from 'react-icons/md' -import { FaClipboardList } from 'react-icons/fa' - -const AddParcours = ({ open, onClose, onSubmitSuccess, id }) => { - const [formData, setFormData] = useState({ - nom: '', - uniter: '', - mention_id: '', - id: '' - }) - - const [mention, setMention] = useState([]) - const [parcour, setParcour] = useState([]) - - useEffect(() => { - window.mention.getMention().then((response) => { - setMention(response) - }) - }, []) - - useEffect(() => { - if (id) { - window.notesysteme.getSingleParcours({ id }).then((response) => { - setParcour(response) - }) - } - }, [id]) - - useEffect(() => { - if (parcour) { - setFormData({ - nom: parcour.nom, - uniter: parcour.uniter, - mention_id: parcour.mention_id, - id: parcour.id - }) - } - }, [parcour]) - - const handleChange = (e) => { - const { name, value } = e.target - setFormData({ ...formData, [name]: value }) - } - - const handleSubmit = async (e) => { - e.preventDefault() - let response = await window.notesysteme.updateParcours(formData) - - if (response.success) { - onSubmitSuccess(true) - onClose() // Close the modal after submission - } - } - - return ( - -
- Mise à jour du parcour - - - - - - - - ) - }} - /> - - - - - - ) - }} - /> - - - option.nom || ''} // Safely access `nom` - value={mention.find((item) => item.id === formData.mention_id) || null} // Bind selected value to form data - onChange={(event, newValue) => { - setFormData((prevData) => ({ - ...prevData, - mention_id: newValue ? newValue.id : null // Store the ID of the selected mention - })) - }} - isOptionEqualToValue={(option, value) => option.id === value.id} // Ensure correct matching of options - renderInput={(params) => ( - - - - - {params.InputProps.startAdornment} - - ) - }} - sx={{ - marginBottom: '5px', - '& .MuiOutlinedInput-root': { - '&:hover fieldset': { - borderColor: '#ff9800' // Set border color on hover - } - } - }} - /> - )} - /> - - - - - - - - -
-
- ) -} - -export default AddParcours diff --git a/src/renderer/src/components/UpdateTranche.jsx b/src/renderer/src/components/UpdateTranche.jsx deleted file mode 100644 index be70be6..0000000 --- a/src/renderer/src/components/UpdateTranche.jsx +++ /dev/null @@ -1,128 +0,0 @@ -import React, { useEffect, useState } from 'react' -import { - Dialog, - DialogActions, - DialogContent, - DialogTitle, - TextField, - Button, - Autocomplete, - InputAdornment, - Box, - Grid -} from '@mui/material' -import { MdLabelImportantOutline } from 'react-icons/md' - -const UpdateTranche = ({ open, onClose, onSubmitSuccess, id }) => { - const [formData, setFormData] = useState({ - id: id, - tranchename: '', - montant: '' - }) - const [tranche, setTranche] = useState([]) - - useEffect(() => { - if (id !== null) { - window.etudiants.getSingleTranche({ id }).then((response) => { - setTranche(response) - }) - setFormData({ - id: id - }) - } - }, [id]) - - useEffect(() => { - setFormData((prev) => ({ - ...prev, - tranchename: tranche.tranchename || '', - montant: tranche.montant || '' - })) - }, [tranche]) - - const handleChange = (e) => { - const { name, value } = e.target - setFormData({ ...formData, [name]: value }) - } - - const handleSubmit = async (e) => { - e.preventDefault() - console.log(formData) - let response = await window.etudiants.updateTranche(formData) - - if (response.changes) { - onClose() - onSubmitSuccess(true) - } - } - - return ( - -
- Ajout tranche - - - - - - - - ) - }} - /> - - - - - - ) - }} - /> - - - - - - - - -
-
- ) -} - -export default UpdateTranche diff --git a/src/renderer/src/components/function/CalculNote.js b/src/renderer/src/components/function/CalculNote.js deleted file mode 100644 index e0fb7fb..0000000 --- a/src/renderer/src/components/function/CalculNote.js +++ /dev/null @@ -1,5 +0,0 @@ -const calculNote = (note, coeficient) => { - return note * coeficient -} - -export default calculNote diff --git a/src/renderer/src/components/function/ChangeCapitalLetter.js b/src/renderer/src/components/function/ChangeCapitalLetter.js deleted file mode 100644 index 70fee34..0000000 --- a/src/renderer/src/components/function/ChangeCapitalLetter.js +++ /dev/null @@ -1,7 +0,0 @@ -const ChangeCapital = (ref) => { - if (ref.current) { - ref.current.value = ref.current.value.toUpperCase() - } -} - -export default ChangeCapital diff --git a/src/renderer/src/components/function/ChangeCapitalizeLetter.js b/src/renderer/src/components/function/ChangeCapitalizeLetter.js deleted file mode 100644 index 4f33dd5..0000000 --- a/src/renderer/src/components/function/ChangeCapitalizeLetter.js +++ /dev/null @@ -1,11 +0,0 @@ -const ChangeCapitalize = (ref) => { - if (ref.current) { - ref.current.value = ref.current.value - .toLowerCase() // Ensure all text is lowercase first - .split(' ') // Split the text into words by spaces - .map((word) => word.charAt(0).toUpperCase() + word.slice(1)) // Capitalize the first letter of each word - .join(' ') // Join the words back with spaces - } -} - -export default ChangeCapitalize diff --git a/src/renderer/src/components/function/FonctionRelever.js b/src/renderer/src/components/function/FonctionRelever.js deleted file mode 100644 index 19b23d8..0000000 --- a/src/renderer/src/components/function/FonctionRelever.js +++ /dev/null @@ -1,41 +0,0 @@ -export const getmentionAfterNotes = (notes) => { - if (notes >= 10 && notes < 12) { - return 'Passable' - } else if (notes >= 12 && notes < 14) { - return 'Assez bien' - } else if (notes >= 14 && notes < 16) { - return 'Bien' - } else if (notes >= 16) { - return 'Très bien' - } else { - return 'Insuffisant' - } -} - -function nextLevel(niveau) { - if (niveau == 'L1') { - return 'L2' - } else if (niveau == 'L2') { - return 'L3' - } else if (niveau == 'L3') { - return 'M1' - } else if (niveau == 'M1') { - return 'M2' - } else if (niveau == 'M2') { - return 'D1' - } else if (niveau == 'D1') { - return 'D2' - } else if (niveau == 'D2') { - return 'D3' - } else if (niveau == 'D3') { - return 'PHD' - } -} - -export const descisionJury = (notes, niveau) => { - if (notes >= 10) { - return `Admis en ${nextLevel(niveau)}` - } else { - return 'Vous redoublez' - } -} diff --git a/src/renderer/src/components/function/GenerateFiche.js b/src/renderer/src/components/function/GenerateFiche.js deleted file mode 100644 index cc49023..0000000 --- a/src/renderer/src/components/function/GenerateFiche.js +++ /dev/null @@ -1,94 +0,0 @@ -import { PDFDocument, rgb, StandardFonts } from 'pdf-lib' - -export const generatePDF = async (students) => { - // Sort by NomPrenom alphabetically - const sortedStudents = students.sort((a, b) => a.nom.localeCompare(b.nom)) - - // function compareMention(id) { - // let mentionText; - // mentions.map((ment) => { - // if (id == ment.id) { - // mentionText = ment.nom - // } - // }) - - // return mentionText; - // } - const pdfDoc = await PDFDocument.create() - const pageWidth = 595 // A4 width in points - const pageHeight = 842 // A4 height in points - const margin = 40 - const fontSize = 12 - const rowHeight = 25 - const tableStartY = pageHeight - margin - 50 - const maxRowsPerPage = Math.floor((tableStartY - margin) / rowHeight) - - const font = await pdfDoc.embedFont(StandardFonts.Helvetica) - const page = pdfDoc.addPage([pageWidth, pageHeight]) - - let y = tableStartY - let rowCount = 0 - - // Add Table Headers - page.drawText('Nom matieres', { - x: pageWidth / 2 - 50, - y, - size: 16, - font, - color: rgb(0, 0, 0) - }) - - y -= 30 - - const headers = ['N°', 'Nom et Prénom', 'Mention', 'Émergement'] - const columnWidths = [50, 200, 100, 100] - const xPositions = [ - margin, - margin + columnWidths[0], - margin + columnWidths[0] + columnWidths[1], - margin + columnWidths[0] + columnWidths[1] + columnWidths[2] - ] - - headers.forEach((header, index) => { - page.drawText(header, { x: xPositions[index], y, size: fontSize, font, color: rgb(0, 0, 0) }) - }) - - y -= rowHeight - - // Function to add a new page when needed - const addNewPage = () => { - const newPage = pdfDoc.addPage([pageWidth, pageHeight]) - y = tableStartY - rowCount = 0 - return newPage - } - - // Loop through student data and populate the table - sortedStudents.forEach((student, index) => { - if (rowCount >= maxRowsPerPage) { - page = addNewPage() - } - - const rowData = [ - (index + 1).toString(), - `${student.nom} ${student.prenom}`, - student.mention, - '' - ] - - rowData.forEach((text, i) => { - page.drawText(text, { x: xPositions[i], y, size: fontSize, font, color: rgb(0, 0, 0) }) - }) - - y -= rowHeight - rowCount++ - }) - - // Save and download PDF - const pdfBytes = await pdfDoc.save() - const blob = new Blob([pdfBytes], { type: 'application/pdf' }) - const link = document.createElement('a') - link.href = URL.createObjectURL(blob) - link.download = 'student_list.pdf' - link.click() -} diff --git a/src/renderer/src/components/function/GetSemestre.js b/src/renderer/src/components/function/GetSemestre.js deleted file mode 100644 index 5542db6..0000000 --- a/src/renderer/src/components/function/GetSemestre.js +++ /dev/null @@ -1,23 +0,0 @@ -function getSemestre(niveau) { - if (niveau === 'L1') { - return ['S1', 'S2'] - } else if (niveau === 'L2') { - return ['S3', 'S4'] - } else if (niveau === 'L3') { - return ['S5', 'S6'] - } else if (niveau === 'M1') { - return ['S7', 'S8'] - } else if (niveau === 'M2') { - return ['S9', 'S10'] - } else if (niveau === 'D') { - return ['S11', 'S12'] - } else if (niveau === 'D2') { - return ['S13', 'S14'] - } else if (niveau === 'D3') { - return ['S15', 'S16'] - } else { - return [] // Return an empty array if the niveau is not found - } -} - -export default getSemestre diff --git a/src/renderer/src/components/function/PDFEditor.js b/src/renderer/src/components/function/PDFEditor.js deleted file mode 100644 index ea82ea5..0000000 --- a/src/renderer/src/components/function/PDFEditor.js +++ /dev/null @@ -1,134 +0,0 @@ -import { PDFDocument } from 'pdf-lib' -import { saveAs } from 'file-saver' -import pdf from '../../assets/carte_etudiant.pdf' -import pdf2 from '../../assets/arriere.pdf' -import pdf3 from '../../assets/business_card_template_001_form.pdf' -import QRCode from 'qrcode' - -const PDFEditor = async (data) => { - // Load the existing PDF files - const existingPdfBytes = await fetch(pdf).then((res) => res.arrayBuffer()) - const existingPdfBytes2 = await fetch(pdf2).then((res) => res.arrayBuffer()) - const existingPdfBytes3 = await fetch(pdf3).then((res) => res.arrayBuffer()) - - // Load the PDFs - const pdfDoc = await PDFDocument.load(existingPdfBytes) - const pdfDoc2 = await PDFDocument.load(existingPdfBytes2) - const pdfDoc3 = await PDFDocument.load(existingPdfBytes3) - - // Get the form from the first PDF (front) - const form = pdfDoc.getForm() - 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('num_inscription').setText("Numéro d'inscription: " + data.f5) - form.flatten() - - // ----------------------------------------- carte frontale ---------------------------------------------------- - const canvas = document.createElement('canvas') - const context = canvas.getContext('2d') - const diameter = 90 - const resolutionScale = 4 - canvas.width = diameter * resolutionScale - canvas.height = diameter * resolutionScale - - const base64Data = data.f8.split(',')[1] - const img = new Image() - img.src = `data:image/png;base64,${base64Data}` - - await new Promise((resolve) => { - img.onload = resolve - }) - - context.scale(resolutionScale, resolutionScale) - context.beginPath() - context.arc(diameter / 2, diameter / 2, diameter / 2, 0, Math.PI * 2) - context.closePath() - context.clip() - context.drawImage(img, 0, 0, diameter, diameter) - - const canvasImageBase64 = canvas.toDataURL('image/png') - const canvasImageBytes = Uint8Array.from(atob(canvasImageBase64.split(',')[1]), (char) => - char.charCodeAt(0) - ) - - const image = await pdfDoc.embedPng(canvasImageBytes) - const page = pdfDoc.getPage(0) - page.drawImage(image, { - x: 74 - diameter / 2, - y: 77 - diameter / 2, - width: diameter, - height: diameter - }) - - const form2 = pdfDoc2.getForm() - const form3 = pdfDoc3.getForm() - const field = form2.getField('f6') - if (field) { - form2.removeField(field) - form3.removeField(field) - } - - // ----------------------------------------------- carte arriere ------------------------------------------- - const paperContent = ` - CUniversity - Nom et prénom: ${data.f1} - Date de naissance: ${data.f2} - Niveau: ${data.f3} - Année scolaire: ${data.f4} - Numéro d'inscription: ${data.f5} - ` - - const qrCanvas = document.createElement('canvas') - const qrWidth = 300 - QRCode.toCanvas( - qrCanvas, - paperContent, - { errorCorrectionLevel: 'H', width: qrWidth }, - (error) => { - if (error) { - console.error(error) - return - } - - const qrImageBase64 = qrCanvas.toDataURL('image/png') - const qrImageBytes = Uint8Array.from(atob(qrImageBase64.split(',')[1]), (char) => - char.charCodeAt(0) - ) - - ;(async () => { - const page2 = pdfDoc2.getPage(0) - const qrImage = await pdfDoc2.embedPng(qrImageBytes) - - const x = 7 - const y = 75 - const qrSize = 95 - - page2.drawImage(qrImage, { - x, - y, - width: qrSize, - height: qrSize - }) - - // Merge the front and back (pages) into a new document - const newPdfDoc = await PDFDocument.create() - // const [frontPage] = await newPdfDoc.copyPages(pdfDoc, [0]); // Front page - const [frontPage] = await newPdfDoc.copyPages(pdfDoc3, [0]) // Front page - const [backPage] = await newPdfDoc.copyPages(pdfDoc2, [0]) // Back page - - newPdfDoc.addPage(frontPage) - newPdfDoc.addPage(backPage) - - const pdfBytes = await newPdfDoc.save() - - // Trigger the download of the merged PDF - const blob = new Blob([pdfBytes], { type: 'application/pdf' }) - saveAs(blob, `carte_etudiant_${data.f1}.pdf`) - })() - } - ) -} - -export default PDFEditor diff --git a/src/renderer/src/components/function/PDFEditorCertificate.js b/src/renderer/src/components/function/PDFEditorCertificate.js deleted file mode 100644 index a0fbbc8..0000000 --- a/src/renderer/src/components/function/PDFEditorCertificate.js +++ /dev/null @@ -1,54 +0,0 @@ -import { PDFDocument } from 'pdf-lib' -import { saveAs } from 'file-saver' -import PDF from '../../assets/certificat scolariter.pdf' - -const PDFEditorCertificat = async (data) => { - function formatDate(dateString) { - const dateObject = new Date(dateString) - return dateObject.toLocaleDateString('fr-FR', { - day: '2-digit', - month: 'long', - year: 'numeric' - }) - } - - function writeniveau(niveaus) { - const niveauxMap = { - L1: '1e année de licences', - L2: '2e année de licences', - L3: '3e année de licences', - M1: '1e année de master', - M2: '2e année de master', - D1: '1e année en doctorat', - D2: '2e année en doctorat', - D3: '3e année en doctorat' - } - return niveauxMap[niveaus] || 'Niveau inconnu' - } - - const existingPdfBytes = await fetch(PDF).then((res) => res.arrayBuffer()) - - // Load the existing PDF - const pdfDoc = await PDFDocument.load(existingPdfBytes) - - // Get the form fields and fill them - const form = pdfDoc.getForm() - form.getTextField('f1').setText(data.f1) - form.getTextField('f2').setText(formatDate(data.f2)) - form.getTextField('f3').setText(data.f3) // Nom du père - form.getTextField('f4').setText(data.f4) // Nom de la mère - form.getTextField('f5').setText(writeniveau(data.f5)) - form.getTextField('f6').setText(data.f6) - form.getTextField('f7').setText(data.f7) - form.getTextField('f8').setText(data.f8) - form.getTextField('f9').setText(data.f9) // Nom du service - - // Save the modified PDF - const pdfBytes = await pdfDoc.save() - - // Trigger the download - const blob = new Blob([pdfBytes], { type: 'application/pdf' }) - saveAs(blob, `certificat_de_scolarite_${data.f1}.pdf`) -} - -export default PDFEditorCertificat diff --git a/src/renderer/src/components/function/PDFEditorRecepisse.js b/src/renderer/src/components/function/PDFEditorRecepisse.js deleted file mode 100644 index 9529704..0000000 --- a/src/renderer/src/components/function/PDFEditorRecepisse.js +++ /dev/null @@ -1,31 +0,0 @@ -import { PDFDocument } from 'pdf-lib' -import { saveAs } from 'file-saver' -import PDF from '../../assets/recepice.pdf' -import dayjs from 'dayjs' - -const PDFEditorRecepice = async (data) => { - const existingPdfBytes = await fetch(PDF).then((res) => res.arrayBuffer()) - const fullDate = dayjs().format('YYYY-MM-DD') - - // Load the existing PDF - const pdfDoc = await PDFDocument.load(existingPdfBytes) - - // Get the form fields and fill them - const form = pdfDoc.getForm() - form.getTextField('f1').setText(data.f1) - form.getTextField('f2').setText(data.f2) - form.getTextField('f3').setText(data.f3) - form.getTextField('f4').setText(data.f4) - form.getTextField('f5').setText(fullDate) - form.getTextField('f6').setText(data.f6) - form.getTextField('f7').setText(data.f7) - - // Save the modified PDF - const pdfBytes = await pdfDoc.save() - - // Trigger the download - const blob = new Blob([pdfBytes], { type: 'application/pdf' }) - saveAs(blob, `recepisser_${data.f3}.pdf`) -} - -export default PDFEditorRecepice diff --git a/src/renderer/src/components/function/PDFEditorStage.js b/src/renderer/src/components/function/PDFEditorStage.js deleted file mode 100644 index 617259a..0000000 --- a/src/renderer/src/components/function/PDFEditorStage.js +++ /dev/null @@ -1,27 +0,0 @@ -import { PDFDocument } from 'pdf-lib' -import { saveAs } from 'file-saver' -import PDF from '../../assets/autorisationstage.pdf' -import dayjs from 'dayjs' - -const PDFEditorStage = async (data) => { - const existingPdfBytes = await fetch(PDF).then((res) => res.arrayBuffer()) - - const fullDate = dayjs().format('YYYY-MM-DD') - - // Load the existing PDF - const pdfDoc = await PDFDocument.load(existingPdfBytes) - - // Get the form fields and fill them - const form = pdfDoc.getForm() - form.getTextField('f1').setText(data.f1) - form.getTextField('f2').setText(data.f1) - - // Save the modified PDF - const pdfBytes = await pdfDoc.save() - - // Trigger the download - const blob = new Blob([pdfBytes], { type: 'application/pdf' }) - saveAs(blob, `autorisation_stage${fullDate}.pdf`) -} - -export default PDFEditorStage diff --git a/src/renderer/src/components/function/PDFEditorV2.js b/src/renderer/src/components/function/PDFEditorV2.js deleted file mode 100644 index 5cf8899..0000000 --- a/src/renderer/src/components/function/PDFEditorV2.js +++ /dev/null @@ -1,151 +0,0 @@ -import { PDFDocument, PDFTextField } from 'pdf-lib' -import PDF from '../../assets/business_card_template_001_form.pdf' -import PDF2 from '../../assets/business_card_template_002.pdf' -import QRCode from 'qrcode' - -async function fillPdfFields(jsonData) { - const response = await fetch(PDF) // Load the PDF file - const response2 = await fetch(PDF2) // Load the second PDF file - const pdfBytes = await response.arrayBuffer() - const pdfBytes2 = await response2.arrayBuffer() - const pdfDoc = await PDFDocument.load(pdfBytes) - const pdfDoc2 = await PDFDocument.load(pdfBytes2) - const form = pdfDoc.getForm() - - const fields = form - .getFields() - .filter((field) => field instanceof PDFTextField) - .map((field) => ({ name: field.getName(), field })) - - const dataMapping = { - f1: jsonData.f1, - f2: jsonData.f2, - f3: jsonData.f3, - f4: jsonData.f4, - f5: jsonData.f5 - } - - // Fill text fields - Object.keys(dataMapping).forEach((key, index) => { - if (fields[index]) { - const { field } = fields[index] - field.setText(dataMapping[key] || '') - console.log(`Setting ${key}: ${dataMapping[key]} -> ${fields[index].name}`) - } - }) - - // ---------------------------------calculate and paste the image in pdf-------------------------------------- - if (jsonData.f8) { - const diameter = 90 - const resolutionScale = 4 - - const canvas = document.createElement('canvas') - const context = canvas.getContext('2d') - canvas.width = diameter * resolutionScale - canvas.height = diameter * resolutionScale - - const base64Data = jsonData.f8.startsWith('data:image') - ? jsonData.f8.split(',')[1] - : jsonData.f8 // Handle case where "data:image/png;base64," is missing - - const img = new Image() - await new Promise((resolve, reject) => { - img.onload = resolve - img.onerror = reject - img.src = `data:image/png;base64,${base64Data}` - }) - - context.scale(resolutionScale, resolutionScale) - context.beginPath() - context.arc(diameter / 2, diameter / 2, diameter / 2, 0, Math.PI * 2) - context.closePath() - context.clip() - context.drawImage(img, 0, 0, diameter, diameter) - - const canvasImageBase64 = canvas.toDataURL('image/png') - const image = await pdfDoc.embedPng(canvasImageBase64) - - const page = pdfDoc.getPage(0) - - page.drawImage(image, { - x: 186.4 - diameter / 2, // Keep the same X position - y: 90 - diameter / 2, // Keep the same Y position - width: diameter * 0.8, // Reduce size (e.g., 70% of original) - height: diameter * 0.8 // Reduce size (e.g., 70% of original) - }) - } - - // -------------------------------------------paste the qrCode in the pd-------------------------------------- - - const paperContent = ` - C-University - Nom et prénom: ${jsonData.f1} - Date de naissance: ${jsonData.f2} - Niveau: ${jsonData.f3} - Année scolaire: ${jsonData.f4} - Numéro d'inscription: ${jsonData.f5} - ` - - const qrCanvas = document.createElement('canvas') - const qrWidth = 300 - - QRCode.toCanvas( - qrCanvas, - paperContent, - { errorCorrectionLevel: 'H', width: qrWidth }, - (error) => { - if (error) { - console.error(error) - return - } - - const qrImageBase64 = qrCanvas.toDataURL('image/png') - const qrImageBytes = Uint8Array.from(atob(qrImageBase64.split(',')[1]), (char) => - char.charCodeAt(0) - ) - - ;(async () => { - const page2 = pdfDoc2.getPage(0) - const qrImage = await pdfDoc2.embedPng(qrImageBytes) - - const x = 4 - const y = 39 - const qrSize = 92 - - page2.drawImage(qrImage, { - x, - y, - width: qrSize, - height: qrSize - }) - - // Merge the front and back (pages) into a new document - const newPdfDoc = await PDFDocument.create() - // const [frontPage] = await newPdfDoc.copyPages(pdfDoc, [0]); // Front page - const [frontPage] = await newPdfDoc.copyPages(pdfDoc, [0]) // Front page - const [backPage] = await newPdfDoc.copyPages(pdfDoc2, [0]) // Back page - - newPdfDoc.addPage(frontPage) - newPdfDoc.addPage(backPage) - - const pdfBytes = await newPdfDoc.save() - - // Trigger the download of the merged PDF - const blob = new Blob([pdfBytes], { type: 'application/pdf' }) - saveAs(blob, `carte_etudiant_${jsonData.f1}.pdf`) - })() - } - ) - - // Serialize the PDF and return the modified document - const modifiedPdfBytes = await pdfDoc.save() - return modifiedPdfBytes -} - -/** - * function who export and filled PDF data - * @param {JSON} jsonData - */ -export const processPdf = async (jsonData) => { - await fillPdfFields(jsonData) -} diff --git a/src/renderer/src/components/function/PDFReader.jsx b/src/renderer/src/components/function/PDFReader.jsx deleted file mode 100644 index 5f85534..0000000 --- a/src/renderer/src/components/function/PDFReader.jsx +++ /dev/null @@ -1,18 +0,0 @@ -import {} from '@react-pdf-viewer/DefaultLayout' - -const PDFReader = () => { - return ( - - - - Section #1 - - - Section #2 - - - - ) -} - -export default PDFReader diff --git a/src/renderer/src/components/function/ProcessNote.js b/src/renderer/src/components/function/ProcessNote.js deleted file mode 100644 index 5199cf2..0000000 --- a/src/renderer/src/components/function/ProcessNote.js +++ /dev/null @@ -1,34 +0,0 @@ -// Function to process and combine notes -function ProcessNotes(notes) { - const groupedBySemestre = notes.reduce((acc, note) => { - if (!acc[note.semestre]) acc[note.semestre] = {} - if (!acc[note.semestre][note.ue]) acc[note.semestre][note.ue] = [] - - acc[note.semestre][note.ue].push(note) - return acc - }, {}) - - const result = {} - for (const semestre in groupedBySemestre) { - result[semestre] = [] - for (const ue in groupedBySemestre[semestre]) { - const elements = groupedBySemestre[semestre][ue] - const totalCredits = elements.reduce((sum, el) => sum + el.credit, 0) - const moyenne = elements.reduce((sum, el) => sum + el.note, 0) / elements.length - - elements.forEach((el, index) => { - result[semestre].push({ - ue, - element: el.element, - credits: el.credits, - note: el.note, - totalCredits: index === 0 ? totalCredits : '', // Only display on the first row for each UE - moyenne: index === 0 ? moyenne.toFixed(2) : '' // Only display on the first row for each UE - }) - }) - } - } - return result -} - -export default ProcessNotes diff --git a/src/renderer/src/components/validation/AddAdmin.js b/src/renderer/src/components/validation/AddAdmin.js deleted file mode 100644 index b89e52f..0000000 --- a/src/renderer/src/components/validation/AddAdmin.js +++ /dev/null @@ -1,53 +0,0 @@ -/** - * function to use to validate the add admin - * @param {*} username - * @param {*} email - * @param {*} password - * @param {*} usernameError - * @param {*} emailError - * @param {*} passwordError - * @returns Boolean - */ -const validationAddAdmin = ( - username, - email, - password, - usernameError, - emailError, - passwordError -) => { - let isValid = true - - const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/ - - // Email validation - if (email.value === '') { - isValid = false - emailError.textContent = 'Email est requis' - } else if (!emailPattern.test(email.value)) { - isValid = false - emailError.textContent = 'Entrez une adresse email valide' - } else { - emailError.textContent = '' - } - - // Password validation - if (password.value === '' || password.value.length < 6) { - isValid = false - passwordError.textContent = 'Le mot de passe doit comporter plus de 6 caractères.' - } else { - passwordError.textContent = '' - } - - // username validation - if (username.value === '') { - isValid = false - usernameError.textContent = 'username réquis.' - } else { - usernameError.textContent = '' - } - - return isValid -} - -export default validationAddAdmin diff --git a/src/renderer/src/components/validation/AddNiveau.js b/src/renderer/src/components/validation/AddNiveau.js deleted file mode 100644 index f907faa..0000000 --- a/src/renderer/src/components/validation/AddNiveau.js +++ /dev/null @@ -1,24 +0,0 @@ -/** - * - * @param {*} nom - * @param {*} error - * @param {Array} arrayNiveau - * @returns boolean - */ -const validationNote = (nom, error, arrayNiveau) => { - let isValid = true - - if (nom.value === '') { - error.textContent = 'Nom requis pour soumettre la formulaire' - isValid = false - } else if (arrayNiveau.includes(nom.value) === true) { - error.textContent = `${nom.value} existe déjà` - isValid = false - } else { - error.textContent = '' - } - - return isValid -} - -export default validationNote diff --git a/src/renderer/src/components/validation/AddNote.js b/src/renderer/src/components/validation/AddNote.js deleted file mode 100644 index 100b363..0000000 --- a/src/renderer/src/components/validation/AddNote.js +++ /dev/null @@ -1,25 +0,0 @@ -/** - * function used to validate add note - * @returns boolean - */ -const validateAddNote = () => { - let input = document.querySelectorAll('.inputAddNote input') - let isValid = false - let count = 0 - - for (let index = 0; index < input.length; index++) { - if (input[index].value == undefined || input[index].value == '') { - count += 1 - } - } - - if (count < input.length) { - isValid = true - } else { - isValid = false - } - - return isValid -} - -export default validateAddNote diff --git a/src/renderer/src/components/validation/ForgotPassword.js b/src/renderer/src/components/validation/ForgotPassword.js deleted file mode 100644 index 2e8b260..0000000 --- a/src/renderer/src/components/validation/ForgotPassword.js +++ /dev/null @@ -1,50 +0,0 @@ -/** - * function to make validation in the forgot password - * @param {*} email - * @param {*} password - * @param {*} passwordC - * @param {*} emailError - * @param {*} passwordError - * @param {*} passwordCError - */ -export const validationForgotPassword = ( - email, - password, - passwordC, - emailError, - passwordError, - passwordCError -) => { - let isValid = true - - const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/ - - // Email validation - if (email.value === '') { - isValid = false - emailError.textContent = 'Email est requis' - } else if (!emailPattern.test(email.value)) { - isValid = false - emailError.textContent = 'Entrez une adresse email valide' - } else { - emailError.textContent = '' - } - - // Password validation - if (password.value === '' || password.value.length < 6) { - isValid = false - passwordError.textContent = 'Le mot de passe doit comporter plus de 6 caractères.' - } else { - passwordError.textContent = '' - } - - // Confirm Password validation - if (passwordC.value !== password.value) { - isValid = false - passwordCError.textContent = 'Le mot de passe ne correspond pas.' - } else { - passwordCError.textContent = '' - } - - return isValid -} diff --git a/src/renderer/src/components/validation/Login.js b/src/renderer/src/components/validation/Login.js deleted file mode 100644 index f1b9a74..0000000 --- a/src/renderer/src/components/validation/Login.js +++ /dev/null @@ -1,50 +0,0 @@ -/** - * function to validate the email and password input - * - * @param {any} userNameRef - * @param {any} password - * @param {any} userNameError - * @param {any} passwordError - * @returns {boolean} - */ -export const ValidationLogin = (userNameRef, password, userNameError, passwordError) => { - let isValid = true - - // Validate username - if (userNameRef.value == '' || userNameRef.value == null) { - isValid = false - userNameError.textContent = "Entrer un nom d'utilisateur" - } - // Validate username - else if (password.value == '' || password.value.length < 6) { - passwordError.textContent = `mot de passe doit être plus de 6 caractères.` - isValid = false - } else { - isValid = true - userNameError.textContent = '' - passwordError.textContent = '' - } - - // remake varification username - if (userNameRef.value !== '') { - userNameError.textContent = '' - } - - // remake varification password - if (password.value.length > 6) { - passwordError.textContent = '' - } else { - passwordError.textContent = `mot de passe doit être plus de 6 caractères.` - } - - return isValid -} - -/** - * function to use when user submit an invalid information - * - * @param {any} userNameError - */ -export const invalidCredential = (userNameError, textC) => { - userNameError.textContent = textC -} diff --git a/src/renderer/src/components/validation/NoteSystem.js b/src/renderer/src/components/validation/NoteSystem.js deleted file mode 100644 index 85200c2..0000000 --- a/src/renderer/src/components/validation/NoteSystem.js +++ /dev/null @@ -1,29 +0,0 @@ -/** - * function to validate ours systeme note - * @param {*} admis - * @param {*} redouble - * @param {*} renvoyer - * @returns Boolean - */ -const validateNOteSystem = (admis, redouble, renvoyer) => { - let isValid = true - - // Check for 'admis' - if (admis.value === '' || isNaN(Number(admis.value))) { - isValid = false - } - - // Check for 'redouble' - if (redouble.value === '' || isNaN(Number(redouble.value))) { - isValid = false - } - - // Check for 'renvoyer' - if (renvoyer.value === '' || isNaN(Number(renvoyer.value))) { - isValid = false - } - - return isValid -} - -export default validateNOteSystem diff --git a/src/renderer/src/components/validation/ReleverDeNote.js b/src/renderer/src/components/validation/ReleverDeNote.js deleted file mode 100644 index 54e44de..0000000 --- a/src/renderer/src/components/validation/ReleverDeNote.js +++ /dev/null @@ -1,23 +0,0 @@ -/** - * function used to validate export relever de note - * @returns {Boolean} - */ -const ReleverDeNote = () => { - let allInput = document.querySelectorAll('.inputToValidateExport input') - let isValid = true - - /** - * each input we will test if there is an empty field, if there is an empty field - * then we will stop the script and send a false value instead of true - */ - for (let index = 0; index < allInput.length; index++) { - if (allInput[index].value == '') { - isValid = false - break - } - } - - return isValid -} - -export default ReleverDeNote diff --git a/src/renderer/src/components/validation/Setting.js b/src/renderer/src/components/validation/Setting.js deleted file mode 100644 index 0cb5930..0000000 --- a/src/renderer/src/components/validation/Setting.js +++ /dev/null @@ -1,74 +0,0 @@ -/** - * Function to use when user updates their profile - * - * @param {*} username - * @param {*} email - * @param {*} password - * @param {*} newPassword - * @param {*} usernameError - * @param {*} emailError - * @param {*} passwordError - * @param {*} newPasswordError - * @returns Boolean - */ -const validationSetting = ( - username, - email, - password, - newPassword, - usernameError, - emailError, - passwordError, - newPasswordError -) => { - let isValid = true - - const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/ - - // Email validation - if (email && email.value !== undefined) { - if (email.value === '') { - isValid = false - emailError.textContent = 'Email est requis' - } else if (!emailPattern.test(email.value)) { - isValid = false - emailError.textContent = 'Entrez une adresse email valide' - } else { - emailError.textContent = '' - } - } - - // Password validation - if (password && password.value !== undefined) { - if (password.value === '' || password.value.length < 6) { - isValid = false - passwordError.textContent = 'Le mot de passe doit comporter plus de 6 caractères.' - } else { - passwordError.textContent = '' - } - } - - // Username validation - if (username && username.value !== undefined) { - if (username.value === '') { - isValid = false - usernameError.textContent = 'Username requis.' - } else { - usernameError.textContent = '' - } - } - - // New password validation - if (newPassword && newPassword.value !== undefined) { - if (newPassword.value !== '' && newPassword.value.length < 6) { - isValid = false - newPasswordError.textContent = 'Le mot de passe doit comporter plus de 6 caractères.' - } else { - newPasswordError.textContent = '' - } - } - - return isValid -} - -export default validationSetting diff --git a/src/renderer/src/components/validation/SingleNiveau.js b/src/renderer/src/components/validation/SingleNiveau.js deleted file mode 100644 index 56ade01..0000000 --- a/src/renderer/src/components/validation/SingleNiveau.js +++ /dev/null @@ -1,24 +0,0 @@ -/** - * function to validate - * @param {*} nom - * @param {*} error - * @param {*} arrayNiveau - * @returns Boolean - */ -const validationSingleNiveau = (nom, error, arrayNiveau) => { - let isValid = true - - if (nom.value === '') { - error.textContent = 'Nom requis pour soumettre la formulaire' - isValid = false - } else if (arrayNiveau.includes(nom.value) === true) { - error.textContent = `${nom.value} existe déjà` - isValid = false - } else { - error.textContent = '' - } - - return isValid -} - -export default validationSingleNiveau diff --git a/src/renderer/src/components/validation/ValidationAddAnneeScolaire.js b/src/renderer/src/components/validation/ValidationAddAnneeScolaire.js deleted file mode 100644 index 3fab8d8..0000000 --- a/src/renderer/src/components/validation/ValidationAddAnneeScolaire.js +++ /dev/null @@ -1,18 +0,0 @@ -/** - * function validation année scolaire form - * @param {*} code - * @param {*} debut - * @param {*} fin - * @returns {Boolean} - */ -const validationAnneeScolaire = (code, debut, fin) => { - let isValid = true - - if (code.value === '' || debut.value === '' || fin.value === '') { - isValid = false - } - - return isValid -} - -export default validationAnneeScolaire diff --git a/src/renderer/src/components/validation/ValidationMatiereAdd.js b/src/renderer/src/components/validation/ValidationMatiereAdd.js deleted file mode 100644 index 4027123..0000000 --- a/src/renderer/src/components/validation/ValidationMatiereAdd.js +++ /dev/null @@ -1,25 +0,0 @@ -/** - * function to validate add matiere - * - * @param {*} nom - * @param {*} error - * @param {*} arrayMatiere - * @returns Boolean - */ -const validationMatiereAdd = (nom, error, arrayMatiere, creditRef) => { - let isValid = true - - if (nom.value === '' || creditRef.value === null || creditRef.value === '') { - error.textContent = 'les champs sont requis pour soumettre la formulaire' - isValid = false - } else if (arrayMatiere.includes(nom.value) === true) { - error.textContent = `${nom.value} existe déjà` - isValid = false - } else { - error.textContent = '' - } - - return isValid -} - -export default validationMatiereAdd diff --git a/src/renderer/src/contexts/AuthContext.jsx b/src/renderer/src/contexts/AuthContext.jsx deleted file mode 100644 index c963ce5..0000000 --- a/src/renderer/src/contexts/AuthContext.jsx +++ /dev/null @@ -1,38 +0,0 @@ -import { createContext, useContext, useState } from 'react' - -const AuthContext = createContext({ - user: null, - token: null, - setUser: () => {}, - setToken: () => {} -}) - -export const AuthContextProvider = ({ children }) => { - const [user, setUser] = useState() - const [token, _setToken] = useState(localStorage.getItem('ACCESS_TOKEN')) - - const setToken = (token) => { - _setToken(token) - - if (token) { - localStorage.setItem('ACCESS_TOKEN', token) - } else { - localStorage.removeItem('ACCESS_TOKEN') - } - } - - return ( - - {children} - - ) -} - -export const useAuthContext = () => useContext(AuthContext) diff --git a/src/renderer/src/contexts/BackgroundContext.jsx b/src/renderer/src/contexts/BackgroundContext.jsx deleted file mode 100644 index 8601ce2..0000000 --- a/src/renderer/src/contexts/BackgroundContext.jsx +++ /dev/null @@ -1,41 +0,0 @@ -import React, { useEffect, useState } from 'react' -import bgImage1 from '../assets/bg1-min.jpg' -import bgImage2 from '../assets/bg2-min.jpg' - -const BackgroundContext = ({ children }) => { - const [backgroundImage, setBackgroundImage] = useState('') // Background image URL - const [loading, setLoading] = useState(true) // To manage loading state - - useEffect(() => { - const images = [bgImage1, bgImage2] - - // Select a random image - const randomImage = images[Math.floor(Math.random() * images.length)] - - // Preload the image - const img = new Image() - img.src = randomImage - - img.onload = () => { - setBackgroundImage(randomImage) // Set the background image once loaded - setLoading(false) // Stop loading - } - }, []) - - return ( -
- {loading ? '' : children} - {/* Optionally add a loader while the background is being loaded */} -
- ) -} - -export default BackgroundContext diff --git a/src/renderer/src/contexts/MoyenneDeClasseContext.jsx b/src/renderer/src/contexts/MoyenneDeClasseContext.jsx deleted file mode 100644 index b440223..0000000 --- a/src/renderer/src/contexts/MoyenneDeClasseContext.jsx +++ /dev/null @@ -1,11 +0,0 @@ -import React, { createContext, useState } from 'react' - -// Create the context -export const DataContext = createContext() - -// Create the provider component -export const DataProvider = ({ children }) => { - const [data, setData] = useState(null) // State to hold data - - return {children} -} diff --git a/src/renderer/src/images/fab.jpg b/src/renderer/src/images/fab.jpg deleted file mode 100644 index 6239012..0000000 Binary files a/src/renderer/src/images/fab.jpg and /dev/null differ diff --git a/src/renderer/src/images/icon.png b/src/renderer/src/images/icon.png deleted file mode 100644 index cf9e8b2..0000000 Binary files a/src/renderer/src/images/icon.png and /dev/null differ diff --git a/src/renderer/src/layouts/DefaultLayout.jsx b/src/renderer/src/layouts/DefaultLayout.jsx deleted file mode 100644 index 045a30e..0000000 --- a/src/renderer/src/layouts/DefaultLayout.jsx +++ /dev/null @@ -1,35 +0,0 @@ -import React from 'react' -import { Outlet, Navigate } from 'react-router-dom' -import { useAuthContext } from '../contexts/AuthContext' -import classe from '../assets/DefaultLayout.module.css' -import Navbar from '../components/Navbar' -import Sidenav from '../components/Sidenav' - -const DefaultLayout = () => { - const { token } = useAuthContext() - - if (!token) { - return - } - - return ( -
-
- {/* Nabvar */} - {/* */} - - {/* Content Area with Sidenav and Outlet */} -
-
- -
-
- -
-
-
-
- ) -} - -export default DefaultLayout diff --git a/src/renderer/src/layouts/LoginLayout.jsx b/src/renderer/src/layouts/LoginLayout.jsx deleted file mode 100644 index 264f67c..0000000 --- a/src/renderer/src/layouts/LoginLayout.jsx +++ /dev/null @@ -1,50 +0,0 @@ -import React, { useEffect, useState } from 'react' -import { Outlet, Navigate } from 'react-router-dom' -import { useAuthContext } from '../contexts/AuthContext' -import Navbar from '../components/Navbar' -import bgImage1 from '../assets/bg1-min.jpg' -import bgImage2 from '../assets/bg2-min.jpg' - -const LoginLayout = () => { - const { token } = useAuthContext() - - if (token) { - return - } - - const [backgroundImage, setBackgroundImage] = useState('') // Background image URL - const [loading, setLoading] = useState(true) // To manage loading state - - // useEffect(() => { - const images = [bgImage1, bgImage2] - - // Select a random image - const randomImage = images[Math.floor(Math.random() * images.length)] - - // Preload the image - const img = new Image() - img.src = randomImage - - img.onload = () => { - setBackgroundImage(randomImage) // Set the background image once loaded - setLoading(false) // Stop loading - } - // }, []); - - return ( -
- - {/* Optionally add a loader while the background is being loaded */} -
- ) -} - -export default LoginLayout diff --git a/src/renderer/src/main.jsx b/src/renderer/src/main.jsx deleted file mode 100644 index 8801049..0000000 --- a/src/renderer/src/main.jsx +++ /dev/null @@ -1,12 +0,0 @@ -import './assets/base.css' -import React from 'react' -import ReactDOM from 'react-dom/client' -import 'bootstrap/dist/css/bootstrap.min.css' -import App from './App' -import 'react-tooltip/dist/react-tooltip.css' - -ReactDOM.createRoot(document.getElementById('root')).render( - - - -) diff --git a/src/renderer/src/test/ModalAddEtudiantsTest.jsx b/src/renderer/src/test/ModalAddEtudiantsTest.jsx deleted file mode 100644 index c3dfb1c..0000000 --- a/src/renderer/src/test/ModalAddEtudiantsTest.jsx +++ /dev/null @@ -1,76 +0,0 @@ -import React, { useState } from 'react' -import { TextField, InputAdornment, Button } from '@mui/material' -import { FaUser } from 'react-icons/fa' - -const AddStudentForm = () => { - const [formData, setFormData] = useState({ nom: '' }) - const [errors, setErrors] = useState({ nom: '' }) - - const handleInputChange = (e) => { - const { name, value } = e.target - - // Set the form data - setFormData((prevData) => ({ - ...prevData, - [name]: value - })) - - // Clear errors when the user starts typing again - setErrors((prevErrors) => ({ - ...prevErrors, - [name]: '' // Clear the error for the specific field - })) - } - - const validate = () => { - let valid = true - let newErrors = {} - - // Example validation for "nom" field (it must not be empty) - if (!formData.nom.trim()) { - newErrors.nom = 'Nom is required' - valid = false - } - - setErrors(newErrors) - return valid - } - - const handleSubmit = (e) => { - e.preventDefault() - - // Validate the form - if (validate()) { - // Form is valid, handle the submission logic - console.log(formData) - } - } - - return ( -
- - - - ) - }} - /> - - - - ) -} - -export default AddStudentForm diff --git a/src/renderer/src/test/TestPSD.JSX b/src/renderer/src/test/TestPSD.JSX deleted file mode 100644 index 810cfc7..0000000 --- a/src/renderer/src/test/TestPSD.JSX +++ /dev/null @@ -1,75 +0,0 @@ -import React, { useEffect, useRef, useState } from 'react' -import PSD from 'psd' - -function PSDViewer({ file }) { - const [imageSrc, setImageSrc] = useState('') - const [text, setText] = useState('Your Text Here') - const canvasRef = useRef(null) - - useEffect(() => { - const loadPSD = async () => { - try { - const psd = await PSD.fromURL(file) - const image = psd.image.toBase64() // Generate Base64 image - setImageSrc(`data:image/png;base64,${image}`) - } catch (error) { - console.error('Error loading PSD file:', error) - } - } - - loadPSD() - }, [file]) - - useEffect(() => { - if (imageSrc && canvasRef.current) { - const canvas = canvasRef.current - const ctx = canvas.getContext('2d') - - // Load the PSD image into the canvas - const img = new Image() - img.src = imageSrc - img.onload = () => { - canvas.width = img.width - canvas.height = img.height - ctx.drawImage(img, 0, 0) - - // Add text overlay - ctx.font = '48px Arial' - ctx.fillStyle = 'red' // Customize text color - ctx.fillText(text, 50, 100) // Customize position - } - } - }, [imageSrc, text]) - - const handleDownload = () => { - const canvas = canvasRef.current - const link = document.createElement('a') - link.download = 'edited-psd.png' - link.href = canvas.toDataURL('image/png') - link.click() - } - - return ( -
-

PSD Viewer and Editor

- setText(e.target.value)} - placeholder="Enter text to overlay" - /> -
{imageSrc ? :

Loading PSD file...

}
- -
- ) -} - -function App() { - return ( -
- -
- ) -} - -export default App diff --git a/src/renderer/src/test/expalintolbar.txt b/src/renderer/src/test/expalintolbar.txt deleted file mode 100644 index b666c75..0000000 --- a/src/renderer/src/test/expalintolbar.txt +++ /dev/null @@ -1,101 +0,0 @@ -To save changes made by the **DataGrid Toolbar Column Chooser** (``) to a temporary Excel file each time the visibility of columns changes, you can use the `onColumnVisibilityModelChange` event of the MUI `DataGrid`. This event triggers whenever column visibility changes, allowing you to update the temp file based on visible columns. - -Here's a step-by-step guide on implementing this: - -### 1. Add `onColumnVisibilityModelChange` Event to `DataGrid` - -Attach `onColumnVisibilityModelChange` to listen for column visibility changes. When triggered, this event can be used to filter the data based on the visible columns, generate a temporary Excel file (`tempFile`), and save it. - -### 2. Filter Data Based on Visible Columns and Export to Excel - -With `xlsx`, filter only the visible columns and write them to a temporary file each time the visibility model changes. - -### Code Implementation - -```javascript -import React, { useState } from 'react'; -import { DataGrid, GridToolbarContainer, GridToolbarColumnsButton } from '@mui/x-data-grid'; -import XLSX from 'xlsx'; - -const ExampleDataGrid = () => { - const [tableData, setTableData] = useState([ - { id: 1, nom: 'sakalava', prenom: 'gagag', age: 25 }, - { id: 2, nom: 'wild', prenom: 'fire', age: 30 }, - ]); - - const [columnVisibilityModel, setColumnVisibilityModel] = useState({ - nom: true, - prenom: true, - age: true, - }); - - const columns = [ - { field: 'nom', headerName: 'Nom', width: 200 }, - { field: 'prenom', headerName: 'Prenom', width: 200 }, - { field: 'age', headerName: 'Age', width: 100 }, - ]; - - // Handle column visibility changes - const handleColumnVisibilityChange = (newModel) => { - setColumnVisibilityModel(newModel); - updateTempFile(newModel); - }; - - // Update temp file based on visible columns - const updateTempFile = (visibilityModel) => { - const visibleColumns = columns - .filter((col) => visibilityModel[col.field]) - .map((col) => col.field); - - // Filter data based on visible columns - const filteredData = tableData.map((row) => { - const filteredRow = {}; - visibleColumns.forEach((col) => { - filteredRow[col] = row[col]; - }); - return filteredRow; - }); - - // Create a new worksheet and workbook - const worksheet = XLSX.utils.json_to_sheet(filteredData); - const workbook = XLSX.utils.book_new(); - XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1'); - - // Write to a temporary file (Blob) - const tempFile = XLSX.write(workbook, { bookType: 'xlsx', type: 'blob' }); - - // Send tempFile to backend or save locally - console.log('Temporary file updated', tempFile); - }; - - return ( -
- ( - - - - ), - }} - /> -
- ); -}; - -export default ExampleDataGrid; -``` - -### Explanation - -1. **Event Listener**: `onColumnVisibilityModelChange` listens for visibility changes and updates `columnVisibilityModel`. -2. **Filtering Visible Columns**: `updateTempFile` uses `columnVisibilityModel` to filter `tableData` for only the visible columns. -3. **Writing to Excel**: The filtered data is written to a new workbook (`tempFile`) as an Excel file, which can be sent to the backend or saved locally. - -### Optional: Trigger Backend Upload - -To upload `tempFile` to your backend, use `FormData` and an `axios` POST request in `updateTempFile`. This ensures the temporary Excel file is updated on each column change event. diff --git a/src/renderer/src/test/qr.html b/src/renderer/src/test/qr.html deleted file mode 100644 index 3ec019c..0000000 --- a/src/renderer/src/test/qr.html +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - Document - - -
-
-
-

université de toamasina

-

***********

-

- ecole superieure
- polytechnique -

-
-
-
- -
-
-

Nom : BE

-

Prénom : Joseph Fabrice

-

Date de naissance : 11-12-2001

-

Niveau : L3

-

Année scolaire : 2023-2024

-

Num inscription : 12345678900

-
-
-
-
-
-
-

QR en ligne

- -
-
-

QR locale

- -
-
-
-
- - diff --git a/src/renderer/src/test/relever.html b/src/renderer/src/test/relever.html deleted file mode 100644 index ece43b4..0000000 --- a/src/renderer/src/test/relever.html +++ /dev/null @@ -1,74 +0,0 @@ - - - - - - Relevé de Note - - - -
-

REPOBLIKAN’I MADAGASIKARA

-

Fitiavana-Tanindrazana-Fandrosoana

-
-

MINISTÈRE DE L’ENSEIGNEMENT SUPÉRIEUR ET DE LA RECHERCHE SCIENTIFIQUE

-

UNIVERSITÉ DE TOAMASINA

-

ECOLE SUPERIEURE POLYTECHNIQUE

-

Fahaizaña sy Fañahy

-
- -
-

RELEVÉE DE NOTE

-

Nom & Prénoms : F3

-

- Niveau : L1 Année scolaire : 2022-2023 -

-

N° inscription : F42

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Unités d’Enseignement (UE)Eléments constitutifsCréditsNoteMoyenne
UEMI1Algèbre4F6F8
UEMI1Analyse5F5
UEPI1Mécanique Général I4F9F13
Total crédit30
- -

Moyenne générale : F41

-

Observation : F47

-

Décision de jury : F46

-

Le Directeur : RATSIMBAZAFY Christian Pierre

-
- - diff --git a/src/renderer/src/test/select2.jsx b/src/renderer/src/test/select2.jsx deleted file mode 100644 index f1aa5f4..0000000 --- a/src/renderer/src/test/select2.jsx +++ /dev/null @@ -1,44 +0,0 @@ -const handleFileChange = (event) => { - const file = event.target.files[0] - setFiles(event.target.files[0]) - if (!file) { - setError('No file selected') - return - } - - const fileExtension = file.name.split('.').pop().toLowerCase() - - if (fileExtension === 'xlsx') { - const reader = new FileReader() - reader.onload = (e) => { - const data = new Uint8Array(e.target.result) - const workbook = XLSX.read(data, { type: 'array' }) - - // Extract data from all sheets and combine - const allData = [] - workbook.SheetNames.forEach((sheetName) => { - const worksheet = workbook.Sheets[sheetName] - const rows = XLSX.utils.sheet_to_json(worksheet, { header: 1 }) - setHeader(rows[0]) // keep the header - allData.push(...rows.slice(1)) // Skip header row for each sheet - }) - setTableData(allData) - } - reader.readAsArrayBuffer(file) - } else if (fileExtension === 'csv') { - const reader = new FileReader() - reader.onload = (e) => { - Papa.parse(e.target.result, { - complete: (results) => { - setHeader(results.data[0]) // keep the header - setTableData(results.data.slice(1)) // Skip header row - }, - header: false - }) - } - reader.readAsText(file) - } else { - setError('Unsupported file format. Please upload .xlsx or .csv file.') - setTableData([]) - } -} diff --git a/src/renderer/src/test/style.css b/src/renderer/src/test/style.css deleted file mode 100644 index ef64334..0000000 --- a/src/renderer/src/test/style.css +++ /dev/null @@ -1,54 +0,0 @@ -body { - font-family: Arial, sans-serif; - line-height: 1.6; - margin: 20px; -} - -.header { - text-align: center; -} - -.header h1, -.header h2, -.header h3 { - margin: 0; -} - -hr { - border: 1px solid black; - margin: 20px 0; -} - -.releve { - margin-top: 20px; -} - -table { - width: 100%; - border-collapse: collapse; - margin-bottom: 20px; -} - -table, -th, -td { - border: 1px solid black; -} - -th, -td { - padding: 10px; - text-align: left; -} - -th { - background-color: #f2f2f2; -} - -td { - text-align: center; -} - -strong { - font-weight: bold; -} diff --git a/src/renderer/src/test/testDate.txt b/src/renderer/src/test/testDate.txt deleted file mode 100644 index edc8945..0000000 --- a/src/renderer/src/test/testDate.txt +++ /dev/null @@ -1,84 +0,0 @@ -In JavaScript, you can manipulate dates and work with months and years easily using the `Date` object. To check if the current month is July of the current year, you can do the following: - -### Steps: -1. **Get the current date**: You can use `new Date()` to get the current date. -2. **Check the current month**: Use `.getMonth()` to get the month (note that months are zero-indexed in JavaScript, meaning `0` is January, `1` is February, and so on). -3. **Check the current year**: Use `.getFullYear()` to get the current year. - -Here’s an example of how to check if it's July of the current year and perform an action: - -### Example Code: - -```javascript -// Get the current date -const currentDate = new Date(); - -// Get the current month (zero-indexed, so 6 represents July) -const currentMonth = currentDate.getMonth(); - -// Get the current year -const currentYear = currentDate.getFullYear(); - -// Check if the current month is July (month 6) and if it is the current year -if (currentMonth === 6) { // July is month 6 (zero-indexed) - console.log("We are in July this year!"); - // Perform your action here -} else { - console.log("It is not July."); -} -``` - -### **Explanation**: -1. `currentDate.getMonth()` will return the current month (0-11), so `6` represents July. -2. `currentDate.getFullYear()` will return the current year as a 4-digit number (e.g., `2024`). -3. The `if (currentMonth === 6)` checks if the current month is July. - -### **Performing Actions Based on Month and Year**: -You can replace the `console.log()` statement with any action or function you need to perform if the condition is met. For example: - -```javascript -if (currentMonth === 6 && currentYear === 2024) { - // Perform action for July 2024 - alert("It is July 2024! Performing action..."); -} else { - // Action for other months or years - alert("Not July 2024."); -} -``` - -### **Bonus: Working with Day.js or Moment.js**: -If you prefer working with date manipulation libraries like **Day.js** or **Moment.js**, you can make the code simpler. - -#### With **Day.js**: -```javascript -const dayjs = require('dayjs'); // If using Node.js, make sure to install dayjs first - -// Get the current date -const currentDate = dayjs(); - -// Check if we are in July this year -if (currentDate.month() === 6) { // 6 represents July - console.log("We are in July this year!"); -} -``` - -#### With **Moment.js**: -```javascript -const moment = require('moment'); // If using Node.js, make sure to install moment.js first - -// Get the current date -const currentDate = moment(); - -// Check if we are in July this year -if (currentDate.month() === 6) { // 6 represents July - console.log("We are in July this year!"); -} -``` - -### Summary: -- You can use `new Date()` to get the current date. -- Use `.getMonth()` to get the current month (remember it’s 0-indexed). -- Use `.getFullYear()` to get the current year. -- For better handling of dates and months, consider using libraries like **Day.js** or **Moment.js** for cleaner and more readable code. - -Let me know if you need more help with date manipulation! diff --git a/text.txt b/text.txt index a28deb1..2c6e625 100644 --- a/text.txt +++ b/text.txt @@ -244,7 +244,7 @@ const FileUploader = () => { Nom - Prénom + Prenom Photos Date de Naissances Niveau