import { useCallback, useRef, useState } from 'react' import { useNavigate } from 'react-router-dom' import { driver, type DriveStep } from 'driver.js' import 'driver.js/dist/driver.css' const TOUR_PENDING_KEY = 'gj-tour-pending-step' export function hasPendingTourStep(): string | null { return localStorage.getItem(TOUR_PENDING_KEY) } export function clearPendingTourStep(): void { localStorage.removeItem(TOUR_PENDING_KEY) } function driverDefaults() { return { showProgress: true, animate: true, allowClose: true, overlayColor: 'rgba(0, 0, 0, 0.6)', stagePadding: 8, stageRadius: 12, popoverClass: 'gj-tour-popover', nextBtnText: 'Next', prevBtnText: 'Back', doneBtnText: 'Got it!', progressText: '{{current}} of {{total}}', } as const } function getHomeSteps(isMobile: boolean): DriveStep[] { return [ { element: '#tour-title-input', popover: { title: 'Give it a Title', description: 'Start by naming your gratitude entry. A short title helps you find it later.', side: 'bottom', align: 'center', }, }, { element: '#tour-content-textarea', popover: { title: 'Write Your Thoughts', description: 'Pour out what you\'re grateful for today. There\'s no right or wrong — just write from the heart.', side: isMobile ? 'top' : 'bottom', align: 'center', }, }, { element: '#tour-save-btn', popover: { title: 'Save Your Entry', description: 'Hit save and your entry is securely encrypted and stored. Only you can read it.', side: 'top', align: 'center', }, }, { element: '#tour-nav-history', popover: { title: 'View Your History', description: 'This takes you to the History page. Let\'s go there next!', side: isMobile ? 'top' : 'right', align: 'center', }, }, ] } function getHistorySteps(isMobile: boolean): DriveStep[] { return [ { element: '#tour-calendar', popover: { title: 'Your Calendar', description: 'Green dots mark days you wrote entries. Navigate between months using the arrows.', side: isMobile ? 'bottom' : 'right', align: 'center', }, }, { element: '#tour-entries-list', popover: { title: 'Your Past Entries', description: 'Tap any date on the calendar to see entries from that day. Tap an entry card to read the full content.', side: isMobile ? 'top' : 'left', align: 'center', }, }, { element: '#tour-nav-settings', popover: { title: 'Your Settings', description: 'Let\'s check out your settings next!', side: isMobile ? 'top' : 'right', align: 'center', }, }, ] } function getSettingsSteps(isMobile: boolean): DriveStep[] { return [ { element: '#tour-edit-profile', popover: { title: 'Edit Your Profile', description: 'Tap the pencil icon to change your display name or profile photo.', side: isMobile ? 'bottom' : 'bottom', align: 'center', }, }, { element: '#tour-theme-switcher', popover: { title: 'Pick Your Theme', description: 'Switch between Light and Dark mode. Your choice is saved automatically.', side: isMobile ? 'top' : 'bottom', align: 'center', }, }, ] } export function useOnboardingTour() { const navigate = useNavigate() const driverRef = useRef | null>(null) const [isTourActive, setIsTourActive] = useState(false) const startTour = useCallback(() => { const isMobile = window.innerWidth < 860 setIsTourActive(true) const driverObj = driver({ ...driverDefaults(), onDestroyStarted: () => { clearPendingTourStep() setIsTourActive(false) driverObj.destroy() }, onNextClick: () => { const activeIndex = driverObj.getActiveIndex() const steps = driverObj.getConfig().steps || [] // Last home step → navigate to /history if (activeIndex === steps.length - 1) { localStorage.setItem(TOUR_PENDING_KEY, 'history') setIsTourActive(false) driverObj.destroy() navigate('/history') return } driverObj.moveNext() }, steps: getHomeSteps(isMobile), }) driverRef.current = driverObj setTimeout(() => driverObj.drive(), 150) }, [navigate]) const continueTourOnHistory = useCallback(() => { const isMobile = window.innerWidth < 860 const driverObj = driver({ ...driverDefaults(), onDestroyStarted: () => { clearPendingTourStep() driverObj.destroy() }, onNextClick: () => { const activeIndex = driverObj.getActiveIndex() const steps = driverObj.getConfig().steps || [] // Last history step → navigate to /settings if (activeIndex === steps.length - 1) { localStorage.setItem(TOUR_PENDING_KEY, 'settings') driverObj.destroy() navigate('/settings') return } driverObj.moveNext() }, steps: getHistorySteps(isMobile), }) driverRef.current = driverObj setTimeout(() => driverObj.drive(), 300) }, [navigate]) const continueTourOnSettings = useCallback(() => { const isMobile = window.innerWidth < 860 const driverObj = driver({ ...driverDefaults(), onDestroyStarted: () => { clearPendingTourStep() driverObj.destroy() }, onNextClick: () => { const activeIndex = driverObj.getActiveIndex() const steps = driverObj.getConfig().steps || [] // Last settings step → navigate to / if (activeIndex === steps.length - 1) { clearPendingTourStep() driverObj.destroy() navigate('/write') return } driverObj.moveNext() }, steps: getSettingsSteps(isMobile), }) driverRef.current = driverObj setTimeout(() => driverObj.drive(), 300) }, [navigate]) return { startTour, continueTourOnHistory, continueTourOnSettings, isTourActive } }