Feature/form validation - #785
Merged
Merged
Conversation
- Add SocialAuthButtons component with Google and Facebook buttons - Include inline SVG icons for both providers (no external deps) - Add divider with configurable 'or ...' label - Fully accessible: aria-label, role=group/separator, aria-hidden on decorative SVGs - Dark mode support via Tailwind dark: variants - No backend integration (UI only) - Fix pre-existing broken login page (code inside return statement) - Refactor register page to use shared SocialAuthButtons component - Add 7 unit tests for SocialAuthButtons (all passing)
…uth UI - feat: add SocialAuthButtons component (Google + Facebook, dark mode, SVG icons) - feat: integrate SocialAuthButtons into login and register pages - test: add 7 unit tests for SocialAuthButtons; all 153 tests pass across 15 suites TypeScript (tsc --noEmit now clean): - lib/api/client.ts: type headers as Record<string,string> to allow Authorization indexing - lib/types.ts: add experienceYears? field to Mentor interface - components/mentors/data.ts: re-export Mentor, ExperienceLevel; add EXPERIENCE_LEVELS array - components/mentors/DiscoveryMentorCard.tsx: nullish coalesce all optional Mentor fields - components/mentors/MentorComparisonDrawer.tsx: add rating ?? 0 and id || mentorId fallbacks - components/DiscussionMetadata.tsx: add full TypeScript types + React.CSSProperties - app/(public)/mentors/data/mockMentors.ts: type as Mentor[], add MENTORS + mentorSlug exports - app/(public)/mentors/[id]/page.tsx: type existing param in filter callback - app/(public)/mentors/components/MentorCard.tsx: replace @heroicons/react with lucide-react - app/(public)/resources/tracks/LearningTracks.tsx: fix LearningTrackCard import path - app/CategoryBadge.tsx: add ColorKey/ColorEntry types, typed COLOR_MAP and props - components/community/CreateDiscussionForm.tsx: import missing Toast component - components/icons.tsx: add named aliases (CodeIcon, GearIcon, ChevronRightIcon, etc.) - components/resources/icons.ts: create re-export barrel for resource icon imports ESLint (0 errors): - components/community/RichTextEditor.tsx: move ToolbarButton to module level - hooks/useDiscussions.ts: wrap setState in async IIFE to fix react-hooks/set-state-in-effect - components/ResourceSearchBar.tsx: wrap setState in microtask - lib/auth-context.tsx: use lazy useState initializer for localStorage reads Prettier: all files formatted clean Bug fixes: - app/layout.tsx: remove duplicate AuthProvider import - app/(dashboard)/community/[id]/page.tsx: fix duplicate content, unescaped JSX entities - app/(public)/discover-mentors/MentorDiscoveryView.tsx: fix corruption, align Mentor fields - app/(public)/mentors/page.tsx: fix duplicate component syntax and missing return wrapper - components/ui/StarRating.tsx: fix 1-indexed partial-fill star calculation - lib/utils.ts: replace missing clsx/tailwind-merge with pure cn() implementation
- feat: create centralised Zod schemas in lib/validations/auth.ts for login and register - feat: add getPasswordStrength helper & PasswordStrengthMeter component with live 4-bar indicator & checklist - feat: create reusable FormField component with accessibility (aria-describedby, aria-invalid, role=alert) - feat: refactor LoginForm & RegisterForm to disable submit when form is invalid (!isValid) - feat: strip confirmPassword from registration payload before calling authContext - test: add unit test suites __tests__/auth/LoginForm.test.tsx (16 tests) and __tests__/auth/RegisterForm.test.tsx (18 tests) - fix: resolve ESLint warnings & errors across modified components (impure Date.now, prefer-const, unused imports)
|
@Unclebaffa Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits. You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀 |
Contributor
|
Please resolve conflict |
Contributor
Author
Conflict resolved |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Detailed Implementation Report: Client-Side Form Validation
1. Executive Summary
We have implemented comprehensive client-side form validation for the Login and Register forms in SkillSync. Built using
react-hook-formandzod, the implementation delivers real-time validation, a live 4-stage password strength indicator, accessiblearia-describedbyerror announcements, disabled submit controls for invalid form states, and unit test coverage.2. Core Features Implemented
A. Centralised Zod Validation Schemas (
lib/validations/auth.ts)loginSchema:email: Required field validation + RFC 5322 email format validation.password: Required field validation.registerSchema:name: Required full name (1 to 80 characters).email: Required email format validation.password: Length validation (8 to 128 characters).confirmPassword: Validated via.superRefine()to ensure exact match withpassword.getPasswordStrength(password):0-9, contains lowercasea-z, contains uppercase/symbols.empty,weak,fair,good,strong), and boolean flags for each criteria.B. Accessible Form Field Wrapper (
components/auth/FormField.tsx)<label>, the input control, error alert text, and optional field hints.useId()hook to link inputs to labels and error text.aria-describedby={${id}-error}dynamically when errors occur so screen readers announce validation errors.aria-invalid={hasError}on the input element.border-red-400 focus:ring-red-300) on validation failure.C. Live Password Strength Meter (
components/auth/PasswordStrengthMeter.tsx)weak): Red (bg-red-500)fair): Amber (bg-amber-400)good): Yellow (bg-yellow-400)strong): Emerald (bg-emerald-500)8+ charactersNumber (0–9)Lowercase (a–z)Uppercase or symbolD. Refactored Form Components
1.
components/auth/LoginForm.tsxloginSchemawithonTouchedvalidation mode.!isValid), submitting (isSubmitting), or loading (isLoading).2.
components/auth/RegisterForm.tsxregisterSchema.<PasswordStrengthMeter value={watch("password")} />.confirmPasswordfrom registration payload before callingregisterUser({ name, email, password }).3. Testing & Code Quality Metrics
Unit Tests Created:
__tests__/auth/LoginForm.test.tsx(16 Tests)noValidateHTML5 attribute presence/dashboardAuthContextaria-invalidandaria-describedbylinking__tests__/auth/RegisterForm.test.tsx(18 Tests)confirmPasswordfromregister()call/dashboardVerification Summary:
npx tsc --noEmit— 0 errorsnpm run lint— 0 errorsCloses #613