diff --git a/frontend/app/admin/layout.tsx b/frontend/app/admin/layout.tsx new file mode 100644 index 0000000..a35b054 --- /dev/null +++ b/frontend/app/admin/layout.tsx @@ -0,0 +1,10 @@ +import { AdminLayout } from "@/components/admin-layout"; +import { AuthLoading } from "@/components/auth-loading"; + +export default function AdminRootLayout({ children }: { children: React.ReactNode }) { + return ( + + {children} + + ); +} diff --git a/frontend/app/admin/page.tsx b/frontend/app/admin/page.tsx new file mode 100644 index 0000000..13d4335 --- /dev/null +++ b/frontend/app/admin/page.tsx @@ -0,0 +1,199 @@ +"use client"; + +import { useState } from "react"; +import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; +import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; +import { Button } from "@/components/ui/button"; +import { Users, Shield, Tags, Settings, BarChart4 } from "lucide-react"; +import Link from "next/link"; + +export default function AdminDashboardPage() { + const [activeTab, setActiveTab] = useState("overview"); + + // Mock data for the admin dashboard + const stats = [ + { + title: "Utilisateurs", + value: "24", + description: "Utilisateurs actifs", + icon: Users, + href: "/admin/users", + }, + { + title: "Tags globaux", + value: "18", + description: "Tags disponibles", + icon: Tags, + href: "/admin/tags", + }, + { + title: "Projets", + value: "32", + description: "Projets créés", + icon: BarChart4, + href: "/admin/stats", + }, + { + title: "Paramètres", + value: "7", + description: "Paramètres système", + icon: Settings, + href: "/admin/settings", + }, + ]; + + // Mock data for recent activities + const recentActivities = [ + { + id: 1, + user: "Jean Dupont", + action: "a créé un nouveau projet", + target: "Formation Dev Web", + date: "2025-05-15T14:32:00", + }, + { + id: 2, + user: "Marie Martin", + action: "a modifié un tag global", + target: "Frontend", + date: "2025-05-15T13:45:00", + }, + { + id: 3, + user: "Admin", + action: "a ajouté un nouvel utilisateur", + target: "Pierre Durand", + date: "2025-05-15T11:20:00", + }, + { + id: 4, + user: "Sophie Lefebvre", + action: "a créé un nouveau groupe", + target: "Groupe A", + date: "2025-05-15T10:15:00", + }, + { + id: 5, + user: "Admin", + action: "a modifié les paramètres système", + target: "Paramètres de notification", + date: "2025-05-14T16:30:00", + }, + ]; + + return ( +
+
+

Administration

+
+ + Mode administrateur +
+
+ + + + Vue d'ensemble + Activité récente + Système + + + +
+ {stats.map((stat, index) => ( + + + {stat.title} + + + +
{stat.value}
+

{stat.description}

+ +
+
+ ))} +
+
+ + + + + Activité récente + + Les dernières actions effectuées sur la plateforme + + + +
+ {recentActivities.map((activity) => ( +
+
+

+ {activity.user} {activity.action}{" "} + {activity.target} +

+

+ {new Date(activity.date).toLocaleString("fr-FR", { + dateStyle: "medium", + timeStyle: "short", + })} +

+
+
+ ))} +
+
+
+
+ + + + + Informations système + + Informations sur l'état du système + + + +
+
+
+

Version de l'application

+

v1.0.0

+
+
+

Dernière mise à jour

+

15 mai 2025

+
+
+

État du serveur

+
+
+

En ligne

+
+
+
+

Utilisation de la base de données

+

42%

+
+
+ +
+ +
+
+
+
+
+
+
+ ); +} \ No newline at end of file diff --git a/frontend/app/admin/settings/page.tsx b/frontend/app/admin/settings/page.tsx new file mode 100644 index 0000000..0eb9216 --- /dev/null +++ b/frontend/app/admin/settings/page.tsx @@ -0,0 +1,581 @@ +"use client"; + +import { useState } from "react"; +import { useForm } from "react-hook-form"; +import { Button } from "@/components/ui/button"; +import { Input } from "@/components/ui/input"; +import { Label } from "@/components/ui/label"; +import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; +import { Separator } from "@/components/ui/separator"; +import { Switch } from "@/components/ui/switch"; +import { Textarea } from "@/components/ui/textarea"; +import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/ui/card"; +import { toast } from "sonner"; +import { + Save, + RefreshCw, + Shield, + Bell, + Mail, + Database, + Server, + FileJson, + Loader2 +} from "lucide-react"; + +export default function AdminSettingsPage() { + const [activeTab, setActiveTab] = useState("general"); + const [isLoading, setIsLoading] = useState(false); + + // Mock system settings + const systemSettings = { + general: { + siteName: "Application de Création de Groupes", + siteDescription: "Une application web moderne dédiée à la création et à la gestion de groupes", + contactEmail: "admin@example.com", + maxProjectsPerUser: "10", + maxPersonsPerProject: "100", + }, + authentication: { + enableGithubAuth: true, + requireEmailVerification: false, + sessionTimeout: "7", + maxLoginAttempts: "5", + passwordMinLength: "8", + }, + notifications: { + enableEmailNotifications: true, + enableSystemNotifications: true, + notifyOnNewUser: true, + notifyOnNewProject: false, + adminEmailRecipients: "admin@example.com", + }, + maintenance: { + maintenanceMode: false, + maintenanceMessage: "Le site est actuellement en maintenance. Veuillez réessayer plus tard.", + debugMode: false, + logLevel: "error", + }, + }; + + const { register: registerGeneral, handleSubmit: handleSubmitGeneral, formState: { errors: errorsGeneral } } = useForm({ + defaultValues: systemSettings.general, + }); + + const { register: registerAuth, handleSubmit: handleSubmitAuth, formState: { errors: errorsAuth } } = useForm({ + defaultValues: systemSettings.authentication, + }); + + const { register: registerNotif, handleSubmit: handleSubmitNotif, formState: { errors: errorsNotif } } = useForm({ + defaultValues: systemSettings.notifications, + }); + + const { register: registerMaint, handleSubmit: handleSubmitMaint, formState: { errors: errorsMaint } } = useForm({ + defaultValues: systemSettings.maintenance, + }); + + const onSubmitGeneral = async (data: any) => { + setIsLoading(true); + // Simulate API call + await new Promise((resolve) => setTimeout(resolve, 1000)); + setIsLoading(false); + toast.success("Paramètres généraux mis à jour avec succès"); + }; + + const onSubmitAuth = async (data: any) => { + setIsLoading(true); + // Simulate API call + await new Promise((resolve) => setTimeout(resolve, 1000)); + setIsLoading(false); + toast.success("Paramètres d'authentification mis à jour avec succès"); + }; + + const onSubmitNotif = async (data: any) => { + setIsLoading(true); + // Simulate API call + await new Promise((resolve) => setTimeout(resolve, 1000)); + setIsLoading(false); + toast.success("Paramètres de notification mis à jour avec succès"); + }; + + const onSubmitMaint = async (data: any) => { + setIsLoading(true); + // Simulate API call + await new Promise((resolve) => setTimeout(resolve, 1000)); + setIsLoading(false); + toast.success("Paramètres de maintenance mis à jour avec succès"); + }; + + const handleExportConfig = async () => { + setIsLoading(true); + // Simulate API call + await new Promise((resolve) => setTimeout(resolve, 1000)); + setIsLoading(false); + toast.success("Configuration exportée avec succès"); + }; + + const handleClearCache = async () => { + setIsLoading(true); + // Simulate API call + await new Promise((resolve) => setTimeout(resolve, 1000)); + setIsLoading(false); + toast.success("Cache vidé avec succès"); + }; + + return ( +
+
+

Paramètres système

+
+ + Configuration globale +
+
+ + + + Général + Authentification + Notifications + Maintenance + + + + +
+ + Paramètres généraux + + Configurez les paramètres généraux de l'application + + + +
+
+ + + {errorsGeneral.siteName && ( +

{errorsGeneral.siteName.message as string}

+ )} +
+
+ + + {errorsGeneral.contactEmail && ( +

{errorsGeneral.contactEmail.message as string}

+ )} +
+
+ +
+ +