91 lines
2.6 KiB
TypeScript
91 lines
2.6 KiB
TypeScript
'use client'
|
|
|
|
import { useState } from 'react'
|
|
import { useAuthStore } from '@/lib/auth'
|
|
|
|
export function AuthButton() {
|
|
const { isAuthenticated, username, loading, login, register, logout } = useAuthStore()
|
|
const [showRegister, setShowRegister] = useState(false)
|
|
const [registerName, setRegisterName] = useState('')
|
|
|
|
const handleLogin = async () => {
|
|
try {
|
|
await login()
|
|
} catch (e: unknown) {
|
|
if (e instanceof Error && e.name === 'NotAllowedError') {
|
|
setShowRegister(true)
|
|
}
|
|
}
|
|
}
|
|
|
|
const handleRegister = async () => {
|
|
if (!registerName.trim()) return
|
|
try {
|
|
await register(registerName.trim())
|
|
setShowRegister(false)
|
|
setRegisterName('')
|
|
} catch (e: unknown) {
|
|
alert('Registration failed: ' + (e instanceof Error ? e.message : 'Unknown error'))
|
|
}
|
|
}
|
|
|
|
if (loading) {
|
|
return <span className="text-sm text-slate-400">Authenticating...</span>
|
|
}
|
|
|
|
if (isAuthenticated) {
|
|
return (
|
|
<div className="flex items-center gap-2 text-sm">
|
|
<span className="text-slate-500">
|
|
Signed in as <strong className="text-blue-600">{username}</strong>
|
|
</span>
|
|
<button
|
|
onClick={logout}
|
|
className="text-slate-400 hover:text-slate-600 underline text-xs"
|
|
>
|
|
Sign out
|
|
</button>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
if (showRegister) {
|
|
return (
|
|
<div className="flex items-center gap-2">
|
|
<input
|
|
type="text"
|
|
value={registerName}
|
|
onChange={(e) => setRegisterName(e.target.value)}
|
|
placeholder="Choose a username"
|
|
className="px-2 py-1 text-sm border rounded"
|
|
onKeyDown={(e) => e.key === 'Enter' && handleRegister()}
|
|
/>
|
|
<button
|
|
onClick={handleRegister}
|
|
className="px-3 py-1 text-sm bg-blue-500 text-white rounded hover:bg-blue-600"
|
|
>
|
|
Create
|
|
</button>
|
|
<button
|
|
onClick={() => setShowRegister(false)}
|
|
className="text-xs text-slate-400 hover:text-slate-600"
|
|
>
|
|
Cancel
|
|
</button>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
return (
|
|
<button
|
|
onClick={handleLogin}
|
|
className="px-3 py-1.5 text-sm border border-slate-300 rounded-lg hover:border-blue-400 hover:text-blue-600 transition-colors flex items-center gap-1.5"
|
|
>
|
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
|
|
<circle cx="12" cy="10" r="3" /><path d="M12 13v8" /><path d="M9 18h6" /><circle cx="12" cy="10" r="7" />
|
|
</svg>
|
|
Sign in with Passkey
|
|
</button>
|
|
)
|
|
}
|