From 34fda5760daa72a2857ba4163bf7e80e8da223cf Mon Sep 17 00:00:00 2001 From: Josh Date: Fri, 2 May 2025 15:39:51 +0000 Subject: [PATCH] Added navigation menu in header. --- src/App.js | 206 +++++++++++++++++++++++++++++++++++++++--------- user_profile.db | Bin 106496 -> 106496 bytes 2 files changed, 168 insertions(+), 38 deletions(-) diff --git a/src/App.js b/src/App.js index 9eb71fd..88264fe 100644 --- a/src/App.js +++ b/src/App.js @@ -1,5 +1,14 @@ import React, { useState, useEffect } from 'react'; -import { Routes, Route, Navigate, useNavigate, useLocation } from 'react-router-dom'; +import { + Routes, + Route, + Navigate, + useNavigate, + useLocation, + Link, +} from 'react-router-dom'; + +// Import all components from the components folder import PremiumRoute from './components/PremiumRoute.js'; import SessionExpiredHandler from './components/SessionExpiredHandler.js'; import GettingStarted from './components/GettingStarted.js'; @@ -18,16 +27,10 @@ function App() { const navigate = useNavigate(); const location = useLocation(); - // Track whether user is authenticated const [isAuthenticated, setIsAuthenticated] = useState(false); - - // Track the user object, including is_premium const [user, setUser] = useState(null); - - // We might also track a "loading" state so we don't redirect prematurely const [isLoading, setIsLoading] = useState(true); - // Hide the "Upgrade to Premium" CTA on certain premium routes const premiumPaths = [ '/milestone-tracker', '/paywall', @@ -37,35 +40,30 @@ function App() { ]; const showPremiumCTA = !premiumPaths.includes(location.pathname); - // On first mount, rehydrate user if there's a token + // Rehydrate user if there's a token useEffect(() => { const token = localStorage.getItem('token'); if (!token) { setIsLoading(false); - return; // No token => not authenticated + return; } - // If we have a token, let's validate it and fetch user data + // Validate token/fetch user fetch('https://dev1.aptivaai.com/api/user-profile', { - headers: { - Authorization: `Bearer ${token}`, - }, + headers: { Authorization: `Bearer ${token}` }, }) .then((res) => { if (!res.ok) { - // e.g. 401 means token invalid/expired - throw new Error('Token invalid or expired'); + throw new Error('Token invalid/expired'); } return res.json(); }) .then((profile) => { - // We have a valid user profile -> set states setUser(profile); setIsAuthenticated(true); }) .catch((err) => { console.error(err); - // If invalid, remove the token to avoid loops localStorage.removeItem('token'); }) .finally(() => { @@ -73,8 +71,15 @@ function App() { }); }, []); + // Logout + const handleLogout = () => { + localStorage.removeItem('token'); + setIsAuthenticated(false); + setUser(null); + navigate('/signin'); + }; + if (isLoading) { - // Optionally show a loading spinner or placeholder return (

Loading...

@@ -86,10 +91,138 @@ function App() {
{/* Header */}
-

- AptivaAI - Career Guidance Platform (beta) -

- {showPremiumCTA && ( +
+

+ AptivaAI - Career Guidance Platform (beta) +

+ + {/* Navigation Menu */} + {isAuthenticated && ( + + )} +
+ + {/* "Upgrade to Premium" button if not premium and on a free path */} + {showPremiumCTA && isAuthenticated && !user?.is_premium && (