'use client' import { useState, useEffect } from 'react' import { createList, updateList } from '@/lib/actions' import { useRouter } from 'next/navigation' import { useToast } from './ToastContainer' import { validateListTitle } from '@/lib/validation' interface ListFormProps { list?: { id: string title: string color: string } onCancel?: () => void onSuccess?: () => void } const PRESET_COLORS = [ '#3B82F6', // blue '#EF4444', // red '#10B981', // green '#F59E0B', // amber '#8B5CF6', // purple '#EC4899', // pink '#06B6D4', // cyan '#F97316', // orange ] export default function ListForm({ list, onCancel, onSuccess }: ListFormProps) { const router = useRouter() const { showToast } = useToast() const [title, setTitle] = useState(list?.title || '') const [color, setColor] = useState(list?.color || PRESET_COLORS[0]) const [isSubmitting, setIsSubmitting] = useState(false) const [error, setError] = useState('') const [touched, setTouched] = useState(false) // Inline validation when title changes useEffect(() => { if (touched) { const result = validateListTitle(title) setError(result.isValid ? '' : result.error || '') } }, [title, touched]) const handleTitleBlur = () => { setTouched(true) const result = validateListTitle(title) setError(result.isValid ? '' : result.error || '') } const handleSubmit = async (e: React.FormEvent) => { e.preventDefault() // Validate before submission const result = validateListTitle(title) if (!result.isValid) { setError(result.error || 'Invalid input') setTouched(true) return } setIsSubmitting(true) setError('') try { if (list) { // Update existing list await updateList(list.id, { title: title.trim(), color }) showToast('List updated successfully', 'success') } else { // Create new list await createList(title.trim(), color) showToast('List created successfully', 'success') } if (onSuccess) { onSuccess() } else { router.refresh() } } catch (err) { const errorMessage = err instanceof Error ? err.message : 'Failed to save list. Please try again.' setError(errorMessage) showToast(errorMessage, 'error') console.error(err) } finally { setIsSubmitting(false) } } return (
setTitle(e.target.value)} onBlur={handleTitleBlur} className={`w-full px-3 sm:px-4 py-3 border rounded-lg focus:outline-none focus:ring-2 text-sm sm:text-base ${ error && touched ? 'border-red-500 focus:ring-red-500' : 'border-gray-300 focus:ring-blue-500' }`} placeholder="Enter list title" disabled={isSubmitting} autoFocus maxLength={200} aria-invalid={error && touched ? 'true' : 'false'} aria-describedby={error && touched ? 'title-error' : undefined} /> {error && touched && (

{error}

)}
{PRESET_COLORS.map((presetColor) => (
{onCancel && ( )}
) }