Files
geniusrun/frontend/src/App.tsx

72 lines
2.4 KiB
TypeScript
Raw Normal View History

import { useEffect, useState } from "react";
import { api, BASE_URL } from "./api/client";
import "./App.css";
2026-07-26 10:00:24 +02:00
import { Activities } from "./pages/Activities";
import { Analysis } from "./pages/Analysis";
import { Plan } from "./pages/Plan";
import { Profile } from "./pages/Profile";
import type { SessionInfo } from "./types/api";
const TABS = [
2026-07-26 10:00:24 +02:00
{ key: "activities", label: "Activities", icon: "☰", Component: Activities },
{ key: "analysis", label: "Analysis", icon: "🔍", Component: Analysis },
{ key: "plan", label: "Training plan", icon: "✎", Component: Plan },
] as const;
type TabKey = (typeof TABS)[number]["key"];
function App({ session }: { session: SessionInfo }) {
const [tab, setTab] = useState<TabKey>("activities");
// Profile isn't a tab: it's reached via the profile name in the top-right
// corner instead, since (for now, single-profile) it's account settings,
2026-07-26 10:00:24 +02:00
// not a content view alongside Activities/Analysis/Training plan.
const [showProfile, setShowProfile] = useState(false);
const [profileName, setProfileName] = useState<string | null>(null);
useEffect(() => {
api.getProfile().then((p) => setProfileName(p.Name)).catch(() => {});
}, []);
const Active = TABS.find((t) => t.key === tab)!.Component;
return (
<div className="app">
<header className="app-header">
<h1>🧞 geniusrun</h1>
<nav className="tabs">
{TABS.map((t) => (
<button
key={t.key}
className={!showProfile && t.key === tab ? "tab active" : "tab"}
onClick={() => {
setShowProfile(false);
setTab(t.key);
}}
>
<span className="tab-icon">{t.icon}</span>
{t.label}
</button>
))}
</nav>
<div className="header-actions">
<button
type="button"
className={showProfile ? "profile-name active" : "profile-name"}
onClick={() => setShowProfile(true)}
>
{profileName ?? "Profile"}
</button>
<form method="post" action={`${BASE_URL}/api/session/logout`} title={session.email}>
<button type="submit" className="logout-link">
Log out
</button>
</form>
</div>
</header>
<main>{showProfile ? <Profile onSaved={(p) => setProfileName(p.Name)} /> : <Active />}</main>
</div>
);
}
export default App;