commit v_1 Tutoriel

This commit is contained in:
2026-02-17 09:34:20 +01:00
parent fde11005ab
commit 1c8845adf7
12 changed files with 322 additions and 20 deletions

Binary file not shown.

View File

@@ -50,6 +50,10 @@
{
"$type": "Bookmark",
"Name": "ST:131:0:{1fc202d4-d401-403c-9834-5b218574bb67}"
},
{
"$type": "Bookmark",
"Name": "ST:0:0:{1c4feeaa-4718-4aa9-859d-94ce25d182ba}"
}
]
}

View File

@@ -1,7 +1,12 @@
{
"Version": 1,
"WorkspaceRootPath": "C:\\Users\\oimer\\source\\repos\\RGC\\",
"Documents": [],
"Documents": [
{
"AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\oimer\\source\\repos\\RGC\\SuiviREForamteur\\suivireforamteur\\src\\HistoriquePage.tsx||{0F2454B1-A556-402D-A7D0-1FDE7F99DEE0}",
"RelativeMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|solutionrelative:SuiviREForamteur\\suivireforamteur\\src\\HistoriquePage.tsx||{0F2454B1-A556-402D-A7D0-1FDE7F99DEE0}"
}
],
"DocumentGroupContainers": [
{
"Orientation": 0,
@@ -9,7 +14,7 @@
"DocumentGroups": [
{
"DockedWidth": 200,
"SelectedChildIndex": -1,
"SelectedChildIndex": 11,
"Children": [
{
"$type": "Bookmark",
@@ -54,6 +59,19 @@
{
"$type": "Bookmark",
"Name": "ST:0:0:{1c4feeaa-4718-4aa9-859d-94ce25d182ba}"
},
{
"$type": "Document",
"DocumentIndex": 0,
"Title": "HistoriquePage.tsx",
"DocumentMoniker": "C:\\Users\\oimer\\source\\repos\\RGC\\SuiviREForamteur\\suivireforamteur\\src\\HistoriquePage.tsx",
"RelativeDocumentMoniker": "SuiviREForamteur\\suivireforamteur\\src\\HistoriquePage.tsx",
"ToolTip": "C:\\Users\\oimer\\source\\repos\\RGC\\SuiviREForamteur\\suivireforamteur\\src\\HistoriquePage.tsx",
"RelativeToolTip": "SuiviREForamteur\\suivireforamteur\\src\\HistoriquePage.tsx",
"ViewState": "AgIAAEIFAAAAAAAAAAAEwFAFAAALAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.003213|",
"WhenOpened": "2026-02-13T08:45:05.704Z",
"EditorCaption": ""
}
]
}

View File

@@ -2,7 +2,10 @@
"ExpandedNodes": [
"",
"\\SuiviREForamteur",
"\\SuiviREForamteur\\suivireforamteur"
"\\SuiviREForamteur\\suivireforamteur",
"\\SuiviREForamteur\\suivireforamteur\\public",
"\\SuiviREForamteur\\suivireforamteur\\src"
],
"SelectedNode": "\\SuiviREForamteur\\suivireforamteur\\src\\HistoriquePage.tsx",
"PreviewInSolutionExplorer": false
}

Binary file not shown.

View File

@@ -941,6 +941,188 @@ body {
min-width: 800px;
}
}
/* ✨ Bouton Tutoriel */
.tutorial-button {
background: linear-gradient(135deg, #8b5cf6 0%, #7c3aed 100%);
color: white;
border: none;
padding: 0.5rem 1rem;
border-radius: 12px;
cursor: pointer;
font-weight: 600;
display: flex;
align-items: center;
gap: 0.4rem;
transition: all 0.3s ease;
font-size: 0.85rem;
white-space: nowrap;
box-shadow: 0 2px 4px rgba(139, 92, 246, 0.3);
}
.tutorial-button:hover {
background: linear-gradient(135deg, #7c3aed 0%, #6d28d9 100%);
transform: translateY(-2px);
box-shadow: 0 6px 12px rgba(139, 92, 246, 0.4);
}
/* ✨ Modal Tutoriel */
.tutorial-modal-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.7);
backdrop-filter: blur(8px);
display: flex;
align-items: center;
justify-content: center;
z-index: 2000;
padding: 1rem;
animation: fadeIn 0.3s ease-out;
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
.tutorial-modal {
background: white;
border-radius: 24px;
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.3);
max-width: 700px;
width: 100%;
overflow: hidden;
animation: slideIn 0.4s ease-out;
}
@keyframes slideIn {
from {
opacity: 0;
transform: translateY(30px) scale(0.95);
}
to {
opacity: 1;
transform: translateY(0) scale(1);
}
}
.tutorial-modal-header {
background: linear-gradient(135deg, #8b5cf6 0%, #7c3aed 100%);
color: white;
padding: 2rem;
text-align: center;
}
.tutorial-modal-header h2 {
font-size: 1.8rem;
margin-bottom: 0.5rem;
font-weight: 700;
}
.tutorial-modal-header p {
font-size: 1rem;
opacity: 0.95;
}
.tutorial-modal-content {
padding: 2rem;
max-height: 60vh;
overflow-y: auto;
}
.tutorial-step-list {
list-style: none;
margin: 1rem 0;
}
.tutorial-step-list li {
padding: 1rem;
margin-bottom: 0.75rem;
background: #f8fafc;
border-radius: 12px;
border-left: 4px solid #8b5cf6;
display: flex;
align-items: start;
gap: 0.75rem;
transition: all 0.3s ease;
}
.tutorial-step-list li:hover {
background: #ede9fe;
transform: translateX(5px);
}
.tutorial-step-icon {
font-size: 1.5rem;
flex-shrink: 0;
}
.tutorial-step-content {
flex: 1;
}
.tutorial-step-title {
font-weight: 600;
color: #1e293b;
margin-bottom: 0.25rem;
font-size: 1rem;
}
.tutorial-step-desc {
color: #64748b;
font-size: 0.9rem;
line-height: 1.5;
}
.tutorial-highlight-box {
background: linear-gradient(135deg, #dcfce7 0%, #bbf7d0 100%);
padding: 1rem;
border-radius: 12px;
border-left: 4px solid #22c55e;
margin: 1rem 0;
}
.tutorial-highlight-box strong {
color: #166534;
display: block;
margin-bottom: 0.5rem;
font-size: 1rem;
}
.tutorial-highlight-box p {
color: #14532d;
line-height: 1.6;
font-size: 0.9rem;
}
.tutorial-modal-footer {
padding: 1.5rem 2rem;
background: #f8fafc;
text-align: center;
}
.tutorial-close-button {
background: linear-gradient(135deg, #22c55e 0%, #16a34a 100%);
color: white;
border: none;
padding: 0.75rem 2rem;
border-radius: 12px;
font-weight: 700;
cursor: pointer;
font-size: 1rem;
display: inline-flex;
align-items: center;
gap: 0.5rem;
transition: all 0.3s ease;
box-shadow: 0 4px 6px -1px rgba(34, 197, 94, 0.3);
}
.tutorial-close-button:hover {
transform: translateY(-3px);
box-shadow: 0 10px 20px -5px rgba(34, 197, 94, 0.4);
}
`;
// ═══════════════════════════════════════════════════════
@@ -1106,6 +1288,7 @@ const HistoriquePage: React.FC<HistoriquePageProps> = ({
const [editCommentaireFormateur, setEditCommentaireFormateur] = useState<string>('');
const [editDateEvalTuteur, setEditDateEvalTuteur] = useState<string>('');
const [editCommentaireRRE, setEditCommentaireRRE] = useState<string>('');
const [showTutorial, setShowTutorial] = useState<boolean>(false);
// ✅ Vérifier si l'utilisateur peut modifier (pas lecteur)
const effectiveRole = impersonatedUser?.role || user.role;
@@ -1316,18 +1499,21 @@ const HistoriquePage: React.FC<HistoriquePageProps> = ({
}, [records, filter, campusFilter, promoFilter, studentFilter]);
const dynamicStatusCounts = useMemo(() => {
// OUI = les deux sont OUI
const oui = preFilteredRecords.filter(r =>
r.autoEvaluation === 'OUI' && r.evaluationTuteur === 'OUI'
).length;
let oui = 0;
let partiel = 0;
let non = 0;
// PARTIEL = les deux sont PARTIEL
const partiel = preFilteredRecords.filter(r =>
r.autoEvaluation === 'PARTIEL' && r.evaluationTuteur === 'PARTIEL'
).length;
preFilteredRecords.forEach(r => {
// Compter auto-évaluation
if (r.autoEvaluation === 'OUI') oui++;
else if (r.autoEvaluation === 'PARTIEL') partiel++;
else non++; // NON ou vide
// NON = tout le reste (combinaisons mixtes, NON, vide, etc.)
const non = preFilteredRecords.length - oui - partiel;
// Compter évaluation tuteur
if (r.evaluationTuteur === 'OUI') oui++;
else if (r.evaluationTuteur === 'PARTIEL') partiel++;
else non++; // NON ou vide
});
return {
tous: preFilteredRecords.length,
@@ -1342,19 +1528,16 @@ const HistoriquePage: React.FC<HistoriquePageProps> = ({
if (statusFilter === 'tous') return true;
if (statusFilter === 'OUI') {
return r.autoEvaluation === 'OUI' && r.evaluationTuteur === 'OUI';
return r.autoEvaluation === 'OUI' || r.evaluationTuteur === 'OUI';
}
if (statusFilter === 'PARTIEL') {
// PARTIEL = les deux sont PARTIEL
return r.autoEvaluation === 'PARTIEL' && r.evaluationTuteur === 'PARTIEL';
return r.autoEvaluation === 'PARTIEL' || r.evaluationTuteur === 'PARTIEL';
}
if (statusFilter === 'NON') {
// NON = tout ce qui n'est ni OUI/OUI ni PARTIEL/PARTIEL
const isOui = r.autoEvaluation === 'OUI' && r.evaluationTuteur === 'OUI';
const isPartiel = r.autoEvaluation === 'PARTIEL' && r.evaluationTuteur === 'PARTIEL';
return !isOui && !isPartiel;
return r.autoEvaluation === 'NON' || !r.autoEvaluation ||
r.evaluationTuteur === 'NON' || !r.evaluationTuteur;
}
return true;
@@ -1800,6 +1983,10 @@ const HistoriquePage: React.FC<HistoriquePageProps> = ({
</div>
<div className="nav-right">
<span className="user-name">{displayName}</span>
{/* ✨ Bouton Tutoriel */}
<button onClick={() => setShowTutorial(true)} className="tutorial-button">
<span>📚</span> Tutoriel
</button>
<button onClick={onLogout} className="logout-button">
<span>🚪</span> Déconnexion
</button>
@@ -2525,6 +2712,96 @@ const HistoriquePage: React.FC<HistoriquePageProps> = ({
</div>,
document.body
)}
{/* ✨ Modal Tutoriel */}
{showTutorial && createPortal(
<div className="tutorial-modal-overlay" onClick={() => setShowTutorial(false)}>
<div className="tutorial-modal" onClick={(e) => e.stopPropagation()}>
<div className="tutorial-modal-header">
<h2>📜 Tutoriel - Page Historique</h2>
<p>Guide rapide d'utilisation</p>
</div>
<div className="tutorial-modal-content">
<h3 style={{ color: '#1e293b', fontSize: '1.3rem', marginBottom: '1rem' }}>
🎯 Comment utiliser cette page ?
</h3>
<ul className="tutorial-step-list">
<li>
<span className="tutorial-step-icon">🔍</span>
<div className="tutorial-step-content">
<div className="tutorial-step-title">Rechercher et filtrer</div>
<div className="tutorial-step-desc">
Utilisez la barre de recherche et les filtres (Campus, Promotion, Étudiant, Statut)
pour trouver rapidement les apprenants.
</div>
</div>
</li>
<li>
<span className="tutorial-step-icon">👁️</span>
<div className="tutorial-step-content">
<div className="tutorial-step-title">Voir l'historique complet</div>
<div className="tutorial-step-desc">
Cliquez sur l'icône 👁️ pour ouvrir la fenêtre de détail avec l'historique
complet des modifications et le formulaire de saisie.
</div>
</div>
</li>
<li>
<span className="tutorial-step-icon">✏️</span>
<div className="tutorial-step-content">
<div className="tutorial-step-title">Ajouter une nouvelle action</div>
<div className="tutorial-step-desc">
Dans la fenêtre de détail, remplissez le formulaire selon votre rôle
(Auto-éval, Éval tuteur, Date, Commentaires) puis cliquez sur "Ajouter l'action".
</div>
</div>
</li>
<li>
<span className="tutorial-step-icon">📄</span>
<div className="tutorial-step-content">
<div className="tutorial-step-title">Exporter en PDF</div>
<div className="tutorial-step-desc">
Cliquez sur l'icône 📄 pour générer et télécharger un PDF complet
avec toutes les données et l'historique de l'apprenant.
</div>
</div>
</li>
<li>
<span className="tutorial-step-icon">📊</span>
<div className="tutorial-step-content">
<div className="tutorial-step-title">Trier les données</div>
<div className="tutorial-step-desc">
Cliquez sur n'importe quel en-tête de colonne (Nom, Date, Statut...)
pour trier les résultats par ordre croissant ou décroissant.
</div>
</div>
</li>
</ul>
<div className="tutorial-highlight-box">
<strong>💡 Bon à savoir</strong>
<p>
Toutes les modifications sont enregistrées.
L'historique est permanent et assure une traçabilité complète de chaque dossier.
</p>
</div>
</div>
<div className="tutorial-modal-footer">
<button className="tutorial-close-button" onClick={() => setShowTutorial(false)}>
<span>🚀</span>
<span>J'ai compris, commencer !</span>
</button>
</div>
</div>
</div>,
document.body
)}
</div>
);
};