feat: implement tutorial flow with URL parameter handling for navigation
This commit is contained in:
parent
9f5da2c43d
commit
4024085dc4
BIN
public/images/misc/cow.png
Normal file
BIN
public/images/misc/cow.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 838 KiB |
@ -10,7 +10,10 @@ import {
|
||||
DocumentTextIcon,
|
||||
ClockIcon,
|
||||
ArrowRightIcon,
|
||||
CheckCircleIcon
|
||||
CheckCircleIcon,
|
||||
HandRaisedIcon,
|
||||
HeartIcon,
|
||||
CheckIcon
|
||||
} from '@heroicons/react/24/outline'
|
||||
|
||||
interface TutorialStep {
|
||||
@ -47,6 +50,23 @@ export default function TutorialModal({
|
||||
|
||||
const isLastStep = currentStep === steps.length
|
||||
const isFirstStep = currentStep === 1
|
||||
|
||||
// Helper function to check if step is completed
|
||||
const isStepCompleted = (stepId: number) => {
|
||||
if (stepId === 2) return step.buttonText.includes("✅") // Email verified
|
||||
if (stepId === 3) return step.buttonText.includes("✅") // ID uploaded
|
||||
if (stepId === 4) return step.buttonText.includes("✅") // Profile completed
|
||||
if (stepId === 5) return step.buttonText.includes("✅") // Agreement signed
|
||||
return false
|
||||
}
|
||||
|
||||
// Get clean button text without emoji
|
||||
const getCleanButtonText = (text: string) => {
|
||||
return text.replace(/✅/g, '').trim().replace(/!$/, '')
|
||||
}
|
||||
|
||||
const stepCompleted = isStepCompleted(step.id)
|
||||
const buttonText = stepCompleted ? getCleanButtonText(step.buttonText) : step.buttonText
|
||||
|
||||
return (
|
||||
<Transition.Root show={isOpen} as={Fragment}>
|
||||
@ -60,11 +80,11 @@ export default function TutorialModal({
|
||||
leaveFrom="opacity-100"
|
||||
leaveTo="opacity-0"
|
||||
>
|
||||
<div className="fixed inset-0 bg-opacity-30 backdrop-blur-sm transition-opacity" />
|
||||
<div className="fixed inset-0 bg-blue-900/60 backdrop-blur-sm transition-opacity" />
|
||||
</Transition.Child>
|
||||
|
||||
<div className="fixed inset-0 z-10 overflow-y-auto">
|
||||
<div className="flex min-h-full items-end justify-center p-4 text-center sm:items-center sm:p-0">
|
||||
<div className="fixed inset-0 z-10">
|
||||
<div className="flex min-h-full items-center justify-center p-4">
|
||||
<Transition.Child
|
||||
as={Fragment}
|
||||
enter="ease-out duration-300"
|
||||
@ -74,91 +94,130 @@ export default function TutorialModal({
|
||||
leaveFrom="opacity-100 translate-y-0 sm:scale-100"
|
||||
leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
|
||||
>
|
||||
<Dialog.Panel className="relative transform overflow-hidden rounded-lg bg-white px-4 pb-4 pt-5 text-left shadow-xl transition-all sm:my-8 sm:w-full sm:max-w-lg sm:p-6">
|
||||
<div className="absolute right-0 top-0 hidden pr-4 pt-4 sm:block">
|
||||
<Dialog.Panel className="relative w-full max-w-5xl h-[60vh]">
|
||||
<div className="relative isolate overflow-hidden bg-slate-50 h-full after:pointer-events-none after:absolute after:inset-0 after:inset-ring after:inset-ring-gray-200/50 sm:rounded-3xl after:sm:rounded-3xl lg:flex lg:gap-x-12 lg:px-8 w-full">
|
||||
{/* Background Gradient */}
|
||||
<svg
|
||||
viewBox="0 0 1024 1024"
|
||||
aria-hidden="true"
|
||||
className="absolute -top-48 -left-48 -z-10 size-96 mask-[radial-gradient(closest-side,white,transparent)]"
|
||||
>
|
||||
<circle r={512} cx={512} cy={512} fill="url(#tutorial-gradient)" fillOpacity="0.7" />
|
||||
<defs>
|
||||
<radialGradient id="tutorial-gradient">
|
||||
<stop stopColor="#3B82F6" />
|
||||
<stop offset={1} stopColor="#8B5CF6" />
|
||||
</radialGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
||||
{/* Close Button */}
|
||||
<button
|
||||
type="button"
|
||||
className="rounded-md bg-white text-gray-400 hover:text-gray-500 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2"
|
||||
className="absolute right-4 top-4 z-10 rounded-md bg-gray-200/70 p-2 text-gray-600 hover:text-gray-800 hover:bg-gray-300/70 focus:outline-none focus:ring-2 focus:ring-blue-500 backdrop-blur-sm"
|
||||
onClick={onClose}
|
||||
>
|
||||
<span className="sr-only">Close</span>
|
||||
<XMarkIcon className="h-6 w-6" aria-hidden="true" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="sm:flex sm:items-start">
|
||||
<div className="mx-auto flex h-12 w-12 flex-shrink-0 items-center justify-center rounded-full bg-blue-100 sm:mx-0 sm:h-10 sm:w-10">
|
||||
<step.icon className="h-6 w-6 text-blue-600" aria-hidden="true" />
|
||||
</div>
|
||||
<div className="mt-3 text-center sm:ml-4 sm:mt-0 sm:text-left">
|
||||
<Dialog.Title as="h3" className="text-lg font-semibold leading-6 text-gray-900">
|
||||
{step.title}
|
||||
</Dialog.Title>
|
||||
<div className="mt-2">
|
||||
<p className="text-sm text-gray-500 mb-3">
|
||||
{step.description}
|
||||
</p>
|
||||
<ul className="text-sm text-gray-700 space-y-2">
|
||||
{step.details.map((detail, index) => (
|
||||
<li key={index} className="flex items-start gap-2">
|
||||
<div className="h-1.5 w-1.5 rounded-full bg-blue-500 mt-2 flex-shrink-0" />
|
||||
<span>{detail}</span>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
{/* Content Section - Left Half */}
|
||||
<div className="lg:flex-1 lg:max-w-md text-center lg:text-left py-8 px-6 flex flex-col justify-center">
|
||||
{/* Icon */}
|
||||
<div className="mx-auto lg:mx-0 flex h-12 w-12 flex-shrink-0 items-center justify-center rounded-full bg-blue-100 mb-4 ring-2 ring-blue-200">
|
||||
<step.icon className="h-6 w-6 text-blue-600" aria-hidden="true" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Progress indicator */}
|
||||
<div className="mt-6">
|
||||
<div className="flex items-center justify-between text-xs text-gray-500 mb-2">
|
||||
<span>Step {currentStep} of {steps.length}</span>
|
||||
<span>{Math.round((currentStep / steps.length) * 100)}% Complete</span>
|
||||
{/* Title */}
|
||||
<h2 className="text-xl font-semibold tracking-tight whitespace-nowrap text-gray-800 sm:text-2xl">
|
||||
{step.title}
|
||||
</h2>
|
||||
|
||||
{/* Description */}
|
||||
<p className="mt-3 text-sm text-gray-600 leading-relaxed h-12 overflow-hidden">
|
||||
{step.description}
|
||||
</p>
|
||||
|
||||
{/* Details */}
|
||||
<ul className="mt-4 text-left text-gray-600 space-y-2">
|
||||
{step.details.map((detail, index) => (
|
||||
<li key={index} className="flex items-start gap-2">
|
||||
<div className="h-1.5 w-1.5 rounded-full bg-blue-500 mt-1.5 flex-shrink-0" />
|
||||
<span className="text-xs leading-5">{detail}</span>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
|
||||
{/* Progress indicator */}
|
||||
<div className="mt-6">
|
||||
<div className="flex items-center justify-between text-xs text-gray-500 mb-2">
|
||||
<span>Step {currentStep} of {steps.length}</span>
|
||||
<span>{Math.round((currentStep / steps.length) * 100)}% Complete</span>
|
||||
</div>
|
||||
<div className="w-full bg-gray-200 rounded-full h-1.5">
|
||||
<div
|
||||
className="bg-gradient-to-r from-blue-500 to-purple-500 h-1.5 rounded-full transition-all duration-500"
|
||||
style={{ width: `${(currentStep / steps.length) * 100}%` }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Action Buttons */}
|
||||
<div className="mt-6 flex items-center justify-center gap-x-3 lg:justify-start">
|
||||
<button
|
||||
type="button"
|
||||
onClick={step.buttonAction}
|
||||
disabled={(!step.canProceed && currentStep !== steps.length) || buttonText.includes("Waiting for admin review") || stepCompleted}
|
||||
className={`rounded-md px-3 py-2 text-sm font-semibold inset-ring inset-ring-gray-200/50 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-600 transition-all flex items-center gap-2 ${
|
||||
stepCompleted
|
||||
? 'bg-green-600 text-white'
|
||||
: (step.canProceed || currentStep === steps.length) && !buttonText.includes("Waiting for admin review")
|
||||
? 'bg-blue-600 text-white hover:bg-blue-500 shadow-lg hover:shadow-xl'
|
||||
: 'bg-gray-300 text-gray-500'
|
||||
}`}
|
||||
>
|
||||
{stepCompleted && <CheckIcon className="h-4 w-4" />}
|
||||
{buttonText}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Navigation Buttons */}
|
||||
{(!isFirstStep || !isLastStep) && (
|
||||
<div className="mt-4 flex items-center justify-center gap-x-4 lg:justify-start">
|
||||
<button
|
||||
type="button"
|
||||
onClick={onPrevious}
|
||||
disabled={isFirstStep}
|
||||
className={`text-xs font-semibold transition-colors ${
|
||||
isFirstStep
|
||||
? 'text-slate-50 cursor-default'
|
||||
: 'text-gray-500 hover:text-gray-700'
|
||||
}`}
|
||||
>
|
||||
← Go back
|
||||
</button>
|
||||
{!isLastStep && (
|
||||
<button
|
||||
type="button"
|
||||
onClick={onNext}
|
||||
className="text-xs font-semibold text-blue-600 hover:text-blue-700 transition-colors"
|
||||
>
|
||||
Continue →
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="w-full bg-gray-200 rounded-full h-2">
|
||||
<div
|
||||
className="bg-blue-600 h-2 rounded-full transition-all duration-300"
|
||||
style={{ width: `${(currentStep / steps.length) * 100}%` }}
|
||||
|
||||
{/* Visual Section - Right Half */}
|
||||
<div className="relative lg:flex-1 mt-4 lg:mt-0 h-32 lg:h-full lg:min-h-[150px] flex items-end justify-end">
|
||||
<img
|
||||
src="/images/misc/cow.png"
|
||||
alt="Profit Planet Mascot"
|
||||
className="max-h-full max-w-full object-contain opacity-90 pl-30"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mt-5 sm:mt-6 sm:flex sm:flex-row-reverse gap-3">
|
||||
<button
|
||||
type="button"
|
||||
onClick={step.buttonAction}
|
||||
disabled={!step.canProceed && currentStep !== 5}
|
||||
className={`inline-flex w-full justify-center rounded-md px-3 py-2 text-sm font-semibold text-white shadow-sm focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 sm:w-auto ${
|
||||
(step.canProceed || currentStep === 5)
|
||||
? 'bg-blue-600 hover:bg-blue-500 focus-visible:outline-blue-600'
|
||||
: 'bg-gray-400 cursor-not-allowed'
|
||||
}`}
|
||||
>
|
||||
{step.buttonText}
|
||||
</button>
|
||||
|
||||
{!isLastStep && (
|
||||
<button
|
||||
type="button"
|
||||
onClick={onNext}
|
||||
className="mt-3 inline-flex w-full justify-center rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50 sm:mt-0 sm:w-auto"
|
||||
>
|
||||
Skip & Next
|
||||
<ArrowRightIcon className="ml-2 h-4 w-4" />
|
||||
</button>
|
||||
)}
|
||||
|
||||
{!isFirstStep && (
|
||||
<button
|
||||
type="button"
|
||||
onClick={onPrevious}
|
||||
className="mt-3 inline-flex w-full justify-center rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50 sm:mt-0 sm:w-auto"
|
||||
>
|
||||
Previous
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</Dialog.Panel>
|
||||
</Transition.Child>
|
||||
</div>
|
||||
@ -179,86 +238,102 @@ export const createTutorialSteps = (
|
||||
onUploadId: () => void,
|
||||
onCompleteInfo: () => void,
|
||||
onSignContract: () => void,
|
||||
onCloseTutorial: () => void
|
||||
onCloseTutorial: () => void,
|
||||
onNext: () => 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.",
|
||||
title: "Hello there! 👋 Welcome to Profit Planet",
|
||||
description: "We're so happy you've decided to join us! This quick tutorial will guide you through setting up your account in just a few simple steps. Let's make this journey together - it'll only take a few minutes!",
|
||||
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"
|
||||
"We'll walk you through each step personally",
|
||||
"Everything is designed to be simple and clear",
|
||||
"You can skip steps if you want to come back later",
|
||||
"Our team is here to help if you need anything"
|
||||
],
|
||||
icon: EnvelopeIcon,
|
||||
buttonText: emailVerified ? "Email Verified ✓" : "Verify Email",
|
||||
buttonAction: onVerifyEmail,
|
||||
icon: HandRaisedIcon,
|
||||
buttonText: "Let's get started! 🚀",
|
||||
buttonAction: onNext,
|
||||
canProceed: true
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: "Step 2: Upload ID Documents",
|
||||
description: "Next, we need to verify your identity by uploading official ID documents.",
|
||||
title: "Let's verify your email address 📧",
|
||||
description: "First things first - we'd love to make sure we can reach you! Please check your email inbox for a friendly message from us and the verification code.",
|
||||
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"
|
||||
"Check your email inbox for our welcome message",
|
||||
"Copy & paste the verification code into the field",
|
||||
"Don't see it? Check your spam folder - sometimes it hides there",
|
||||
"Need a new email? Just click below and we'll send another"
|
||||
],
|
||||
icon: IdentificationIcon,
|
||||
buttonText: idUploaded ? "ID Uploaded ✓" : "Upload ID",
|
||||
buttonAction: onUploadId,
|
||||
canProceed: emailVerified
|
||||
icon: EnvelopeIcon,
|
||||
buttonText: emailVerified ? "Email verified! ✅" : "Verify my email",
|
||||
buttonAction: emailVerified ? onNext : onVerifyEmail,
|
||||
canProceed: true
|
||||
},
|
||||
{
|
||||
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"
|
||||
title: "Time to upload your ID 📋",
|
||||
description: "Now we need to get to know you better! Please upload a clear photo of your official ID. Don't worry - this information is completely secure and helps us keep everyone safe.",
|
||||
details: [
|
||||
"Take a clear, well-lit photo of your ID document",
|
||||
"Make sure all text is easily readable",
|
||||
"Passport, driver's license, or national ID all work perfectly",
|
||||
"We protect your privacy - this is just for verification"
|
||||
],
|
||||
icon: UserIcon,
|
||||
buttonText: additionalInfo ? "Profile Complete ✓" : "Complete Profile",
|
||||
buttonAction: onCompleteInfo,
|
||||
canProceed: emailVerified && idUploaded
|
||||
icon: IdentificationIcon,
|
||||
buttonText: idUploaded ? "ID uploaded! ✅" : "Upload my ID",
|
||||
buttonAction: idUploaded ? onNext : onUploadId,
|
||||
canProceed: true
|
||||
},
|
||||
{
|
||||
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"
|
||||
title: "Complete your profile 👤",
|
||||
description: `Almost there! Now let's fill out your ${userType === 'personal' ? 'personal' : 'company'} profile. This helps us customize your experience and ensure everything runs smoothly.`,
|
||||
details: userType === 'personal' ? [
|
||||
"Share your full name and date of birth with us",
|
||||
"Add your current address (we keep this private)",
|
||||
"Include a phone number so we can reach you if needed",
|
||||
"All information is required for account security"
|
||||
] : [
|
||||
"Tell us about your company and business details",
|
||||
"Add your business address and contact information",
|
||||
"Upload any business documents we might need",
|
||||
"Make sure everything matches your official records"
|
||||
],
|
||||
icon: DocumentTextIcon,
|
||||
buttonText: contractSigned ? "Contract Signed ✓" : "Sign Contract",
|
||||
icon: UserIcon,
|
||||
buttonText: additionalInfo ? "Profile completed! ✅" : "Complete my profile",
|
||||
buttonAction: additionalInfo ? onNext : onCompleteInfo,
|
||||
canProceed: true
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
title: "Our team is preparing your contract ⏳",
|
||||
description: "Excellent! Now our team needs to manually review your information and prepare your personalized contract. This ensures everything is perfectly tailored to your needs.",
|
||||
details: [
|
||||
"Our admin team is currently reviewing your submitted documents",
|
||||
"We're preparing a personalized contract just for you",
|
||||
"This process typically takes 1-2 business days",
|
||||
"You'll receive an email notification once your contract is ready to sign"
|
||||
],
|
||||
icon: ClockIcon,
|
||||
buttonText: contractSigned ? "Contract signed! ✅" : "Waiting for admin review",
|
||||
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.",
|
||||
id: 6,
|
||||
title: "You're all set! 🎉 Welcome to the community",
|
||||
description: "Congratulations! You've completed all the steps perfectly. Our friendly team will now review your information - we'll have you approved and ready to go very soon!",
|
||||
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"
|
||||
"Our team will carefully review everything you've submitted",
|
||||
"This usually takes just 1-2 business days",
|
||||
"We'll send you a celebratory email once you're approved",
|
||||
"In the meantime, feel free to explore"
|
||||
],
|
||||
icon: ClockIcon,
|
||||
buttonText: "I Understand",
|
||||
icon: HeartIcon,
|
||||
buttonText: "I understand!",
|
||||
buttonAction: onCloseTutorial,
|
||||
canProceed: true // Always enable "I Understand" button
|
||||
canProceed: true
|
||||
}
|
||||
]
|
||||
@ -51,6 +51,33 @@ export default function QuickActionDashboardPage() {
|
||||
const additionalInfo = userStatus?.profile_completed || false
|
||||
const contractSigned = userStatus?.contract_signed || false
|
||||
|
||||
// Check if we should open tutorial (from URL parameter) - separate useEffect after status is loaded
|
||||
useEffect(() => {
|
||||
if (!isClient || loading || !userStatus) return
|
||||
|
||||
const urlParams = new URLSearchParams(window.location.search)
|
||||
if (urlParams.get('tutorial') === 'true') {
|
||||
// Remove the parameter from URL
|
||||
const newUrl = window.location.pathname
|
||||
window.history.replaceState({}, '', newUrl)
|
||||
|
||||
// Open tutorial and go to next step
|
||||
setTimeout(() => {
|
||||
setIsTutorialOpen(true)
|
||||
// Determine next step based on completion status
|
||||
if (!emailVerified) {
|
||||
setCurrentTutorialStep(2)
|
||||
} else if (!idUploaded) {
|
||||
setCurrentTutorialStep(3)
|
||||
} else if (!additionalInfo) {
|
||||
setCurrentTutorialStep(4)
|
||||
} else {
|
||||
setCurrentTutorialStep(5)
|
||||
}
|
||||
}, 500)
|
||||
}
|
||||
}, [isClient, loading, userStatus, emailVerified, idUploaded, additionalInfo])
|
||||
|
||||
const statusItems: StatusItem[] = [
|
||||
{
|
||||
key: 'email',
|
||||
@ -82,19 +109,19 @@ export default function QuickActionDashboardPage() {
|
||||
}
|
||||
]
|
||||
|
||||
// Action handlers - navigate to proper QuickAction pages
|
||||
// Action handlers - navigate to proper QuickAction pages with tutorial callback
|
||||
const handleVerifyEmail = useCallback(() => {
|
||||
router.push('/quickaction-dashboard/register-email-verify')
|
||||
router.push('/quickaction-dashboard/register-email-verify?tutorial=true')
|
||||
}, [router])
|
||||
|
||||
const handleUploadId = useCallback(() => {
|
||||
const userType = user?.userType || 'personal'
|
||||
router.push(`/quickaction-dashboard/register-upload-id/${userType}`)
|
||||
router.push(`/quickaction-dashboard/register-upload-id/${userType}?tutorial=true`)
|
||||
}, [router, user])
|
||||
|
||||
const handleCompleteInfo = useCallback(() => {
|
||||
const userType = user?.userType || 'personal'
|
||||
router.push(`/quickaction-dashboard/register-additional-information/${userType}`)
|
||||
router.push(`/quickaction-dashboard/register-additional-information/${userType}?tutorial=true`)
|
||||
}, [router, user])
|
||||
|
||||
const handleSignContract = useCallback(() => {
|
||||
@ -143,7 +170,8 @@ export default function QuickActionDashboardPage() {
|
||||
handleUploadId,
|
||||
handleCompleteInfo,
|
||||
handleSignContract,
|
||||
closeTutorial
|
||||
closeTutorial,
|
||||
() => setCurrentTutorialStep(prev => prev + 1) // onNext function
|
||||
)
|
||||
|
||||
const canSignContract = emailVerified && idUploaded && additionalInfo
|
||||
|
||||
@ -128,7 +128,15 @@ export default function CompanyAdditionalInformationPage() {
|
||||
|
||||
// Redirect to next step after short delay
|
||||
setTimeout(() => {
|
||||
router.push('/quickaction-dashboard/register-sign-contract/company')
|
||||
// Check if we came from tutorial
|
||||
const urlParams = new URLSearchParams(window.location.search)
|
||||
const fromTutorial = urlParams.get('tutorial') === 'true'
|
||||
|
||||
if (fromTutorial) {
|
||||
router.push('/quickaction-dashboard?tutorial=true')
|
||||
} else {
|
||||
router.push('/quickaction-dashboard/register-sign-contract/company')
|
||||
}
|
||||
}, 1500)
|
||||
|
||||
} catch (error: any) {
|
||||
|
||||
@ -170,7 +170,15 @@ export default function PersonalAdditionalInformationPage() {
|
||||
|
||||
// Redirect to next step after short delay
|
||||
setTimeout(() => {
|
||||
router.push('/quickaction-dashboard/register-sign-contract/personal')
|
||||
// Check if we came from tutorial
|
||||
const urlParams = new URLSearchParams(window.location.search)
|
||||
const fromTutorial = urlParams.get('tutorial') === 'true'
|
||||
|
||||
if (fromTutorial) {
|
||||
router.push('/quickaction-dashboard?tutorial=true')
|
||||
} else {
|
||||
router.push('/quickaction-dashboard/register-sign-contract/personal')
|
||||
}
|
||||
}, 1500)
|
||||
|
||||
} catch (error: any) {
|
||||
|
||||
@ -199,7 +199,15 @@ export default function EmailVerifyPage() {
|
||||
await refreshStatus() // Refresh user status
|
||||
// Redirect after 2 seconds
|
||||
setTimeout(() => {
|
||||
window.location.href = '/quickaction-dashboard'
|
||||
// Check if we came from tutorial
|
||||
const urlParams = new URLSearchParams(window.location.search)
|
||||
const fromTutorial = urlParams.get('tutorial') === 'true'
|
||||
|
||||
if (fromTutorial) {
|
||||
window.location.href = '/quickaction-dashboard?tutorial=true'
|
||||
} else {
|
||||
window.location.href = '/quickaction-dashboard'
|
||||
}
|
||||
}, 2000)
|
||||
} else {
|
||||
setError(data.error || 'Verification failed. Please try again.')
|
||||
|
||||
@ -123,8 +123,16 @@ export function useCompanyUploadId() {
|
||||
await refreshStatus()
|
||||
|
||||
setTimeout(() => {
|
||||
// keep same redirect as page used before
|
||||
window.location.href = '/quickaction-dashboard/register-additional-information'
|
||||
// Check if we came from tutorial
|
||||
const urlParams = new URLSearchParams(window.location.search)
|
||||
const fromTutorial = urlParams.get('tutorial') === 'true'
|
||||
|
||||
if (fromTutorial) {
|
||||
window.location.href = '/quickaction-dashboard?tutorial=true'
|
||||
} else {
|
||||
// keep same redirect as page used before
|
||||
window.location.href = '/quickaction-dashboard/register-additional-information'
|
||||
}
|
||||
}, 1500)
|
||||
} catch (err: any) {
|
||||
console.error('Company ID upload error:', err)
|
||||
|
||||
@ -128,7 +128,15 @@ export function usePersonalUploadId() {
|
||||
setSuccess(true)
|
||||
await refreshStatus()
|
||||
setTimeout(() => {
|
||||
window.location.href = '/quickaction-dashboard'
|
||||
// Check if we came from tutorial
|
||||
const urlParams = new URLSearchParams(window.location.search)
|
||||
const fromTutorial = urlParams.get('tutorial') === 'true'
|
||||
|
||||
if (fromTutorial) {
|
||||
window.location.href = '/quickaction-dashboard?tutorial=true'
|
||||
} else {
|
||||
window.location.href = '/quickaction-dashboard'
|
||||
}
|
||||
}, 2000)
|
||||
} else {
|
||||
setError(data.message || 'Upload failed. Please try again.')
|
||||
|
||||
Loading…
Reference in New Issue
Block a user