Initial commit

This commit is contained in:
Jose Selesan
2026-04-08 22:53:11 -03:00
commit 9ae270609d
179 changed files with 28096 additions and 0 deletions

View File

@@ -0,0 +1,100 @@
import { useState } from 'react'
import { Link, useNavigate } from '@tanstack/react-router'
import { zodResolver } from '@hookform/resolvers/zod'
import { useForm } from 'react-hook-form'
import { z } from 'zod'
import { Button } from '@/components/ui/button'
import { Field, FieldError, FieldLabel } from '@/components/ui/field'
import { Input } from '@/components/ui/input'
import { useAuth } from '@/lib/auth'
const loginSchema = z.object({
email: z.string().email('Ingresá un email válido.'),
password: z.string().min(6, 'La contraseña debe tener al menos 6 caracteres.'),
})
type LoginForm = z.infer<typeof loginSchema>
type LoginPageProps = {
redirectTo?: string
}
export function LoginPage({ redirectTo = '/' }: LoginPageProps) {
const navigate = useNavigate()
const { signInWithPassword } = useAuth()
const [submitError, setSubmitError] = useState<string | null>(null)
const {
register,
handleSubmit,
formState: { errors, isSubmitting, isValid },
} = useForm<LoginForm>({
resolver: zodResolver(loginSchema),
mode: 'onChange',
defaultValues: {
email: '',
password: '',
},
})
const onSubmit = async (values: LoginForm) => {
setSubmitError(null)
try {
await signInWithPassword(values)
await navigate({ to: redirectTo })
} catch {
setSubmitError('No pudimos iniciar sesión. Verificá tus credenciales.')
}
}
return (
<main className="mx-auto flex min-h-screen w-full max-w-6xl items-center px-6">
<section className="w-full max-w-3xl rounded-xl border bg-card p-6 text-card-foreground shadow-sm">
<h1 className="mb-2 text-2xl font-semibold">Iniciar sesión</h1>
<p className="mb-4 text-sm text-muted-foreground">
Ingresá con tu cuenta para acceder a Home.
</p>
<form className="space-y-3" onSubmit={handleSubmit(onSubmit)}>
<Field data-invalid={Boolean(errors.email)}>
<FieldLabel htmlFor="email">Email</FieldLabel>
<Input
id="email"
type="email"
placeholder="tu@email.com"
aria-invalid={Boolean(errors.email)}
{...register('email')}
/>
<FieldError errors={[errors.email]} />
</Field>
<Field data-invalid={Boolean(errors.password)}>
<FieldLabel htmlFor="password">Contraseña</FieldLabel>
<Input
id="password"
type="password"
placeholder="••••••••"
aria-invalid={Boolean(errors.password)}
{...register('password')}
/>
<FieldError errors={[errors.password]} />
</Field>
{submitError && <p className="text-sm text-destructive">{submitError}</p>}
<Button type="submit" className="w-full" disabled={!isValid || isSubmitting}>
{isSubmitting ? 'Ingresando...' : 'Ingresar'}
</Button>
</form>
<p className="mt-4 text-center text-sm text-muted-foreground">
¿Solo querés explorar?{' '}
<Link to="/about" className="text-primary hover:underline">
Ir a About
</Link>
</p>
</section>
</main>
)
}