From 5de28f2eaf9b699c275f9e0e74774c7546b03312 Mon Sep 17 00:00:00 2001 From: seaznCode Date: Wed, 22 Oct 2025 18:51:34 +0200 Subject: [PATCH] feat: implement tutorial modal with step-by-step guidance for new users --- src/app/components/TutorialModal.tsx | 264 +++++++++++++++++++++++++ src/app/quickaction-dashboard/page.tsx | 92 ++++++++- 2 files changed, 348 insertions(+), 8 deletions(-) create mode 100644 src/app/components/TutorialModal.tsx diff --git a/src/app/components/TutorialModal.tsx b/src/app/components/TutorialModal.tsx new file mode 100644 index 0000000..7c67ecd --- /dev/null +++ b/src/app/components/TutorialModal.tsx @@ -0,0 +1,264 @@ +'use client' + +import { Fragment } from 'react' +import { Dialog, Transition } from '@headlessui/react' +import { + XMarkIcon, + EnvelopeIcon, + IdentificationIcon, + UserIcon, + DocumentTextIcon, + ClockIcon, + ArrowRightIcon, + CheckCircleIcon +} from '@heroicons/react/24/outline' + +interface TutorialStep { + id: number + title: string + description: string + details: string[] + icon: React.ComponentType> + buttonText: string + buttonAction: () => void + canProceed: boolean +} + +interface TutorialModalProps { + isOpen: boolean + onClose: () => void + currentStep: number + steps: TutorialStep[] + onNext: () => void + onPrevious: () => void +} + +export default function TutorialModal({ + isOpen, + onClose, + currentStep, + steps, + onNext, + onPrevious +}: TutorialModalProps) { + const step = steps[currentStep - 1] + + if (!step) return null + + const isLastStep = currentStep === steps.length + const isFirstStep = currentStep === 1 + + return ( + + + +
+ + +
+
+ + +
+ +
+ +
+
+
+
+ + {step.title} + +
+

+ {step.description} +

+
    + {step.details.map((detail, index) => ( +
  • +
    + {detail} +
  • + ))} +
+
+
+
+ + {/* Progress indicator */} +
+
+ Step {currentStep} of {steps.length} + {Math.round((currentStep / steps.length) * 100)}% Complete +
+
+
+
+
+ +
+ + + {!isLastStep && ( + + )} + + {!isFirstStep && ( + + )} +
+ + +
+
+
+
+ ) +} + +// Tutorial step data +export const createTutorialSteps = ( + emailVerified: boolean, + idUploaded: boolean, + additionalInfo: boolean, + contractSigned: boolean, + userType: string, + onVerifyEmail: () => void, + onUploadId: () => void, + onCompleteInfo: () => void, + onSignContract: () => void, + onCloseTutorial: () => void +): TutorialStep[] => [ + { + id: 1, + title: "Step 1: Verify Your Email", + description: "Let's start by verifying your email address. This is essential for account security.", + details: [ + "Check your email inbox for our verification message", + "Click the verification link in the email", + "If you don't see it, check your spam folder", + "You can request a new verification email if needed" + ], + icon: EnvelopeIcon, + buttonText: emailVerified ? "Email Verified ✓" : "Verify Email", + buttonAction: onVerifyEmail, + canProceed: true + }, + { + id: 2, + title: "Step 2: Upload ID Documents", + description: "Next, we need to verify your identity by uploading official ID documents.", + details: [ + "Prepare a clear photo of your ID (passport, driver's license, or national ID)", + "Ensure all text is clearly readable", + "Take photos in good lighting conditions", + "Both front and back sides may be required" + ], + icon: IdentificationIcon, + buttonText: idUploaded ? "ID Uploaded ✓" : "Upload ID", + buttonAction: onUploadId, + canProceed: emailVerified + }, + { + id: 3, + title: "Step 3: Complete Your Profile", + description: `Fill out your ${userType === 'personal' ? 'personal' : 'company'} profile with additional information.`, + details: userType === 'personal' ? [ + "Enter your full name and date of birth", + "Provide your current address", + "Add phone number for contact", + "All fields are required for verification" + ] : [ + "Enter your company details and tax information", + "Provide business address and contact info", + "Upload any required business documents", + "Ensure all information matches your official records" + ], + icon: UserIcon, + buttonText: additionalInfo ? "Profile Complete ✓" : "Complete Profile", + buttonAction: onCompleteInfo, + canProceed: emailVerified && idUploaded + }, + { + id: 4, + title: "Step 4: Sign the Contract", + description: "Almost done! Now you need to review and sign our service agreement.", + details: [ + "Read through the terms and conditions carefully", + "Review the service agreement details", + "Digitally sign the contract to proceed", + "This finalizes your account setup process" + ], + icon: DocumentTextIcon, + buttonText: contractSigned ? "Contract Signed ✓" : "Sign Contract", + buttonAction: onSignContract, + canProceed: emailVerified && idUploaded && additionalInfo + }, + { + id: 5, + title: "Final Step: Admin Verification", + description: "Congratulations! You've completed all required steps. Now wait for admin approval.", + details: [ + "Our team will review your submitted information", + "Verification typically takes 1-2 business days", + "You'll receive an email notification once approved", + "You can continue using limited features while waiting" + ], + icon: ClockIcon, + buttonText: "I Understand", + buttonAction: onCloseTutorial, + canProceed: true // Always enable "I Understand" button + } +] \ No newline at end of file diff --git a/src/app/quickaction-dashboard/page.tsx b/src/app/quickaction-dashboard/page.tsx index ba27441..90861a4 100644 --- a/src/app/quickaction-dashboard/page.tsx +++ b/src/app/quickaction-dashboard/page.tsx @@ -3,6 +3,7 @@ import { useState, useCallback, useEffect } from 'react' import { useRouter } from 'next/navigation' import PageLayout from '../components/PageLayout' +import TutorialModal, { createTutorialSteps } from '../components/TutorialModal' import useAuthStore from '../store/authStore' import { useUserStatus } from '../hooks/useUserStatus' import { @@ -14,7 +15,8 @@ import { DocumentCheckIcon, ArrowUpOnSquareIcon, PencilSquareIcon, - ClipboardDocumentCheckIcon + ClipboardDocumentCheckIcon, + AcademicCapIcon } from '@heroicons/react/24/outline' interface StatusItem { @@ -31,8 +33,16 @@ export default function QuickActionDashboardPage() { const { userStatus, loading, error, refreshStatus } = useUserStatus() const [isClient, setIsClient] = useState(false) + // Tutorial state + const [isTutorialOpen, setIsTutorialOpen] = useState(false) + const [currentTutorialStep, setCurrentTutorialStep] = useState(1) + const [hasSeenTutorial, setHasSeenTutorial] = useState(false) + useEffect(() => { setIsClient(true) + // Check if user has seen tutorial before + const tutorialSeen = localStorage.getItem('tutorial_seen') + setHasSeenTutorial(!!tutorialSeen) }, []) // Derive status from real backend data @@ -92,6 +102,50 @@ export default function QuickActionDashboardPage() { router.push(`/quickaction-dashboard/register-sign-contract/${userType}`) }, [router, user]) + // Tutorial handlers + const startTutorial = useCallback(() => { + setCurrentTutorialStep(1) + setIsTutorialOpen(true) + }, []) + + const closeTutorial = useCallback(() => { + setIsTutorialOpen(false) + localStorage.setItem('tutorial_seen', 'true') + setHasSeenTutorial(true) + }, []) + + const nextTutorialStep = useCallback(() => { + setCurrentTutorialStep(prev => prev + 1) + }, []) + + const previousTutorialStep = useCallback(() => { + setCurrentTutorialStep(prev => Math.max(1, prev - 1)) + }, []) + + // Auto-start tutorial for new users + useEffect(() => { + if (isClient && !hasSeenTutorial && !loading && userStatus) { + // Auto-start tutorial if user hasn't completed first step + if (!emailVerified) { + setTimeout(() => setIsTutorialOpen(true), 1000) + } + } + }, [isClient, hasSeenTutorial, loading, userStatus, emailVerified]) + + // Create tutorial steps + const tutorialSteps = createTutorialSteps( + emailVerified, + idUploaded, + additionalInfo, + contractSigned, + user?.userType || 'personal', + handleVerifyEmail, + handleUploadId, + handleCompleteInfo, + handleSignContract, + closeTutorial + ) + const canSignContract = emailVerified && idUploaded && additionalInfo // NEW: resend cooldown tracking (10 minutes like verify page) @@ -204,13 +258,25 @@ export default function QuickActionDashboardPage() { {/* Quick Actions */}
-
- - i - -

- Quick Actions -

+
+
+ + i + +

+ Quick Actions +

+
+
{/* Email Verification */} @@ -306,6 +372,16 @@ export default function QuickActionDashboardPage() {
+ + {/* Tutorial Modal */} + ) } \ No newline at end of file -- 2.39.5