parent
754ea69bc6
commit
8d923c4135
8 changed files with 146 additions and 116 deletions
@ -0,0 +1,51 @@ |
||||
<div class='relative block hidden' id='account-dropdown'> |
||||
<button |
||||
class='flex h-8 w-24 items-center justify-center rounded-full bg-gradient-to-r from-blue-500 to-blue-700 py-2 px-4 text-sm font-medium text-white hover:from-blue-500 hover:to-blue-600' |
||||
type='button' |
||||
data-account-button |
||||
> |
||||
<span>Account</span> |
||||
</button> |
||||
|
||||
<div |
||||
class='absolute right-0 z-10 mt-2 hidden w-48 rounded-md bg-slate-800 py-1 shadow-xl' |
||||
> |
||||
<ul> |
||||
<li class='px-1'> |
||||
<a |
||||
href='/profile' |
||||
class='block rounded px-4 py-2 text-sm font-medium text-slate-100 hover:bg-slate-700' |
||||
> |
||||
Your Profile |
||||
</a> |
||||
</li> |
||||
<li class='px-1'> |
||||
<button |
||||
class='block w-full rounded px-4 py-2 text-left text-sm font-medium text-slate-100 hover:bg-slate-700' |
||||
type='button' |
||||
data-logout-button |
||||
> |
||||
Logout |
||||
</button> |
||||
</li> |
||||
</ul> |
||||
</div> |
||||
</div> |
||||
|
||||
<script> |
||||
import Cookies from 'js-cookie'; |
||||
import { TOKEN_COOKIE_NAME } from '../../lib/utils'; |
||||
|
||||
const accountButton = document.querySelector('[data-account-button]'); |
||||
const accountMenu = accountButton?.nextElementSibling; |
||||
const logoutButton = accountMenu?.querySelector('[data-logout-button]'); |
||||
|
||||
accountButton?.addEventListener('click', () => { |
||||
accountMenu?.classList.toggle('hidden'); |
||||
}); |
||||
|
||||
logoutButton?.addEventListener('click', () => { |
||||
Cookies.remove(TOKEN_COOKIE_NAME); |
||||
window.location.reload(); |
||||
}); |
||||
</script> |
@ -0,0 +1,40 @@ |
||||
--- |
||||
import Spinner from '../Spinner.astro'; |
||||
import AccountDropdown from './AccountDropdown.astro'; |
||||
--- |
||||
|
||||
<div> |
||||
<div |
||||
class='flex h-8 w-24 items-center justify-center rounded-full bg-gradient-to-r from-blue-500 to-blue-700 py-2 px-4 text-sm text-white hover:from-blue-500 hover:to-blue-600' |
||||
id='navigation-spinner' |
||||
> |
||||
<Spinner className='text-white' /> |
||||
</div> |
||||
|
||||
<AccountDropdown /> |
||||
|
||||
<a |
||||
id='register-button' |
||||
class='hidden flex h-8 w-24 cursor-pointer items-center justify-center rounded-full bg-gradient-to-r from-blue-500 to-blue-700 py-2 px-4 text-sm font-medium text-white hover:from-blue-500 hover:to-blue-600' |
||||
href='/signup' |
||||
> |
||||
<span>Register</span> |
||||
</a> |
||||
</div> |
||||
|
||||
<script> |
||||
import Cookies from 'js-cookie'; |
||||
import { TOKEN_COOKIE_NAME } from '../../lib/utils'; |
||||
const spinner = document.getElementById('navigation-spinner'); |
||||
const registerButton = document.getElementById('register-button'); |
||||
const accountDropdown = document.getElementById('account-dropdown'); |
||||
spinner?.classList.add('hidden'); |
||||
|
||||
const token = Cookies.get(TOKEN_COOKIE_NAME); |
||||
|
||||
if (token) { |
||||
accountDropdown?.classList.remove('hidden'); |
||||
} else { |
||||
registerButton?.classList.remove('hidden'); |
||||
} |
||||
</script> |
@ -1,56 +0,0 @@ |
||||
import Cookies from 'js-cookie'; |
||||
import { TOKEN_COOKIE_NAME } from '../../lib/utils'; |
||||
import { useEffect, useState } from 'preact/hooks'; |
||||
|
||||
export default function AccountDropdown() { |
||||
const [isOpen, setIsOpen] = useState(false); |
||||
|
||||
useEffect(() => { |
||||
// If user click outside the dropdown, and dropdown is open then close it.
|
||||
const handleOpen = () => { |
||||
if (isOpen) setIsOpen(false); |
||||
}; |
||||
|
||||
document.addEventListener('click', handleOpen); |
||||
return () => document.removeEventListener('click', handleOpen); |
||||
}, [isOpen]); |
||||
|
||||
return ( |
||||
<div className="relative"> |
||||
<button |
||||
className="flex h-8 w-24 items-center justify-center rounded-full bg-gradient-to-r from-blue-500 to-blue-700 py-2 px-4 text-sm font-medium text-white hover:from-blue-500 hover:to-blue-600" |
||||
onClick={() => setIsOpen((p) => !p)} |
||||
> |
||||
<span>Account</span> |
||||
</button> |
||||
|
||||
<div |
||||
className={`absolute right-0 z-10 mt-2 w-48 rounded-md bg-slate-800 py-1 shadow-xl ${ |
||||
isOpen ? 'block' : 'hidden' |
||||
}`}
|
||||
> |
||||
<ul> |
||||
<li className="px-1"> |
||||
<a |
||||
href="/profile" |
||||
className="block rounded px-4 py-2 text-sm font-medium text-slate-100 hover:bg-slate-700" |
||||
> |
||||
Your Profile |
||||
</a> |
||||
</li> |
||||
<li className="px-1"> |
||||
<button |
||||
className="block w-full rounded px-4 py-2 text-left text-sm font-medium text-slate-100 hover:bg-slate-700" |
||||
onClick={() => { |
||||
Cookies.remove(TOKEN_COOKIE_NAME); |
||||
window.location.reload(); |
||||
}} |
||||
> |
||||
Logout |
||||
</button> |
||||
</li> |
||||
</ul> |
||||
</div> |
||||
</div> |
||||
); |
||||
} |
@ -1,55 +0,0 @@ |
||||
import { useAuth } from '../../hooks/use-auth'; |
||||
import AccountDropdown from './account-dropdown'; |
||||
|
||||
export default function AccountNavigation() { |
||||
const { user, isLoading } = useAuth(); |
||||
|
||||
console.log('user', user, isLoading); |
||||
|
||||
return ( |
||||
<div> |
||||
{isLoading ? ( |
||||
<div className="flex h-8 w-24 items-center justify-center rounded-full bg-gradient-to-r from-blue-500 to-blue-700 py-2 px-4 text-sm text-white hover:from-blue-500 hover:to-blue-600"> |
||||
<Spinner className="text-white" /> |
||||
</div> |
||||
) : ( |
||||
<> |
||||
{user ? ( |
||||
<AccountDropdown /> |
||||
) : ( |
||||
<a |
||||
className="flex h-8 w-24 cursor-pointer items-center justify-center rounded-full bg-gradient-to-r from-blue-500 to-blue-700 py-2 px-4 text-sm font-medium text-white hover:from-blue-500 hover:to-blue-600" |
||||
href="/signup" |
||||
> |
||||
<span>Register</span> |
||||
</a> |
||||
)} |
||||
</> |
||||
)} |
||||
</div> |
||||
); |
||||
} |
||||
|
||||
export function Spinner({ className }: { className?: string }) { |
||||
return ( |
||||
<svg |
||||
className={`h-5 w-5 animate-spin ${className}`} |
||||
xmlns="http://www.w3.org/2000/svg" |
||||
fill="none" |
||||
viewBox="0 0 24 24" |
||||
> |
||||
<circle |
||||
className="stroke-[4px] opacity-25" |
||||
cx={12} |
||||
cy={12} |
||||
r={10} |
||||
stroke="currentColor" |
||||
/> |
||||
<path |
||||
className="opacity-75" |
||||
fill="currentColor" |
||||
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" |
||||
/> |
||||
</svg> |
||||
); |
||||
} |
@ -0,0 +1,23 @@ |
||||
--- |
||||
const { className = '', ...rest } = Astro.props; |
||||
--- |
||||
|
||||
<svg |
||||
class={`animate-spin h-5 w-5 ${className}`} |
||||
xmlns='http://www.w3.org/2000/svg' |
||||
fill='none' |
||||
viewBox='0 0 24 24' |
||||
{...rest} |
||||
> |
||||
<circle |
||||
class='stroke-[4px] opacity-25' |
||||
cx='12' |
||||
cy='12' |
||||
r='10' |
||||
stroke='currentColor'></circle> |
||||
<path |
||||
class='opacity-75' |
||||
fill='currentColor' |
||||
d='M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z' |
||||
></path> |
||||
</svg> |
After Width: | Height: | Size: 754 B |
Loading…
Reference in new issue