Chỉnh sửa giao diện Tour Dashboard
This commit is contained in:
Vendored
+19
-4
@@ -1,6 +1,6 @@
|
||||
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
||||
import { useEffect, useState } from 'react';
|
||||
import { MapContainer, TileLayer, Marker, Popup, useMap } from 'react-leaflet';
|
||||
import { MapContainer, TileLayer, Marker, Popup, useMap, useMapEvents } from 'react-leaflet';
|
||||
import L from 'leaflet';
|
||||
import 'leaflet/dist/leaflet.css';
|
||||
import { useTourStore } from './useTourStore.js';
|
||||
@@ -21,14 +21,29 @@ function RecenterMap({ position }) {
|
||||
}, [position, map]);
|
||||
return null;
|
||||
}
|
||||
function MapTracker() {
|
||||
const setMapCenter = useTourStore(state => state.setMapCenter);
|
||||
useMapEvents({
|
||||
moveend: (e) => {
|
||||
const map = e.target;
|
||||
const center = map.getCenter();
|
||||
setMapCenter([center.lat, center.lng]);
|
||||
},
|
||||
});
|
||||
return null;
|
||||
}
|
||||
export const ExploreMap = ({ onBack, onLogout, user, onViewTour }) => {
|
||||
const { publicTours, fetchPublicTours, fetchTour, updateTour, deleteTour } = useTourStore();
|
||||
const { publicTours, fetchPublicTours, fetchTour, updateTour, deleteTour, mapCenter, setMapCenter } = useTourStore();
|
||||
const [userPos, setUserPos] = useState([10.7769, 106.7009]);
|
||||
const [isAdminModalOpen, setIsAdminModalOpen] = useState(false);
|
||||
const [isCreateModalOpen, setIsCreateModalOpen] = useState(false);
|
||||
useEffect(() => {
|
||||
fetchPublicTours();
|
||||
navigator.geolocation.getCurrentPosition((pos) => setUserPos([pos.coords.latitude, pos.coords.longitude]), () => console.log("Không thể lấy vị trí người dùng"));
|
||||
navigator.geolocation.getCurrentPosition((pos) => {
|
||||
const posArray = [pos.coords.latitude, pos.coords.longitude];
|
||||
setUserPos(posArray);
|
||||
setMapCenter(posArray);
|
||||
}, () => console.log("Không thể lấy vị trí người dùng"));
|
||||
}, []);
|
||||
const handleEditTour = async (tour) => {
|
||||
const newTitle = window.prompt("Nhập tên mới cho Tour:", tour.title);
|
||||
@@ -51,7 +66,7 @@ export const ExploreMap = ({ onBack, onLogout, user, onViewTour }) => {
|
||||
}
|
||||
}
|
||||
};
|
||||
return (_jsxs("div", { className: "h-screen w-full relative", children: [_jsx("button", { onClick: onBack, className: "absolute top-6 left-6 z-[1000] bg-white p-3 rounded-full shadow-xl hover:bg-gray-50 transition-all", children: _jsx(X, { className: "w-6 h-6 text-gray-800" }) }), onLogout && (_jsxs("button", { onClick: onLogout, className: "absolute top-6 right-6 z-[1000] bg-white px-4 py-3 rounded-2xl shadow-xl hover:bg-red-50 hover:text-red-600 transition-all flex items-center gap-2 font-bold text-gray-700", children: [_jsx(LogOut, { className: "w-5 h-5" }), _jsx("span", { className: "hidden sm:inline", children: "\u0110\u0103ng xu\u1EA5t" })] })), user?.isAdmin && (_jsxs("button", { onClick: () => setIsAdminModalOpen(true), className: "absolute top-6 right-40 z-[1000] bg-blue-600 px-4 py-3 rounded-2xl shadow-xl hover:bg-blue-700 text-white transition-all flex items-center gap-2 font-bold", children: [_jsx(Settings, { className: "w-5 h-5" }), _jsx("span", { className: "hidden sm:inline", children: "Qu\u1EA3n l\u00FD h\u1EC7 th\u1ED1ng" })] })), user && (_jsxs("button", { onClick: () => setIsCreateModalOpen(true), className: "absolute top-6 right-80 z-[1000] bg-green-600 px-4 py-3 rounded-2xl shadow-xl hover:bg-green-700 text-white transition-all flex items-center gap-2 font-bold", children: [_jsx(Navigation, { className: "w-5 h-5" }), _jsx("span", { className: "hidden sm:inline", children: "T\u1EA1o Tour m\u1EDBi" })] })), _jsx("div", { className: "absolute top-6 left-20 z-[1000] bg-white/90 backdrop-blur-md px-6 py-3 rounded-2xl shadow-xl border border-white/20 hidden sm:block", children: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Navigation, { className: "w-4 h-4 text-blue-600" }), _jsx("span", { className: "font-bold text-gray-800", children: "\u0110ang kh\u00E1m ph\u00E1 khu v\u1EF1c c\u1EE7a b\u1EA1n" })] }) }), _jsxs(MapContainer, { center: userPos, zoom: 13, className: "h-full w-full", children: [_jsx(TileLayer, { url: "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", attribution: '\u00A9 OpenStreetMap contributors' }), _jsx(RecenterMap, { position: userPos }), publicTours.map((tour) => {
|
||||
return (_jsxs("div", { className: "h-screen w-full relative", children: [_jsx("button", { onClick: onBack, className: "absolute top-6 left-6 z-[1000] bg-white p-3 rounded-full shadow-xl hover:bg-gray-50 transition-all", children: _jsx(X, { className: "w-6 h-6 text-gray-800" }) }), onLogout && (_jsxs("button", { onClick: onLogout, className: "absolute top-6 right-6 z-[1000] bg-white px-4 py-3 rounded-2xl shadow-xl hover:bg-red-50 hover:text-red-600 transition-all flex items-center gap-2 font-bold text-gray-700", children: [_jsx(LogOut, { className: "w-5 h-5" }), _jsx("span", { className: "hidden sm:inline", children: "\u0110\u0103ng xu\u1EA5t" })] })), user?.isAdmin && (_jsxs("button", { onClick: () => setIsAdminModalOpen(true), className: "absolute top-6 right-40 z-[1000] bg-blue-600 px-4 py-3 rounded-2xl shadow-xl hover:bg-blue-700 text-white transition-all flex items-center gap-2 font-bold", children: [_jsx(Settings, { className: "w-5 h-5" }), _jsx("span", { className: "hidden sm:inline", children: "Qu\u1EA3n l\u00FD h\u1EC7 th\u1ED1ng" })] })), user && (_jsxs("button", { onClick: () => setIsCreateModalOpen(true), className: "absolute top-6 right-80 z-[1000] bg-green-600 px-4 py-3 rounded-2xl shadow-xl hover:bg-green-700 text-white transition-all flex items-center gap-2 font-bold", children: [_jsx(Navigation, { className: "w-5 h-5" }), _jsx("span", { className: "hidden sm:inline", children: "T\u1EA1o Tour m\u1EDBi" })] })), _jsx("div", { className: "absolute top-6 left-20 z-[1000] bg-white/90 backdrop-blur-md px-6 py-3 rounded-2xl shadow-xl border border-white/20 hidden sm:block", children: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Navigation, { className: "w-4 h-4 text-blue-600" }), _jsx("span", { className: "font-bold text-gray-800", children: "\u0110ang kh\u00E1m ph\u00E1 khu v\u1EF1c c\u1EE7a b\u1EA1n" })] }) }), _jsxs(MapContainer, { center: mapCenter, zoom: 13, className: "h-full w-full", children: [_jsx(TileLayer, { url: "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", attribution: '\u00A9 OpenStreetMap contributors' }), _jsx(MapTracker, {}), _jsx(RecenterMap, { position: userPos }), publicTours.map((tour) => {
|
||||
const location = tour.legs?.[0]?.locations?.[0];
|
||||
if (!location)
|
||||
return null;
|
||||
|
||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+64
-14
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+2
@@ -4,6 +4,7 @@ interface TourState {
|
||||
publicTours: any[];
|
||||
userRole: string | null;
|
||||
activeLegId: string | null;
|
||||
mapCenter: [number, number];
|
||||
setTour: (tour: any) => void;
|
||||
updateLegs: (legs: any[]) => void;
|
||||
createTour: (tourData: any) => Promise<any>;
|
||||
@@ -15,6 +16,7 @@ interface TourState {
|
||||
addLocation: (tourId: string, locationData: any) => Promise<void>;
|
||||
optimizeRouting: (legId: string) => Promise<void>;
|
||||
setActiveLegId: (id: string | null) => void;
|
||||
setMapCenter: (pos: [number, number]) => void;
|
||||
fetchTour: (id: string) => Promise<void>;
|
||||
fetchPublicTours: () => Promise<void>;
|
||||
}
|
||||
|
||||
Vendored
+2
@@ -5,9 +5,11 @@ export const useTourStore = create((set, get) => ({
|
||||
publicTours: [],
|
||||
userRole: null,
|
||||
activeLegId: null,
|
||||
mapCenter: [10.7769, 106.7009],
|
||||
setTour: (tour) => set({ currentTour: tour }),
|
||||
updateLegs: (legs) => set({ legs }),
|
||||
setActiveLegId: (id) => set({ activeLegId: id }),
|
||||
setMapCenter: (pos) => set({ mapCenter: pos }),
|
||||
fetchTour: async (id) => {
|
||||
const API_BASE = `http://${window.location.hostname}:3001`;
|
||||
const response = await fetch(`${API_BASE}/api/v1/tours/${id}`);
|
||||
|
||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user