Browse Source

14082025

master
andrymodeste 4 months ago
parent
commit
f4ad4ecf12
  1. 70
      database/Models/Matieres.js
  2. 29
      database/Models/Parcours.js
  3. 12
      src/main/backup.js
  4. 22
      src/main/index.js
  5. 4
      src/preload/index.backup.js
  6. 6
      src/preload/index.js
  7. 23
      src/renderer/src/components/AddNotes.jsx
  8. 136
      src/renderer/src/components/Parcours.jsx
  9. 107
      src/renderer/src/components/Resultat.jsx
  10. 144
      src/renderer/src/components/Student.jsx
  11. 5
      src/renderer/src/components/SystemeNote.jsx
  12. 52
      src/renderer/src/components/function/PDFEditorV2.js

70
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
if (niveau !== 'L1') {
if (semestre.length < 2) {
console.error('Error: Semestre array does not contain enough elements.')
return
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 [];
}
// Prepare the query
let matiereQuery = `
let sql, params;
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
const [rows] = await pool.query(sql, params);
return rows;
} catch (error) {
return { success: false, error: 'Erreur veullez réeseyer' + 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 {

29
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
}

12
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

22
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

4
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),

6
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(),

23
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 */}
<Grid container spacing={2}>
{matieres.map((mat) => (
<Grid item xs={12} sm={3} key={mat.nom}>
<Grid item xs={12} sm={3} key={mat.id}>
<TextField
label={mat.nom}
name={mat.id}
@ -266,31 +260,32 @@ const AddNotes = () => {
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: (
<InputAdornment position="start">
<CgNotes />
</InputAdornment>
)
),
}}
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
},
}}
/>
</Grid>
))}
</Grid>
<Grid
item
xs={12}

136
src/renderer/src/components/Parcours.jsx

@ -4,7 +4,7 @@ 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 { FaPlus, FaTrash } 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'
@ -45,6 +45,107 @@ const Parcours = () => {
}
})
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 = () => (
<Modal
open={open}
onClose={handleClose}
aria-labelledby="modal-title"
aria-describedby="modal-description"
>
<Box
sx={{
position: 'absolute',
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)',
width: 450,
bgcolor: 'background.paper',
boxShadow: 24,
p: 4
}}
>
{isDeleted ? (
<Typography
style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: '10px' }}
>
<img src={success} alt="" width={50} height={50} /> <span>Supprimé avec succès</span>
</Typography>
) : (
<Typography
style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: '10px' }}
>
<img src={warning} alt="" width={50} height={50} />{' '}
<span>Voulez-vous supprimer ce parcours ?</span>
</Typography>
)}
<Box
sx={{
marginTop: '2%',
display: 'flex',
gap: '20px',
alignItems: 'end',
justifyContent: 'flex-end'
}}
>
{isDeleted ? (
<Button onClick={handleClose} color="warning" variant="contained">
OK
</Button>
) : (
<div>
<Button
onClick={() => deleteButton(ids)}
sx={{ mr: 1 }}
color="warning"
variant="contained"
>
Oui
</Button>
<Button onClick={handleClose} color="warning" variant="contained">
Non
</Button>
</div>
)}
</Box>
</Box>
</Modal>
)
const columns = [
{ field: 'nom', headerName: 'Nom', width: 230 },
{ field: 'uniter', headerName: 'Uniter', width: 180 },
@ -70,6 +171,36 @@ const Parcours = () => {
</Tooltip>
</Button>
</Link>
<Button
color="error"
variant="contained"
onClick={() => openDeleteModal(params.value)}
sx={{
marginTop: '13px',
minWidth: '50px', // largeur mini
height: '30px', // hauteur
padding: '4px', // espace interne
}}
>
<FaTrash
style={{ fontSize: '20px', color: 'white', outline: 'none' }}
className={`delete${params.value}`}
/>
<Tooltip
anchorSelect={`.delete${params.value}`}
style={{ fontSize: '15px', zIndex: 22 }}
place="top"
>
Supprimer
</Tooltip>
</Button>
</div>
)
},
{
renderCell: (params) => (
<div>
</div>
)
}
@ -122,6 +253,7 @@ const Parcours = () => {
return (
<div className={classe.mainHome}>
{modals()}
<AddParcours open={openModalAdd} onClose={closeModalAdd} onSubmitSuccess={handleFormSubmit} />
<UpdateParcour
id={idToSend}
@ -138,7 +270,7 @@ const Parcours = () => {
</h1>
<Link to={'#'} onClick={openModalAddFunction}>
<Button color="warning" variant="contained">
<FaPlus style={{ fontSize: '20px' }} /> AJouter
<FaPlus style={{ fontSize: '20px' }} /> Ajouter
</Button>
</Link>
</div>

107
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 = () => {
<div className={classeHome.boxEtudiantsCard}>
<Paper
sx={{
height: 'auto', // Auto height to make the grid responsive
height: 'auto',
width: '100%',
// minHeight: 500, // Ensures a minimum height
display: 'flex',
flexDirection: 'column',
padding: '2%'
}}
>
<table className="table table-bordered table-striped text-center shadow-sm" id="myTable2">
{/* En-tête avec logos et texte */}
<div
style={{
display: 'flex',
alignItems: 'flex-start',
justifyContent: 'space-between',
marginBottom: '20px',
position: 'relative'
}}
>
<img src={logoRelerev1} alt="Logo gauche" width={70} />
{/* Texte centré entre les logos */}
<div
style={{
position: 'absolute',
left: '50%',
transform: 'translateX(-50%)',
textAlign: 'center',
fontSize: '10px',
lineHeight: '1.2'
}}
>
<div style={{ fontWeight: 'bold' }}>REPOBLIKAN'I MADAGASIKARA</div>
<div style={{ fontStyle: 'italic' }}>Fitiavana-Tanindrazana-Fandrosoana</div>
<div>********************</div>
<div style={{ fontWeight: 'bold' }}>MINISTÈRE DE L'ENSEIGNEMENT SUPÉRIEUR</div>
<div style={{ fontWeight: 'bold' }}>ET DE LA RECHERCHE SCIENTIFIQUE</div>
<div>********************</div>
<div style={{ fontWeight: 'bold' }}>UNIVERSITÉ DE TOAMASINA</div>
<div style={{ fontWeight: 'bold' }}>ÉCOLE SUPÉRIEURE POLYTECHNIQUE</div>
</div>
<img src={logoRelerev2} alt="Logo droite" width={90} height={90} />
</div>
{/* Informations du parcours */}
<div style={{ marginBottom: '15px', fontSize: '12px' }}>
<div><strong>Parcours :</strong> GC</div>
<div><strong>Niveau :</strong> {niveau}</div>
<div><strong>Année Universitaire :</strong> {scolaire}</div>
</div>
<table
className="table table-bordered table-striped text-center shadow-sm"
id="myTable2"
style={{ fontSize: '12px' }}
>
<thead className="table-secondary">
<tr>
<td colSpan={4} className="py-3">
<h6>
Niveau {niveau} | Année Scolaire {scolaire}
<td colSpan={4} className="py-3" style={{ backgroundColor: '#f8f9fa' }}>
<h6 style={{ margin: 0, fontWeight: 'bold' }}>
Résultat de la Deuxième Session : {niveau} admis en L3 par ordre de mérite
</h6>
</td>
</tr>
<tr>
<th>Nom</th>
<th>Prenom</th>
<th>Mention</th>
<th>Moyenne</th>
<tr style={{ backgroundColor: '#e9ecef' }}>
<th style={{ width: '10%', fontWeight: 'bold' }}>RANG</th>
<th style={{ width: '30%', fontWeight: 'bold' }}>NOMS</th>
<th style={{ width: '40%', fontWeight: 'bold' }}>PRÉNOMS</th>
<th style={{ width: '20%', fontWeight: 'bold' }}>Moyenne</th>
</tr>
</thead>
<tbody>
{sortedStudents.map((sorted) => (
{sortedStudents.map((sorted, index) => (
<tr key={sorted.id}>
<td>{sorted.nom}</td>
<td>{sorted.prenom}</td>
<td>{returnmention(sorted.mention)}</td>
<td className="fw-bold">{sorted.moyenne}</td>
<td style={{ fontWeight: 'bold' }}>{index + 1}.</td>
<td style={{ textAlign: 'left', paddingLeft: '10px', fontWeight: 'bold' }}>{sorted.nom}</td>
<td style={{ textAlign: 'left', paddingLeft: '10px' }}>{sorted.prenom}</td>
<td style={{ fontWeight: 'bold' }}>{sorted.moyenne}</td>
</tr>
))}
</tbody>

144
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,6 +82,115 @@ 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 = () => (
<Modal
open={openDeleteModal}
onClose={handleCloseDeleteModal}
aria-labelledby="modal-title"
aria-describedby="modal-description"
>
<Box
sx={{
position: 'absolute',
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)',
width: 450,
bgcolor: 'background.paper',
boxShadow: 24,
p: 4
}}
>
{isDeleted ? (
<Typography
style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: '10px' }}
>
<img src={success} alt="" width={50} height={50} />
<span>Étudiant supprimé avec succès</span>
</Typography>
) : (
<Typography
style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: '10px' }}
>
<img src={warning} alt="" width={50} height={50} />
<span>Voulez-vous supprimer cet étudiant ?</span>
</Typography>
)}
<Box
sx={{
marginTop: '2%',
display: 'flex',
gap: '20px',
alignItems: 'end',
justifyContent: 'flex-end'
}}
>
{isDeleted ? (
<Button onClick={handleCloseDeleteModal} color="warning" variant="contained">
OK
</Button>
) : (
<div>
<Button
onClick={handleDelete}
sx={{ mr: 1 }}
color="error"
variant="contained"
>
Oui
</Button>
<Button onClick={handleCloseDeleteModal} color="warning" variant="contained">
Non
</Button>
</div>
)}
</Box>
</Box>
</Modal>
)
const SeeNote = ({ params }) => {
const matchingNote = notes.find(
(element) =>
@ -171,7 +282,7 @@ const Student = () => {
{
field: 'action',
headerName: 'Action',
width: 300,
width: 350,
renderCell: (params) => (
<div style={{ display: 'flex', gap: '10px' }}>
<Link to={`/single/${params.value}`}>
@ -189,6 +300,7 @@ const Student = () => {
</Tooltip>
</Button>
</Link>
<Link to={`/tranche/${params.value}`} className={`verif${params.value}`}>
<Button color="warning" variant="contained">
<MdVerified style={{ fontSize: '20px', color: 'white' }} />
@ -286,6 +398,31 @@ const Student = () => {
</Link>
</Tooltip>
</Link>
<Button
color="error"
variant="contained"
onClick={() => handleOpenDeleteModal(params.value)}
className={`delete${params.value}`}
sx={{
marginTop: '10px',
minWidth: '30px', // largeur mini
height: '30px', // hauteur
padding: '4px', // espace interne
}}
>
<FaTrash style={{ fontSize: '16px', color: 'white' }} />
<Tooltip
anchorSelect={`.delete${params.value}`}
className="custom-tooltip"
place="top"
>
Supprimer
</Tooltip>
</Button>
</div>
)
}
@ -449,6 +586,7 @@ const Student = () => {
return (
<div className={classe.mainHome}>
{deleteModal()}
<style>
{`
.custom-tooltip {

5
src/renderer/src/components/SystemeNote.jsx

@ -21,6 +21,7 @@ const SystemeNote = () => {
renvoyer: ''
})
const [noteSy, setNoteSy] = useState([])
const [status, setStatus] = useState(200)
@ -37,7 +38,8 @@ const SystemeNote = () => {
}
useEffect(() => {
window.notesysteme.getSyteme().then((response) => {
window.notesysteme.getSysteme().then((response) => {
console.log('response:',response);
setNoteSy(response)
})
}, [])
@ -71,6 +73,7 @@ const SystemeNote = () => {
setOpen(true)
}
}
console.log('form:',noteSy);
const admisRef = useRef()
const redoubleRef = useRef()

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

@ -1,7 +1,8 @@
import { PDFDocument, PDFTextField } from 'pdf-lib'
import { PDFDocument, rgb } 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'
import { saveAs } from 'file-saver'
async function fillPdfFields(jsonData) {
const response = await fetch(PDF) // Load the PDF file
@ -10,27 +11,29 @@ async function fillPdfFields(jsonData) {
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}`)
// Get the first page to draw text on
const page = pdfDoc.getPage(0)
// Define positions for text (adjust these coordinates based on your red dots)
const textPositions = [
{ x: 45, y: 92, text: `${jsonData.f1 || ''}`, fontSize: 10 }, // Nom et prénom
{ x: 45, y: 75, text: `${jsonData.f2 || ''}`, fontSize: 10 }, // Date de naissance
{ x: 45, y: 58, text: `${jsonData.f3 || ''}`, fontSize: 10 }, // Niveau
{ x: 45, y: 38, text: `${jsonData.f4 || ''}`, fontSize: 10 }, // Année scolaire
{ x: 60, y: 23, text: `${jsonData.f5 || ''}`, fontSize: 10 } // Numéro d'inscription
]
// Draw text at specified positions
textPositions.forEach((item, index) => {
if (item.text.trim()) {
page.drawText(item.text, {
x: item.x,
y: item.y,
size: item.fontSize - 2,
color: rgb(1, 1, 1), // Black text
})
console.log(`Drawing text at position ${index + 1}: ${item.text} at (${item.x}, ${item.y})`)
}
})
@ -65,8 +68,6 @@ async function fillPdfFields(jsonData) {
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
@ -75,10 +76,10 @@ async function fillPdfFields(jsonData) {
})
}
// -------------------------------------------paste the qrCode in the pd--------------------------------------
// -------------------------------------------paste the qrCode in the pdf--------------------------------------
const paperContent = `
C-University
ECOLE POLYTECHNIQUE DE TOAMASINA
Nom et prenom: ${jsonData.f1}
Date de naissance: ${jsonData.f2}
Niveau: ${jsonData.f3}
@ -121,7 +122,6 @@ async function fillPdfFields(jsonData) {
// 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

Loading…
Cancel
Save