setShareMenu(null)} />
+
{/* Tự động di chuyển bản đồ đến vị trí người dùng khi tìm thấy tọa độ */}
@@ -169,7 +204,16 @@ export const ExploreMap = ({ onBack, onLogout, user, onViewTour }: { onBack: ()
key={tour.id}
position={markerPos}
eventHandlers={{
- click: () => onViewTour(tour.id)
+ click: () => onViewTour(tour.id),
+ contextmenu: (e) => {
+ // Hiển thị menu tại vị trí chuột
+ setShareMenu({
+ x: e.containerPoint.x,
+ y: e.containerPoint.y,
+ id: tour.id,
+ title: tour.title
+ });
+ }
}}
icon={L.divIcon({
className: 'custom-bubble',
@@ -203,6 +247,22 @@ export const ExploreMap = ({ onBack, onLogout, user, onViewTour }: { onBack: ()
+ {/* Context Menu Chia sẻ */}
+ {shareMenu && (
+ e.stopPropagation()}
+ >
+
+
+ )}
+
{/* Admin Modal */}
setIsAdminModalOpen(false)} />
@@ -215,6 +275,14 @@ export const ExploreMap = ({ onBack, onLogout, user, onViewTour }: { onBack: ()
onViewTour(tour.id);
}}
/>
+
+ notificationModal.closeModal()}
+ />
);
};
\ No newline at end of file
diff --git a/frontend/src/pages/TourDetailPage.tsx b/frontend/src/pages/TourDetailPage.tsx
index dd8359f..1065bcb 100644
--- a/frontend/src/pages/TourDetailPage.tsx
+++ b/frontend/src/pages/TourDetailPage.tsx
@@ -28,7 +28,8 @@ import {
Clock,
Check,
X,
- MessageSquare
+ MessageSquare,
+ Share2
} from 'lucide-react';
import L from 'leaflet';
@@ -263,6 +264,22 @@ export const TourDetailPage = ({ onBack }: { onBack: () => void }) => {
loadData();
}, []);
+ const handleShare = () => {
+ if (!currentTour) return;
+ // Tạo link với query param ?viewTour=...
+ const shareUrl = `${window.location.origin}?viewTour=${currentTour.id}`;
+ if (navigator.share) {
+ navigator.share({
+ title: currentTour.title,
+ url: shareUrl,
+ }).catch(() => {});
+ } else {
+ navigator.clipboard.writeText(shareUrl).then(() => {
+ notificationModal.openModal('Thành công', 'Đã sao chép liên kết chia sẻ chuyến đi!', 'success');
+ });
+ }
+ };
+
// Thiết lập kết nối WebSocket Real-time
useEffect(() => {
if (!currentTour) return;
@@ -457,7 +474,13 @@ export const TourDetailPage = ({ onBack }: { onBack: () => void }) => {
{tourInfo.title}
- {/* Spacer */}
+
{/* Tour Header Info */}