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

/**
* @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>
);
}