You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
147 lines
5.4 KiB
TypeScript
147 lines
5.4 KiB
TypeScript
/**
|
|
* @license
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
import React from 'react';
|
|
import { BrowserRouter as Router, Routes, Route, Navigate, Link } from 'react-router-dom';
|
|
import { AuthProvider, useAuth } from './components/AuthContext';
|
|
import Home from './pages/Home';
|
|
import GenerateSynthesis from './pages/GenerateSynthesis';
|
|
import SynthesisDetail from './pages/SynthesisDetail';
|
|
import Sources from './pages/Sources';
|
|
import Settings from './pages/Settings';
|
|
import { LogOut, BrainCircuit, Settings as SettingsIcon } from 'lucide-react';
|
|
|
|
function ProtectedRoute({ children }: { children: React.ReactNode }) {
|
|
const { user, loading } = useAuth();
|
|
if (loading) return <div className="flex justify-center items-center h-screen"><div className="animate-spin rounded-full h-12 w-12 border-b-2 border-indigo-600"></div></div>;
|
|
if (!user) return <Navigate to="/login" />;
|
|
return <>{children}</>;
|
|
}
|
|
|
|
function Login() {
|
|
const { user, signIn } = useAuth();
|
|
if (user) return <Navigate to="/" />;
|
|
|
|
return (
|
|
<div className="min-h-screen flex items-center justify-center bg-gray-50 py-12 px-4 sm:px-6 lg:px-8">
|
|
<div className="max-w-md w-full space-y-8">
|
|
<div>
|
|
<BrainCircuit className="mx-auto h-12 w-12 text-indigo-600" />
|
|
<h2 className="mt-6 text-center text-3xl font-extrabold text-gray-900">
|
|
AI Weekly Synth
|
|
</h2>
|
|
<p className="mt-2 text-center text-sm text-gray-600">
|
|
Votre synthèse hebdomadaire des actualités IA
|
|
</p>
|
|
</div>
|
|
<div className="mt-8 space-y-6">
|
|
<button
|
|
onClick={signIn}
|
|
className="group relative w-full flex justify-center py-2 px-4 border border-transparent text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
|
|
>
|
|
Se connecter avec Google
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
function Layout({ children }: { children: React.ReactNode }) {
|
|
const { user, signOut } = useAuth();
|
|
|
|
return (
|
|
<div className="min-h-screen bg-gray-50">
|
|
<nav className="bg-white shadow-sm border-b border-gray-200">
|
|
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
|
<div className="flex justify-between h-16">
|
|
<div className="flex">
|
|
<div className="flex-shrink-0 flex items-center">
|
|
<BrainCircuit className="h-8 w-8 text-indigo-600" />
|
|
<Link to="/" className="ml-2 text-xl font-bold text-gray-900">AI Weekly Synth</Link>
|
|
</div>
|
|
<div className="hidden sm:ml-6 sm:flex sm:space-x-8">
|
|
<Link to="/" className="border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700 inline-flex items-center px-1 pt-1 border-b-2 text-sm font-medium">
|
|
Synthèses
|
|
</Link>
|
|
<Link to="/sources" className="border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700 inline-flex items-center px-1 pt-1 border-b-2 text-sm font-medium">
|
|
Sources personnalisées
|
|
</Link>
|
|
</div>
|
|
</div>
|
|
<div className="flex items-center">
|
|
{user && (
|
|
<div className="flex items-center space-x-4">
|
|
<span className="text-sm text-gray-700">{user.email}</span>
|
|
<Link to="/settings" className="text-gray-400 hover:text-gray-600 p-2 rounded-full hover:bg-gray-100 transition-colors" title="Paramètres">
|
|
<SettingsIcon className="h-5 w-5" />
|
|
</Link>
|
|
<button
|
|
onClick={signOut}
|
|
className="inline-flex items-center px-3 py-1.5 border border-gray-300 shadow-sm text-sm font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
|
|
>
|
|
<LogOut className="h-4 w-4 mr-2" />
|
|
Déconnexion
|
|
</button>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</nav>
|
|
<main>
|
|
{children}
|
|
</main>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export default function App() {
|
|
return (
|
|
<AuthProvider>
|
|
<Router>
|
|
<Routes>
|
|
<Route path="/login" element={<Login />} />
|
|
<Route path="/" element={
|
|
<ProtectedRoute>
|
|
<Layout>
|
|
<Home />
|
|
</Layout>
|
|
</ProtectedRoute>
|
|
} />
|
|
<Route path="/sources" element={
|
|
<ProtectedRoute>
|
|
<Layout>
|
|
<Sources />
|
|
</Layout>
|
|
</ProtectedRoute>
|
|
} />
|
|
<Route path="/settings" element={
|
|
<ProtectedRoute>
|
|
<Layout>
|
|
<Settings />
|
|
</Layout>
|
|
</ProtectedRoute>
|
|
} />
|
|
<Route path="/generate" element={
|
|
<ProtectedRoute>
|
|
<Layout>
|
|
<GenerateSynthesis />
|
|
</Layout>
|
|
</ProtectedRoute>
|
|
} />
|
|
<Route path="/synthesis/:id" element={
|
|
<ProtectedRoute>
|
|
<Layout>
|
|
<SynthesisDetail />
|
|
</Layout>
|
|
</ProtectedRoute>
|
|
} />
|
|
</Routes>
|
|
</Router>
|
|
</AuthProvider>
|
|
);
|
|
}
|