import { useRef, useEffect, useMemo, useState } from 'react' import { __ } from '@wordpress/i18n' import classNames from 'classnames' import { useBookingContext } from '../../providers/BookingFormProvider/BookingFormProvider' import { getPlainTextFromHtml } from '../../lib/utils' import { getServiceAssociatedLocations } from '../../lib/locationFilter/getServiceAssociatedLocations' import { ILocationOption } from './types' import './LocationDropdown.scss' const MapPinIcon = () => ( ) const ChevronDownIcon = () => ( ) const LocationCard = ({ option, isSelected, onClick, }: { option: ILocationOption isSelected?: boolean onClick: () => void }) => { const descriptionText = option.description ? getPlainTextFromHtml(option.description) : '' return (
{option.label} {descriptionText && ( {descriptionText} )}
) } interface LocationDropdownProps { locations?: ILocationOption[] | null } export const LocationDropdown = ({ locations: locationsOverride = undefined, }: LocationDropdownProps = {}) => { const { bookingMode, preset, formData, onLocationSelect, extractedAttrLocations } = useBookingContext() const wording = preset?.wording ?? {} const allLocations: ILocationOption[] = useMemo(() => { const raw = (preset?.locations ?? []) as ILocationOption[] const linkedEntities = bookingMode === 'units' ? ((preset?.units ?? []) as Array<{ locations?: any[] }>) : ((preset?.services ?? []) as Array<{ locations?: any[] }>) return getServiceAssociatedLocations(raw, linkedEntities) }, [bookingMode, preset?.locations, preset?.services, preset?.units]) const baseLocations = extractedAttrLocations.length > 0 ? allLocations.filter( (loc) => extractedAttrLocations.includes(String(loc.id)) || extractedAttrLocations.includes(String(loc.value)) ) : allLocations const locations: ILocationOption[] = locationsOverride ?? baseLocations const selectedId = formData?.location != null ? String(formData.location) : '' const selected = locations.find( (loc) => String(loc.id) === selectedId || String(loc.value) === selectedId ) const [isOpen, setIsOpen] = useState(false) const wrapperRef = useRef(null) useEffect(() => { const handleClickOutside = (event: MouseEvent) => { if (wrapperRef.current && !wrapperRef.current.contains(event.target as Node)) { setIsOpen(false) } } document.addEventListener('mousedown', handleClickOutside) return () => document.removeEventListener('mousedown', handleClickOutside) }, []) const displayLabel = selected?.label ?? wording.select_location ?? __('Select location', 'webba-booking-lite') const displayDescription = selected?.description ? getPlainTextFromHtml(selected.description) : '' return (
setIsOpen((prev) => !prev)} aria-expanded={isOpen} aria-haspopup="listbox" aria-label={wording.location ?? __('Location', 'webba-booking-lite')} > {displayLabel} {displayDescription && ( {displayDescription} )}
{isOpen && (
{locations.map((option) => (
{ onLocationSelect(option.id) setIsOpen(false) }} />
))}
)}
) }