Files
TodoList/apps/web/src/App.tsx
T

74 lines
2.5 KiB
TypeScript

import { useState } from "react";
import { Navigate, Route, Routes, useNavigate } from "react-router-dom";
import { EmailLoginPage } from "@/pages/email-login-page";
import { OAuthCallbackPage } from "@/pages/oauth-callback-page";
import { TodoShellPage } from "@/pages/todo-shell-page";
import type { EmailLoginResult } from "@/services/auth-api";
import { loadSession, saveSession, type WebSession } from "@/services/session-storage";
function toWebSession(payload: EmailLoginResult): WebSession {
return {
accessToken: payload.accessToken,
refreshToken: payload.refreshToken,
user: {
id: payload.user.id,
email: payload.user.email
}
};
}
function App() {
const [session, setSession] = useState<WebSession | null>(() => loadSession());
const navigate = useNavigate();
return (
<div className="min-h-screen bg-[#f6f8f7] text-[#122117]">
<header className="border-b border-[#d7e2db] bg-white/90 backdrop-blur">
<div className="mx-auto flex h-16 w-full max-w-6xl items-center justify-between px-4">
<div className="flex items-center gap-2">
<div className="h-8 w-8 rounded-lg bg-[#0a7a5a]" />
<span className="text-lg font-semibold tracking-tight">TodoList</span>
</div>
<span className="text-sm text-[#3a5a4a]">{session ? session.user.email : "未登录"}</span>
</div>
</header>
<main className="mx-auto w-full max-w-6xl px-4 py-8">
<Routes>
<Route
path="/login/email"
element={
<EmailLoginPage
onLoginSuccess={(payload) => {
const nextSession = toWebSession(payload);
saveSession(nextSession);
setSession(nextSession);
navigate("/");
}}
/>
}
/>
<Route
path="/auth/callback/:provider"
element={
<OAuthCallbackPage
onBootstrapSession={(nextSession) => {
setSession(nextSession);
}}
/>
}
/>
<Route
path="/"
element={
session ? <TodoShellPage session={session} /> : <Navigate to="/login/email" replace />
}
/>
<Route path="*" element={<Navigate to={session ? "/" : "/login/email"} replace />} />
</Routes>
</main>
</div>
);
}
export default App;