34 lines
2.1 KiB
TypeScript
34 lines
2.1 KiB
TypeScript
"use client";
|
|
|
|
import { useState, useTransition } from "react";
|
|
import { LogOut, LoaderCircle } from "lucide-react";
|
|
|
|
export function LogoutButton({ iconOnly = false, fullWidth = false, returnTo = "/login" }: { iconOnly?: boolean; fullWidth?: boolean; returnTo?: "/login" | "/clock/login" }) {
|
|
const [pending, startTransition] = useTransition();
|
|
const [failed, setFailed] = useState(false);
|
|
return <div className="relative">
|
|
<button type="button" aria-label="Sign out" title="Sign out" disabled={pending}
|
|
className={`flex min-h-11 min-w-11 items-center gap-3 rounded-lg text-sm font-medium text-gray-500 transition hover:bg-gray-100 focus-visible:outline-2 focus-visible:outline-[#30638E] dark:text-gray-400 dark:hover:bg-white/5 ${fullWidth ? "w-full justify-start px-3" : iconOnly ? "h-11 w-11 justify-center" : "justify-center px-4"}`}
|
|
onClick={() => startTransition(async () => {
|
|
setFailed(false);
|
|
try {
|
|
const response = await fetch("/api/auth/logout", { method: "POST" });
|
|
if (!response.ok) throw new Error("Could not sign out.");
|
|
// Old workers may have cached dashboards. Clear them even after upgrading.
|
|
try {
|
|
if ("caches" in window) await Promise.all((await caches.keys()).map((key) => caches.delete(key)));
|
|
} catch { /* Cookie deletion still signs the user out if cache storage is unavailable. */ }
|
|
if ("BroadcastChannel" in window) {
|
|
const channel = new BroadcastChannel("mega-auth");
|
|
channel.postMessage("logout");
|
|
channel.close();
|
|
}
|
|
window.location.replace(returnTo);
|
|
} catch { setFailed(true); }
|
|
})}>
|
|
{pending ? <LoaderCircle className="h-4 w-4 animate-spin" /> : <LogOut className="h-4 w-4" />}
|
|
{!iconOnly && (pending ? "Signing out…" : "Sign out")}
|
|
</button>
|
|
{failed && <p role="alert" className="absolute right-0 top-full z-50 mt-2 w-56 rounded-xl border border-[#D1495B]/20 bg-white p-3 text-sm text-[#D1495B] shadow-lg dark:bg-surface">Couldn't sign out. Please try again.</p>}
|
|
</div>;
|
|
}
|