diff --git a/frontend/src/components/AddLocationModal.tsx b/frontend/src/components/AddLocationModal.tsx index 6ea5c0a..262d918 100644 --- a/frontend/src/components/AddLocationModal.tsx +++ b/frontend/src/components/AddLocationModal.tsx @@ -316,8 +316,61 @@ export const AddLocationModal = ({ isOpen, onClose, tourId, initialLegId, editin {/* Mini Map Picker */} -
- +
+ {/* Map Search Bar Overlay - Tích hợp tìm kiếm trực tiếp trên bản đồ */} +
+
+
+ handleSearchLocation(e.target.value)} + /> + + {isSearching ? ( + + ) : formData.name && ( + + )} +
+ + {/* Dropdown kết quả tìm kiếm ngay trong khung bản đồ */} + {(searchResults.length > 0 || hasNoResults) && ( +
+ {hasNoResults ? ( +
Không tìm thấy địa điểm phù hợp...
+ ) : ( + searchResults.map((result, idx) => ( + + )) + )} +
+ )} +
+
+ + @@ -339,57 +392,15 @@ export const AddLocationModal = ({ isOpen, onClose, tourId, initialLegId, editin )}
-
+
-
- handleSearchLocation(e.target.value)} - /> -
- {isSearching ? ( - - ) : formData.name ? ( - - ) : ( - - )} -
-
- - {(searchResults.length > 0 || hasNoResults) && ( -
- {hasNoResults ? ( -
- Không tìm thấy địa điểm nào phù hợp... -
- ) : ( - searchResults.map((result, idx) => ( - - )) - )} -
- )} + setFormData({...formData, name: e.target.value})} + />
diff --git a/frontend/src/pages/TourDetailPage.tsx b/frontend/src/pages/TourDetailPage.tsx index b6a709d..787f09a 100644 --- a/frontend/src/pages/TourDetailPage.tsx +++ b/frontend/src/pages/TourDetailPage.tsx @@ -24,6 +24,8 @@ import { List, Map as MapIconLucide, MapPin, + Search, + Loader2, Flag, Clock, Check, @@ -198,6 +200,29 @@ export const TourDetailPage = ({ onBack, tourId, isPublicView = false }: { onBac const [commentLocationName, setCommentLocationName] = useState(''); const [joinRequestActionId, setJoinRequestActionId] = useState(null); + // State tìm kiếm cho chế độ Bản đồ trong Tab Lộ trình + const [searchQuery, setSearchQuery] = useState(''); + const [searchResults, setSearchResults] = useState([]); + const [isSearching, setIsSearching] = useState(false); + + const handleSearchLocation = async (query: string) => { + setSearchQuery(query); + if (query.trim().length < 2) { + setSearchResults([]); + return; + } + setIsSearching(true); + try { + const res = await fetch(`https://nominatim.openstreetmap.org/search?format=json&q=${encodeURIComponent(query)}&limit=5&addressdetails=1&namedetails=1&accept-language=vi`); + const data = await res.json(); + setSearchResults(data); + } catch (e) { + console.error("Lỗi tìm kiếm:", e); + } finally { + setIsSearching(false); + } + }; + const fetchTour = useTourStore(state => state.fetchTour); const fetchPublicTourDetails = useTourStore(state => state.fetchPublicTourDetails); // New action @@ -803,6 +828,53 @@ export const TourDetailPage = ({ onBack, tourId, isPublicView = false }: { onBac }} isPublicView={isPublicView} /> ) : (
+ {/* Search Bar Overlay - Thanh tìm kiếm địa điểm trên bản đồ lộ trình */} + {!isPublicView && ( +
+
+ handleSearchLocation(e.target.value)} + /> + + {isSearching ? ( + + ) : searchQuery && ( + + )} + + {/* Kết quả tìm kiếm */} + {searchResults.length > 0 && ( +
+ {searchResults.map((result, idx) => ( + + ))} +
+ )} +
+
+ )}