'use client'; import { useState, type FormEvent } from 'react'; import { useRouter } from 'next/navigation'; import { ConflictWarning, type ScheduleConflict, } from '@/components/meetings/ConflictWarning'; interface Member { userId: number; name: string; } export function MeetingForm({ projectId, members, }: { projectId: number; members: Member[]; }) { const router = useRouter(); const [title, setTitle] = useState(''); const [startAt, setStartAt] = useState(''); const [endAt, setEndAt] = useState(''); const [selected, setSelected] = useState([]); const [conflicts, setConflicts] = useState(null); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); async function onSubmit(event: FormEvent) { event.preventDefault(); setLoading(true); setError(null); setConflicts(null); const res = await fetch(`/api/projects/${projectId}/meetings`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ title, startAt, endAt, memberIds: selected }), }); setLoading(false); if (res.ok) { const data = (await res.json()) as { meeting: { id: number }; conflicts: ScheduleConflict[]; }; setConflicts(data.conflicts); setTitle(''); setStartAt(''); setEndAt(''); setSelected([]); router.refresh(); } else { const b = (await res.json().catch(() => null)) as { error?: { message?: string }; } | null; setError(b?.error?.message ?? '作成に失敗しました'); } } function toggleMember(userId: number) { setSelected((prev) => prev.includes(userId) ? prev.filter((u) => u !== userId) : [...prev, userId] ); } return (
setTitle(e.target.value)} className="mt-1 w-full rounded border px-3 py-2" required data-testid="meeting-title" />
setStartAt(e.target.value)} className="mt-1 w-full rounded border px-3 py-2" required data-testid="meeting-start" />
setEndAt(e.target.value)} className="mt-1 w-full rounded border px-3 py-2" required data-testid="meeting-end" />
{members.map((m) => ( ))}
{error && (

{error}

)} {conflicts && } ); }