import { createContext, useContext, useState, useCallback, useEffect } from 'react'; import Joyride, { type CallBackProps, type Step, STATUS } from 'react-joyride'; import { useLocation } from 'react-router-dom'; interface OnboardingContextType { startTour: (tourName: string) => void; endTour: () => void; isActive: boolean; resetOnboarding: () => void; } const OnboardingContext = createContext(undefined); const ONBOARDING_KEY = 'mockupaws_onboarding_completed'; // Tour steps for different pages const dashboardSteps: Step[] = [ { target: '[data-tour="dashboard-stats"]', content: 'Welcome to mockupAWS! These cards show your key metrics at a glance.', title: 'Dashboard Overview', disableBeacon: true, placement: 'bottom', }, { target: '[data-tour="scenarios-nav"]', content: 'Manage all your AWS cost simulation scenarios here.', title: 'Scenarios', placement: 'right', }, { target: '[data-tour="compare-nav"]', content: 'Compare different scenarios side by side to make better decisions.', title: 'Compare Scenarios', placement: 'right', }, { target: '[data-tour="theme-toggle"]', content: 'Switch between light and dark mode for your comfort.', title: 'Theme Settings', placement: 'bottom', }, ]; const scenariosSteps: Step[] = [ { target: '[data-tour="scenario-list"]', content: 'Here you can see all your scenarios. Select multiple to compare them.', title: 'Your Scenarios', disableBeacon: true, placement: 'bottom', }, { target: '[data-tour="bulk-actions"]', content: 'Use bulk actions to manage multiple scenarios at once.', title: 'Bulk Operations', placement: 'bottom', }, { target: '[data-tour="keyboard-shortcuts"]', content: 'Press "?" anytime to see available keyboard shortcuts.', title: 'Keyboard Shortcuts', placement: 'top', }, ]; const tours: Record = { dashboard: dashboardSteps, scenarios: scenariosSteps, }; export function OnboardingProvider({ children }: { children: React.ReactNode }) { const [run, setRun] = useState(false); const [steps, setSteps] = useState([]); const [tourName, setTourName] = useState(''); const location = useLocation(); // Check if user has completed onboarding useEffect(() => { const completed = localStorage.getItem(ONBOARDING_KEY); if (!completed) { // Start dashboard tour for first-time users const timer = setTimeout(() => { startTour('dashboard'); }, 1000); return () => clearTimeout(timer); } }, []); // Auto-start tour when navigating to new pages useEffect(() => { const completed = localStorage.getItem(ONBOARDING_KEY); if (completed) return; const path = location.pathname; if (path === '/scenarios' && tourName !== 'scenarios') { const timer = setTimeout(() => { startTour('scenarios'); }, 500); return () => clearTimeout(timer); } }, [location.pathname, tourName]); const startTour = useCallback((name: string) => { const tourSteps = tours[name]; if (tourSteps) { setSteps(tourSteps); setTourName(name); setRun(true); } }, []); const endTour = useCallback(() => { setRun(false); }, []); const resetOnboarding = useCallback(() => { localStorage.removeItem(ONBOARDING_KEY); startTour('dashboard'); }, [startTour]); const handleJoyrideCallback = useCallback((data: CallBackProps) => { const { status } = data; const finishedStatuses: string[] = [STATUS.FINISHED, STATUS.SKIPPED]; if (finishedStatuses.includes(status)) { setRun(false); // Mark onboarding as completed when dashboard tour is finished if (tourName === 'dashboard') { localStorage.setItem(ONBOARDING_KEY, 'true'); } } }, [tourName]); return ( {children} ); } export function useOnboarding() { const context = useContext(OnboardingContext); if (context === undefined) { throw new Error('useOnboarding must be used within an OnboardingProvider'); } return context; }