Bladeren bron

[Auth] Add /api/auth/signout route + SignOutButton in app header

Adds POST /api/auth/signout that calls supabase.auth.signOut() via the
cookie-synced server client, plus a client-side <SignOutButton /> wired
into the (app) layout header. Clears the React Query cache on signout
so the next user starts with a clean slate.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
User 2 maanden geleden
bovenliggende
commit
44ff76c
3 gewijzigde bestanden met toevoegingen van 44 en 0 verwijderingen
  1. 2 0
      src/app/(app)/layout.tsx
  2. 13 0
      src/app/api/auth/signout/route.ts
  3. 29 0
      src/components/auth/sign-out-button.tsx

+ 2 - 0
src/app/(app)/layout.tsx

@@ -1,4 +1,5 @@
 import Link from "next/link";
+import { SignOutButton } from "@/components/auth/sign-out-button";
 
 export default function AppLayout({ children }: { children: React.ReactNode }) {
   return (
@@ -8,6 +9,7 @@ export default function AppLayout({ children }: { children: React.ReactNode }) {
           <Link href="/" className="text-lg font-bold text-foreground">
             MovieDice
           </Link>
+          <SignOutButton />
         </nav>
       </header>
       <main className="flex-1">{children}</main>

+ 13 - 0
src/app/api/auth/signout/route.ts

@@ -0,0 +1,13 @@
+import { NextResponse } from "next/server";
+import { getSupabaseServerClient } from "@/lib/supabase/server";
+
+export async function POST() {
+  const supabase = await getSupabaseServerClient();
+  const { error } = await supabase.auth.signOut();
+
+  if (error) {
+    return NextResponse.json({ error: "Failed to sign out" }, { status: 500 });
+  }
+
+  return NextResponse.json({ ok: true });
+}

+ 29 - 0
src/components/auth/sign-out-button.tsx

@@ -0,0 +1,29 @@
+"use client";
+
+import { useState } from "react";
+import { useRouter } from "next/navigation";
+import { useQueryClient } from "@tanstack/react-query";
+
+export function SignOutButton() {
+  const router = useRouter();
+  const queryClient = useQueryClient();
+  const [pending, setPending] = useState(false);
+
+  async function handleSignOut() {
+    setPending(true);
+    await fetch("/api/auth/signout", { method: "POST" });
+    queryClient.clear();
+    router.push("/");
+    router.refresh();
+  }
+
+  return (
+    <button
+      onClick={handleSignOut}
+      disabled={pending}
+      className="rounded bg-neutral-800 px-3 py-1.5 text-sm text-neutral-300 hover:bg-neutral-700 disabled:opacity-50"
+    >
+      Sign out
+    </button>
+  );
+}