'use client' import { useEffect, useMemo, useState } from 'react' import ConsumerInput from '@/components/consumer/ConsumerInput' import ConsumerModal from '@/components/consumer/ConsumerModal' import SearchAltIcon from '@/components/icons/SearchAltIcon' import { coerceToString, formatPersonName } from '@/helpers' import { addToast } from '@/lib/toast' import { fetchPreviousAttendees, setPreviousAttendeeGuests, type PreviousAttendee } from '@/services/events' import { texts } from '@/texts' interface Step5GuestListProps { isOpen: boolean onOpenChange: (open: boolean) => void eventId: string attendees: PreviousAttendee[] onFinish: () => void } export default function Step5GuestList({ isOpen, onOpenChange, eventId, attendees, onFinish }: Step5GuestListProps) { const [search, setSearch] = useState('') const [selectedIds, setSelectedIds] = useState([]) const [isLinking, setIsLinking] = useState(false) useEffect(() => { if (!isOpen) return setSearch('') setSelectedIds([]) }, [isOpen]) const filteredAttendees = useMemo(() => { const query = search.trim().toLowerCase() if (!query) return attendees return attendees.filter((attendee) => { const name = formatPersonName(attendee.firstName, attendee.lastName, '').toLowerCase() return name.includes(query) }) }, [attendees, search]) const allFilteredSelected = filteredAttendees.length > 0 && filteredAttendees.every((attendee) => selectedIds.includes(attendee.userId)) const toggleAttendee = (userId: string, checked: boolean) => { setSelectedIds((prev) => (checked ? [...prev, userId] : prev.filter((id) => id !== userId))) } const toggleSelectAll = (checked: boolean) => { const filteredIds = filteredAttendees.map((attendee) => attendee.userId) if (checked) { setSelectedIds((prev) => Array.from(new Set([...prev, ...filteredIds]))) return } setSelectedIds((prev) => prev.filter((id) => !filteredIds.includes(id))) } const handleSendInvitations = async () => { if (selectedIds.length === 0) { onOpenChange(false) onFinish() return } setIsLinking(true) try { await setPreviousAttendeeGuests(eventId, selectedIds) addToast({ title: texts.events.guestsSaved, color: 'success' }) onOpenChange(false) onFinish() } catch { addToast({ title: texts.events.guestsSaveFailed, color: 'danger' }) } finally { setIsLinking(false) } } return ( void handleSendInvitations()} >

{texts.events.invitePreviousGuestsDescription}

} name="guestSearch" placeholder={texts.events.guestSearchPlaceholder} value={search} onClear={() => { setSearch('') }} onValueChange={(next) => { setSearch(coerceToString(next)) }} /> { toggleSelectAll(Boolean(checked)) }} />
{filteredAttendees.length === 0 ? (

{texts.common.emptyChoice}

) : ( filteredAttendees.map((attendee) => (
{ toggleAttendee(attendee.userId, Boolean(checked)) }} />
)) )}
) } export async function loadPreviousAttendeesForStep5(): Promise { try { return await fetchPreviousAttendees() } catch { return [] } }