+
+
Tell us about yourself
+
Establish your basic profile parameters.
+
+
+ {/* Username */}
+
+
+ Username *
+
+
+
+
+
+
handleFieldChange('username', e.target.value)}
+ onBlur={() => handleFieldBlur('username')}
+ aria-invalid={!!usernameError}
+ aria-describedby={usernameError ? 'username-error' : undefined}
+ className={`w-full pl-10 pr-4 py-3 bg-white dark:bg-slate-900 border ${
+ usernameError ? 'border-red-500 ring-2 ring-red-500/10' : 'border-slate-200 dark:border-slate-800/80'
+ } rounded-lg outline-none focus:ring-2 focus:ring-cyan-500 focus:border-transparent transition-all dark:text-slate-100`}
+ />
+
+ {usernameError && (
+
+ {formState.validation.username.errors[0]?.message}
+
+ )}
+
+
+ {/* Role Selection */}
+
+
+ I want to use TeachLink as a... *
+
+
+ {/* Student Card */}
+
handleFieldChange('role', 'student')}
+ className={`flex items-start p-4 rounded-xl border text-left transition-all ${
+ formState.values.role === 'student'
+ ? 'border-cyan-500 bg-cyan-50/50 dark:bg-cyan-950/20 ring-2 ring-cyan-500/20'
+ : 'border-slate-200 dark:border-slate-800/80 hover:bg-slate-50 dark:hover:bg-slate-800/30'
+ }`}
+ >
+
+
+
+
+
Student / Learner
+
+ Explore courses, connect a Starknet wallet to store certificates off-chain, and build your web3 identity.
+
+
+
+
+ {/* Instructor Card */}
+
handleFieldChange('role', 'instructor')}
+ className={`flex items-start p-4 rounded-xl border text-left transition-all ${
+ formState.values.role === 'instructor'
+ ? 'border-blue-500 bg-blue-50/50 dark:bg-blue-950/20 ring-2 ring-blue-500/20'
+ : 'border-slate-200 dark:border-slate-800/80 hover:bg-slate-50 dark:hover:bg-slate-800/30'
+ }`}
+ >
+
+
+
+
+
Instructor / Teacher
+
+ Share your technical skills, build comprehensive courses, and issue decentralized credentials.
+
+
+
+
+ {roleError && (
+
+ {formState.validation.role.errors[0]?.message}
+
+ )}
+
+
+ {/* Date of Birth */}
+
+
+ Date of Birth *
+
+
+
+
+
+
handleFieldChange('dob', e.target.value)}
+ onBlur={() => handleFieldBlur('dob')}
+ aria-invalid={!!dobError}
+ aria-describedby={dobError ? 'dob-error' : undefined}
+ className={`w-full pl-10 pr-4 py-3 bg-white dark:bg-slate-900 border ${
+ dobError ? 'border-red-500 ring-2 ring-red-500/10' : 'border-slate-200 dark:border-slate-800/80'
+ } rounded-lg outline-none focus:ring-2 focus:ring-cyan-500 focus:border-transparent transition-all dark:text-slate-100`}
+ />
+
+ {dobError && (
+
+ {formState.validation.dob.errors[0]?.message}
+
+ )}
+
+
+ {/* Short Bio */}
+
+
+ Short Bio (Optional)
+
+
+
+ {bioError ? (
+
+ {formState.validation.bio.errors[0]?.message}
+
+ ) : (
+
+ )}
+
+ {formState.values.bio ? formState.values.bio.length : 0}/200
+
+
+
+
+ );
+ };
+
+ // Step 2 UI Renderer
+ const renderPreferencesStep = () => {
+ const interestError = formState.touched.interest && formState.validation.interest && !formState.validation.interest.isValid;
+ const notificationsError = formState.touched.notifications && formState.validation.notifications && !formState.validation.notifications.isValid;
+ const languageError = formState.touched.language && formState.validation.language && !formState.validation.language.isValid;
+
+ return (
+
+
+
Set your preferences
+
Configure how you would like to interact with the platform.
+
+
+ {/* Learning Interest */}
+
+
+ Primary Interest *
+
+
+ handleFieldChange('interest', e.target.value)}
+ onBlur={() => handleFieldBlur('interest')}
+ aria-invalid={!!interestError}
+ aria-describedby={interestError ? 'interest-error' : undefined}
+ className={`w-full px-4 py-3 bg-white dark:bg-slate-900 border ${
+ interestError ? 'border-red-500 ring-2 ring-red-500/10' : 'border-slate-200 dark:border-slate-800/80'
+ } rounded-lg outline-none focus:ring-2 focus:ring-cyan-500 focus:border-transparent transition-all dark:text-slate-100`}
+ >
+ Select your primary area
+ Web3 & Starknet Smart Contracts
+ Frontend Engineering (React / Next.js)
+ DevOps, CI/CD & Cloud Infrastructure
+
+
+ {interestError && (
+
+ {formState.validation.interest.errors[0]?.message}
+
+ )}
+
+
+ {/* Notifications */}
+
+
+ Preferred Notification Channel *
+
+
+
+
+
+
handleFieldChange('notifications', e.target.value)}
+ onBlur={() => handleFieldBlur('notifications')}
+ aria-invalid={!!notificationsError}
+ aria-describedby={notificationsError ? 'notifications-error' : undefined}
+ className={`w-full pl-10 pr-4 py-3 bg-white dark:bg-slate-900 border ${
+ notificationsError ? 'border-red-500 ring-2 ring-red-500/10' : 'border-slate-200 dark:border-slate-800/80'
+ } rounded-lg outline-none focus:ring-2 focus:ring-cyan-500 focus:border-transparent transition-all dark:text-slate-100`}
+ >
+ Email Notifications Only
+ In-App Notifications Only
+ Both Email and In-App
+
+
+ {notificationsError && (
+
+ {formState.validation.notifications.errors[0]?.message}
+
+ )}
+
+
+ {/* Language Preference */}
+
+
+ Interface Language *
+
+
+
+
+
+
handleFieldChange('language', e.target.value)}
+ onBlur={() => handleFieldBlur('language')}
+ aria-invalid={!!languageError}
+ aria-describedby={languageError ? 'language-error' : undefined}
+ className={`w-full pl-10 pr-4 py-3 bg-white dark:bg-slate-900 border ${
+ languageError ? 'border-red-500 ring-2 ring-red-500/10' : 'border-slate-200 dark:border-slate-800/80'
+ } rounded-lg outline-none focus:ring-2 focus:ring-cyan-500 focus:border-transparent transition-all dark:text-slate-100`}
+ >
+ English
+ Español (Spanish)
+ العربية (Arabic)
+ Français (French)
+ 日本語 (Japanese)
+
+
+ {languageError && (
+
+ {formState.validation.language.errors[0]?.message}
+
+ )}
+
+
+ {/* Newsletter Subscription */}
+
+
+ handleFieldChange('newsletter', e.target.checked)}
+ className="w-5 h-5 text-cyan-600 bg-white border-slate-300 rounded focus:ring-cyan-500 focus:ring-2 dark:bg-slate-900 dark:border-slate-800"
+ />
+
+
+
+ Subscribe to newsletter updates
+
+
+ Receive notifications about hot courses, Starknet ecosystem rewards, and technical tutorials once a week.
+
+
+
+
+ );
+ };
+
+ // Step 3 UI Renderer
+ const renderWalletStep = () => {
+ const isConnected = !!formState.values.walletAddress;
+
+ return (
+
+ {/* Decorative gradient glowing spheres */}
+
+
+
+ {/* Main content container */}
+
+ {/* Logo and header */}
+
+
+
+ Welcome to Onboarding
+
+
+ Set up your identity and technical preferences to get started with TeachLink's decentralized platform.
+
+
+
+ {/* Wizard Card Container */}
+
+ {(currentStep) => {
+ switch (currentStep.id) {
+ case 'personal-setup':
+ return renderPersonalStep();
+ case 'preferences':
+ return renderPreferencesStep();
+ case 'wallet-integration':
+ return renderWalletStep();
+ default:
+ return null;
+ }
+ }}
+
+
+
+ );
+}
diff --git a/src/components/forms/FormWizardController.tsx b/src/components/forms/FormWizardController.tsx
index 14a6a048..e817a4f3 100644
--- a/src/components/forms/FormWizardController.tsx
+++ b/src/components/forms/FormWizardController.tsx
@@ -23,6 +23,7 @@ interface FormWizardControllerProps {
validateBeforeNext?: boolean;
className?: string;
children: (currentStep: WizardStep, progress: WizardProgress) => React.ReactNode;
+ fields?: FieldDescriptor[];
}
export const FormWizardController: React.FC