Skip to content

Commit 2191a6f

Browse files
Zeff01claude
andcommitted
feat: Add navigation controls to onboarding flow
Allow users to freely navigate between onboarding steps: - Add "Back to Videos" button on Quiz step - Add "Back to Quiz" button on Commitment step - Make stepper steps clickable to jump directly to any step - Add hover effects and visual feedback on stepper - Add handleStepClick to manage step navigation logic Benefits: - Users can review previous videos even after completing them - More flexible onboarding experience - Better UX for users who want to revisit content - Helpful for testing and debugging onboarding flow Also added reset_onboarding_progress.sql helper script for database resets. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 86e62e9 commit 2191a6f

3 files changed

Lines changed: 103 additions & 11 deletions

File tree

‎apps/codebility/app/applicant/onboarding/_components/OnboardingClient.tsx‎

Lines changed: 61 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,32 @@ export default function OnboardingClient({
109109
setCurrentStep("quiz");
110110
};
111111

112+
const handleBackToVideos = () => {
113+
setCurrentStep("videos");
114+
};
115+
116+
const handleBackToQuiz = () => {
117+
setCurrentStep("quiz");
118+
};
119+
120+
const handleStepClick = (stepNumber: number) => {
121+
if (stepNumber >= 1 && stepNumber <= 4) {
122+
// Navigate to video step
123+
setCurrentStep("videos");
124+
setProgress((prev) => ({
125+
...prev,
126+
currentVideo: stepNumber as 1 | 2 | 3 | 4,
127+
}));
128+
} else if (stepNumber === 5) {
129+
// Navigate to quiz/commitment based on quiz status
130+
if (applicantData.quiz_passed && !applicantData.commitment_signed_at) {
131+
setCurrentStep("commitment");
132+
} else {
133+
setCurrentStep("quiz");
134+
}
135+
}
136+
};
137+
112138
const handleQuizComplete = (score: number, total: number) => {
113139
setQuizScore(score);
114140
setQuizTotal(total);
@@ -186,6 +212,7 @@ export default function OnboardingClient({
186212
<OnboardingStepper
187213
progress={progress}
188214
currentVideo={currentStep === "videos" ? progress.currentVideo : 5}
215+
onStepClick={handleStepClick}
189216
/>
190217
</div>
191218

@@ -235,17 +262,43 @@ export default function OnboardingClient({
235262
)}
236263

237264
{currentStep === "quiz" && (
238-
<Quiz
239-
applicantId={applicantId}
240-
onQuizComplete={handleQuizComplete}
241-
/>
265+
<>
266+
<Quiz
267+
applicantId={applicantId}
268+
onQuizComplete={handleQuizComplete}
269+
/>
270+
271+
{/* Back to Videos Button */}
272+
<div className="mt-6">
273+
<Button
274+
onClick={handleBackToVideos}
275+
variant="outline"
276+
className="w-full sm:w-auto"
277+
>
278+
← Back to Videos
279+
</Button>
280+
</div>
281+
</>
242282
)}
243283

244284
{currentStep === "commitment" && (
245-
<Commitment
246-
userName={`${user.first_name} ${user.last_name}`}
247-
onComplete={handleCommitmentComplete}
248-
/>
285+
<>
286+
<Commitment
287+
userName={`${user.first_name} ${user.last_name}`}
288+
onComplete={handleCommitmentComplete}
289+
/>
290+
291+
{/* Back to Quiz Button */}
292+
<div className="mt-6">
293+
<Button
294+
onClick={handleBackToQuiz}
295+
variant="outline"
296+
className="w-full sm:w-auto"
297+
>
298+
← Back to Quiz
299+
</Button>
300+
</div>
301+
</>
249302
)}
250303
</div>
251304

‎apps/codebility/app/applicant/onboarding/_components/OnboardingStepper.tsx‎

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,13 @@ import { OnboardingProgressType } from "../_service/type";
66
interface OnboardingStepperProps {
77
progress: OnboardingProgressType;
88
currentVideo: number;
9+
onStepClick?: (step: number) => void;
910
}
1011

1112
export default function OnboardingStepper({
1213
progress,
1314
currentVideo,
15+
onStepClick,
1416
}: OnboardingStepperProps) {
1517
const steps = [
1618
{ number: 1, title: "Introduction", completed: progress.video1 },
@@ -20,6 +22,12 @@ export default function OnboardingStepper({
2022
{ number: 5, title: "Quiz & Commitment", completed: false }, // Will be updated based on quiz/commitment status
2123
];
2224

25+
const handleStepClick = (stepNumber: number) => {
26+
if (onStepClick) {
27+
onStepClick(stepNumber);
28+
}
29+
};
30+
2331
return (
2432
<div className="w-full">
2533
<div className="flex items-center justify-between">
@@ -28,12 +36,13 @@ export default function OnboardingStepper({
2836
{/* Step Circle */}
2937
<div className="flex flex-col items-center">
3038
<div
31-
className={`flex h-12 w-12 items-center justify-center rounded-full border-2 transition-all ${
39+
onClick={() => handleStepClick(step.number)}
40+
className={`flex h-12 w-12 items-center justify-center rounded-full border-2 transition-all cursor-pointer hover:scale-110 ${
3241
step.completed
33-
? "border-green-500 bg-green-500 text-white"
42+
? "border-green-500 bg-green-500 text-white hover:bg-green-600"
3443
: currentVideo === step.number
3544
? "border-blue-500 bg-blue-500 text-white"
36-
: "border-gray-700 bg-gray-900 text-gray-500"
45+
: "border-gray-700 bg-gray-900 text-gray-500 hover:border-gray-600"
3746
}`}
3847
>
3948
{step.completed ? (
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
-- Reset Onboarding Progress Script
2+
-- This script resets an applicant's onboarding progress completely
3+
-- Replace 'YOUR_APPLICANT_ID' with the actual applicant ID
4+
5+
-- Step 1: Reset all video progress to incomplete
6+
UPDATE public.onboarding_videos
7+
SET
8+
completed = FALSE,
9+
watched_duration = 0,
10+
completed_at = NULL,
11+
updated_at = NOW()
12+
WHERE applicant_id = 'YOUR_APPLICANT_ID';
13+
14+
-- Step 2: Reset quiz and commitment data in applicant table
15+
UPDATE public.applicant
16+
SET
17+
quiz_score = NULL,
18+
quiz_total = NULL,
19+
quiz_passed = FALSE,
20+
quiz_completed_at = NULL,
21+
signature_data = NULL,
22+
commitment_signed_at = NULL,
23+
can_do_mobile = NULL,
24+
updated_at = NOW()
25+
WHERE id = 'YOUR_APPLICANT_ID';
26+
27+
-- Step 3: Verify the reset (optional - for checking)
28+
-- SELECT * FROM public.onboarding_videos WHERE applicant_id = 'YOUR_APPLICANT_ID';
29+
-- SELECT quiz_score, quiz_total, quiz_passed, quiz_completed_at, commitment_signed_at
30+
-- FROM public.applicant WHERE id = 'YOUR_APPLICANT_ID';

0 commit comments

Comments
 (0)