feat: thêm tính năng tìm tôi để tự động di chuyển bản đồ về vị trí của người dùng
This commit is contained in:
@@ -27,6 +27,7 @@ import {
|
|||||||
Map as MapIconLucide,
|
Map as MapIconLucide,
|
||||||
MapPin,
|
MapPin,
|
||||||
Search,
|
Search,
|
||||||
|
LocateFixed,
|
||||||
Loader2,
|
Loader2,
|
||||||
Car,
|
Car,
|
||||||
Bike,
|
Bike,
|
||||||
@@ -87,6 +88,16 @@ const MapTourBounds = ({ locations }: { locations: any[] }) => {
|
|||||||
|
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
// Component Helper để di chuyển tâm bản đồ về vị trí người dùng khi nhấn nút
|
||||||
|
const RecenterUser = ({ position, trigger }: { position: [number, number] | null, trigger: number }) => {
|
||||||
|
const map = useMap();
|
||||||
|
useEffect(() => {
|
||||||
|
if (position && trigger > 0) {
|
||||||
|
map.setView(position, 16, { animate: true });
|
||||||
|
}
|
||||||
|
}, [trigger, position, map]);
|
||||||
|
return null;
|
||||||
|
};
|
||||||
// Menu ngữ cảnh cho bản đồ
|
// Menu ngữ cảnh cho bản đồ
|
||||||
const MapContextMenu = ({ onAction }: { onAction: (action: string, latlng: L.LatLng) => void }) => {
|
const MapContextMenu = ({ onAction }: { onAction: (action: string, latlng: L.LatLng) => void }) => {
|
||||||
const [menuPos, setMenuPos] = useState<{ x: number, y: number, latlng: L.LatLng } | null>(null);
|
const [menuPos, setMenuPos] = useState<{ x: number, y: number, latlng: L.LatLng } | null>(null);
|
||||||
@@ -297,6 +308,7 @@ export const TourDetailPage = ({
|
|||||||
const [searchQuery, setSearchQuery] = useState('');
|
const [searchQuery, setSearchQuery] = useState('');
|
||||||
const [searchResults, setSearchResults] = useState<any[]>([]);
|
const [searchResults, setSearchResults] = useState<any[]>([]);
|
||||||
const [isSearching, setIsSearching] = useState(false);
|
const [isSearching, setIsSearching] = useState(false);
|
||||||
|
const [locateTrigger, setLocateTrigger] = useState(0);
|
||||||
const [isRoutingLoading, setIsRoutingLoading] = useState(false);
|
const [isRoutingLoading, setIsRoutingLoading] = useState(false);
|
||||||
const [travelMode, setTravelMode] = useState<'driving' | 'bike' | 'foot'>('driving');
|
const [travelMode, setTravelMode] = useState<'driving' | 'bike' | 'foot'>('driving');
|
||||||
const [routes, setRoutes] = useState<any[]>([]);
|
const [routes, setRoutes] = useState<any[]>([]);
|
||||||
@@ -1202,6 +1214,9 @@ export const TourDetailPage = ({
|
|||||||
{/* Tự động đóng khung Start và End khi dữ liệu thay đổi */}
|
{/* Tự động đóng khung Start và End khi dữ liệu thay đổi */}
|
||||||
<MapTourBounds locations={allLocations} />
|
<MapTourBounds locations={allLocations} />
|
||||||
|
|
||||||
|
{/* Xử lý di chuyển tâm bản đồ về phía người dùng */}
|
||||||
|
<RecenterUser position={userLocation} trigger={locateTrigger} />
|
||||||
|
|
||||||
{/* Hiển thị vị trí hiện tại của người dùng */}
|
{/* Hiển thị vị trí hiện tại của người dùng */}
|
||||||
{userLocation && (
|
{userLocation && (
|
||||||
<Marker position={userLocation} icon={mapIcons.user} zIndexOffset={1000}>
|
<Marker position={userLocation} icon={mapIcons.user} zIndexOffset={1000}>
|
||||||
@@ -1386,6 +1401,16 @@ export const TourDetailPage = ({
|
|||||||
>
|
>
|
||||||
<Footprints className="w-4 h-4" />
|
<Footprints className="w-4 h-4" />
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
{/* Nút Tìm tôi */}
|
||||||
|
<button
|
||||||
|
onClick={() => setLocateTrigger(prev => prev + 1)}
|
||||||
|
disabled={!userLocation}
|
||||||
|
className={`p-2.5 rounded-xl transition-all border-t border-gray-100 mt-1 ${!userLocation ? 'opacity-30 cursor-not-allowed' : 'text-blue-600 hover:bg-blue-50'}`}
|
||||||
|
title="Vị trí của tôi"
|
||||||
|
>
|
||||||
|
<LocateFixed className="w-4 h-4" />
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Chỉ báo đang tìm đường */}
|
{/* Chỉ báo đang tìm đường */}
|
||||||
|
|||||||
Reference in New Issue
Block a user