feat(shell): integrate auth-aware nav into locale layout

Add AuthNavActions component and integrate shell into locale layout

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
nxtkofi 2026-04-21 23:26:36 +02:00
parent e8d557b0d2
commit 2a6a7980ec
2 changed files with 78 additions and 1 deletions

View file

@ -2,6 +2,8 @@ import { setRequestLocale } from 'next-intl/server';
import { hasLocale } from 'next-intl';
import { notFound } from 'next/navigation';
import { routing } from '@/i18n/routing';
import { AppShell } from '@/components/core/AppShell';
import { AppNav } from '@/components/core/AppNav';
export function generateStaticParams() {
return routing.locales.map((locale) => ({ locale }));
@ -22,5 +24,10 @@ export default async function LocaleLayout({
setRequestLocale(locale);
return <>{children}</>;
return (
<AppShell>
<AppNav />
<main className="flex-1">{children}</main>
</AppShell>
);
}

View file

@ -0,0 +1,70 @@
"use client";
import Link from "next/link";
import { useTranslations } from "next-intl";
import { routes } from "@/lib/routes";
import { authClient } from "@/lib/auth-client";
import { Button } from "@/components/ui/button";
import { cn } from "@/lib/utils";
interface AuthNavActionsProps {
className?: string;
}
export function AuthNavActions({ className }: AuthNavActionsProps) {
const t = useTranslations("Navigation");
const { data: session, isPending } = authClient.useSession();
if (isPending) {
return (
<div className={cn("flex items-center gap-2", className)}>
<div className="h-9 w-20 bg-muted animate-pulse rounded" />
</div>
);
}
const isAuthenticated = !!session?.user;
const handleSignOut = async () => {
await authClient.signOut({
fetchOptions: {
onSuccess: () => {
window.location.href = routes.public.home;
},
},
});
};
return (
<div data-testid="nav-auth-actions" className={cn("flex items-center gap-2", className)}>
{isAuthenticated ? (
<>
<div data-testid="nav-private-links" className="flex items-center gap-2">
<Button variant="ghost" asChild>
<Link href={routes.private.dashboard}>{t("Dashboard")}</Link>
</Button>
<Button variant="ghost" asChild>
<Link href={routes.private.settings}>{t("Settings")}</Link>
</Button>
</div>
<Button
data-testid="sign-out-button"
variant="outline"
onClick={handleSignOut}
>
{t("SignOut")}
</Button>
</>
) : (
<div data-testid="nav-public-links" className="flex items-center gap-2">
<Button variant="ghost" asChild>
<Link href={routes.public.signIn}>{t("SignIn")}</Link>
</Button>
<Button asChild>
<Link href={routes.public.signUp}>{t("SignUp")}</Link>
</Button>
</div>
)}
</div>
);
}