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:
2026-06-17 21:53:46 +07:00
parent 40b1c4f2ab
commit da32d59161
+98 -17
View File
@@ -363,6 +363,7 @@ export const TourDetailPage = ({
const [activeTab, setActiveTab] = useState<'plan' | 'expense' | 'photo' | 'settings'>('plan'); const [activeTab, setActiveTab] = useState<'plan' | 'expense' | 'photo' | 'settings'>('plan');
const [viewMode, setViewMode] = useState<'map' | 'timeline'>('timeline'); const [viewMode, setViewMode] = useState<'map' | 'timeline'>('timeline');
const [isAddLocationOpen, setIsAddLocationOpen] = useState(false); const [isAddLocationOpen, setIsAddLocationOpen] = useState(false);
const [isMapFullscreen, setIsMapFullscreen] = useState(false);
const [isAddMemberOpen, setIsAddMemberOpen] = useState(false); const [isAddMemberOpen, setIsAddMemberOpen] = useState(false);
const [isAddPhotoOpen, setIsAddPhotoOpen] = useState(false); const [isAddPhotoOpen, setIsAddPhotoOpen] = useState(false);
const [isStartPointAction, setIsStartPointAction] = useState(false); const [isStartPointAction, setIsStartPointAction] = useState(false);
@@ -749,9 +750,9 @@ export const TourDetailPage = ({
}, [routes, selectedRouteIndex]); }, [routes, selectedRouteIndex]);
const handleNavigateToLocation = (location: any) => { const handleNavigateToLocation = (location: any) => {
setViewMode('map');
setMapCenter([location.latitude, location.longitude]); setMapCenter([location.latitude, location.longitude]);
setLocateTrigger(prev => prev + 1); setLocateTrigger(prev => prev + 1);
setIsMapFullscreen(true);
notify({ notify({
title: 'Bắt đầu chỉ đường', title: 'Bắt đầu chỉ đường',
@@ -1393,19 +1394,10 @@ export const TourDetailPage = ({
onNavigate={handleNavigateToLocation} onNavigate={handleNavigateToLocation}
/> />
) : ( ) : (
<div className="fixed inset-0 z-[2000] bg-white animate-in fade-in duration-500"> <div className="h-[60vh] w-full rounded-3xl overflow-hidden shadow-xl border-4 border-white relative 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>
{/* Search Bar Overlay - Thanh tìm kiếm địa điểm trên bản đồ lộ trình */} {/* Search Bar Overlay - Thanh tìm kiếm địa điểm trên bản đồ lộ trình */}
{!isPublicView && ( {!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"> <div className="relative group">
<input <input
type="text" 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) */} {/* Overlay thông tin lộ trình đề xuất (Lộ trình thông dụng nhất) */}
{selectedRouteInfo && drivingRoute.length > 0 && ( {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"> <div className="flex items-center gap-2">
<Navigation className="w-4 h-4 text-blue-600 rotate-45 fill-blue-600" /> <Navigation className="w-3.5 h-3.5 text-blue-600 rotate-45" />
<span className="text-[11px] font-black text-gray-700 uppercase tracking-widest">{selectedRouteInfo.label}</span> <span className="text-[10px] font-black text-gray-400 uppercase tracking-tighter">{selectedRouteInfo.label}</span>
</div> </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>{selectedRouteInfo.distance} km</span>
<span className="text-gray-400 opacity-40"></span> <span className="text-gray-300"></span>
<span>{selectedRouteInfo.duration}</span> <span>{selectedRouteInfo.duration}</span>
</div> </div>
</div> </div>
@@ -2100,6 +2092,95 @@ export const TourDetailPage = ({
</div> </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 */} {/* Add Member Modal */}
{currentTour && ( {currentTour && (
<AddMemberModal <AddMemberModal