diff --git a/public/images/misc/cow.png b/public/images/misc/cow.png new file mode 100644 index 0000000..b958ff1 Binary files /dev/null and b/public/images/misc/cow.png differ diff --git a/src/app/components/TutorialModal.tsx b/src/app/components/TutorialModal.tsx index 7c67ecd..2b35425 100644 --- a/src/app/components/TutorialModal.tsx +++ b/src/app/components/TutorialModal.tsx @@ -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 ( @@ -60,11 +80,11 @@ export default function TutorialModal({ leaveFrom="opacity-100" leaveTo="opacity-0" > -
+
-
-
+
+
- -
+ +
+ {/* Background Gradient */} + + + {/* Close Button */} -
-
-
-
-
- - {step.title} - -
-

- {step.description} -

-
    - {step.details.map((detail, index) => ( -
  • -
    - {detail} -
  • - ))} -
+ {/* Content Section - Left Half */} +
+ {/* Icon */} +
+
-
-
- {/* Progress indicator */} -
-
- Step {currentStep} of {steps.length} - {Math.round((currentStep / steps.length) * 100)}% Complete + {/* Title */} +

+ {step.title} +

+ + {/* Description */} +

+ {step.description} +

+ + {/* Details */} +
    + {step.details.map((detail, index) => ( +
  • +
    + {detail} +
  • + ))} +
+ + {/* Progress indicator */} +
+
+ Step {currentStep} of {steps.length} + {Math.round((currentStep / steps.length) * 100)}% Complete +
+
+
+
+
+ + {/* Action Buttons */} +
+ +
+ + {/* Navigation Buttons */} + {(!isFirstStep || !isLastStep) && ( +
+ + {!isLastStep && ( + + )} +
+ )}
-
-
+ Profit Planet Mascot
- -
- - - {!isLastStep && ( - - )} - - {!isFirstStep && ( - - )} -
@@ -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 } ] \ No newline at end of file diff --git a/src/app/quickaction-dashboard/page.tsx b/src/app/quickaction-dashboard/page.tsx index d869251..3f442e3 100644 --- a/src/app/quickaction-dashboard/page.tsx +++ b/src/app/quickaction-dashboard/page.tsx @@ -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 diff --git a/src/app/quickaction-dashboard/register-additional-information/company/page.tsx b/src/app/quickaction-dashboard/register-additional-information/company/page.tsx index 0533494..9e539f7 100644 --- a/src/app/quickaction-dashboard/register-additional-information/company/page.tsx +++ b/src/app/quickaction-dashboard/register-additional-information/company/page.tsx @@ -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) { diff --git a/src/app/quickaction-dashboard/register-additional-information/personal/page.tsx b/src/app/quickaction-dashboard/register-additional-information/personal/page.tsx index 9940d66..8d4133a 100644 --- a/src/app/quickaction-dashboard/register-additional-information/personal/page.tsx +++ b/src/app/quickaction-dashboard/register-additional-information/personal/page.tsx @@ -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) { diff --git a/src/app/quickaction-dashboard/register-email-verify/page.tsx b/src/app/quickaction-dashboard/register-email-verify/page.tsx index 610131b..a1eb211 100644 --- a/src/app/quickaction-dashboard/register-email-verify/page.tsx +++ b/src/app/quickaction-dashboard/register-email-verify/page.tsx @@ -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.') diff --git a/src/app/quickaction-dashboard/register-upload-id/company/hooks/useCompanyUploadId.ts b/src/app/quickaction-dashboard/register-upload-id/company/hooks/useCompanyUploadId.ts index 9742bf3..478937c 100644 --- a/src/app/quickaction-dashboard/register-upload-id/company/hooks/useCompanyUploadId.ts +++ b/src/app/quickaction-dashboard/register-upload-id/company/hooks/useCompanyUploadId.ts @@ -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) diff --git a/src/app/quickaction-dashboard/register-upload-id/personal/hooks/usePersonalUploadId.ts b/src/app/quickaction-dashboard/register-upload-id/personal/hooks/usePersonalUploadId.ts index c94ebdc..6b0ee08 100644 --- a/src/app/quickaction-dashboard/register-upload-id/personal/hooks/usePersonalUploadId.ts +++ b/src/app/quickaction-dashboard/register-upload-id/personal/hooks/usePersonalUploadId.ts @@ -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.')