diff --git a/frontend/src/app/(dashboard)/layout.tsx b/frontend/src/app/(dashboard)/layout.tsx
index 181c20b..89e2f02 100644
--- a/frontend/src/app/(dashboard)/layout.tsx
+++ b/frontend/src/app/(dashboard)/layout.tsx
@@ -2,6 +2,7 @@ import * as React from "react";
import { AppSidebar } from "@/components/app-sidebar";
import { MobileFilters } from "@/components/mobile-filters";
import { SearchSidebar } from "@/components/search-sidebar";
+import { UserNavMobile } from "@/components/user-nav-mobile";
import {
SidebarInset,
SidebarProvider,
@@ -16,26 +17,31 @@ export default function DashboardLayout({
modal: React.ReactNode;
}) {
return (
-
-
-
-
-
-
- {children}
- {modal}
-
+
+
+
+
+
+
+
+ {children}
+ {modal}
+
+
+
+
+
-
+
-
-
-
-
-
-
+
+
+
);
}
diff --git a/frontend/src/app/(dashboard)/profile/page.tsx b/frontend/src/app/(dashboard)/profile/page.tsx
index cc02784..d1c1746 100644
--- a/frontend/src/app/(dashboard)/profile/page.tsx
+++ b/frontend/src/app/(dashboard)/profile/page.tsx
@@ -1,19 +1,23 @@
"use client";
-import { Calendar, LogOut, Settings } from "lucide-react";
+import { Calendar, LogIn, LogOut, Settings } from "lucide-react";
import Link from "next/link";
-import { redirect } from "next/navigation";
+import { useSearchParams } from "next/navigation";
import * as React from "react";
import { ContentList } from "@/components/content-list";
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import { Button } from "@/components/ui/button";
+import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { useAuth } from "@/providers/auth-provider";
import { ContentService } from "@/services/content.service";
import { FavoriteService } from "@/services/favorite.service";
+import { Spinner } from "@/components/ui/spinner";
export default function ProfilePage() {
const { user, isAuthenticated, isLoading, logout } = useAuth();
+ const searchParams = useSearchParams();
+ const tab = searchParams.get("tab") || "memes";
const fetchMyMemes = React.useCallback(
(params: { limit: number; offset: number }) =>
@@ -26,9 +30,36 @@ export default function ProfilePage() {
[],
);
- if (isLoading) return null;
+ if (isLoading) {
+ return (
+
+
+
+ );
+ }
+
if (!isAuthenticated || !user) {
- redirect("/login");
+ return (
+
+
+
+
+
+
+ Profil inaccessible
+
+ Vous devez être connecté pour voir votre profil, vos mèmes et vos
+ favoris.
+
+
+
+
+
+
+
+ );
}
return (
@@ -79,10 +110,14 @@ export default function ProfilePage() {
-
+
- Mes Mèmes
- Mes Favoris
+
+ Mes Mèmes
+
+
+ Mes Favoris
+
diff --git a/frontend/src/app/(dashboard)/upload/page.tsx b/frontend/src/app/(dashboard)/upload/page.tsx
index 2567fbf..2049f8f 100644
--- a/frontend/src/app/(dashboard)/upload/page.tsx
+++ b/frontend/src/app/(dashboard)/upload/page.tsx
@@ -1,15 +1,16 @@
"use client";
import { zodResolver } from "@hookform/resolvers/zod";
-import { Image as ImageIcon, Loader2, Upload, X } from "lucide-react";
+import { Image as ImageIcon, Loader2, LogIn, Upload, X } from "lucide-react";
import NextImage from "next/image";
+import Link from "next/link";
import { useRouter } from "next/navigation";
import * as React from "react";
import { useForm } from "react-hook-form";
import { toast } from "sonner";
import * as z from "zod";
import { Button } from "@/components/ui/button";
-import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
+import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import {
Form,
FormControl,
@@ -27,8 +28,10 @@ import {
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
+import { useAuth } from "@/providers/auth-provider";
import { CategoryService } from "@/services/category.service";
import { ContentService } from "@/services/content.service";
+import { Spinner } from "@/components/ui/spinner";
import type { Category } from "@/types/content";
const uploadSchema = z.object({
@@ -42,6 +45,7 @@ type UploadFormValues = z.infer;
export default function UploadPage() {
const router = useRouter();
+ const { isAuthenticated, isLoading } = useAuth();
const [categories, setCategories] = React.useState([]);
const [file, setFile] = React.useState(null);
const [preview, setPreview] = React.useState(null);
@@ -57,8 +61,42 @@ export default function UploadPage() {
});
React.useEffect(() => {
- CategoryService.getAll().then(setCategories).catch(console.error);
- }, []);
+ if (isAuthenticated) {
+ CategoryService.getAll().then(setCategories).catch(console.error);
+ }
+ }, [isAuthenticated]);
+
+ if (isLoading) {
+ return (
+
+
+
+ );
+ }
+
+ if (!isAuthenticated) {
+ return (
+
+
+
+
+
+
+ Connexion requise
+
+ Vous devez être connecté pour partager vos meilleurs mèmes avec la
+ communauté.
+
+
+
+
+
+
+
+ );
+ }
const handleFileChange = (e: React.ChangeEvent) => {
const selectedFile = e.target.files?.[0];
diff --git a/frontend/src/components/app-sidebar.tsx b/frontend/src/components/app-sidebar.tsx
index 13e7536..49905bf 100644
--- a/frontend/src/components/app-sidebar.tsx
+++ b/frontend/src/components/app-sidebar.tsx
@@ -3,7 +3,9 @@
import {
ChevronRight,
Clock,
+ Heart,
HelpCircle,
+ History,
Home,
LayoutGrid,
LogIn,
@@ -14,7 +16,7 @@ import {
User as UserIcon,
} from "lucide-react";
import Link from "next/link";
-import { usePathname } from "next/navigation";
+import { usePathname, useSearchParams } from "next/navigation";
import * as React from "react";
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import {
@@ -68,6 +70,7 @@ const mainNav = [
export function AppSidebar() {
const pathname = usePathname();
+ const searchParams = useSearchParams();
const { user, logout, isAuthenticated } = useAuth();
const [categories, setCategories] = React.useState([]);
@@ -149,6 +152,36 @@ export function AppSidebar() {
+
+
+ Ma Bibliothèque
+
+
+
+
+
+ Mes Favoris
+
+
+
+
+
+
+
+ Mes Mèmes
+
+
+
+
+
diff --git a/frontend/src/components/user-nav-mobile.tsx b/frontend/src/components/user-nav-mobile.tsx
new file mode 100644
index 0000000..c70387f
--- /dev/null
+++ b/frontend/src/components/user-nav-mobile.tsx
@@ -0,0 +1,39 @@
+"use client";
+
+import { LogIn, User as UserIcon } from "lucide-react";
+import Link from "next/link";
+import * as React from "react";
+import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
+import { Button } from "@/components/ui/button";
+import { useAuth } from "@/providers/auth-provider";
+
+export function UserNavMobile() {
+ const { user, isAuthenticated, isLoading } = useAuth();
+
+ if (isLoading) {
+ return ;
+ }
+
+ if (!isAuthenticated || !user) {
+ return (
+
+ );
+ }
+
+ return (
+
+ );
+}