import { A, useNavigate } from '@solidjs/router'; import { createMemo, createSignal, For, Show } from 'solid-js'; import AdminShell from '~/components/AdminShell'; const API = '/api/gateway'; const EXTERNAL_ROLES = ['company', 'job_seeker', 'customer', 'photographer', 'video_editor', 'graphic_designer', 'social_media_manager', 'fitness_trainer', 'catering_services', 'makeup_artist', 'tutor', 'developer']; const FIELD_TYPES = ['text', 'textarea', 'number', 'email', 'tel', 'date', 'select', 'url', 'file', 'checkbox'] as const; type FieldType = typeof FIELD_TYPES[number]; type OnboardingField = { id: string; label: string; type: FieldType; required: boolean; placeholder?: string; helperText?: string; options?: { label: string; value: string }[]; }; type OnboardingStep = { id: string; title: string; description?: string; fields: OnboardingField[]; }; const makeId = (prefix: string) => `${prefix}_${Math.random().toString(36).slice(2, 10)}`; function makeDefaultStep(idx: number): OnboardingStep { return { id: makeId('step'), title: `Step ${idx + 1}`, description: '', fields: [] }; } export default function CreateOnboardingFlowPage() { const navigate = useNavigate(); const [title, setTitle] = createSignal(''); const [roleKey, setRoleKey] = createSignal('company'); const [description, setDescription] = createSignal(''); const [finalMessage, setFinalMessage] = createSignal('Your onboarding has been submitted for review. We will notify you once it is approved.'); const [steps, setSteps] = createSignal([makeDefaultStep(0), makeDefaultStep(1)]); const [saving, setSaving] = createSignal(false); const [error, setError] = createSignal(''); const totalFields = createMemo(() => steps().reduce((sum, s) => sum + s.fields.length, 0)); const updateStep = (stepId: string, patch: Partial) => setSteps((prev) => prev.map((s) => s.id === stepId ? { ...s, ...patch } : s)); const addStep = () => setSteps((prev) => [...prev, makeDefaultStep(prev.length)]); const removeStep = (stepId: string) => setSteps((prev) => prev.filter((s) => s.id !== stepId)); const addField = (stepId: string) => { const step = steps().find((s) => s.id === stepId)!; updateStep(stepId, { fields: [...step.fields, { id: makeId('fld'), label: 'New Field', type: 'text', required: false, placeholder: '' }], }); }; const removeField = (stepId: string, fieldId: string) => { const step = steps().find((s) => s.id === stepId)!; updateStep(stepId, { fields: step.fields.filter((f) => f.id !== fieldId) }); }; const updateField = (stepId: string, fieldId: string, patch: Partial) => { const step = steps().find((s) => s.id === stepId)!; updateStep(stepId, { fields: step.fields.map((f) => f.id === fieldId ? { ...f, ...patch } : f) }); }; const handleSubmit = async (status: 'draft' | 'published') => { if (!title().trim()) { setError('Flow title is required'); return; } if (steps().length === 0) { setError('Add at least one step'); return; } try { setSaving(true); setError(''); const payload = { title: title().trim(), roleKey: roleKey(), description: description().trim(), finalSubmissionMessage: finalMessage(), version: 1, steps: steps(), is_active: status === 'published', }; const res = await fetch(`${API}/api/admin/onboarding-config`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ schema_json: payload, is_active: status === 'published' }), }); if (!res.ok) { const body = await res.json().catch(() => ({})); throw new Error(body.message || 'Failed to create onboarding flow'); } navigate('/admin/onboarding-schemas'); } catch (err: any) { setError(err.message || 'Failed to create onboarding flow'); } finally { setSaving(false); } }; return (

Create Onboarding Flow

Build one onboarding flow at a time. Start with the role, add steps, then configure fields for each step.

Back to Onboarding
{error()}
{/* Info stats */}
Role
{roleKey().replace(/_/g, ' ').toUpperCase()}
Steps
{steps().length}
Total Fields
{totalFields()}
{/* Flow metadata */}

Flow Details

Configure the flow title, target role, and final submission message.

setTitle(e.currentTarget.value)} placeholder="e.g. Photographer Onboarding" />
setDescription(e.currentTarget.value)} placeholder="Short description of this onboarding flow" />