File size: 2,932 Bytes
005df22 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | import React from 'react';
import { Link, useLocation } from 'react-router-dom';
import { LogOut, Settings } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { cn } from '@/lib/utils';
import { apiFetch } from '@/lib/api';
import { useAuth } from '@/context/AuthContext';
/**
* Signed-in user menu (sign-out, settings). Sign-in is handled by RequireAuth + SignIn page.
*/
export default function GoogleAuthBar() {
const location = useLocation();
const { phase, googleOn, microsoftOn, user, refresh } = useAuth();
const logout = async () => {
try {
await apiFetch('/api/auth/logout', { method: 'POST' });
await refresh();
} catch (e) {
console.error(e);
}
};
if (phase === 'loading' || (phase === 'ready' && !googleOn && !microsoftOn)) {
if (phase === 'loading') {
return (
<div
className="h-9 w-24 shrink-0 rounded-md bg-slate-100/80 animate-pulse"
aria-hidden
/>
);
}
return null;
}
if (phase === 'error' || !user) {
return null;
}
const settingsActive =
location.pathname === '/settings' || location.pathname.startsWith('/settings/');
return (
<div className="flex max-w-[min(100vw-6rem,28rem)] flex-wrap items-center justify-end gap-2">
<Button
asChild
variant="ghost"
size="icon"
className={cn(
'h-9 w-9 shrink-0 text-slate-600 hover:text-violet-700 hover:bg-violet-50',
settingsActive && 'text-violet-700 bg-violet-50'
)}
title="Settings"
aria-current={settingsActive ? 'page' : undefined}
>
<Link to="/settings">
<Settings className="h-5 w-5" aria-hidden />
<span className="sr-only">Settings</span>
</Link>
</Button>
{user.picture ? (
<img
src={user.picture}
alt=""
className="h-8 w-8 shrink-0 rounded-full border border-slate-200 object-cover"
referrerPolicy="no-referrer"
/>
) : null}
<span className="hidden min-w-0 truncate text-sm text-slate-600 lg:inline">
{user.name || user.email || 'Signed in'}
</span>
<Button
type="button"
variant="outline"
size="sm"
className="shrink-0 gap-1"
onClick={logout}
title="Sign out"
>
<LogOut className="h-3.5 w-3.5" />
<span className="hidden sm:inline">Sign out</span>
</Button>
</div>
);
}
|