import { createSignal } from 'solid-js'; import AdminShell from '~/components/AdminShell'; import { saveRuntimeConfig } from '~/lib/runtime/storage'; import type { RuntimeOnboardingConfig, RuntimeOnboardingStep } from '~/lib/runtime/types'; function buildDefaultConfig(): RuntimeOnboardingConfig { return { schemaId: 'photographer_onboarding_v1', roleKey: 'PHOTOGRAPHER', version: 1, steps: [ { id: 'step_1_service', title: 'Select Service Category', fields: [ { id: 'profession', label: 'Service Category', type: 'select', required: true, options: [ { label: 'Photographer', value: 'Photographer' }, { label: 'Makeup Artist', value: 'Makeup Artist' }, ], }, ], }, ], }; } function stringifySteps(steps: RuntimeOnboardingStep[]): string { return JSON.stringify(steps, null, 2); } export default function CreateOnboardingSchemaPage() { const [config, setConfig] = createSignal(buildDefaultConfig()); const [stepsJson, setStepsJson] = createSignal(stringifySteps(buildDefaultConfig().steps)); const [statusMessage, setStatusMessage] = createSignal(''); const [stepsError, setStepsError] = createSignal(''); const syncSteps = (raw: string) => { setStepsJson(raw); try { const parsed = JSON.parse(raw) as RuntimeOnboardingStep[]; if (!Array.isArray(parsed)) { setStepsError('Steps JSON must be an array.'); return; } setConfig({ ...config(), steps: parsed }); setStepsError(''); } catch { setStepsError('Invalid JSON. Fix syntax before saving.'); } }; const persist = (status: 'draft' | 'published') => { const payload = config(); if (!payload.schemaId.trim()) { setStatusMessage('Schema ID is required before saving.'); return; } if (stepsError()) { setStatusMessage('Fix steps JSON errors before saving.'); return; } if (payload.steps.length === 0) { setStatusMessage('Add at least one onboarding step before saving.'); return; } saveRuntimeConfig('onboarding', payload.schemaId, payload, status); setStatusMessage(status === 'draft' ? 'Draft saved in runtime storage.' : 'Onboarding schema published in runtime storage.'); }; return (

Create Onboarding Flow

All onboarding fields, validations, upload rules, and select behaviors are runtime schema-driven.

Onboarding Builder

setConfig({ ...config(), schemaId: e.currentTarget.value })} />
setConfig({ ...config(), roleKey: e.currentTarget.value.toUpperCase() })} />
setConfig({ ...config(), version: Number(e.currentTarget.value || 1) })} />