dev1/src/App.js
2025-05-08 17:23:19 +00:00

346 lines
11 KiB
JavaScript

import React, { useState, useEffect } from 'react';
import {
Routes,
Route,
Navigate,
useNavigate,
useLocation,
Link,
} from 'react-router-dom';
// Import all components
import PremiumRoute from './components/PremiumRoute.js';
import SessionExpiredHandler from './components/SessionExpiredHandler.js';
import GettingStarted from './components/GettingStarted.js';
import SignIn from './components/SignIn.js';
import SignUp from './components/SignUp.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 MilestoneTracker from './components/MilestoneTracker.js';
import Paywall from './components/Paywall.js';
import OnboardingContainer from './components/PremiumOnboarding/OnboardingContainer.js';
import MultiScenarioView from './components/MultiScenarioView.js';
// 1) Import your ResumeRewrite component
import ResumeRewrite from './components/ResumeRewrite.js'; // adjust the path if needed
function App() {
const navigate = useNavigate();
const location = useLocation();
const [isAuthenticated, setIsAuthenticated] = useState(false);
const [user, setUser] = useState(null);
const [isLoading, setIsLoading] = useState(true);
// If you want Resume Optimizer to be considered a "premium path" too:
const premiumPaths = [
'/milestone-tracker',
'/paywall',
'/financial-profile',
'/multi-scenario',
'/premium-onboarding',
'/resume-optimizer', // add it here if you want
];
const showPremiumCTA = !premiumPaths.includes(location.pathname);
// 2) We'll define "canAccessPremium" to handle *both* is_premium or is_pro_premium
const canAccessPremium = user?.is_premium || user?.is_pro_premium;
// Rehydrate user if there's a token
useEffect(() => {
const token = localStorage.getItem('token');
if (!token) {
setIsLoading(false);
return;
}
// Validate token/fetch user
fetch('https://dev1.aptivaai.com/api/user-profile', {
headers: { Authorization: `Bearer ${token}` },
})
.then((res) => {
if (!res.ok) {
throw new Error('Token invalid/expired');
}
return res.json();
})
.then((profile) => {
setUser(profile);
setIsAuthenticated(true);
})
.catch((err) => {
console.error(err);
localStorage.removeItem('token');
})
.finally(() => {
setIsLoading(false);
});
}, []);
// Logout
const handleLogout = () => {
localStorage.removeItem('token');
setIsAuthenticated(false);
setUser(null);
navigate('/signin');
};
if (isLoading) {
return (
<div className="flex h-screen items-center justify-center">
<p>Loading...</p>
</div>
);
}
return (
<div className="flex min-h-screen flex-col bg-gray-50 text-gray-800">
{/* Header */}
<header className="flex items-center justify-between border-b bg-white px-6 py-4 shadow-sm">
<div className="flex items-center space-x-8">
<h1 className="text-lg font-semibold">
AptivaAI - Career Guidance Platform (beta)
</h1>
{/* Navigation Menu */}
{isAuthenticated && (
<nav>
<ul className="flex space-x-4">
{/* Free sections */}
<li>
<Link
className="text-blue-600 hover:text-blue-800"
to="/getting-started"
>
Getting Started
</Link>
</li>
<li>
<Link
className="text-blue-600 hover:text-blue-800"
to="/interest-inventory"
>
Interest Inventory
</Link>
</li>
<li>
<Link
className="text-blue-600 hover:text-blue-800"
to="/dashboard"
>
Dashboard
</Link>
</li>
<li>
<Link
className="text-blue-600 hover:text-blue-800"
to="/profile"
>
Profile
</Link>
</li>
{/* Premium sections (still checking only user?.is_premium for these) */}
<li>
{user?.is_premium ? (
<Link
className="text-blue-600 hover:text-blue-800"
to="/milestone-tracker"
>
Career Planner
</Link>
) : (
<span className="text-gray-400 cursor-not-allowed">
Milestone Tracker{' '}
<span className="text-green-600">
(Premium Subscribers Only)
</span>
</span>
)}
</li>
<li>
{user?.is_premium ? (
<Link
className="text-blue-600 hover:text-blue-800"
to="/financial-profile"
>
Financial Profile
</Link>
) : (
<span className="text-gray-400 cursor-not-allowed">
Financial Profile{' '}
<span className="text-green-600">
(Premium Subscribers Only)
</span>
</span>
)}
</li>
<li>
{user?.is_premium ? (
<Link
className="text-blue-600 hover:text-blue-800"
to="/multi-scenario"
>
Multi Scenario
</Link>
) : (
<span className="text-gray-400 cursor-not-allowed">
Multi Scenario{' '}
<span className="text-green-600">
(Premium Subscribers Only)
</span>
</span>
)}
</li>
<li>
{user?.is_premium ? (
<Link
className="text-blue-600 hover:text-blue-800"
to="/premium-onboarding"
>
Premium Onboarding
</Link>
) : (
<span className="text-gray-400 cursor-not-allowed">
Premium Onboarding{' '}
<span className="text-green-600">
(Premium Subscribers Only)
</span>
</span>
)}
</li>
{/* 3) A new link for Resume Optimizer that checks canAccessPremium */}
<li>
{canAccessPremium ? (
<Link
className="text-blue-600 hover:text-blue-800"
to="/resume-optimizer"
>
Resume Optimizer
</Link>
) : (
<span className="text-gray-400 cursor-not-allowed">
Resume Optimizer{' '}
<span className="text-green-600">
(Premium or Pro Only)
</span>
</span>
)}
</li>
{/* Logout */}
<li>
<button
className="text-red-600 hover:text-red-800"
onClick={handleLogout}
>
Logout
</button>
</li>
</ul>
</nav>
)}
</div>
{/* "Upgrade to Premium" button if not premium/pro and on a free path */}
{showPremiumCTA && isAuthenticated && !canAccessPremium && (
<button
className="rounded bg-blue-600 px-5 py-2 text-sm font-medium text-white transition-colors hover:bg-blue-700"
onClick={() => navigate('/paywall')}
>
Upgrade to Premium
</button>
)}
</header>
{/* Main Content */}
<main className="flex-1 p-6">
<Routes>
{/* Default to /signin */}
<Route path="/" element={<Navigate to="/signin" />} />
{/* Public routes */}
<Route
path="/signin"
element={
<SignIn setIsAuthenticated={setIsAuthenticated} setUser={setUser} />
}
/>
<Route path="/signup" element={<SignUp />} />
{/* Paywall (public) */}
<Route path="/paywall" element={<Paywall />} />
{/* Authenticated routes */}
{isAuthenticated && (
<>
<Route path="/getting-started" element={<GettingStarted />} />
<Route path="/interest-inventory" element={<InterestInventory />} />
<Route path="/dashboard" element={<Dashboard />} />
<Route path="/profile" element={<UserProfile />} />
{/* Premium-only routes */}
<Route
path="/milestone-tracker"
element={
<PremiumRoute user={user}>
<MilestoneTracker />
</PremiumRoute>
}
/>
<Route
path="/financial-profile"
element={
<PremiumRoute user={user}>
<FinancialProfileForm />
</PremiumRoute>
}
/>
<Route
path="/multi-scenario"
element={
<PremiumRoute user={user}>
<MultiScenarioView />
</PremiumRoute>
}
/>
<Route
path="/premium-onboarding"
element={
<PremiumRoute user={user}>
<OnboardingContainer />
</PremiumRoute>
}
/>
{/* 4) The new Resume Optimizer route */}
<Route
path="/resume-optimizer"
element={
<PremiumRoute user={user}>
<ResumeRewrite />
</PremiumRoute>
}
/>
</>
)}
{/* 404 / Fallback */}
<Route path="*" element={<Navigate to="/signin" />} />
</Routes>
</main>
{/* Session Handler */}
<SessionExpiredHandler />
</div>
);
}
export default App;