feat: static login & register pages

This commit is contained in:
2024-01-04 22:24:58 -06:00
parent a6e072703d
commit 8c95537324
5 changed files with 301 additions and 0 deletions
+77
View File
@@ -0,0 +1,77 @@
'use client'
import Button from '@/components/ui/Button'
import Typography from '@/components/ui/Typography'
import FormGroup from '@/components/ui/form/FormGroup'
import Input from '@/components/ui/form/Input'
import PasswordInput from '@/components/ui/form/PasswordInput'
import { useFormik } from 'formik'
import { type FC } from 'react'
import { object, string } from 'yup'
interface LoginData {
email: string
password: string
}
const loginSchema = object({
email: string().email('El correo electrónico no es válido').required('El correo electrónico es requerido'),
password: string().required('La contraseña es requerida')
})
const LoginForm: FC = () => {
const formik = useFormik<LoginData>({
initialValues: {
email: '',
password: ''
},
onSubmit: (values) => {
console.log(values)
},
validationSchema: loginSchema
})
return (
<form
onSubmit={formik.handleSubmit}
>
<FormGroup>
<label htmlFor="email">Correo electrónico</label>
<Input
id="email"
name="email"
type="email"
onChange={formik.handleChange}
value={formik.values.email}
status={formik.touched.email !== undefined && formik.errors.email !== undefined ? 'danger' : undefined}
onBlur={formik.handleBlur}
fullWidth
/>
{formik.touched.email !== undefined && formik.errors.email !== undefined && (
<Typography variant="caption" color="danger">{formik.errors.email}</Typography>
)}
</FormGroup>
<FormGroup>
<label htmlFor="password">Contraseña</label>
<PasswordInput
id="password"
name="password"
onChange={formik.handleChange}
value={formik.values.password}
status={formik.touched.password !== undefined && formik.errors.password !== undefined ? 'danger' : undefined}
onBlur={formik.handleBlur}
fullWidth
/>
{formik.touched.password !== undefined && formik.errors.password !== undefined && (
<Typography variant="caption" color="danger">{formik.errors.password}</Typography>
)}
</FormGroup>
<FormGroup>
<Button
type="submit"
>
Iniciar sesión
</Button>
</FormGroup>
</form>
)
}
export default LoginForm
+53
View File
@@ -0,0 +1,53 @@
import LoginForm from '@/app/login/LoginForm'
import Typography from '@/components/ui/Typography'
import { css, cx } from '@/styled-system/css'
import { Center } from '@/styled-system/jsx'
import { container } from '@/styled-system/patterns'
import { card } from '@/styled-system/recipes'
import NextLink from 'next/link'
import { type FC } from 'react'
const LoginPage: FC = () => {
return (
<>
<Center
className={cx(
container(),
css({
minHeight: 'calc(100vh - 60px - 72px)'
}))
}
>
<div
className={cx(
card().body,
css({
width: '100%',
maxWidth: { sm: 'breakpoint-sm' },
overflow: 'visible'
})
)}
>
<div
className={
card().header
}
>
<Typography align="center" variant="h1">
Iniciar sesión
</Typography>
</div>
<div
className={card().content}
>
<LoginForm />
<Typography variant="caption" align="center" >
No tienes una cuenta? <NextLink href="/register">Regístrate</NextLink>
</Typography>
</div>
</div>
</Center>
</>
)
}
export default LoginPage
+100
View File
@@ -0,0 +1,100 @@
'use client'
import Button from '@/components/ui/Button'
import Typography from '@/components/ui/Typography'
import FormGroup from '@/components/ui/form/FormGroup'
import Input from '@/components/ui/form/Input'
import PasswordInput from '@/components/ui/form/PasswordInput'
import { useFormik } from 'formik'
import { type FC } from 'react'
import { object, ref, string } from 'yup'
interface RegisterData {
email: string
password: string
passwordConfirmation: string
}
const RegisterSchema = object({
email: string().email('El correo electrónico no es válido').required('El correo electrónico es requerido'),
password: string()
.min(6, 'La contraseña debe tener al menos 6 caracteres')
.matches(/[a-z]/, 'La contraseña debe tener al menos una letra minúscula')
.matches(/[A-Z]/, 'La contraseña debe tener al menos una letra mayúscula')
.matches(/[0-9]/, 'La contraseña debe tener al menos un número')
.required('La contraseña es requerida'),
passwordConfirmation: string().oneOf([ref('password')], 'Las contraseñas no coinciden').required('La confirmación de la contraseña es requerida')
})
const RegisterForm: FC = () => {
const formik = useFormik<RegisterData>({
initialValues: {
email: '',
password: '',
passwordConfirmation: ''
},
onSubmit: (values) => {
console.log(values)
},
validationSchema: RegisterSchema
})
return (
<form
onSubmit={formik.handleSubmit}
>
<FormGroup>
<label htmlFor="email">Correo electrónico</label>
<Input
id="email"
name="email"
type="email"
onChange={formik.handleChange}
value={formik.values.email}
status={formik.touched.email !== undefined && formik.errors.email !== undefined ? 'danger' : undefined}
onBlur={formik.handleBlur}
fullWidth
/>
{formik.touched.email !== undefined && formik.errors.email !== undefined && (
<Typography variant="caption" color="danger">{formik.errors.email}</Typography>
)}
</FormGroup>
<FormGroup>
<label htmlFor="password">Contraseña</label>
<PasswordInput
id="password"
name="password"
onChange={formik.handleChange}
value={formik.values.password}
status={formik.touched.password !== undefined && formik.errors.password !== undefined ? 'danger' : undefined}
onBlur={formik.handleBlur}
fullWidth
/>
{formik.touched.password !== undefined && formik.errors.password !== undefined && (
<Typography variant="caption" color="danger">{formik.errors.password}</Typography>
)}
</FormGroup>
<FormGroup>
<label htmlFor="passwordConfirmation">Confirmación de la contraseña</label>
<PasswordInput
id="passwordConfirmation"
name="passwordConfirmation"
onChange={formik.handleChange}
value={formik.values.passwordConfirmation}
status={formik.touched.passwordConfirmation !== undefined && formik.errors.passwordConfirmation !== undefined ? 'danger' : undefined}
onBlur={formik.handleBlur}
fullWidth
/>
{formik.touched.passwordConfirmation !== undefined && formik.errors.passwordConfirmation !== undefined && (
<Typography variant="caption" color="danger">{formik.errors.passwordConfirmation}</Typography>
)}
</FormGroup>
<FormGroup>
<Button
type="submit"
>
Registrarse
</Button>
</FormGroup>
</form>
)
}
export default RegisterForm
+54
View File
@@ -0,0 +1,54 @@
import RegisterForm from '@/app/register/RegisterForm'
import Typography from '@/components/ui/Typography'
import { css, cx } from '@/styled-system/css'
import { Center } from '@/styled-system/jsx'
import { container } from '@/styled-system/patterns'
import { card } from '@/styled-system/recipes'
import NextLink from 'next/link'
import { type FC } from 'react'
const RegisterPage: FC = () => {
return (
<>
<Center
className={cx(
container(),
css({
minHeight: 'calc(100vh - 60px - 72px)'
}))
}
>
<div
className={cx(
card().body,
css({
width: '100%',
maxWidth: { sm: 'breakpoint-sm' },
overflow: 'visible'
})
)}
>
<div
className={
card().header
}
>
<Typography align="center" variant="h1">
Regístrate
</Typography>
</div>
<div
className={card().content}
>
<RegisterForm />
<Typography variant="caption" align="center" >
Ya tienes una cuenta? <NextLink href="/login">Inicia sesión</NextLink>
</Typography>
</div>
</div>
</Center>
</>
)
}
export default RegisterPage
+17
View File
@@ -1,8 +1,12 @@
'use client'
import EntGamers from '@/assets/logos/EntGamers'
import Menu from '@/components/layout/Menu'
import Tooltip from '@/components/ui/Tooltip'
import { css } from '@/styled-system/css'
import { Container } from '@/styled-system/jsx'
import { iconButton } from '@/styled-system/recipes'
import { faUser } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import NextLink from 'next/link'
import { useCallback, useEffect, useState, type FC } from 'react'
@@ -65,6 +69,19 @@ const Header: FC = () => {
</NextLink>
</div>
<div>
<Tooltip
title="Próximamente"
position="bottom"
>
<NextLink
href="/login"
className={
iconButton()
}
>
<FontAwesomeIcon icon={faUser} fixedWidth />
</NextLink>
</Tooltip>
<Menu />
</div>
</Container>