diff --git a/frontend/src/components/AddLocationModal.tsx b/frontend/src/components/AddLocationModal.tsx index 76b4c0d..ae3617a 100644 --- a/frontend/src/components/AddLocationModal.tsx +++ b/frontend/src/components/AddLocationModal.tsx @@ -1,7 +1,7 @@ -import React, { useState, useEffect, useRef } from 'react'; +import React, { useState, useEffect, useRef, useMemo } from 'react'; import { format, parseISO } from 'date-fns'; import { X, MapPin, Loader2, Clock, Map as MapIcon, Navigation, Search } from 'lucide-react'; -import { useTourStore } from '@/store/useTourStore.js'; +import { useTourStore } from '@/store/useTourStore'; import { MapContainer, TileLayer, Marker, useMapEvents, useMap } from 'react-leaflet'; import L from 'leaflet'; @@ -79,6 +79,7 @@ export const AddLocationModal = ({ isOpen, onClose, tourId, initialLegId, editin }); const [isLoading, setIsLoading] = useState(false); const [searchResults, setSearchResults] = useState([]); + const [hasNoResults, setHasNoResults] = useState(false); const [isSearching, setIsSearching] = useState(false); const searchTimeout = useRef(null); @@ -121,6 +122,12 @@ export const AddLocationModal = ({ isOpen, onClose, tourId, initialLegId, editin } }, [initialLegId, editingLocation, isOpen]); + // Memoize tọa độ để tránh việc bản đồ tự động reset tâm khi re-render (ví dụ khi gõ tìm kiếm) + const currentCoords = useMemo<[number, number]>( + () => [formData.latitude, formData.longitude], + [formData.latitude, formData.longitude] + ); + // Tự động cập nhật vị trí bản đồ theo chặng được chọn (Lấy điểm cuối của chặng đó làm tham chiếu) useEffect(() => { if (isOpen && !editingLocation && formData.legId && !formData.name) { @@ -155,15 +162,23 @@ export const AddLocationModal = ({ isOpen, onClose, tourId, initialLegId, editin if (query.trim().length < 2) { setSearchResults([]); setIsSearching(false); + setHasNoResults(false); return; } setIsSearching(true); + setHasNoResults(false); searchTimeout.current = setTimeout(async () => { try { - const res = await fetch(`https://nominatim.openstreetmap.org/search?format=json&q=${encodeURIComponent(query)}&limit=8&addressdetails=1&accept-language=vi`); + // Loại bỏ countrycodes=vn để tìm kiếm rộng hơn, thêm namedetails=1 để lấy tên chính xác + const res = await fetch(`https://nominatim.openstreetmap.org/search?format=json&q=${encodeURIComponent(query)}&limit=15&addressdetails=1&namedetails=1&accept-language=vi`, { + headers: { + 'Accept-Language': 'vi' + } + }); const data = await res.json(); setSearchResults(data); + setHasNoResults(data.length === 0); } catch (e) { console.error("Lỗi tìm kiếm địa điểm:", e); } finally { @@ -175,9 +190,12 @@ export const AddLocationModal = ({ isOpen, onClose, tourId, initialLegId, editin const selectSearchResult = (result: any) => { const lat = parseFloat(result.lat); const lon = parseFloat(result.lon); + // Ưu tiên lấy tên từ namedetails nếu có, nếu không lấy phần đầu của display_name + const locationName = result.namedetails?.name || result.display_name.split(',')[0]; + setFormData(prev => ({ ...prev, - name: result.display_name.split(',')[0], + name: locationName, address: result.display_name, latitude: lat, longitude: lon @@ -297,10 +315,10 @@ export const AddLocationModal = ({ isOpen, onClose, tourId, initialLegId, editin {/* Mini Map Picker */}
- + - - + +
CHUỘT PHẢI ĐỂ CHỌN VỊ TRÍ @@ -318,7 +336,7 @@ export const AddLocationModal = ({ isOpen, onClose, tourId, initialLegId, editin )} -
setSearchResults([])}> +
@@ -333,7 +351,7 @@ export const AddLocationModal = ({ isOpen, onClose, tourId, initialLegId, editin {isSearching ? ( ) : formData.name ? ( - ) : ( @@ -342,19 +360,32 @@ export const AddLocationModal = ({ isOpen, onClose, tourId, initialLegId, editin
- {searchResults.length > 0 && ( -
- {searchResults.map((result, idx) => ( - - ))} + {(searchResults.length > 0 || hasNoResults) && ( +
+ {hasNoResults ? ( +
+ Không tìm thấy địa điểm nào phù hợp... +
+ ) : ( + searchResults.map((result, idx) => ( + + )) + )}
)}