diff --git a/database/Models/Matieres.js b/database/Models/Matieres.js index 8614c39..694bf01 100644 --- a/database/Models/Matieres.js +++ b/database/Models/Matieres.js @@ -41,19 +41,19 @@ async function getMatiere() { return { success: false, error: 'Erreur veullez réeseyer' + error } } } - async function displayMatiereFromForm(niveau, mention_id, parcours) { - // Fetch the semestre array - let semestre = await matiereSysteme(niveau) // Ensure this returns an array with at least 2 items + console.log('modele: ',niveau,mention_id,parcours); + let semestre = await matiereSysteme(niveau); + console.log(semestre); + if (!semestre || semestre.length < 2) { + console.error('Semestre insuffisant pour', niveau); + return []; + } - if (niveau !== 'L1') { - if (semestre.length < 2) { - console.error('Error: Semestre array does not contain enough elements.') - return - } + let sql, params; - // Prepare the query - let matiereQuery = ` + if (niveau !== 'L1') { + sql = ` SELECT DISTINCT m.* FROM matieres m JOIN matiere_semestre ms ON m.id = ms.matiere_id @@ -62,55 +62,31 @@ async function displayMatiereFromForm(niveau, mention_id, parcours) { JOIN parcours p ON pm.parcour_id = p.id WHERE (s.nom LIKE ? OR s.nom LIKE ?) AND ms.mention_id = ? - AND p.nom = ? - ` - - try { - // Execute the query with parameters - let [rows] = await pool.query(matiereQuery, [ - `%${semestre[0]}%`, - `%${semestre[1]}%`, - mention_id, - parcours - ]) - - // Log the response - return rows - } catch (error) { - return { success: false, error: 'Erreur veullez réeseyer' + error } - } + AND p.nom LIKE ? + `; + params = [`%${semestre[0]}%`, `%${semestre[1]}%`, mention_id, `%${parcours}%`]; } else { - if (semestre.length < 2) { - console.error('Error: Semestre array does not contain enough elements.') - return - } - - // Prepare the query - let matiereQuery = ` + sql = ` SELECT DISTINCT m.* FROM matieres m JOIN matiere_semestre ms ON m.id = ms.matiere_id JOIN semestres s ON ms.semestre_id = s.id WHERE (s.nom LIKE ? OR s.nom LIKE ?) AND ms.mention_id = ? - ` + `; + params = [`%${semestre[0]}%`, `%${semestre[1]}%`, mention_id]; + } - try { - // Execute the query with parameters - let [rows] = await pool.query(matiereQuery, [ - `%${semestre[0]}%`, - `%${semestre[1]}%`, - mention_id - ]) - - // Log the response - return rows - } catch (error) { - return { success: false, error: 'Erreur veullez réeseyer' + error } - } + try { + const [rows] = await pool.query(sql, params); + return rows; + } catch (error) { + console.error(error); + return []; } } + /** * function to get single matiere * @param {*} id @@ -188,12 +164,10 @@ async function updateMatiereNiveau(formData) { } async function deleteMatiere(id) { - console.log("id: ", id); const sql = 'DELETE FROM matieres WHERE id = ?'; try { let [result] = await pool.query(sql, [id]); - console.log("Résultat DELETE:", result); if (result.affectedRows === 0) { return { diff --git a/database/Models/Parcours.js b/database/Models/Parcours.js index ec9dd8e..93397cf 100644 --- a/database/Models/Parcours.js +++ b/database/Models/Parcours.js @@ -41,6 +41,8 @@ async function getParcours() { } } + + async function getSingleParcours(id) { const sql = 'SELECT * FROM parcours WHERE id = ?' @@ -219,6 +221,32 @@ async function extractFiche(matiere_id) { } } +async function deleteParcours(id) { + console.log("id: ", id); + const sql = 'DELETE FROM parcours WHERE id = ?'; + + try { + let [result] = await pool.query(sql, [id]); + console.log("Résultat DELETE:", result); + + if (result.affectedRows === 0) { + return { + success: false, + message: 'Parcours 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 }; + + } +} + module.exports = { insertParcour, getParcours, @@ -227,5 +255,6 @@ module.exports = { updateparcour, parcourMatiere, extractFiche, + deleteParcours, getParcourMatiere } diff --git a/src/main/backup.js b/src/main/backup.js index c5b0afd..2c9baa5 100644 --- a/src/main/backup.js +++ b/src/main/backup.js @@ -92,7 +92,7 @@ const { deletes, updateparcour, parcourMatiere, - extractFiche, + deleteParcours, getParcourMatiere } = require('../../database/Models/Parcours') @@ -797,13 +797,9 @@ ipcMain.handle('getSingleParcours', async (event, credentials) => { return get }) -ipcMain.handle('deleteParcours', async (event, credentials) => { - const { id } = credentials - // console.log(formData, id); - const get = deletes(id) - - return get -}) + ipcMain.handle('deleteParcours', async (event, id) => { + return await deleteParcours(id); + }); ipcMain.handle('updateParcours', async (event, credentials) => { const { nom, uniter, mention_id, id } = credentials diff --git a/src/main/index.js b/src/main/index.js index c2dddda..5396e39 100644 --- a/src/main/index.js +++ b/src/main/index.js @@ -20,6 +20,7 @@ const { FilterDataByNiveau, updateEtudiant, changePDP, + deleteEtudiant, updateParcours, createTranche, getTranche, @@ -48,7 +49,6 @@ const { updateMatiereNiveau, displayMatiereFromForm, deleteMatiere, - deleteEtudiant, asygnationToMention, getMentionMatiere, getMentionMatiereChecked, @@ -93,6 +93,7 @@ const { updateparcour, parcourMatiere, extractFiche, + deleteParcours, getParcourMatiere } = require('../../database/Models/Parcours') @@ -622,11 +623,11 @@ ipcMain.handle('noteMatiere', async (event, credentials) => { }) ipcMain.handle('displayMatiereFromForm', async (event, credentials) => { - const { niveau, mention_id, parcours } = credentials + const { niveau, mention_id, parcours } = credentials; + const get = displayMatiereFromForm(niveau, mention_id, parcours); + return get; +}); - const get = displayMatiereFromForm(niveau, mention_id, parcours) - return get -}) ipcMain.handle('createMention', async (event, credentials) => { const { nom, uniter } = credentials @@ -665,11 +666,13 @@ ipcMain.handle('deleteNiveaus', async (event, credentials) => { ipcMain.handle('deleteMatiere', async (event, id) => { return await deleteMatiere(id); }); + ipcMain.handle('deleteEtudiant', async (event, id) => { return await deleteEtudiant(id); }); + ipcMain.handle('asign', async (event, credentials) => { const { formData, id } = credentials // console.log(formData, id); @@ -782,13 +785,10 @@ ipcMain.handle('getSingleParcours', async (event, credentials) => { return get }) -ipcMain.handle('deleteParcours', async (event, credentials) => { - const { id } = credentials - // console.log(formData, id); - const get = deletes(id) +ipcMain.handle('deleteParcours', async (event, id) => { + return await deleteParcours(id); +}); - return get -}) ipcMain.handle('updateParcours', async (event, credentials) => { const { nom, uniter, mention_id, id } = credentials diff --git a/src/preload/index.backup.js b/src/preload/index.backup.js index bccb2e0..3d8fa0d 100644 --- a/src/preload/index.backup.js +++ b/src/preload/index.backup.js @@ -79,6 +79,7 @@ if (process.contextIsolated) { getSingle: (credential) => ipcRenderer.invoke('single', credential), updateEtudiants: (credentials) => ipcRenderer.invoke('updateETudiants', credentials), getDataToDashboards: () => getDataToDashboard(), + deleteEtudiant: (credentials) => ipcRenderer.invoke('deleteEtudiant', credentials), updateEtudiantsPDP: (credentials) => ipcRenderer.invoke('updateETudiantsPDP', credentials), importExcel: (credentials) => ipcRenderer.invoke('importexcel', credentials), changeParcours: (credentials) => ipcRenderer.invoke('changeParcours', credentials), @@ -137,7 +138,6 @@ if (process.contextIsolated) { displayMatiereFromForm: (credentials) => ipcRenderer.invoke('displayMatiereFromForm', credentials), deleteMatiere: (credentials) => ipcRenderer.invoke('deleteMatiere', credentials), - deleteEtudiant: (credentials) => ipcRenderer.invoke('deleteEtudiant', credentials), asign: (credentials) => ipcRenderer.invoke('asign', credentials), getAsign: (credentials) => ipcRenderer.invoke('getAsign', credentials), asignSemestre: (credentials) => ipcRenderer.invoke('asignSemestre', credentials), @@ -157,7 +157,7 @@ if (process.contextIsolated) { * contextBridge for note systeme */ contextBridge.exposeInMainWorld('notesysteme', { - getSyteme: () => getSysteme(), + getSysteme: () => getSysteme(), updateNoteSysteme: (credentials) => ipcRenderer.invoke('updateNoteSysteme', credentials), insertParcours: (credentials) => ipcRenderer.invoke('insertParcours', credentials), getSingleParcours: (credentials) => ipcRenderer.invoke('getSingleParcours', credentials), diff --git a/src/preload/index.js b/src/preload/index.js index 2ead89b..184005b 100644 --- a/src/preload/index.js +++ b/src/preload/index.js @@ -82,6 +82,7 @@ if (process.contextIsolated) { getTranche: (credentials) => ipcRenderer.invoke('getTranche', credentials), updateTranche: (credentials) => ipcRenderer.invoke('updateTranche', credentials), deleteTranche: (credentials) => ipcRenderer.invoke('deleteTranche', credentials), + deleteEtudiant: (id) => ipcRenderer.invoke('deleteEtudiant', id), getSingleTranche: (credentials) => ipcRenderer.invoke('getSingleTranche', credentials) }) @@ -133,7 +134,6 @@ if (process.contextIsolated) { displayMatiereFromForm: (credentials) => ipcRenderer.invoke('displayMatiereFromForm', credentials), deleteMatiere: (id) => ipcRenderer.invoke('deleteMatiere', id), - deleteEtudiant: (id) => ipcRenderer.invoke('deleteEtudiant', id), asign: (credentials) => ipcRenderer.invoke('asign', credentials), getAsign: (credentials) => ipcRenderer.invoke('getAsign', credentials), asignSemestre: (credentials) => ipcRenderer.invoke('asignSemestre', credentials), @@ -153,11 +153,11 @@ if (process.contextIsolated) { * contextBridge for note systeme */ contextBridge.exposeInMainWorld('notesysteme', { - getSyteme: () => getSysteme(), + getSysteme: () => getSysteme(), updateNoteSysteme: (credentials) => ipcRenderer.invoke('updateNoteSysteme', credentials), insertParcours: (credentials) => ipcRenderer.invoke('insertParcours', credentials), + deleteParcours: (id) => ipcRenderer.invoke('deleteParcours', id), 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(), diff --git a/src/renderer/src/components/AddNotes.jsx b/src/renderer/src/components/AddNotes.jsx index 9a56200..73da243 100644 --- a/src/renderer/src/components/AddNotes.jsx +++ b/src/renderer/src/components/AddNotes.jsx @@ -52,9 +52,6 @@ const AddNotes = () => { window.matieres.displayMatiereFromForm({ niveau, mention_id, parcours }).then((response) => { setMatieres(response) - console.log("resulat teste:1", response); - console.log("resulat teste:2", mention_id); - console.log("resulat teste:3", parcours); }) setIsSubmitted(false) } @@ -95,7 +92,6 @@ const AddNotes = () => { formData, annee_scolaire }) - console.log(response) if (response.success) { setOpen(true) setStatut(200) @@ -112,8 +108,6 @@ const AddNotes = () => { } } - console.log('matiere: ',matieres); - const [statut, setStatut] = useState(200) /** @@ -258,7 +252,7 @@ const AddNotes = () => { {/* map the all matiere to the form */} {matieres.map((mat) => ( - + { color="warning" fullWidth value={formData[mat.id] || ''} // Access the correct value from formData - onChange={ - (e) => setFormData({ ...formData, [mat.id]: e.target.value }) // Update the specific key + onChange={(e) => + 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 - } + borderColor: '#ff9800', // Set the border color on hover + }, }, '& .MuiInputBase-input::placeholder': { - fontSize: '11px' // Set the placeholder font size - } + fontSize: '11px', // Set the placeholder font size + }, }} /> ))} + { } }) + const [isDeleted, setIsDeleted] = useState(false) + const [ids, setIds] = useState(0) + + const deleteButton = async (id) => { + console.log(id); + let response = await window.notesysteme.deleteParcours(id); + console.log(response); + if (response.success) { + const updatedParcours = parcours.filter((parcour) => parcour.id !== id) + setParcours(updatedParcours) + setIsDeleted(true) + } + } + + /** + * hook to open modal + */ + const [open, setOpen] = useState(false) + + /** + * function to close modal + */ + const handleClose = () => { + setOpen(false) + setIsDeleted(false) + } + + /** + * function to open delete modal + */ + const openDeleteModal = (id) => { + setIds(id) + setOpen(true) + } + + const modals = () => ( + + + {isDeleted ? ( + + Supprimé avec succès + + ) : ( + + {' '} + Voulez-vous supprimer ce parcours ? + + )} + + {isDeleted ? ( + + ) : ( +
+ + +
+ )} +
+
+
+ ) + const columns = [ { field: 'nom', headerName: 'Nom', width: 230 }, { field: 'uniter', headerName: 'Uniter', width: 180 }, @@ -70,6 +171,36 @@ const Parcours = () => { + + + ) + }, + { + renderCell: (params) => ( +
+
) } @@ -122,6 +253,7 @@ const Parcours = () => { return (
+ {modals()} {
@@ -196,4 +328,4 @@ const Parcours = () => { ) } -export default Parcours +export default Parcours \ No newline at end of file diff --git a/src/renderer/src/components/Resultat.jsx b/src/renderer/src/components/Resultat.jsx index d91817c..b770939 100644 --- a/src/renderer/src/components/Resultat.jsx +++ b/src/renderer/src/components/Resultat.jsx @@ -8,6 +8,8 @@ import { IoMdReturnRight } from 'react-icons/io' import jsPDF from 'jspdf' import autoTable from 'jspdf-autotable' import { FaDownload } from 'react-icons/fa' +import logoRelerev1 from '../assets/logorelever.png' +import logoRelerev2 from '../assets/logorelever2.png' const Resultat = () => { const { niveau, scolaire } = useParams() @@ -59,22 +61,32 @@ const Resultat = () => { format: 'a4' }) + pdf.addImage(logoRelerev1, 'PNG', 10, 5, 40, 20) + pdf.addImage(logoRelerev2, 'PNG', 175, 5, 30, 30) + + // Ajouter le texte entre les logos + pdf.setFontSize(10) + pdf.text('REPOBLIKAN\'I MADAGASIKARA', 105, 10, { align: 'center' }) + pdf.text('Fitiavana-Tanindrazana-Fandrosoana', 105, 14, { align: 'center' }) + pdf.text('********************', 105, 18, { align: 'center' }) + pdf.text('MINISTÈRE DE L\'ENSEIGNEMENT SUPÉRIEUR', 105, 22, { align: 'center' }) + pdf.text('ET DE LA RECHERCHE SCIENTIFIQUE', 105, 26, { align: 'center' }) + pdf.text('********************', 105, 30, { align: 'center' }) + pdf.text('UNIVERSITÉ DE TOAMASINA', 105, 34, { align: 'center' }) + pdf.text('ÉCOLE SUPÉRIEURE POLYTECHNIQUE', 105, 38, { align: 'center' }) + // Select the table autoTable(pdf, { - html: '#myTable2', // ID de la table - startY: 20, + html: '#myTable2', + startY: 50, // décalé vers le bas pour laisser la place aux logos et texte theme: 'grid', headStyles: { fillColor: 'gray', halign: 'center', fontStyle: 'bold', textColor: 'black' - }, // 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) - } + }, + styles: { fontSize: 8, cellPadding: 2, halign: 'center' } }) pdf.save(`Resultat-${niveau}-${scolaire}.pdf`) @@ -175,36 +187,83 @@ const Resultat = () => {
- + {/* En-tête avec logos et texte */} +
+ Logo gauche + + {/* Texte centré entre les logos */} +
+
REPOBLIKAN'I MADAGASIKARA
+
Fitiavana-Tanindrazana-Fandrosoana
+
********************
+
MINISTÈRE DE L'ENSEIGNEMENT SUPÉRIEUR
+
ET DE LA RECHERCHE SCIENTIFIQUE
+
********************
+
UNIVERSITÉ DE TOAMASINA
+
ÉCOLE SUPÉRIEURE POLYTECHNIQUE
+
+ + Logo droite +
+ + {/* Informations du parcours */} +
+
Parcours : GC
+
Niveau : {niveau}
+
Année Universitaire : {scolaire}
+
+ +
- - - - - - + + + + + - {sortedStudents.map((sorted) => ( + {sortedStudents.map((sorted, index) => ( - - - - + + + + ))} @@ -215,4 +274,4 @@ const Resultat = () => { ) } -export default Resultat +export default Resultat \ No newline at end of file diff --git a/src/renderer/src/components/Student.jsx b/src/renderer/src/components/Student.jsx index edca75d..1525ab9 100644 --- a/src/renderer/src/components/Student.jsx +++ b/src/renderer/src/components/Student.jsx @@ -3,12 +3,12 @@ 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 { Button, InputAdornment, Box, Typography, Modal } 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 { FaCertificate, FaGraduationCap, FaPlus, FaReceipt, FaToolbox, FaTrash } from 'react-icons/fa' import { createTheme, ThemeProvider } from '@mui/material/styles' import InputLabel from '@mui/material/InputLabel' import MenuItem from '@mui/material/MenuItem' @@ -24,6 +24,8 @@ import ModalStage from './ModalStage' import ModalRecepice from './ModalRecepice' import { processPdf } from './function/PDFEditorV2' import { MdVerified } from 'react-icons/md' +import warning from '../assets/warning.svg' +import success from '../assets/success.svg' const Student = () => { const theme = createTheme({ @@ -80,12 +82,121 @@ const Student = () => { }) }, []) + // État pour le modal de suppression + const [openDeleteModal, setOpenDeleteModal] = useState(false) + const [isDeleted, setIsDeleted] = useState(false) + const [studentToDelete, setStudentToDelete] = useState(null) + + /** + * Fonction pour ouvrir le modal de suppression + */ + const handleOpenDeleteModal = (id) => { + setStudentToDelete(id) + setOpenDeleteModal(true) + } + + /** + * Fonction pour fermer le modal de suppression + */ + const handleCloseDeleteModal = () => { + setOpenDeleteModal(false) + setIsDeleted(false) + setStudentToDelete(null) + } + + /** + * Fonction de suppression de l'étudiant + */ + const handleDelete = async () => { + try { + const response = await window.etudiants.deleteEtudiant(studentToDelete) + if (response.success || response) { + const updatedEtudiants = etudiants.filter((etudiant) => etudiant.id !== studentToDelete) + setEtudiants(updatedEtudiants) + setIsDeleted(true) + } + } catch (error) { + console.error("Erreur lors de la suppression :", error) + // Optionnel: gérer l'erreur avec un état d'erreur + } + } + + /** + * Modal de suppression + */ + const deleteModal = () => ( + + + {isDeleted ? ( + + + Étudiant supprimé avec succès + + ) : ( + + + Voulez-vous supprimer cet étudiant ? + + )} + + {isDeleted ? ( + + ) : ( +
+ + +
+ )} +
+
+
+ ) + const SeeNote = ({ params }) => { const matchingNote = notes.find( (element) => element.etudiant_niveau === params.row.niveau && element.etudiant_id === params.value ) - + return (
{matchingNote ? ( @@ -171,7 +282,7 @@ const Student = () => { { field: 'action', headerName: 'Action', - width: 300, + width: 350, renderCell: (params) => (
@@ -189,6 +300,7 @@ const Student = () => { + + +
) } @@ -449,6 +586,7 @@ const Student = () => { return (
+ {deleteModal()}
-
- Niveau {niveau} | Année Scolaire {scolaire} +
+
+ Résultat de la Deuxième Session : {niveau} admis en L3 par ordre de mérite
NomPrenomMentionMoyenne
RANGNOMSPRÉNOMSMoyenne
{sorted.nom}{sorted.prenom}{returnmention(sorted.mention)}{sorted.moyenne}{index + 1}.{sorted.nom}{sorted.prenom}{sorted.moyenne}