feat: nhấn nút toggle status full bản đồ, nhấn nút bản đồ thì giao diện cũ
This commit is contained in:
@@ -363,6 +363,7 @@ export const TourDetailPage = ({
|
||||
const [activeTab, setActiveTab] = useState<'plan' | 'expense' | 'photo' | 'settings'>('plan');
|
||||
const [viewMode, setViewMode] = useState<'map' | 'timeline'>('timeline');
|
||||
const [isAddLocationOpen, setIsAddLocationOpen] = useState(false);
|
||||
const [isMapFullscreen, setIsMapFullscreen] = useState(false);
|
||||
const [isAddMemberOpen, setIsAddMemberOpen] = useState(false);
|
||||
const [isAddPhotoOpen, setIsAddPhotoOpen] = useState(false);
|
||||
const [isStartPointAction, setIsStartPointAction] = useState(false);
|
||||
@@ -749,9 +750,9 @@ export const TourDetailPage = ({
|
||||
}, [routes, selectedRouteIndex]);
|
||||
|
||||
const handleNavigateToLocation = (location: any) => {
|
||||
setViewMode('map');
|
||||
setMapCenter([location.latitude, location.longitude]);
|
||||
setLocateTrigger(prev => prev + 1);
|
||||
setIsMapFullscreen(true);
|
||||
|
||||
notify({
|
||||
title: 'Bắt đầu chỉ đường',
|
||||
@@ -1393,19 +1394,10 @@ export const TourDetailPage = ({
|
||||
onNavigate={handleNavigateToLocation}
|
||||
/>
|
||||
) : (
|
||||
<div className="fixed inset-0 z-[2000] bg-white animate-in fade-in duration-500">
|
||||
{/* Nút X để quay lại từ chế độ bản đồ toàn màn hình */}
|
||||
<button
|
||||
onClick={() => setViewMode('timeline')}
|
||||
className="absolute top-4 left-4 z-[1002] w-11 h-11 bg-white/90 backdrop-blur-md rounded-full shadow-2xl flex items-center justify-center border border-white/20 hover:bg-white transition-all active:scale-95 group"
|
||||
title="Quay lại danh sách"
|
||||
>
|
||||
<X className="w-6 h-6 text-gray-800 group-hover:rotate-90 transition-transform duration-300" />
|
||||
</button>
|
||||
|
||||
<div className="h-[60vh] w-full rounded-3xl overflow-hidden shadow-xl border-4 border-white relative animate-in fade-in duration-500">
|
||||
{/* Search Bar Overlay - Thanh tìm kiếm địa điểm trên bản đồ lộ trình */}
|
||||
{!isPublicView && (
|
||||
<div className="absolute top-4 right-4 z-[1001] w-48 md:w-64">
|
||||
<div className="absolute top-3 right-3 z-[1001] w-48 md:w-64">
|
||||
<div className="relative group">
|
||||
<input
|
||||
type="text"
|
||||
@@ -1453,14 +1445,14 @@ export const TourDetailPage = ({
|
||||
|
||||
{/* Overlay thông tin lộ trình đề xuất (Lộ trình thông dụng nhất) */}
|
||||
{selectedRouteInfo && drivingRoute.length > 0 && (
|
||||
<div className="absolute top-4 left-1/2 -translate-x-1/2 z-[1001] bg-white/20 backdrop-blur-lg px-6 py-2.5 rounded-full border border-white/30 flex items-center gap-4 animate-in fade-in slide-in-from-top-2 duration-500 shadow-xl">
|
||||
<div className="absolute top-3 left-1/2 -translate-x-1/2 z-[1001] bg-white/80 backdrop-blur-md px-4 py-2 rounded-2xl shadow-xl border border-white flex items-center gap-3 animate-in fade-in slide-in-from-top-2 duration-500">
|
||||
<div className="flex items-center gap-2">
|
||||
<Navigation className="w-4 h-4 text-blue-600 rotate-45 fill-blue-600" />
|
||||
<span className="text-[11px] font-black text-gray-700 uppercase tracking-widest">{selectedRouteInfo.label}</span>
|
||||
<Navigation className="w-3.5 h-3.5 text-blue-600 rotate-45" />
|
||||
<span className="text-[10px] font-black text-gray-400 uppercase tracking-tighter">{selectedRouteInfo.label}</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-3 text-sm font-black text-blue-700 whitespace-nowrap">
|
||||
<div className="flex items-center gap-2 text-xs font-bold text-blue-700 whitespace-nowrap">
|
||||
<span>{selectedRouteInfo.distance} km</span>
|
||||
<span className="text-gray-400 opacity-40">•</span>
|
||||
<span className="text-gray-300">•</span>
|
||||
<span>{selectedRouteInfo.duration}</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -2100,6 +2092,95 @@ export const TourDetailPage = ({
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Fullscreen Map Overlay - Hiển thị khi click vào nút trạng thái/chỉ đường */}
|
||||
{isMapFullscreen && (
|
||||
<div className="fixed inset-0 z-[5000] bg-white animate-in fade-in slide-in-from-bottom-16 duration-500">
|
||||
{/* Nút X để quay lại */}
|
||||
<button
|
||||
onClick={() => setIsMapFullscreen(false)}
|
||||
className="absolute top-4 left-4 z-[1002] w-11 h-11 bg-white/90 backdrop-blur-md rounded-full shadow-2xl flex items-center justify-center border border-white/20 hover:bg-white transition-all active:scale-95 group"
|
||||
title="Đóng bản đồ"
|
||||
>
|
||||
<X className="w-6 h-6 text-gray-800 group-hover:rotate-90 transition-transform duration-300" />
|
||||
</button>
|
||||
|
||||
{/* Transparent Top Bar Label - Glassmorphism style */}
|
||||
{selectedRouteInfo && drivingRoute.length > 0 && (
|
||||
<div className="absolute top-4 left-1/2 -translate-x-1/2 z-[1001] bg-white/20 backdrop-blur-lg px-6 py-2.5 rounded-full border border-white/30 flex items-center gap-4 animate-in fade-in slide-in-from-top-2 duration-500 shadow-xl">
|
||||
<div className="flex items-center gap-2">
|
||||
<Navigation className="w-4 h-4 text-blue-600 rotate-45 fill-blue-600" />
|
||||
<span className="text-[11px] font-black text-gray-700 uppercase tracking-widest">{selectedRouteInfo.label}</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-3 text-sm font-black text-blue-700 whitespace-nowrap">
|
||||
<span>{selectedRouteInfo.distance} km</span>
|
||||
<span className="text-gray-400 opacity-40">•</span>
|
||||
<span>{selectedRouteInfo.duration}</span>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<MapContainer
|
||||
center={mapCenter}
|
||||
zoom={mapZoom}
|
||||
className="h-full w-full"
|
||||
preferCanvas={true}
|
||||
>
|
||||
<TileLayer url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" />
|
||||
<MapTourBounds locations={allLocations} />
|
||||
<RecenterUser position={userLocation} trigger={locateTrigger} />
|
||||
<MapRotationHandler rotation={mapRotation} />
|
||||
|
||||
{userLocation && (
|
||||
<Marker position={userLocation} icon={mapIcons.user} />
|
||||
)}
|
||||
|
||||
{routes.length > 0 ? (
|
||||
routes.map((r, i) => (
|
||||
<Polyline
|
||||
key={`fs-poly-${i}`}
|
||||
positions={r.geometry.coordinates.map((c: any) => [c[1], c[0]])}
|
||||
color={i === selectedRouteIndex ? "#2563eb" : "#94a3b8"}
|
||||
weight={i === selectedRouteIndex ? 6 : 4}
|
||||
opacity={i === selectedRouteIndex ? 1 : 0.4}
|
||||
/>
|
||||
))
|
||||
) : allLocations.length > 1 && (
|
||||
<Polyline positions={allLocations.map(l => [l.latitude, l.longitude]) as any} color="#3b82f6" weight={3} dashArray="5, 10" />
|
||||
)}
|
||||
|
||||
{allLocations.map((loc: any, index: number) => {
|
||||
const isStart = startPoint && startPoint.id === loc.id;
|
||||
const isEnd = endPoint && endPoint.id === loc.id;
|
||||
return (
|
||||
<Marker key={`fs-marker-${loc.id}`} position={[loc.latitude, loc.longitude]} icon={isStart ? mapIcons.start : isEnd ? mapIcons.end : mapIcons.visit}>
|
||||
<Popup>
|
||||
<div className="font-bold">{loc.name}</div>
|
||||
</Popup>
|
||||
</Marker>
|
||||
);
|
||||
})}
|
||||
</MapContainer>
|
||||
|
||||
{/* Overlay điều khiển trên bản đồ toàn màn hình */}
|
||||
<div className="absolute top-4 right-4 z-[1001] flex flex-col gap-2">
|
||||
<button
|
||||
onClick={() => setIsMapControlsOpen(!isMapControlsOpen)}
|
||||
className="w-11 h-11 bg-white/90 backdrop-blur-md rounded-2xl shadow-xl border border-white text-blue-600 flex items-center justify-center transition-all active:scale-95"
|
||||
>
|
||||
{travelMode === 'driving' ? <Car className="w-5 h-5" /> : travelMode === 'bike' ? <Bike className="w-5 h-5" /> : <Footprints className="w-5 h-5" />}
|
||||
</button>
|
||||
|
||||
{isMapControlsOpen && (
|
||||
<div className="bg-white/90 backdrop-blur-md p-1.5 rounded-2xl shadow-xl border border-white flex flex-col gap-1.5 animate-in slide-in-from-top-2">
|
||||
<button onClick={() => { setTravelMode('driving'); setIsMapControlsOpen(false); }} className={`w-9 h-9 flex items-center justify-center rounded-xl ${travelMode === 'driving' ? 'bg-blue-600 text-white' : 'text-gray-500'}`}><Car className="w-4 h-4" /></button>
|
||||
<button onClick={() => { setTravelMode('bike'); setIsMapControlsOpen(false); }} className={`w-9 h-9 flex items-center justify-center rounded-xl ${travelMode === 'bike' ? 'bg-blue-600 text-white' : 'text-gray-500'}`}><Bike className="w-4 h-4" /></button>
|
||||
<button onClick={() => { setTravelMode('foot'); setIsMapControlsOpen(false); }} className={`w-9 h-9 flex items-center justify-center rounded-xl ${travelMode === 'foot' ? 'bg-blue-600 text-white' : 'text-gray-500'}`}><Footprints className="w-4 h-4" /></button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Add Member Modal */}
|
||||
{currentTour && (
|
||||
<AddMemberModal
|
||||
|
||||
Reference in New Issue
Block a user