From 90475d4130fbff2bcb0ab1fe0c340b7570089843 Mon Sep 17 00:00:00 2001 From: 3dtours Date: Thu, 25 Jun 2026 11:58:32 +0700 Subject: [PATCH] =?UTF-8?q?fix:=20Ng=C4=83n=20b=E1=BA=A3n=20=C4=91?= =?UTF-8?q?=E1=BB=93=20ExploreMap=20t=E1=BB=B1=20=C4=91=E1=BB=99ng=20nh?= =?UTF-8?q?=E1=BA=A3y=20v=E1=BB=81=20v=E1=BB=8B=20tr=C3=AD=20ng=C6=B0?= =?UTF-8?q?=E1=BB=9Di=20d=C3=B9ng=20khi=20thay=20=C4=91=E1=BB=95i=20zoom?= =?UTF-8?q?=20tr=C3=AAn=20mobile?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Tách userPos (dùng cho marker) và mapCenter (dùng cho center bản đồ) thành 2 state riêng biệt - MapContainer dùng center={mapCenter} cố định thay vì center={userPos} bị GPS thay đổi liên tục - Xóa component RecenterMap tự động re-center khi userPos thay đổi - Thêm nút 'Vị trí của tôi' để người dùng chủ động nhấn mới nhảy bản đồ đến vị trí của mình - requestGpsPosition cập nhật cả mapCenter lẫn store để map thực sự nhảy khi người dùng chủ động yêu cầu - Các thao tác khác như click gợi ý tìm kiếm, click ảnh trên bản đồ cũng cập nhật mapCenter để map nhảy đúng vị trí - Áp dụng cho ExploreMap.tsx - bản đồ chính khi người dùng mở app --- frontend/src/pages/ExploreMap.tsx | 71 ++++++++++++++++++++++--------- 1 file changed, 50 insertions(+), 21 deletions(-) diff --git a/frontend/src/pages/ExploreMap.tsx b/frontend/src/pages/ExploreMap.tsx index 59f373a..2eb4d97 100644 --- a/frontend/src/pages/ExploreMap.tsx +++ b/frontend/src/pages/ExploreMap.tsx @@ -39,15 +39,6 @@ const PHOTO_TAG_LABELS: { [key: string]: string } = { 'thu-cung': '🐕 Thú cưng' }; -// Component Helper để cập nhật tâm bản đồ khi vị trí người dùng thay đổi -function RecenterMap({ position }: { position: [number, number] }) { - const map = useMap(); - useEffect(() => { - map.setView(position, map.getZoom()); - }, [position, map]); - return null; -} - // Component Helper để đóng menu khi tương tác với bản đồ function MapEvents({ onMapAction }: { onMapAction: () => void }) { useMapEvents({ @@ -202,7 +193,11 @@ export const ExploreMap = ({ onBack, onLogout, user, onViewTour, onOpenMyPhotos, return null; }); - const [userPos, setUserPos] = useState<[number, number]>(initialViewState?.center || [10.7769, 106.7009]); + // Map dùng center cố định để không bị GPS tự nhảy vị trí người dùng + const defaultCenter = initialViewState?.center || [10.7769, 106.7009]; + + const [userPos, setUserPos] = useState<[number, number]>(defaultCenter); + const [mapCenter, setLocalMapCenter] = useState<[number, number]>(initialViewState?.center || defaultCenter); const [mapZoom] = useState(initialViewState?.zoom || 13); const [publicPhotos, setPublicPhotos] = useState([]); const [selectedPhoto, setSelectedPhoto] = useState(null); @@ -262,7 +257,7 @@ export const ExploreMap = ({ onBack, onLogout, user, onViewTour, onOpenMyPhotos, const [blacklist, setBlacklist] = useState([]); const [isReportModalOpen, setIsReportModalOpen] = useState(false); const [isBlacklistOpen, setIsBlacklistOpen] = useState(false); - const mapCenter = useTourStore(state => state.mapCenter); + const storeMapCenter = useTourStore(state => state.mapCenter); // Recommendations and GPS States const [recommendedLocations, setRecommendedLocations] = useState([]); @@ -342,6 +337,7 @@ export const ExploreMap = ({ onBack, onLogout, user, onViewTour, onOpenMyPhotos, const posArray: [number, number] = [pos.coords.latitude, pos.coords.longitude]; setUserGpsPos(posArray); setUserPos(posArray); + setLocalMapCenter(posArray); setMapCenter(posArray); }, () => { @@ -435,7 +431,28 @@ export const ExploreMap = ({ onBack, onLogout, user, onViewTour, onOpenMyPhotos, fetchTrustedUsers(); fetchBlacklist(); fetchRecommendations(); + // Luôn tải danh sách ảnh công khai để hiển thị trên bản đồ cho tất cả mọi người + fetchPublicPhotos(); + + // Chỉ tải danh sách tour khi người dùng đã đăng nhập và có token + if (user || localStorage.getItem('token')) { + fetchPublicTours(); + } }, []); + + // Chỉ lấy vị trí GPS ban đầu để hiển thị marker, KHÔNG tự động nhảy bản đồ đến vị trí đó + // Người dùng phải chủ động nhấn nút định vị mới nhảy bản đồ đến vị trí của mình + useEffect(() => { + if (!initialViewState && navigator.geolocation) { + navigator.geolocation.getCurrentPosition( + (pos) => { + const posArray: [number, number] = [pos.coords.latitude, pos.coords.longitude]; + setUserPos(posArray); + }, + () => console.log("Không thể lấy vị trí người dùng") + ); + } + }, [initialViewState]); const [isFilterDropdownOpen, setIsFilterDropdownOpen] = useState(false); // State để điều khiển hiển thị dropdown lọc const [searchQuery, setSearchQuery] = useState(''); // State cho giá trị tìm kiếm const [suggestions, setSuggestions] = useState<{ type: 'tour' | 'location', id: string, name: string, lat?: number, lon?: number }[]>([]); @@ -576,6 +593,7 @@ export const ExploreMap = ({ onBack, onLogout, user, onViewTour, onOpenMyPhotos, } else if (s.lat && s.lon) { const pos: [number, number] = [s.lat, s.lon]; setUserPos(pos); + setLocalMapCenter(pos); setMapCenter(pos); notify({ title: 'Tìm thấy địa điểm', @@ -783,6 +801,18 @@ export const ExploreMap = ({ onBack, onLogout, user, onViewTour, onOpenMyPhotos, {/* Nhóm bên phải: Các thao tác người dùng */}
+ {/* Nút định vị người dùng */} + + {/* Nút Ảnh của tôi */} {isLoggedInOrGuest && (
- + @@ -905,9 +935,6 @@ export const ExploreMap = ({ onBack, onLogout, user, onViewTour, onOpenMyPhotos, {/* Đóng menu và dropdown khi tương tác bản đồ */} { setShareMenu(null); setSuggestions([]); setIsFilterDropdownOpen(false); }} /> - - {/* Tự động di chuyển bản đồ đến vị trí người dùng khi tìm thấy tọa độ */} - {filteredTours.map((tour) => { @@ -1403,6 +1430,7 @@ export const ExploreMap = ({ onBack, onLogout, user, onViewTour, onOpenMyPhotos,