import { useState, useEffect } from 'react'; import { LandingPage } from './pages/LandingPage'; import { ExploreMap } from './pages/ExploreMap'; import { TourDetailPage } from './pages/TourDetailPage'; import SignupPage from './pages/SignupPage'; import { MyPhotosPage } from './pages/MyPhotosPage'; import { MyNotePage } from './pages/MyNotePage'; import { JoinTourPage } from './pages/JoinTourPage'; import { MemberDashboard } from './pages/MemberDashboard'; import { AdminDashboard } from './pages/AdminDashboard'; import { ShareJourneyPage } from './pages/ShareJourneyPage'; import { TourNavigationPage } from './pages/TourNavigationPage'; import { ConfirmProvider } from './hooks/useConfirm'; import { NotificationProvider } from './hooks/useNotification'; function App() { const params = new URLSearchParams(window.location.search); const viewTourId = params.get('viewTour'); const pathParts = window.location.pathname.split('/'); const isJourneyShare = pathParts[1] === 'journey' && pathParts[2]; const journeyTokenVal = isJourneyShare ? pathParts[2] : null; const [user, setUser] = useState(null); const [shareJourneyToken, setShareJourneyToken] = useState(journeyTokenVal); const [currentPage, setCurrentPage] = useState<'landing' | 'dashboard' | 'admin' | 'explore' | 'tourDetail' | 'signup' | 'myPhotos' | 'notes' | 'joinTour' | 'shareJourney' | 'tourNavigation'>( journeyTokenVal ? 'shareJourney' : (viewTourId ? 'tourDetail' : (window.location.pathname === '/join-tour' || params.has('token') ? 'joinTour' : 'landing')) ); const [currentTourId, setCurrentTourId] = useState(viewTourId); const [isPublicTourView, setIsPublicTourView] = useState(!!viewTourId); const [previousPage, setPreviousPage] = useState<'explore' | 'dashboard' | 'landing'>('explore'); const [navigationPayload, setNavigationPayload] = useState<{ tourId: string; origin: { lat: number; lng: number }; destination: { lat: number; lng: number; name: string }; tourTitle: string } | null>(null); useEffect(() => { const params = new URLSearchParams(window.location.search); const viewTourId = params.get('viewTour'); const isJoinTour = window.location.pathname === '/join-tour' || params.has('token'); const pathParts = window.location.pathname.split('/'); const journeyToken = pathParts[1] === 'journey' && pathParts[2] ? pathParts[2] : null; // Check if user just finished uploading from a public tour const fromPublicUpload = localStorage.getItem('fromPublicUpload'); if (fromPublicUpload) { localStorage.removeItem('fromPublicUpload'); setCurrentPage('landing'); return; } // Khôi phục thông tin đăng nhập nếu có const token = localStorage.getItem('token'); const guestToken = localStorage.getItem('guest_token'); const storedUser = localStorage.getItem('user'); const storedGuestUser = localStorage.getItem('guest_user'); let loggedInUser = null; if (token && storedUser) { try { loggedInUser = JSON.parse(storedUser); setUser(loggedInUser); } catch (e) { localStorage.removeItem('token'); localStorage.removeItem('user'); } } if (journeyToken) { setShareJourneyToken(journeyToken); setCurrentPage('shareJourney'); } else if (isJoinTour) { setCurrentPage('joinTour'); } else if (viewTourId) { setCurrentPage('tourDetail'); } else { // CRITICAL: Check for guest token FIRST - guests should NEVER access dashboard // regardless of whether they also have other tokens if (guestToken) { setCurrentPage('landing'); } else if (loggedInUser) { // Real authenticated user (no guest token) if (loggedInUser.isAdmin) { setCurrentPage('admin'); } else { setCurrentPage('dashboard'); } } else { setCurrentPage('landing'); } } }, []); const handleLoginSuccess = (loggedInUser: any) => { setUser(loggedInUser); // Nếu có pending token, ta vẫn giữ ở trang joinTour để nó tự động thực hiện join const pendingInviteToken = localStorage.getItem('pendingInviteToken'); if (pendingInviteToken) { setCurrentPage('joinTour'); } else if (loggedInUser.isAdmin) { // Nếu là admin, chuyển đến admin dashboard setCurrentPage('admin'); } else { // Only set to dashboard if this is a real user (has token), not a guest const token = localStorage.getItem('token'); const guestToken = localStorage.getItem('guest_token'); if (token && !guestToken) { setCurrentPage('dashboard'); } else { setCurrentPage('landing'); } } }; const handleLogout = () => { localStorage.removeItem('token'); localStorage.removeItem('user'); setUser(null); setCurrentPage('landing'); }; const handleViewTour = (tourId: string, fromPage?: 'explore' | 'dashboard') => { setCurrentTourId(tourId); setIsPublicTourView(false); // Không phải chế độ công khai nếu đến từ bản đồ khám phá setPreviousPage(fromPage || (currentPage === 'dashboard' ? 'dashboard' : 'explore')); setCurrentPage('tourDetail'); }; const handleBackFromTourDetail = () => { const wasPublicView = isPublicTourView; setCurrentTourId(null); setIsPublicTourView(false); if (wasPublicView) { setCurrentPage('landing'); } else if (user) { setCurrentPage(previousPage); } else { setCurrentPage('landing'); } }; const handleOpenNavigationPage = (payload: { tourId: string; origin: { lat: number; lng: number }; destination: { lat: number; lng: number; name: string }; tourTitle: string }) => { setNavigationPayload(payload); setCurrentPage('tourNavigation'); }; const handleBackFromNavigation = () => { setNavigationPayload(null); setCurrentPage('tourDetail'); }; const handleBackFromSignup = () => { const pendingInviteToken = localStorage.getItem('pendingInviteToken'); if (pendingInviteToken) { setCurrentPage('joinTour'); } else { setCurrentPage('landing'); } }; const handleSignupSuccess = () => { // Sau khi đăng ký, ta có thể tự động đăng nhập hoặc quay lại landing/joinTour const pendingInviteToken = localStorage.getItem('pendingInviteToken'); const token = localStorage.getItem('token'); const storedUser = localStorage.getItem('user'); if (token && storedUser) { try { const loggedInUser = JSON.parse(storedUser); setUser(loggedInUser); if (pendingInviteToken) { setCurrentPage('joinTour'); } else { setCurrentPage('dashboard'); } return; } catch (e) {} } if (pendingInviteToken) { setCurrentPage('joinTour'); } else { setCurrentPage('landing'); } }; const handleBackFromExplore = () => { // Only allow real users (with token, not guest_token) const token = localStorage.getItem('token'); const guestToken = localStorage.getItem('guest_token'); const isRealUser = token && !guestToken; if (user && isRealUser) { setCurrentPage('dashboard'); } else { setCurrentPage('landing'); } }; const handleGoToDashboard = () => { // Only allow real users (with token, not guest_token) const token = localStorage.getItem('token'); const guestToken = localStorage.getItem('guest_token'); const isRealUser = token && !guestToken; if (user && isRealUser) { setPreviousPage('explore'); setCurrentPage('dashboard'); } else { setCurrentPage('landing'); } }; const handleGoToHome = () => { window.history.pushState({}, '', '/'); setShareJourneyToken(null); const token = localStorage.getItem('token'); const guestToken = localStorage.getItem('guest_token'); // Only real authenticated users can access dashboard, not guests const isRealUser = token && !guestToken; setCurrentPage(isRealUser ? 'dashboard' : 'landing'); }; return ( {(() => { if (currentPage === 'admin') { return ( ); } if (currentPage === 'dashboard') { // SECURITY: Prevent any guest from accessing dashboard const guestToken = localStorage.getItem('guest_token'); if (guestToken) { console.warn('[App] Guest user attempted to access dashboard - forcing redirect to landing'); setCurrentPage('landing'); return ( setCurrentPage('signup')} /> ); } return ( setCurrentPage('explore')} onViewTour={handleViewTour} onOpenMyPhotos={() => setCurrentPage('myPhotos')} /> ); } if (currentPage === 'tourDetail') { return ( setCurrentPage('notes')} onOpenNavigationPage={handleOpenNavigationPage} /> ); } if (currentPage === 'notes') { return setCurrentPage('tourDetail')} />; } if (currentPage === 'tourNavigation' && navigationPayload) { return ( ); } if (currentPage === 'explore') { return ( setCurrentPage('myPhotos')} onLoginSuccess={handleLoginSuccess} onGoToDashboard={handleGoToDashboard} /> ); } if (currentPage === 'myPhotos') { return ( setCurrentPage('explore')} /> ); } if (currentPage === 'signup') { return ; } if (currentPage === 'joinTour') { return ( setCurrentPage('signup')} onViewTour={(tourId) => { setCurrentTourId(tourId); setIsPublicTourView(false); setCurrentPage('tourDetail'); }} onGoToHome={() => { const loggedIn = !!localStorage.getItem('token'); setCurrentPage(loggedIn ? 'explore' : 'landing'); }} /> ); } if (currentPage === 'shareJourney') { return ( ); } return setCurrentPage('explore')} onGoToSignup={() => setCurrentPage('signup')} onGoToMap={() => setCurrentPage('explore')} onLoginSuccess={handleLoginSuccess} isInitialSetup={false} />; })()} ); } export default App;