import { useState, useEffect, FormEvent } from 'react' import { useNavigate, useParams, Link } from 'react-router-dom' export function QuestionnaireForm() { const { id } = useParams() const isEditing = !!id const navigate = useNavigate() const [title, setTitle] = useState('') const [slug, setSlug] = useState('') const [description, setDescription] = useState('') const [ogImage, setOgImage] = useState('') const [isPrivate, setIsPrivate] = useState(false) const [error, setError] = useState('') const [slugError, setSlugError] = useState('') const [loading, setLoading] = useState(false) useEffect(() => { if (isEditing) { fetchQuestionnaire() } }, [id]) async function fetchQuestionnaire() { try { const res = await fetch(`/api/admin/questionnaires/${id}`, { credentials: 'include' }) const data = await res.json() if (data.questionnaire) { setTitle(data.questionnaire.title) setSlug(data.questionnaire.slug) setDescription(data.questionnaire.description || '') setOgImage(data.questionnaire.og_image || '') setIsPrivate(!!data.questionnaire.is_private) } } catch (error) { console.error('Failed to fetch questionnaire:', error) } } // Auto-generate slug from title (only when creating new) function handleTitleChange(value: string) { setTitle(value) if (!isEditing && !slug) { const autoSlug = value .toLowerCase() .replace(/[^a-z0-9\s-]/g, '') .replace(/\s+/g, '-') .replace(/-+/g, '-') .substring(0, 50) setSlug(autoSlug) } } function handleSlugChange(value: string) { const cleanSlug = value .toLowerCase() .replace(/[^a-z0-9-]/g, '') .substring(0, 50) setSlug(cleanSlug) setSlugError('') } async function checkSlugAvailability() { if (!slug || slug.length < 3) return try { const excludeParam = isEditing ? `?excludeId=${id}` : '' const res = await fetch(`/api/admin/questionnaires/check-slug/${slug}${excludeParam}`, { credentials: 'include' }) const data = await res.json() if (!data.available) { setSlugError('Deze slug is al in gebruik') } } catch (err) { console.error('Failed to check slug:', err) } } async function handleSubmit(e: FormEvent) { e.preventDefault() setError('') setLoading(true) try { const url = isEditing ? `/api/admin/questionnaires/${id}` : '/api/admin/questionnaires' const method = isEditing ? 'PUT' : 'POST' const res = await fetch(url, { method, headers: { 'Content-Type': 'application/json' }, credentials: 'include', body: JSON.stringify({ title, slug, description, ogImage, isPrivate }), }) const data = await res.json() if (!res.ok) { throw new Error(data.error || 'Vragenlijst opslaan mislukt') } navigate('/admin/dashboard') } catch (err) { setError(err instanceof Error ? err.message : 'Opslaan mislukt') } finally { setLoading(false) } } return (
← Terug naar Dashboard

{isEditing ? 'Vragenlijst Bewerken' : 'Vragenlijst Maken'}

{error && (
{error}
)}
handleTitleChange(e.target.value)} className="w-full px-4 py-3 bg-bg-input border border-border rounded-lg text-text placeholder-text-faint focus:outline-none focus:border-accent focus:ring-2 focus:ring-accent/20 transition-colors" placeholder="bijv. Teambuilding Activiteiten" required autoFocus />
/q/ handleSlugChange(e.target.value)} onBlur={checkSlugAvailability} className={`flex-1 px-4 py-3 bg-bg-input border rounded-lg text-text placeholder-text-faint focus:outline-none focus:ring-2 transition-colors font-mono ${ slugError ? 'border-danger focus:border-danger focus:ring-danger/20' : 'border-border focus:border-accent focus:ring-accent/20' }`} placeholder="teambuilding-2024" required minLength={3} maxLength={50} />
{slugError && (

{slugError}

)}

Alleen kleine letters, cijfers en koppeltekens. 3-50 tekens.