/** * Modal to add a restaurant concept. Used from Property Management (Dining, Venues & Amenities). * - Textbox filters over existing concept names (from all properties); user can select if available. * - If not found, user can proceed to create/add a new concept for this property. * onSave(name, propertyCode) — propertyCode required when adding from a property context. */ const RestaurantModal = ({ onSave, onClose, saving, propertyCode }) => { const { useState, useEffect, useRef } = React; const [inputValue, setInputValue] = useState(''); const [suggestions, setSuggestions] = useState([]); const [loadingSuggestions, setLoadingSuggestions] = useState(false); const [selectedSuggestion, setSelectedSuggestion] = useState(null); // { name } when user picked from list const [showDropdown, setShowDropdown] = useState(false); const dropdownRef = useRef(null); // Debounced fetch of concept names (skip when user just selected a suggestion so dropdown doesn't re-open) useEffect(() => { if (!inputValue.trim()) { setSuggestions([]); setShowDropdown(false); return; } if (selectedSuggestion && inputValue.trim() === selectedSuggestion.name) { setSuggestions([]); setShowDropdown(false); return; } const t = setTimeout(async () => { setLoadingSuggestions(true); try { const q = encodeURIComponent(inputValue.trim()); const res = await fetch(`/api/restaurants/concept-names?q=${q}&limit=15`, { headers: window.getApiHeaders ? window.getApiHeaders() : { 'X-OTO-User': window.localStorage.getItem('oto_username') || '' } }); if (res.ok) { const data = await res.json(); const names = data.concept_names || []; setSuggestions(names); setShowDropdown(names.length > 0); } else { setSuggestions([]); } } catch (err) { setSuggestions([]); } finally { setLoadingSuggestions(false); } }, 200); return () => clearTimeout(t); }, [inputValue, selectedSuggestion]); // Click outside to close dropdown useEffect(() => { const handleClickOutside = (e) => { if (dropdownRef.current && !dropdownRef.current.contains(e.target)) { setShowDropdown(false); } }; document.addEventListener('mousedown', handleClickOutside); return () => document.removeEventListener('mousedown', handleClickOutside); }, []); const handleSelectSuggestion = (name) => { setInputValue(name); setSelectedSuggestion({ name }); setShowDropdown(false); setSuggestions([]); }; const handleSubmit = (e) => { e.preventDefault(); const trimmed = (inputValue || '').trim(); if (!trimmed || !propertyCode) return; onSave(trimmed, propertyCode); setInputValue(''); setSelectedSuggestion(null); }; const displayValue = selectedSuggestion ? selectedSuggestion.name : inputValue; const canCreate = (inputValue || '').trim().length > 0; return (
e.stopPropagation()}>

Add Dining Brand

Type to search existing dining brands or enter a new name to create one for this property.

{ setInputValue(e.target.value); setSelectedSuggestion(null); }} onFocus={() => suggestions.length > 0 && setShowDropdown(true)} placeholder="Search or enter dining brand name" className="w-full border border-gray-300 rounded-lg px-4 py-2 mb-1 focus:ring-2 focus:ring-primary focus:border-primary" autoFocus /> {loadingSuggestions && (
)} {showDropdown && suggestions.length > 0 && (
    {suggestions.map((name) => (
  • handleSelectSuggestion(name)} className="px-4 py-2 cursor-pointer hover:bg-primary/10 text-gray-900" > {name}
  • ))}
)}
); }; if (typeof window !== 'undefined') window.RestaurantModal = RestaurantModal;