From 5fd44899ae7f9fec1a780687499fecae91e861ca Mon Sep 17 00:00:00 2001 From: Tanushree-RD <217297962+Tanushree-RD@users.noreply.github.com> Date: Sun, 13 Sep 2026 22:45:56 +0530 Subject: [PATCH] refactor(student): adopt React Hook Form and Zod for onboarding --- apps/web/app/(onboarding)/student/page.tsx | 33 +++++++- .../app/(onboarding)/student/schema.test.ts | 83 +++++++++++++++++++ 2 files changed, 113 insertions(+), 3 deletions(-) create mode 100644 apps/web/app/(onboarding)/student/schema.test.ts diff --git a/apps/web/app/(onboarding)/student/page.tsx b/apps/web/app/(onboarding)/student/page.tsx index 29f7b3e..be26204 100644 --- a/apps/web/app/(onboarding)/student/page.tsx +++ b/apps/web/app/(onboarding)/student/page.tsx @@ -468,7 +468,14 @@ export default function StudentOnboardingPage() { {/* Step 2: Education */}
step > 1 && setStep(2)} + onClick={async () => { + if (step > 1) { + setStep(2) + } else { + const isValid = await trigger(['fullName', 'headline']) + if (isValid) setStep(2) + } + }} >
step > 2 && setStep(3)} + onClick={async () => { + if (step > 2) { + setStep(3) + } else { + const valid1 = await trigger(['fullName', 'headline']) + if (!valid1) return + const valid2 = await trigger(['school', 'degree', 'graduationYear']) + if (valid2) setStep(3) + } + }} >
step > 3 && setStep(4)} + onClick={async () => { + if (step > 3) { + setStep(4) + } else { + const valid1 = await trigger(['fullName', 'headline']) + if (!valid1) return + const valid2 = await trigger(['school', 'degree', 'graduationYear']) + if (!valid2) return + const valid3 = await trigger(['skills']) + if (valid3 && skills.length > 0) setStep(4) + } + }} >
{ + const validData = { + fullName: 'Alex Chen', + headline: 'CS Student | Full-Stack Developer', + bio: 'Enthusiastic developer looking for opportunities.', + school: 'Stanford University', + degree: 'B.S. Computer Science', + graduationYear: '2026', + gpa: '3.9', + specialization: 'AI / Machine Learning', + skills: ['React', 'TypeScript', 'Next.js'], + experienceRole: 'Frontend Intern', + experienceCompany: 'DK24 Labs', + experienceSummary: 'Built key UI components', + githubUrl: 'https://github.com/alexchen', + linkedinUrl: 'https://linkedin.com/in/alexchen', + portfolioUrl: 'https://alexchen.dev', + resumeUrl: 'https://drive.google.com/resume.pdf', + } + + it('validates a valid student onboarding data object', () => { + const result = studentCompleteOnboardingSchema.safeParse(validData) + expect(result.success).toBe(true) + }) + + it('fails validation when fullName is too short or empty', () => { + const resultEmpty = studentStep1Schema.safeParse({ fullName: '' }) + expect(resultEmpty.success).toBe(false) + + const resultShort = studentStep1Schema.safeParse({ fullName: 'A' }) + expect(resultShort.success).toBe(false) + }) + + it('fails validation when school or degree is empty', () => { + const invalidSchool = studentStep2Schema.safeParse({ + school: '', + degree: 'B.S.', + graduationYear: '2026', + }) + expect(invalidSchool.success).toBe(false) + + const invalidDegree = studentStep2Schema.safeParse({ + school: 'Stanford', + degree: '', + graduationYear: '2026', + }) + expect(invalidDegree.success).toBe(false) + }) + + it('fails validation when skills array is empty', () => { + const invalidSkills = studentStep3Schema.safeParse({ + skills: [], + }) + expect(invalidSkills.success).toBe(false) + }) + + it('validates optional URLs correctly', () => { + const validUrls = studentStep4Schema.safeParse({ + githubUrl: '', + linkedinUrl: 'https://linkedin.com/in/alexchen', + portfolioUrl: '', + resumeUrl: '', + }) + expect(validUrls.success).toBe(true) + + const invalidUrl = studentStep4Schema.safeParse({ + githubUrl: 'not-a-valid-url', + linkedinUrl: '', + portfolioUrl: '', + resumeUrl: '', + }) + expect(invalidUrl.success).toBe(false) + }) +})