@@ -1,728 +0,0 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import Joyride, { STATUS } from 'react-joyride';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
|
||||
const GlobalTutorial = ({ userId, userRole }) => {
|
||||
const [runTour, setRunTour] = useState(false);
|
||||
const [dontShowAgain, setDontShowAgain] = useState(false);
|
||||
const [availableSteps, setAvailableSteps] = useState([]);
|
||||
const location = useLocation();
|
||||
|
||||
const isEmployee = userRole === "Collaborateur" || userRole === "Apprenti";
|
||||
const canViewAllFilters = ['president', 'rh', 'admin', 'directeur de campus', 'directrice de campus'].includes(userRole?.toLowerCase());
|
||||
|
||||
// 🎯 NOUVELLE FONCTION : Vérifier si un élément existe dans le DOM
|
||||
const elementExists = (selector) => {
|
||||
return document.querySelector(selector) !== null;
|
||||
};
|
||||
|
||||
// 🎯 NOUVELLE FONCTION : Filtrer les étapes selon les éléments disponibles
|
||||
const filterAvailableSteps = (steps) => {
|
||||
return steps.filter(step => {
|
||||
// Les étapes centrées (body) sont toujours affichées
|
||||
if (step.target === 'body') return true;
|
||||
|
||||
// Pour les autres, vérifier si l'élément existe
|
||||
const element = document.querySelector(step.target);
|
||||
if (!element) {
|
||||
console.log(`⚠️ Élément non trouvé, étape ignorée: ${step.target}`);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Vérifier si l'élément est visible
|
||||
const isVisible = element.offsetParent !== null;
|
||||
if (!isVisible) {
|
||||
console.log(`⚠️ Élément caché, étape ignorée: ${step.target}`);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
};
|
||||
|
||||
// 🎯 Déclencher le tutoriel avec vérification
|
||||
useEffect(() => {
|
||||
if (userId) {
|
||||
let tutorialKey = '';
|
||||
|
||||
if (location.pathname === '/dashboard') {
|
||||
tutorialKey = 'dashboard';
|
||||
} else if (location.pathname === '/manager') {
|
||||
tutorialKey = 'manager';
|
||||
} else if (location.pathname === '/calendar') {
|
||||
tutorialKey = 'calendar';
|
||||
}
|
||||
|
||||
if (tutorialKey) {
|
||||
const hasSeenTutorial = localStorage.getItem(`${tutorialKey}-tutorial-completed-${userId}`);
|
||||
|
||||
if (!hasSeenTutorial) {
|
||||
// ⭐ NOUVEAU : Attendre que le DOM soit chargé
|
||||
setTimeout(() => {
|
||||
const allSteps = getTourSteps();
|
||||
const available = filterAvailableSteps(allSteps);
|
||||
|
||||
console.log(`📊 Étapes totales: ${allSteps.length}, disponibles: ${available.length}`);
|
||||
|
||||
if (available.length > 2) { // Au moins 3 étapes (intro + 1 élément + conclusion)
|
||||
setAvailableSteps(available);
|
||||
setRunTour(true);
|
||||
} else {
|
||||
console.log('⚠️ Pas assez d\'éléments pour le tutoriel, annulation');
|
||||
}
|
||||
}, 2000);
|
||||
}
|
||||
}
|
||||
}
|
||||
}, [userId, location.pathname]);
|
||||
|
||||
// 🎯 Obtenir les étapes selon la page actuelle
|
||||
const getTourSteps = () => {
|
||||
// ==================== DASHBOARD ====================
|
||||
if (location.pathname === '/dashboard') {
|
||||
return [
|
||||
{
|
||||
target: 'body',
|
||||
content: (
|
||||
<div>
|
||||
<h2 className="text-xl font-bold mb-2">👋 Bienvenue sur votre application GTA !</h2>
|
||||
<p>Découvrez toutes les fonctionnalités en quelques étapes. Ce tutoriel ne s'affichera qu'une seule fois.</p>
|
||||
</div>
|
||||
),
|
||||
placement: 'center',
|
||||
disableBeacon: true,
|
||||
},
|
||||
{
|
||||
target: '[data-tour="dashboard"]',
|
||||
content: '🏠 Accédez à votre tableau de bord pour voir vos soldes de congés.',
|
||||
placement: 'right',
|
||||
},
|
||||
{
|
||||
target: '[data-tour="demandes"]',
|
||||
content: '📋 Consultez et gérez toutes vos demandes de congés ici.',
|
||||
placement: 'right',
|
||||
},
|
||||
{
|
||||
target: '[data-tour="calendrier"]',
|
||||
content: '📅 Visualisez vos congés et ceux de votre équipe dans le calendrier.',
|
||||
placement: 'right',
|
||||
},
|
||||
{
|
||||
target: '[data-tour="mon-equipe"]',
|
||||
content: '👥 Consultez votre équipe et leurs absences.',
|
||||
placement: 'right',
|
||||
},
|
||||
{
|
||||
target: '[data-tour="nouvelle-demande"]',
|
||||
content: '➕ Cliquez ici pour créer une nouvelle demande de congé, RTT ou récupération.',
|
||||
placement: 'left',
|
||||
},
|
||||
{
|
||||
target: '[data-tour="notifications"]',
|
||||
content: '🔔 Consultez ici vos notifications (validations, refus, modifications de vos demandes).',
|
||||
placement: 'bottom',
|
||||
},
|
||||
{
|
||||
target: '[data-tour="refresh"]',
|
||||
content: '🔄 Rafraîchissez manuellement vos données. Mais pas d\'inquiétude : elles se mettent à jour automatiquement en temps réel !',
|
||||
placement: 'bottom',
|
||||
},
|
||||
{
|
||||
target: '[data-tour="demandes-recentes"]',
|
||||
content: '📄 Consultez rapidement vos 5 dernières demandes et leur statut. Cliquez sur "Voir toutes les demandes" pour accéder à la page complète.',
|
||||
placement: 'top',
|
||||
},
|
||||
{
|
||||
target: '[data-tour="conges-service"]',
|
||||
content: '👥 Visualisez les congés de votre service pour le mois en cours. Pratique pour planifier vos absences !',
|
||||
placement: 'top',
|
||||
},
|
||||
{
|
||||
target: 'body',
|
||||
content: (
|
||||
<div>
|
||||
<h2 className="text-lg font-bold mb-2">📊 Vos compteurs de congés</h2>
|
||||
<p>Découvrez maintenant vos différents soldes de congés disponibles.</p>
|
||||
</div>
|
||||
),
|
||||
placement: 'center',
|
||||
},
|
||||
{
|
||||
target: '[data-tour="cp-n-1"]',
|
||||
content: '📅 Vos congés payés de l\'année précédente. ⚠️ Attention : ils doivent être soldés avant le 31 décembre de l\'année en cours !',
|
||||
placement: 'top',
|
||||
},
|
||||
{
|
||||
target: '[data-tour="cp-n"]',
|
||||
content: '📈 Vos congés payés de l\'année en cours, en cours d\'acquisition. Ils se cumulent au fil des mois travaillés.',
|
||||
placement: 'top',
|
||||
},
|
||||
{
|
||||
target: '[data-tour="rtt"]',
|
||||
content: '⏰ Vos RTT disponibles pour l\'année en cours. Ils sont acquis progressivement et à consommer avant le 31/12.',
|
||||
placement: 'top',
|
||||
},
|
||||
{
|
||||
target: '[data-tour="recup"]',
|
||||
content: '🔄 Vos jours de récupération accumulés suite à des heures supplémentaires.',
|
||||
placement: 'top',
|
||||
},
|
||||
{
|
||||
target: 'body',
|
||||
content: (
|
||||
<div>
|
||||
<h2 className="text-xl font-bold mb-2">🎉 Vous êtes prêt !</h2>
|
||||
<p className="mb-3">Vous pouvez maintenant utiliser l'application en toute autonomie.</p>
|
||||
<div className="bg-cyan-50 border border-cyan-200 rounded-lg p-3 mt-3">
|
||||
<p className="text-sm text-cyan-900">
|
||||
💡 <strong>Besoin d'aide ?</strong> Cliquez sur le bouton <strong>"Aide"</strong> 🆘 en bas à droite pour relancer ce tutoriel à tout moment.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
placement: 'center',
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
// ==================== MANAGER ====================
|
||||
if (location.pathname === '/manager') {
|
||||
const baseSteps = [
|
||||
{
|
||||
target: 'body',
|
||||
content: (
|
||||
<div>
|
||||
<h2 className="text-xl font-bold mb-2">👥 Bienvenue dans la gestion d'équipe !</h2>
|
||||
<p>Découvrez comment gérer {isEmployee ? 'votre équipe' : 'les demandes de congés de votre équipe'}.</p>
|
||||
</div>
|
||||
),
|
||||
placement: 'center',
|
||||
disableBeacon: true,
|
||||
}
|
||||
];
|
||||
|
||||
if (!isEmployee) {
|
||||
// Pour les managers/validateurs
|
||||
return [
|
||||
...baseSteps,
|
||||
{
|
||||
target: '[data-tour="demandes-attente"]',
|
||||
content: '⏳ Consultez ici toutes les demandes en attente de validation. Vous pouvez les approuver ou les refuser directement.',
|
||||
placement: 'right',
|
||||
},
|
||||
{
|
||||
target: '[data-tour="approuver-btn"]',
|
||||
content: '✅ Cliquez sur "Approuver" pour valider une demande. Vous pourrez ajouter un commentaire optionnel.',
|
||||
placement: 'top',
|
||||
},
|
||||
{
|
||||
target: '[data-tour="refuser-btn"]',
|
||||
content: '❌ Cliquez sur "Refuser" pour rejeter une demande. Un commentaire expliquant le motif sera obligatoire.',
|
||||
placement: 'top',
|
||||
},
|
||||
{
|
||||
target: '[data-tour="mon-equipe"]',
|
||||
content: '👥 Consultez la liste complète de votre équipe. Cliquez sur un membre pour voir le détail de ses demandes.',
|
||||
placement: 'left',
|
||||
},
|
||||
{
|
||||
target: '[data-tour="historique-demandes"]',
|
||||
content: '📋 L\'historique complet de toutes les demandes de votre équipe avec leur statut (validée, refusée, en attente).',
|
||||
placement: 'top',
|
||||
},
|
||||
{
|
||||
target: '[data-tour="document-joint"]',
|
||||
content: '📎 Si un document est joint à une demande (certificat médical par exemple), vous pouvez le consulter ici.',
|
||||
placement: 'left',
|
||||
},
|
||||
{
|
||||
target: 'body',
|
||||
content: (
|
||||
<div>
|
||||
<h2 className="text-xl font-bold mb-2">🎉 Vous êtes prêt à gérer votre équipe !</h2>
|
||||
<p className="mb-3">Vous savez maintenant valider les demandes et suivre les absences de vos collaborateurs.</p>
|
||||
<div className="bg-cyan-50 border border-cyan-200 rounded-lg p-3 mt-3">
|
||||
<p className="text-sm text-cyan-900">
|
||||
💡 <strong>Astuce :</strong> Les données se mettent à jour automatiquement en temps réel. Vous recevrez des notifications pour chaque nouvelle demande.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
placement: 'center',
|
||||
}
|
||||
];
|
||||
} else {
|
||||
// Pour les collaborateurs/apprentis
|
||||
return [
|
||||
...baseSteps,
|
||||
{
|
||||
target: '[data-tour="mon-equipe"]',
|
||||
content: '👥 Consultez ici la liste de votre équipe. Vous pouvez voir les membres de votre service.',
|
||||
placement: 'left',
|
||||
},
|
||||
{
|
||||
target: '[data-tour="membre-equipe"]',
|
||||
content: '👤 Cliquez sur un membre pour voir le détail de ses informations et absences.',
|
||||
placement: 'left',
|
||||
},
|
||||
{
|
||||
target: 'body',
|
||||
content: (
|
||||
<div>
|
||||
<h2 className="text-xl font-bold mb-2">✅ C'est tout pour cette section !</h2>
|
||||
<p className="mb-3">Vous pouvez maintenant consulter votre équipe facilement.</p>
|
||||
<div className="bg-cyan-50 border border-cyan-200 rounded-lg p-3 mt-3">
|
||||
<p className="text-sm text-cyan-900">
|
||||
💡 <strong>Besoin d'aide ?</strong> N'hésitez pas à contacter votre manager pour toute question.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
placement: 'center',
|
||||
}
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== CALENDAR ====================
|
||||
if (location.pathname === '/calendar') {
|
||||
const baseSteps = [
|
||||
{
|
||||
target: 'body',
|
||||
content: (
|
||||
<div>
|
||||
<h2 className="text-xl font-bold mb-2">📅 Bienvenue dans le calendrier !</h2>
|
||||
<p>Découvrez comment visualiser et gérer les congés {canViewAllFilters ? 'de toute l\'entreprise' : 'de votre équipe'}.</p>
|
||||
</div>
|
||||
),
|
||||
placement: 'center',
|
||||
disableBeacon: true,
|
||||
},
|
||||
{
|
||||
target: '[data-tour="pto-counter"]',
|
||||
content: '📊 Votre solde PTO (Paid Time Off) total : somme de vos CP N-1, CP N et RTT disponibles.',
|
||||
placement: 'bottom',
|
||||
},
|
||||
{
|
||||
target: '[data-tour="navigation-mois"]',
|
||||
content: '◀️▶️ Naviguez entre les mois pour consulter les congés passés et à venir.',
|
||||
placement: 'bottom',
|
||||
}
|
||||
];
|
||||
|
||||
// Étapes pour les filtres selon le rôle
|
||||
if (canViewAllFilters) {
|
||||
baseSteps.push(
|
||||
{
|
||||
target: '[data-tour="filtres-btn"]',
|
||||
content: '🔍 Accédez aux filtres pour affiner votre vue : société, campus, service, collaborateurs...',
|
||||
placement: 'left',
|
||||
},
|
||||
{
|
||||
target: '[data-tour="filtre-societe"]',
|
||||
content: '🏢 Filtrez par société pour voir uniquement les congés d\'une entité spécifique.',
|
||||
placement: 'bottom',
|
||||
},
|
||||
{
|
||||
target: '[data-tour="filtre-campus"]',
|
||||
content: '🏫 Filtrez par campus pour visualiser les absences par site géographique.',
|
||||
placement: 'bottom',
|
||||
},
|
||||
{
|
||||
target: '[data-tour="filtre-service"]',
|
||||
content: '👔 Filtrez par service pour voir les congés d\'un département spécifique.',
|
||||
placement: 'bottom',
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// Étapes communes pour tous
|
||||
baseSteps.push(
|
||||
{
|
||||
target: '[data-tour="selection-collaborateurs"]',
|
||||
content: '👥 Sélectionnez les collaborateurs que vous souhaitez afficher dans le calendrier. Pratique pour se concentrer sur certaines personnes !',
|
||||
placement: 'top',
|
||||
},
|
||||
{
|
||||
target: '[data-tour="refresh-btn"]',
|
||||
content: '🔄 Rafraîchissez manuellement les données. Mais rassurez-vous : elles se mettent à jour automatiquement en temps réel via SSE !',
|
||||
placement: 'left',
|
||||
},
|
||||
{
|
||||
target: 'body',
|
||||
content: (
|
||||
<div>
|
||||
<h2 className="text-lg font-bold mb-2">📅 Sélectionner des dates</h2>
|
||||
<p>Vous pouvez sélectionner des dates directement dans le calendrier pour créer une demande de congé rapidement.</p>
|
||||
</div>
|
||||
),
|
||||
placement: 'center',
|
||||
},
|
||||
{
|
||||
target: '[data-tour="calendar-grid"]',
|
||||
content: '🖱️ Cliquez sur une date de début, puis sur une date de fin pour sélectionner une période. Un menu contextuel apparaîtra pour choisir le type de congé.',
|
||||
placement: 'top',
|
||||
},
|
||||
{
|
||||
target: '[data-tour="legende"]',
|
||||
content: '🎨 La légende vous aide à identifier les différents types de congés : validés (vert), en attente (orange), formation (bleu), etc.',
|
||||
placement: 'top',
|
||||
},
|
||||
{
|
||||
target: 'body',
|
||||
content: (
|
||||
<div>
|
||||
<h2 className="text-xl font-bold mb-2">🎉 Vous maîtrisez le calendrier !</h2>
|
||||
<p className="mb-3">Vous savez maintenant visualiser les congés, filtrer par équipe et créer rapidement des demandes.</p>
|
||||
<div className="bg-cyan-50 border border-cyan-200 rounded-lg p-3 mt-3">
|
||||
<p className="text-sm text-cyan-900">
|
||||
💡 <strong>Astuce :</strong> Survolez une case de congé pour voir tous les détails (employé, type, période, statut). Sur mobile, appuyez sur la case !
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
placement: 'center',
|
||||
}
|
||||
);
|
||||
|
||||
return baseSteps;
|
||||
}
|
||||
|
||||
return [];
|
||||
};
|
||||
|
||||
// 🎯 Obtenir la clé localStorage selon la page
|
||||
const getTutorialKey = () => {
|
||||
if (location.pathname === '/dashboard') return 'dashboard';
|
||||
if (location.pathname === '/manager') return 'manager';
|
||||
if (location.pathname === '/calendar') return 'calendar';
|
||||
return '';
|
||||
};
|
||||
|
||||
// 🎯 Gérer la fin du tutoriel
|
||||
const handleJoyrideCallback = (data) => {
|
||||
const { status } = data;
|
||||
const finishedStatuses = [STATUS.FINISHED, STATUS.SKIPPED];
|
||||
|
||||
if (finishedStatuses.includes(status)) {
|
||||
setRunTour(false);
|
||||
setDontShowAgain(false);
|
||||
}
|
||||
};
|
||||
|
||||
// Si on n'a pas d'étapes disponibles, ne rien afficher
|
||||
if (availableSteps.length === 0) return null;
|
||||
|
||||
return (
|
||||
<Joyride
|
||||
steps={availableSteps}
|
||||
run={runTour}
|
||||
continuous
|
||||
showProgress={true}
|
||||
showSkipButton={false}
|
||||
scrollToFirstStep
|
||||
scrollOffset={100}
|
||||
callback={handleJoyrideCallback}
|
||||
styles={{
|
||||
options: {
|
||||
primaryColor: '#0891b2',
|
||||
zIndex: 10000,
|
||||
},
|
||||
}}
|
||||
floaterProps={{
|
||||
disableAnimation: true,
|
||||
}}
|
||||
locale={{
|
||||
back: 'Retour',
|
||||
close: 'Fermer',
|
||||
last: 'Terminer',
|
||||
next: 'Suivant',
|
||||
skip: 'Passer'
|
||||
}}
|
||||
tooltipComponent={({
|
||||
continuous,
|
||||
index,
|
||||
step,
|
||||
backProps,
|
||||
primaryProps,
|
||||
skipProps,
|
||||
closeProps,
|
||||
tooltipProps,
|
||||
size,
|
||||
isLastStep
|
||||
}) => {
|
||||
const [showConfirmModal, setShowConfirmModal] = React.useState(false);
|
||||
const tutorialKey = getTutorialKey();
|
||||
|
||||
const handleFinish = () => {
|
||||
if (dontShowAgain) {
|
||||
localStorage.setItem(`${tutorialKey}-tutorial-completed-${userId}`, 'true');
|
||||
}
|
||||
setRunTour(false);
|
||||
setDontShowAgain(false);
|
||||
};
|
||||
|
||||
const handleSkip = () => {
|
||||
if (dontShowAgain) {
|
||||
setShowConfirmModal(true);
|
||||
} else {
|
||||
setRunTour(false);
|
||||
setDontShowAgain(false);
|
||||
}
|
||||
};
|
||||
|
||||
const confirmSkip = () => {
|
||||
localStorage.setItem(`${tutorialKey}-tutorial-completed-${userId}`, 'true');
|
||||
setShowConfirmModal(false);
|
||||
setRunTour(false);
|
||||
setDontShowAgain(false);
|
||||
};
|
||||
|
||||
const cancelSkip = () => {
|
||||
setShowConfirmModal(false);
|
||||
setDontShowAgain(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{/* Modal de confirmation */}
|
||||
{showConfirmModal && (
|
||||
<div style={{
|
||||
position: 'fixed',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
backgroundColor: 'rgba(0, 0, 0, 0.5)',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
zIndex: 10001
|
||||
}}
|
||||
onClick={(e) => {
|
||||
if (e.target === e.currentTarget) {
|
||||
cancelSkip();
|
||||
}
|
||||
}}>
|
||||
<div style={{
|
||||
backgroundColor: 'white',
|
||||
borderRadius: '16px',
|
||||
padding: '24px',
|
||||
maxWidth: '400px',
|
||||
width: '90%',
|
||||
boxShadow: '0 20px 50px rgba(0,0,0,0.3)'
|
||||
}}>
|
||||
<div style={{
|
||||
fontSize: '48px',
|
||||
marginBottom: '16px',
|
||||
textAlign: 'center'
|
||||
}}>
|
||||
⚠️
|
||||
</div>
|
||||
<h3 style={{
|
||||
fontSize: '18px',
|
||||
fontWeight: 'bold',
|
||||
marginBottom: '12px',
|
||||
color: '#111827',
|
||||
textAlign: 'center'
|
||||
}}>
|
||||
Ne plus afficher le tutoriel ?
|
||||
</h3>
|
||||
<p style={{
|
||||
fontSize: '14px',
|
||||
color: '#6b7280',
|
||||
marginBottom: '24px',
|
||||
textAlign: 'center',
|
||||
lineHeight: '1.5'
|
||||
}}>
|
||||
Êtes-vous sûr de vouloir désactiver définitivement ce tutoriel ?
|
||||
{tutorialKey === 'dashboard' && ' Vous pourrez le réactiver plus tard en cliquant sur le bouton "Aide".'}
|
||||
</p>
|
||||
<div style={{
|
||||
display: 'flex',
|
||||
gap: '12px',
|
||||
justifyContent: 'center'
|
||||
}}>
|
||||
<button
|
||||
onClick={cancelSkip}
|
||||
style={{
|
||||
padding: '10px 20px',
|
||||
borderRadius: '8px',
|
||||
border: '1px solid #d1d5db',
|
||||
backgroundColor: 'white',
|
||||
color: '#374151',
|
||||
cursor: 'pointer',
|
||||
fontSize: '14px',
|
||||
fontWeight: '500',
|
||||
transition: 'all 0.2s'
|
||||
}}
|
||||
>
|
||||
Annuler
|
||||
</button>
|
||||
<button
|
||||
onClick={confirmSkip}
|
||||
style={{
|
||||
padding: '10px 20px',
|
||||
borderRadius: '8px',
|
||||
border: 'none',
|
||||
backgroundColor: '#ef4444',
|
||||
color: 'white',
|
||||
cursor: 'pointer',
|
||||
fontSize: '14px',
|
||||
fontWeight: '500',
|
||||
transition: 'all 0.2s'
|
||||
}}
|
||||
>
|
||||
Oui, ne plus afficher
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Tooltip principal */}
|
||||
<div {...tooltipProps} style={{
|
||||
backgroundColor: 'white',
|
||||
borderRadius: '12px',
|
||||
padding: '20px',
|
||||
maxWidth: '400px',
|
||||
boxShadow: '0 10px 25px rgba(0,0,0,0.15)',
|
||||
fontSize: '14px'
|
||||
}}>
|
||||
<div style={{ marginBottom: '15px', color: '#374151' }}>
|
||||
{step.content}
|
||||
</div>
|
||||
|
||||
{/* Case à cocher "Ne plus afficher" */}
|
||||
<div style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: '8px',
|
||||
marginTop: '12px',
|
||||
marginBottom: '12px',
|
||||
padding: '10px',
|
||||
backgroundColor: '#f9fafb',
|
||||
borderRadius: '8px',
|
||||
border: '1px solid #e5e7eb'
|
||||
}}>
|
||||
<input
|
||||
type="checkbox"
|
||||
id={`dont-show-again-${index}`}
|
||||
checked={dontShowAgain}
|
||||
onChange={(e) => setDontShowAgain(e.target.checked)}
|
||||
style={{
|
||||
width: '18px',
|
||||
height: '18px',
|
||||
cursor: 'pointer',
|
||||
accentColor: '#0891b2'
|
||||
}}
|
||||
/>
|
||||
<label
|
||||
htmlFor={`dont-show-again-${index}`}
|
||||
style={{
|
||||
fontSize: '13px',
|
||||
color: '#374151',
|
||||
cursor: 'pointer',
|
||||
userSelect: 'none',
|
||||
fontWeight: '500'
|
||||
}}
|
||||
>
|
||||
Ne plus afficher ce tutoriel
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div style={{
|
||||
display: 'flex',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
paddingTop: '12px',
|
||||
borderTop: '1px solid #e5e7eb'
|
||||
}}>
|
||||
<span style={{ fontSize: '13px', color: '#6b7280', fontWeight: '500' }}>
|
||||
Étape {index + 1} sur {size}
|
||||
</span>
|
||||
|
||||
<div style={{ display: 'flex', gap: '8px' }}>
|
||||
{index > 0 && (
|
||||
<button
|
||||
{...backProps}
|
||||
style={{
|
||||
padding: '8px 14px',
|
||||
borderRadius: '8px',
|
||||
border: '1px solid #d1d5db',
|
||||
backgroundColor: 'white',
|
||||
color: '#6b7280',
|
||||
cursor: 'pointer',
|
||||
fontSize: '13px',
|
||||
fontWeight: '500',
|
||||
transition: 'all 0.2s'
|
||||
}}>
|
||||
Retour
|
||||
</button>
|
||||
)}
|
||||
|
||||
{!isLastStep && (
|
||||
<button
|
||||
{...primaryProps}
|
||||
style={{
|
||||
padding: '8px 18px',
|
||||
borderRadius: '8px',
|
||||
border: 'none',
|
||||
backgroundColor: '#0891b2',
|
||||
color: 'white',
|
||||
cursor: 'pointer',
|
||||
fontSize: '13px',
|
||||
fontWeight: '500',
|
||||
transition: 'all 0.2s'
|
||||
}}
|
||||
>
|
||||
Suivant
|
||||
</button>
|
||||
)}
|
||||
|
||||
{isLastStep && (
|
||||
<button
|
||||
onClick={handleFinish}
|
||||
style={{
|
||||
padding: '8px 18px',
|
||||
borderRadius: '8px',
|
||||
border: 'none',
|
||||
backgroundColor: '#0891b2',
|
||||
color: 'white',
|
||||
cursor: 'pointer',
|
||||
fontSize: '13px',
|
||||
fontWeight: '500',
|
||||
transition: 'all 0.2s'
|
||||
}}
|
||||
>
|
||||
Terminer
|
||||
</button>
|
||||
)}
|
||||
|
||||
<button
|
||||
onClick={handleSkip}
|
||||
style={{
|
||||
padding: '8px 14px',
|
||||
borderRadius: '8px',
|
||||
border: '1px solid #d1d5db',
|
||||
backgroundColor: 'white',
|
||||
color: '#6b7280',
|
||||
cursor: 'pointer',
|
||||
fontSize: '13px',
|
||||
fontWeight: '500',
|
||||
transition: 'all 0.2s'
|
||||
}}
|
||||
>
|
||||
Passer
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default GlobalTutorial;
|
||||
Reference in New Issue
Block a user