feat: déplacer le bouton logout dans le menu hamburger mobile
Sur mobile, le bouton logout est désormais dans le drawer MobileNav (en bas, après Settings) et masqué dans le header. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -93,7 +93,9 @@ export default async function AppLayout({ children }: { children: ReactNode }) {
|
|||||||
<Icon name="settings" size="md" />
|
<Icon name="settings" size="md" />
|
||||||
</Link>
|
</Link>
|
||||||
<ThemeToggle />
|
<ThemeToggle />
|
||||||
|
<div className="hidden md:block">
|
||||||
<LogoutButton />
|
<LogoutButton />
|
||||||
|
</div>
|
||||||
<MobileNav
|
<MobileNav
|
||||||
navItems={[
|
navItems={[
|
||||||
{ href: "/", label: t("nav.dashboard"), icon: "dashboard" },
|
{ href: "/", label: t("nav.dashboard"), icon: "dashboard" },
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
import { useState, useEffect, useTransition } from "react";
|
import { useState, useEffect, useTransition } from "react";
|
||||||
import { createPortal } from "react-dom";
|
import { createPortal } from "react-dom";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
|
import { useRouter } from "next/navigation";
|
||||||
import { NavIcon } from "./ui";
|
import { NavIcon } from "./ui";
|
||||||
import { useTranslation } from "../../lib/i18n/context";
|
import { useTranslation } from "../../lib/i18n/context";
|
||||||
import type { UserDto } from "@/lib/api";
|
import type { UserDto } from "@/lib/api";
|
||||||
@@ -32,10 +33,17 @@ export function MobileNav({ navItems, users, activeUserId, setActiveUserAction }
|
|||||||
setActiveUserAction: (formData: FormData) => Promise<void>;
|
setActiveUserAction: (formData: FormData) => Promise<void>;
|
||||||
}) {
|
}) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const router = useRouter();
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
const [mounted, setMounted] = useState(false);
|
const [mounted, setMounted] = useState(false);
|
||||||
const [, startTransition] = useTransition();
|
const [, startTransition] = useTransition();
|
||||||
|
|
||||||
|
async function handleLogout() {
|
||||||
|
await fetch("/api/auth/logout", { method: "POST" });
|
||||||
|
router.push("/login");
|
||||||
|
router.refresh();
|
||||||
|
}
|
||||||
|
|
||||||
function select(userId: string | null) {
|
function select(userId: string | null) {
|
||||||
startTransition(async () => {
|
startTransition(async () => {
|
||||||
const fd = new FormData();
|
const fd = new FormData();
|
||||||
@@ -128,6 +136,17 @@ export function MobileNav({ navItems, users, activeUserId, setActiveUserAction }
|
|||||||
<NavIcon name="settings" />
|
<NavIcon name="settings" />
|
||||||
<span className="font-medium">{t("nav.settings")}</span>
|
<span className="font-medium">{t("nav.settings")}</span>
|
||||||
</Link>
|
</Link>
|
||||||
|
<button
|
||||||
|
onClick={() => { setIsOpen(false); handleLogout(); }}
|
||||||
|
className="w-full flex items-center gap-3 px-3 py-3 rounded-lg text-muted-foreground hover:text-foreground hover:bg-accent transition-colors duration-200 active:scale-[0.98]"
|
||||||
|
>
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="shrink-0">
|
||||||
|
<path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4" />
|
||||||
|
<polyline points="16 17 21 12 16 7" />
|
||||||
|
<line x1="21" y1="12" x2="9" y2="12" />
|
||||||
|
</svg>
|
||||||
|
<span className="font-medium">{t("auth.logout")}</span>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
import type { TranslationKey } from "./fr";
|
import type { TranslationKey } from "./fr";
|
||||||
|
|
||||||
const en: Record<TranslationKey, string> = {
|
const en: Record<TranslationKey, string> = {
|
||||||
|
// Auth
|
||||||
|
"auth.logout": "Log out",
|
||||||
|
|
||||||
// Navigation
|
// Navigation
|
||||||
"nav.dashboard": "Dashboard",
|
"nav.dashboard": "Dashboard",
|
||||||
"nav.books": "Books",
|
"nav.books": "Books",
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
const fr = {
|
const fr = {
|
||||||
|
// Auth
|
||||||
|
"auth.logout": "Se déconnecter",
|
||||||
|
|
||||||
// Navigation
|
// Navigation
|
||||||
"nav.dashboard": "Tableau de bord",
|
"nav.dashboard": "Tableau de bord",
|
||||||
"nav.books": "Livres",
|
"nav.books": "Livres",
|
||||||
|
|||||||
Reference in New Issue
Block a user