femto-webapp/src/app/auth/pages/LoginPage.tsx
2025-05-20 10:06:18 +02:00

112 lines
3.3 KiB
TypeScript

import { useRef, useState, FormEvent, useEffect } from 'react'
import SingleColumnLayout from '../../../layouts/SingleColumnLayout.tsx'
import TextInput from '../../../components/inputs/TextInput.tsx'
import Button from '../../../components/buttons/Button.tsx'
import { AuthService } from '../authService.ts'
import { useNavigate } from 'react-router-dom'
import { useUser } from '../../user/user.ts'
import NavBar from '../../../components/NavBar.tsx'
import NavButton from '../../../components/buttons/NavButton.tsx'
import LinkButton from '../../../components/buttons/LinkButton.tsx'
interface LoginPageProps {
authService: AuthService
}
export default function LoginPage({ authService }: LoginPageProps) {
const [isSubmitting, setIsSubmitting] = useState(false)
const [username, setUsername] = useState('')
const [password, setPassword] = useState('')
const [error, setError] = useState<string | null>(null)
const usernameInputRef = useRef<HTMLInputElement | null>(null)
const passwordInputRef = useRef<HTMLInputElement | null>(null)
const navigate = useNavigate()
const user = useUser()
useEffect(() => {
if (user) {
const search = new URLSearchParams(window.location.search)
navigate(search.get('t') || '/')
}
}, [user, navigate])
const onSubmit = async (e: FormEvent<HTMLFormElement>) => {
e.preventDefault()
if (!username) {
setError("it's not username :(")
return
}
if (!password) {
setError("it's not password :(")
return
}
setError(null)
setIsSubmitting(true)
try {
await authService.login(username, password)
} catch (error: unknown) {
setError(error instanceof Error ? error.message : 'something went terribly wrong')
} finally {
setIsSubmitting(false)
}
}
return (
<SingleColumnLayout
navbar={
<NavBar>
<NavButton to={'/'}>home</NavButton>
</NavBar>
}
>
<main className="w-full mx-auto p-4">
<div className="mt-12">
<form className="flex flex-col gap-4 max-w-md" onSubmit={onSubmit}>
<div className="flex flex-col gap-1">
<label htmlFor="username" className="text-sm text-gray-600">
username
</label>
<TextInput
ref={usernameInputRef}
id="username"
value={username}
onInput={setUsername}
className={'mb-4'}
/>
</div>
<div className="flex flex-col gap-1">
<label htmlFor="password" className="text-sm text-gray-600">
password
</label>
<TextInput
ref={passwordInputRef}
type="password"
id="password"
value={password}
onInput={setPassword}
className={'mb-3'}
/>
</div>
<Button className="mt-4" disabled={isSubmitting} type="submit">
{isSubmitting ? 'wait...' : 'make login pls'}
</Button>
<LinkButton secondary to={{ pathname: '/signup', search: window.location.search }}>
register instead?
</LinkButton>
<span className="text-xs h-3 text-red-500">{error}</span>
</form>
</div>
</main>
</SingleColumnLayout>
)
}