feat: introduce new app routes with modular structure and enhanced features

Added modular app routes including `login`, `dashboard`, `categories`, `trends`, and `upload`. Introduced reusable components such as `ContentList`, `ContentSkeleton`, and `AppSidebar` for improved UI consistency. Enhanced authentication with `AuthProvider` and implemented lazy loading, dynamic layouts, and infinite scrolling for better performance.
This commit is contained in:
Mathis HERRIOT
2026-01-14 13:52:08 +01:00
parent 0c045e8d3c
commit 0b07320974
41 changed files with 2341 additions and 43 deletions

View File

@@ -0,0 +1,124 @@
"use client";
import * as React from "react";
import Link from "next/link";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import * as z from "zod";
import { useAuth } from "@/providers/auth-provider";
import { Button } from "@/components/ui/button";
import {
Card,
CardContent,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
} from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import {
Form,
FormControl,
FormField,
FormItem,
FormLabel,
FormMessage,
} from "@/components/ui/form";
import { ArrowLeft } from "lucide-react";
const loginSchema = z.object({
email: z.string().email({ message: "Email invalide" }),
password: z.string().min(6, { message: "Le mot de passe doit faire au moins 6 caractères" }),
});
type LoginFormValues = z.infer<typeof loginSchema>;
export default function LoginPage() {
const { login } = useAuth();
const [loading, setLoading] = React.useState(false);
const form = useForm<LoginFormValues>({
resolver: zodResolver(loginSchema),
defaultValues: {
email: "",
password: "",
},
});
async function onSubmit(values: LoginFormValues) {
setLoading(true);
try {
await login(values.email, values.password);
} catch (error) {
// Error is handled in useAuth via toast
} finally {
setLoading(false);
}
}
return (
<div className="min-h-screen flex items-center justify-center bg-zinc-50 dark:bg-zinc-950 p-4">
<div className="w-full max-w-md space-y-4">
<Link
href="/"
className="inline-flex items-center text-sm text-muted-foreground hover:text-primary transition-colors"
>
<ArrowLeft className="mr-2 h-4 w-4" />
Retour à l'accueil
</Link>
<Card>
<CardHeader>
<CardTitle className="text-2xl">Connexion</CardTitle>
<CardDescription>
Entrez vos identifiants pour accéder à votre compte MemeGoat.
</CardDescription>
</CardHeader>
<CardContent>
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
<FormField
control={form.control}
name="email"
render={({ field }) => (
<FormItem>
<FormLabel>Email</FormLabel>
<FormControl>
<Input placeholder="goat@example.com" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="password"
render={({ field }) => (
<FormItem>
<FormLabel>Mot de passe</FormLabel>
<FormControl>
<Input type="password" placeholder="••••••••" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<Button type="submit" className="w-full" disabled={loading}>
{loading ? "Connexion en cours..." : "Se connecter"}
</Button>
</form>
</Form>
</CardContent>
<CardFooter className="flex flex-col space-y-2">
<p className="text-sm text-center text-muted-foreground">
Vous n'avez pas de compte ?{" "}
<Link href="/register" className="text-primary hover:underline font-medium">
S'inscrire
</Link>
</p>
</CardFooter>
</Card>
</div>
</div>
);
}