import { useEffect, useState } from 'react' import { createPortal } from 'react-dom' import { Plus, Trash2, X } from 'lucide-react' import { useLocale } from '@meshkee/dashboard-ui' import { useToast } from '../context/ToastContext' import { useT } from '../i18n/useT' import { ApiError } from '../lib/api' import { updateRollCall, type RollCall } from '../services/rollCallService' import modalStyles from './VariationsModal.module.css' import styles from './RollCallFormModal.module.css' interface RollCallTasksModalProps { open: boolean rollCall: RollCall | null onClose: () => void onSaved: (rollCall: RollCall) => void } const ANIMATION_MS = 220 export function RollCallTasksModal({ open, rollCall, onClose, onSaved, }: RollCallTasksModalProps) { const t = useT() const { locale, dir } = useLocale() const { showToast } = useToast() const [mounted, setMounted] = useState(open) const [closing, setClosing] = useState(false) const [tasks, setTasks] = useState(['']) const [saving, setSaving] = useState(false) const [error, setError] = useState('') useEffect(() => { if (open) { setMounted(true) setClosing(false) setError('') setTasks( rollCall && rollCall.tasks.length > 0 ? rollCall.tasks.map((task) => task.title) : [''], ) } else if (mounted) { setClosing(true) const timer = setTimeout(() => { setMounted(false) setClosing(false) }, ANIMATION_MS) return () => clearTimeout(timer) } }, [open, mounted, rollCall]) useEffect(() => { if (!mounted || closing) return const prevOverflow = document.body.style.overflow document.body.style.overflow = 'hidden' const onKey = (e: KeyboardEvent) => { if (e.key === 'Escape') onClose() } document.addEventListener('keydown', onKey) return () => { document.body.style.overflow = prevOverflow document.removeEventListener('keydown', onKey) } }, [mounted, closing, onClose]) if (!mounted || !rollCall) return null function updateTask(index: number, value: string) { setTasks((prev) => prev.map((task, i) => (i === index ? value : task))) } function addTask() { setTasks((prev) => [...prev, '']) } function removeTask(index: number) { setTasks((prev) => { if (prev.length <= 1) return [''] return prev.filter((_, i) => i !== index) }) } async function handleSubmit(e: React.FormEvent) { e.preventDefault() if (!rollCall) return setError('') const cleaned = tasks.map((task) => task.trim()).filter(Boolean) setSaving(true) try { const result = await updateRollCall(rollCall.id, { tasks: cleaned.map((title) => ({ title })), }) onSaved(result.rollCall) showToast(t('rollCall.toast.tasksSaved'), 'success') onClose() } catch (err) { const message = err instanceof ApiError ? err.message : t('rollCall.error.save') setError(message) showToast(message, 'error') } finally { setSaving(false) } } return createPortal(
e.stopPropagation()} role="dialog" aria-modal="true" aria-labelledby="roll-call-tasks-title" lang={locale} dir={dir} >

{t('rollCall.tasksModal.title')}

{t('rollCall.tasksModal.subtitle')}

{error && (
{error}
)}
{t('rollCall.field.tasks')}
{tasks.map((task, index) => (
updateTask(index, e.target.value)} placeholder={t('rollCall.field.taskPlaceholder')} aria-label={t('rollCall.field.taskN', { n: index + 1 })} />
))}
, document.body, ) }