import React, { useState, useEffect, useMemo } from 'react'; import { Routes, Route, Navigate, useNavigate, useLocation, Link, } from 'react-router-dom'; import { Button } from './components/ui/button.js'; import { cn } from './utils/cn.js'; import PromptModal from './components/ui/PromptModal.js'; import PremiumRoute from './components/PremiumRoute.js'; import SessionExpiredHandler from './components/SessionExpiredHandler.js'; import SignInLanding from './components/SignInLanding.js'; import SignIn from './components/SignIn.js'; import SignUp from './components/SignUp.js'; import PlanningLanding from './components/PlanningLanding.js'; import CareerExplorer from './components/CareerExplorer.js'; import PreparingLanding from './components/PreparingLanding.js'; import EducationalProgramsPage from './components/EducationalProgramsPage.js'; import EnhancingLanding from './components/EnhancingLanding.js'; import RetirementLanding from './components/RetirementLanding.js'; import InterestInventory from './components/InterestInventory.js'; import Dashboard from './components/Dashboard.js'; import UserProfile from './components/UserProfile.js'; import FinancialProfileForm from './components/FinancialProfileForm.js'; import CareerProfileList from './components/CareerProfileList.js'; import CareerProfileForm from './components/CareerProfileForm.js'; import CollegeProfileList from './components/CollegeProfileList.js'; import CollegeProfileForm from './components/CollegeProfileForm.js'; import CareerRoadmap from './components/CareerRoadmap.js'; import Paywall from './components/Paywall.js'; import OnboardingContainer from './components/PremiumOnboarding/OnboardingContainer.js'; import RetirementPlanner from './components/RetirementPlanner.js'; import ResumeRewrite from './components/ResumeRewrite.js'; import LoanRepaymentPage from './components/LoanRepaymentPage.js'; import usePageContext from './utils/usePageContext.js'; import ChatDrawer from './components/ChatDrawer.js'; import ChatCtx from './contexts/ChatCtx.js'; import BillingResult from './components/BillingResult.js'; export const ProfileCtx = React.createContext(); function App() { const navigate = useNavigate(); const location = useLocation(); const { pageContext, snapshot: routeSnapshot } = usePageContext(); const [drawerOpen, setDrawerOpen] = useState(false); const [drawerPane, setDrawerPane] = useState('support'); const [retireProps, setRetireProps] = useState(null); /* ------------------------------------------ ChatDrawer – route-aware tool handlers ------------------------------------------ */ const uiToolHandlers = useMemo(() => { if (pageContext === "CareerExplorer") { return { // __tool:addCareerToComparison:{"socCode":"15-2051","careerName":"Data Scientist"} addCareerToComparison: ({ socCode, careerName }) => { console.log('[dispatch]', socCode, careerName); window.dispatchEvent( new CustomEvent("add-career", { detail: { socCode, careerName } }) ); }, // __tool:openCareerModal:{"socCode":"15-2051"} openCareerModal: ({ socCode }) => { window.dispatchEvent( new CustomEvent("open-career", { detail: { socCode } }) ); } }; } return {}; // every other page exposes no UI tools }, [pageContext]); // Auth states const [isAuthenticated, setIsAuthenticated] = useState(false); const [user, setUser] = useState(null); const [chatSnapshot, setChatSnapshot] = useState(null); // Loading state while verifying token const [isLoading, setIsLoading] = useState(true); // User states const [financialProfile, setFinancialProfile] = useState(null); const [scenario, setScenario] = useState(null); // Logout warning modal const [showLogoutWarning, setShowLogoutWarning] = useState(false); // Check if user can access premium const canAccessPremium = user?.is_premium || user?.is_pro_premium; // List of premium paths for your CTA logic const premiumPaths = [ '/career-roadmap', '/paywall', '/financial-profile', '/retirement-planner', '/premium-onboarding', '/enhancing', '/retirement', '/resume-optimizer', ]; const showPremiumCTA = !premiumPaths.includes(location.pathname); // Helper to see if user is mid–premium-onboarding function isOnboardingInProgress() { try { const stored = JSON.parse(localStorage.getItem('premiumOnboardingState') || '{}'); // If step < 4 (example), user is in progress return stored.step && stored.step < 4; } catch (e) { return false; } } // ============================== // 1) Single Rehydrate UseEffect // ============================== useEffect(() => { const token = localStorage.getItem('token'); if (!token) { // No token => not authenticated setIsLoading(false); return; } // If we have a token, validate it by fetching user fetch('/api/user-profile', { headers: { Authorization: `Bearer ${token}` }, }) .then((res) => { if (!res.ok) throw new Error('Token invalid on server side'); return res.json(); }) .then((profile) => { // Successfully got user profile => user is authenticated setUser(profile); setIsAuthenticated(true); }) .catch((err) => { console.error(err); // Invalid token => remove it, force sign in localStorage.removeItem('token'); navigate('/signin?session=expired'); }) .finally(() => { // Either success or fail, we're done loading setIsLoading(false); }); }, [navigate]); // ========================== // 2) Logout Handler + Modal // ========================== const handleLogoutClick = () => { if (isOnboardingInProgress()) { // Show a modal to confirm losing onboarding data setShowLogoutWarning(true); } else { // No onboarding => just logout confirmLogout(); } }; const confirmLogout = () => { localStorage.removeItem('token'); localStorage.removeItem('id'); localStorage.removeItem('careerSuggestionsCache'); localStorage.removeItem('lastSelectedCareerProfileId'); localStorage.removeItem('selectedCareer'); localStorage.removeItem('aiClickCount'); localStorage.removeItem('aiClickDate'); localStorage.removeItem('aiRecommendations'); localStorage.removeItem('premiumOnboardingState'); // ← NEW localStorage.removeItem('financialProfile'); // ← if you cache it setFinancialProfile(null); // ← reset any React-context copy setScenario(null); setIsAuthenticated(false); setUser(null); setShowLogoutWarning(false); // Reset auth setIsAuthenticated(false); setUser(null); setShowLogoutWarning(false); navigate('/signin'); }; const cancelLogout = () => { setShowLogoutWarning(false); }; // ==================================== // 3) If still verifying the token, show loading // ==================================== if (isLoading) { return (
Loading...