diff --git a/src/components/dashboard/GuidedTour.jsx b/src/components/dashboard/GuidedTour.jsx new file mode 100644 index 0000000..a7f5aec --- /dev/null +++ b/src/components/dashboard/GuidedTour.jsx @@ -0,0 +1,241 @@ +import React, { useState, useEffect, useCallback } from "react"; +import { motion, AnimatePresence } from "framer-motion"; +import { X, ChevronRight, ChevronLeft, Sparkles } from "lucide-react"; +import { Button } from "@/components/ui/button"; + +const tourSteps = [ + { + targetId: "user-menu-btn", + title: "User Actions & Account Controls", + description: "This area contains your account actions and user controls. Access your profile, contact support, manage store information, and sign out from here.", + position: "bottom-right", + }, + { + targetId: "notifications-btn", + title: "Notifications & Alerts", + description: "This bell icon is your notification center. You'll receive important system alerts, bulletins, program updates, and action items here. Unread notifications are shown with a red badge count.", + position: "bottom-right", + }, + { + targetId: "dashboard-main", + title: "Your Performance Dashboard", + description: "This is your main dashboard — track parcels received, consolidations completed, financial earnings, and compliance events all in one place.", + position: "center", + }, + { + targetId: "sidebar", + title: "Navigation & Settings", + description: "Use the sidebar to navigate between Program Management, Communication & Support, and Member Management. Access your profile and Stripe Connect settings here.", + position: "right", + }, + { + targetId: null, + title: "Complete Your Stripe Onboarding", + description: "You're almost done! The final step is to set up your Stripe Express account so you can receive electronic program payouts from PackageHub.", + position: "center", + isFinal: true, + }, +]; + +export default function GuidedTour({ onComplete }) { + const [currentStep, setCurrentStep] = useState(0); + const [spotlightRect, setSpotlightRect] = useState(null); + const [tooltipStyle, setTooltipStyle] = useState({}); + + const calculatePosition = useCallback(() => { + const step = tourSteps[currentStep]; + if (!step.targetId) { + setSpotlightRect(null); + setTooltipStyle({ + top: "50%", + left: "50%", + transform: "translate(-50%, -50%)", + }); + return; + } + + const el = document.getElementById(step.targetId); + if (!el) { + setSpotlightRect(null); + return; + } + + const rect = el.getBoundingClientRect(); + const padding = 8; + setSpotlightRect({ + top: rect.top - padding, + left: rect.left - padding, + width: rect.width + padding * 2, + height: rect.height + padding * 2, + }); + + // Calculate tooltip position + let style = {}; + if (step.position === "bottom-right") { + style = { + top: rect.bottom + 16, + right: window.innerWidth - rect.right, + }; + } else if (step.position === "right") { + style = { + top: rect.top + 60, + left: rect.right + 16, + }; + } else { + style = { + top: "50%", + left: "50%", + transform: "translate(-50%, -50%)", + }; + } + setTooltipStyle(style); + }, [currentStep]); + + useEffect(() => { + calculatePosition(); + window.addEventListener("resize", calculatePosition); + return () => window.removeEventListener("resize", calculatePosition); + }, [calculatePosition]); + + const step = tourSteps[currentStep]; + const isLast = currentStep === tourSteps.length - 1; + const isFirst = currentStep === 0; + + return ( +
+ {step.description}
+