/* eslint-disable @typescript-eslint/no-explicit-any */ import { Box, CircularProgress, TextField } from '@mui/material' import { LocalizationProvider, StaticDatePicker as DatePicker } from '@mui/x-date-pickers' import { AdapterMoment } from '@mui/x-date-pickers/AdapterMoment' import _get from 'lodash/get' import _map from 'lodash/map' import _sortBy from 'lodash/sortBy' import moment from 'moment-timezone' import React, { ReactNode, useMemo, useState } from 'react' import { TimeSlotTicketRow } from './TimeSlotTicketRow' interface Props { event: any; eventId: number; availableDates: string[]; selectedDate: string | null; timeSlotGroups: { [key: string]: any[] }; setTimeSlotGroups: (value: { [key: string]: any[] }) => void; setSelectedDate: (value: string | null) => void; getTimeSlots: (date: string | null, type?: string) => Promise; selectedTickets: any; handleTicketSelect: any; sortBySoldOut: boolean; hideTicketsHeader: boolean; ticketsHeaderComponent?: ReactNode; showGroupNameBlock?: boolean; currencySymbol?: string; isSeatMapAllowed?: boolean; } interface TimeSlotOption { timeKey: string; ticketInstance: any; } interface UniqueTicket { ticket: any; availableTimeSlots: TimeSlotOption[]; } const TimeSlotsSection: React.FC = ({ event, availableDates, selectedDate, timeSlotGroups, setSelectedDate, getTimeSlots, selectedTickets, handleTicketSelect, sortBySoldOut, hideTicketsHeader, ticketsHeaderComponent, currencySymbol, }) => { const [loading, setLoading] = useState(false) const [selectedTimeSlots, setSelectedTimeSlots] = useState<{ [key: string]: string }>({}) const handleDateChange = async (date: string | null) => { setSelectedDate(date) setSelectedTimeSlots({}) // Reset time slot selections when date changes if (date) { setLoading(true) try { await getTimeSlots(date) } catch (error) { console.error('Error fetching time slots:', error) } finally { setLoading(false) } } } const isDateDisabled = (date: string) => { const formattedDate = moment(date).format('YYYY-MM-DD') return !availableDates.includes(formattedDate) } // Group tickets by unique ticket type using displayName + price const uniqueTickets = useMemo(() => { const ticketMap: { [key: string]: UniqueTicket } = {} // Iterate through all time slots _map(timeSlotGroups, (tickets, timeKey) => { tickets.forEach((ticket: any) => { // Use displayName + price as the unique identifier for ticket types // This handles cases where multiple ticket types share the same optionName const ticketKey = `${ticket.displayName || ticket.name}_${ticket.price}` if (!ticketMap[ticketKey]) { ticketMap[ticketKey] = { ticket: { ...ticket }, availableTimeSlots: [], } } // Store both the time key and the ticket instance for this slot if (!ticketMap[ticketKey].availableTimeSlots.find((slot: any) => slot.timeKey === timeKey)) { ticketMap[ticketKey].availableTimeSlots.push({ timeKey, ticketInstance: ticket, }) } }) }) // Convert to array and sort const ticketsArray = Object.values(ticketMap) return sortBySoldOut ? _sortBy(_sortBy(ticketsArray, t => t.ticket.sortOrder), t => t.ticket.soldOut) : _sortBy(ticketsArray, t => t.ticket.sortOrder) }, [timeSlotGroups, sortBySoldOut]) const handleTimeSlotSelect = (ticketKey: string, timeKey: string, ticketInstance: any) => { setSelectedTimeSlots(prev => ({ ...prev, [ticketKey]: timeKey, })) // Reset quantity when time slot changes if (selectedTickets[ticketInstance.id]) { handleTicketSelect(ticketInstance.id, 0) } } const handleTicketSelectWithTimeSlot = (ticketKey: string, quantity: number, ticketInstance: any) => { const timeSlot = selectedTimeSlots[ticketKey] if (!timeSlot && quantity > 0) { return // Don't allow quantity selection without time slot } if (ticketInstance) { handleTicketSelect(ticketInstance.id, quantity) } } const symbol = _get(event, 'currency.symbol') const priceSymbol = currencySymbol || symbol return ( } showToolbar={false} componentsProps={{ actionBar: { actions: [] } }} disablePast /> {loading ? ( ) : ( {!hideTicketsHeader && ticketsHeaderComponent} {uniqueTickets.map(({ ticket, availableTimeSlots }) => { const ticketKey = `${ticket.displayName || ticket.name}_${ticket.price}` const isSoldOut = ticket.sold_out || !(ticket.displayTicket || ticket.slotGroupId) || ticket.soldOut return ( ) })} )} ) } export default TimeSlotsSection