14082025
This commit is contained in:
parent
f1aefc3073
commit
f4ad4ecf12
@ -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 [];
|
||||
}
|
||||
|
||||
let sql, params;
|
||||
|
||||
if (niveau !== 'L1') {
|
||||
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
|
||||
@ -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 {
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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),
|
||||
|
||||
@ -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(),
|
||||
|
||||
@ -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}
|
||||
|
||||
@ -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>
|
||||
@ -196,4 +328,4 @@ const Parcours = () => {
|
||||
)
|
||||
}
|
||||
|
||||
export default Parcours
|
||||
export default Parcours
|
||||
@ -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>
|
||||
@ -215,4 +274,4 @@ const Resultat = () => {
|
||||
)
|
||||
}
|
||||
|
||||
export default Resultat
|
||||
export default Resultat
|
||||
@ -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 = () => (
|
||||
<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) =>
|
||||
element.etudiant_niveau === params.row.niveau && element.etudiant_id === params.value
|
||||
)
|
||||
|
||||
|
||||
return (
|
||||
<div style={{ display: 'flex', gap: '10px' }}>
|
||||
{matchingNote ? (
|
||||
@ -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 {
|
||||
|
||||
@ -21,9 +21,10 @@ const SystemeNote = () => {
|
||||
renvoyer: ''
|
||||
})
|
||||
|
||||
|
||||
const [noteSy, setNoteSy] = useState([])
|
||||
const [status, setStatus] = useState(200)
|
||||
|
||||
|
||||
/**
|
||||
* function to set the data in state
|
||||
* @param {*} e
|
||||
@ -35,13 +36,14 @@ const SystemeNote = () => {
|
||||
[name]: value
|
||||
}))
|
||||
}
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
window.notesysteme.getSyteme().then((response) => {
|
||||
window.notesysteme.getSysteme().then((response) => {
|
||||
console.log('response:',response);
|
||||
setNoteSy(response)
|
||||
})
|
||||
}, [])
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
if (noteSy) {
|
||||
setFormData({
|
||||
@ -52,13 +54,13 @@ const SystemeNote = () => {
|
||||
})
|
||||
}
|
||||
}, [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)
|
||||
@ -71,7 +73,8 @@ const SystemeNote = () => {
|
||||
setOpen(true)
|
||||
}
|
||||
}
|
||||
|
||||
console.log('form:',noteSy);
|
||||
|
||||
const admisRef = useRef()
|
||||
const redoubleRef = useRef()
|
||||
const renvoyerRef = useRef()
|
||||
|
||||
@ -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 }))
|
||||
// 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
|
||||
]
|
||||
|
||||
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}`)
|
||||
// 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
|
||||
|
||||
@ -148,4 +148,4 @@ async function fillPdfFields(jsonData) {
|
||||
*/
|
||||
export const processPdf = async (jsonData) => {
|
||||
await fillPdfFields(jsonData)
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user