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)
}}
/>
))}
)}
)
}