mirror of
https://github.com/rzmk/learnhouse.git
synced 2025-12-19 04:19:25 +00:00
feat: enhance onboarding experience with new assignment and payment steps
- Added new onboarding steps for creating assignments and managing payments. - Updated state management to persist the current onboarding step in local storage. - Implemented temporary closure logic for the onboarding modal, allowing users to resume after 24 hours. - Improved modal handling and UI adjustments for better user experience.
This commit is contained in:
parent
734cf072ad
commit
581eff7668
3 changed files with 80 additions and 11 deletions
|
|
@ -9,7 +9,9 @@ import OnBoardAI from '@public/onboarding/OnBoardAI.png';
|
||||||
import OnBoardUGs from '@public/onboarding/OnBoardUGs.png';
|
import OnBoardUGs from '@public/onboarding/OnBoardUGs.png';
|
||||||
import OnBoardAccess from '@public/onboarding/OnBoardAccess.png';
|
import OnBoardAccess from '@public/onboarding/OnBoardAccess.png';
|
||||||
import OnBoardMore from '@public/onboarding/OnBoardMore.png';
|
import OnBoardMore from '@public/onboarding/OnBoardMore.png';
|
||||||
import { ArrowRight, Book, Check, Globe, Info, PictureInPicture, Sparkle, Sprout, SquareUser } from 'lucide-react';
|
import OnBoardAssignments from '@public/onboarding/OnBoardAssignments.png';
|
||||||
|
import OnBoardPayments from '@public/onboarding/OnBoardPayments.png';
|
||||||
|
import { ArrowRight, Book, Check, Globe, Info, PictureInPicture, Sparkle, Sprout, SquareUser, CreditCard } from 'lucide-react';
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
import { getUriWithOrg } from '@services/config/config';
|
import { getUriWithOrg } from '@services/config/config';
|
||||||
import { useOrg } from '@components/Contexts/OrgContext';
|
import { useOrg } from '@components/Contexts/OrgContext';
|
||||||
|
|
@ -27,9 +29,14 @@ interface OnboardingStep {
|
||||||
}
|
}
|
||||||
|
|
||||||
const Onboarding: React.FC = () => {
|
const Onboarding: React.FC = () => {
|
||||||
const [currentStep, setCurrentStep] = useState(0);
|
const [currentStep, setCurrentStep] = useState(() => {
|
||||||
|
// Initialize with saved step or 0
|
||||||
|
const savedStep = localStorage.getItem('onboardingLastStep');
|
||||||
|
return savedStep ? parseInt(savedStep) : 0;
|
||||||
|
});
|
||||||
const [isModalOpen, setIsModalOpen] = useState(false);
|
const [isModalOpen, setIsModalOpen] = useState(false);
|
||||||
const [isOnboardingComplete, setIsOnboardingComplete] = useState(true);
|
const [isOnboardingComplete, setIsOnboardingComplete] = useState(true);
|
||||||
|
const [isTemporarilyClosed, setIsTemporarilyClosed] = useState(false);
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const org = useOrg() as any;
|
const org = useOrg() as any;
|
||||||
const isUserAdmin = useAdminStatus() as any;
|
const isUserAdmin = useAdminStatus() as any;
|
||||||
|
|
@ -108,6 +115,30 @@ const Onboarding: React.FC = () => {
|
||||||
|
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
imageSrc: OnBoardAssignments,
|
||||||
|
title: 'Create and Grade Assignments',
|
||||||
|
description: 'Engage students with assignments, track their progress, and provide feedback through our intuitive grading system.',
|
||||||
|
buttons: [
|
||||||
|
{
|
||||||
|
label: 'Create Assignment',
|
||||||
|
action: () => router.push(getUriWithOrg(org?.slug, '/dash/assignments?new=true')),
|
||||||
|
icon: <Book size={16} />,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
imageSrc: OnBoardPayments,
|
||||||
|
title: 'Monetize Your Content',
|
||||||
|
description: 'Set up payment plans, sell courses, and manage subscriptions with our integrated payment system.',
|
||||||
|
buttons: [
|
||||||
|
{
|
||||||
|
label: 'Payment Settings',
|
||||||
|
action: () => router.push(getUriWithOrg(org?.slug, '/dash/payments/customers')),
|
||||||
|
icon: <CreditCard size={16} />,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
imageSrc: OnBoardMore,
|
imageSrc: OnBoardMore,
|
||||||
title: 'To infinity and beyond',
|
title: 'To infinity and beyond',
|
||||||
|
|
@ -123,28 +154,60 @@ const Onboarding: React.FC = () => {
|
||||||
];
|
];
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// Check if onboarding is already completed in local storage
|
// Check both completion and temporary closure status
|
||||||
const isOnboardingCompleted = localStorage.getItem('isOnboardingCompleted');
|
const isOnboardingCompleted = localStorage.getItem('isOnboardingCompleted');
|
||||||
|
const temporarilyClosed = localStorage.getItem('onboardingTemporarilyClosed');
|
||||||
|
const lastClosedTime = localStorage.getItem('onboardingLastClosedTime');
|
||||||
|
|
||||||
setIsOnboardingComplete(isOnboardingCompleted === 'true');
|
setIsOnboardingComplete(isOnboardingCompleted === 'true');
|
||||||
setIsModalOpen(!isOnboardingCompleted); // Show modal if onboarding is not completed
|
setIsTemporarilyClosed(temporarilyClosed === 'true');
|
||||||
|
|
||||||
|
// If temporarily closed, check if 24 hours have passed
|
||||||
|
if (temporarilyClosed === 'true' && lastClosedTime) {
|
||||||
|
const hoursSinceClosed = (Date.now() - parseInt(lastClosedTime)) / (1000 * 60 * 60);
|
||||||
|
if (hoursSinceClosed >= 24) {
|
||||||
|
// Reset temporary closure after 24 hours
|
||||||
|
localStorage.removeItem('onboardingTemporarilyClosed');
|
||||||
|
localStorage.removeItem('onboardingLastClosedTime');
|
||||||
|
setIsTemporarilyClosed(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show modal if onboarding is not completed and not temporarily closed
|
||||||
|
setIsModalOpen(!isOnboardingCompleted && !temporarilyClosed);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
// Update stored step whenever currentStep changes
|
||||||
|
useEffect(() => {
|
||||||
|
localStorage.setItem('onboardingLastStep', currentStep.toString());
|
||||||
|
}, [currentStep]);
|
||||||
|
|
||||||
|
const handleModalClose = () => {
|
||||||
|
// Store temporary closure status and timestamp
|
||||||
|
localStorage.setItem('onboardingTemporarilyClosed', 'true');
|
||||||
|
localStorage.setItem('onboardingLastClosedTime', Date.now().toString());
|
||||||
|
// Current step is already saved via the useEffect above
|
||||||
|
setIsTemporarilyClosed(true);
|
||||||
|
setIsModalOpen(false);
|
||||||
|
};
|
||||||
|
|
||||||
const nextStep = () => {
|
const nextStep = () => {
|
||||||
if (currentStep < onboardingData.length - 1) {
|
if (currentStep < onboardingData.length - 1) {
|
||||||
setCurrentStep(currentStep + 1);
|
setCurrentStep(currentStep + 1);
|
||||||
} else {
|
} else {
|
||||||
// Mark onboarding as completed in local storage
|
// Mark onboarding as completed in local storage
|
||||||
localStorage.setItem('isOnboardingCompleted', 'true');
|
localStorage.setItem('isOnboardingCompleted', 'true');
|
||||||
setIsModalOpen(false); // Close modal after completion
|
localStorage.removeItem('onboardingLastStep'); // Clean up stored step
|
||||||
setIsOnboardingComplete(true); // Show success message
|
setIsModalOpen(false);
|
||||||
|
setIsOnboardingComplete(true);
|
||||||
console.log('Onboarding completed');
|
console.log('Onboarding completed');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const skipOnboarding = () => {
|
const skipOnboarding = () => {
|
||||||
// Mark onboarding as completed in local storage
|
|
||||||
localStorage.setItem('isOnboardingCompleted', 'true');
|
localStorage.setItem('isOnboardingCompleted', 'true');
|
||||||
setIsModalOpen(false); // Close modal after skipping
|
localStorage.removeItem('onboardingLastStep'); // Clean up stored step
|
||||||
|
setIsModalOpen(false);
|
||||||
console.log('Onboarding skipped');
|
console.log('Onboarding skipped');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -168,8 +231,7 @@ const Onboarding: React.FC = () => {
|
||||||
currentStep={currentStep}
|
currentStep={currentStep}
|
||||||
nextStep={nextStep}
|
nextStep={nextStep}
|
||||||
skipOnboarding={skipOnboarding}
|
skipOnboarding={skipOnboarding}
|
||||||
setIsModalOpen={setIsModalOpen}
|
setIsModalOpen={handleModalClose}
|
||||||
|
|
||||||
goToStep={goToStep}
|
goToStep={goToStep}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
|
|
@ -213,7 +275,14 @@ const OnboardingScreen: React.FC<OnboardingScreenProps> = ({
|
||||||
<div className='flex flex-col'>
|
<div className='flex flex-col'>
|
||||||
<div className='onboarding_screens flex-col px-4 py-4'>
|
<div className='onboarding_screens flex-col px-4 py-4'>
|
||||||
<div className='flex-grow rounded-xl'>
|
<div className='flex-grow rounded-xl'>
|
||||||
<Image unoptimized className='mx-auto shadow-md shadow-gray-200 rounded-lg aspect-auto' alt='' priority quality={100} src={step.imageSrc} />
|
<Image
|
||||||
|
unoptimized
|
||||||
|
className='mx-auto shadow-md shadow-gray-200 rounded-lg w-[730px] h-[330px] object-cover'
|
||||||
|
alt=''
|
||||||
|
priority
|
||||||
|
quality={100}
|
||||||
|
src={step.imageSrc}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className='grid grid-flow-col justify-stretch space-x-3 mt-4'>
|
<div className='grid grid-flow-col justify-stretch space-x-3 mt-4'>
|
||||||
{onboardingData.map((_, index) => (
|
{onboardingData.map((_, index) => (
|
||||||
|
|
|
||||||
BIN
apps/web/public/onboarding/OnBoardAssignments.png
Normal file
BIN
apps/web/public/onboarding/OnBoardAssignments.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 614 KiB |
BIN
apps/web/public/onboarding/OnBoardPayments.png
Normal file
BIN
apps/web/public/onboarding/OnBoardPayments.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 775 KiB |
Loading…
Add table
Add a link
Reference in a new issue