feat: updated cuenta page
This commit is contained in:
@@ -0,0 +1,76 @@
|
|||||||
|
'use client'
|
||||||
|
import Button from '@/components/ui/Button'
|
||||||
|
import ButtonGroup from '@/components/ui/ButtonGroup'
|
||||||
|
import useSession from '@/hooks/useSession'
|
||||||
|
import { css } from '@/styled-system/css'
|
||||||
|
import { AnimatePresence, motion } from 'framer-motion'
|
||||||
|
import { useState, type FC } from 'react'
|
||||||
|
import UpdateEmail from './UpdateEmail'
|
||||||
|
import UpdatePassword from './UpdatePassword'
|
||||||
|
import UpdateUserName from './UpdateUserName'
|
||||||
|
import UpdateUserPreferences from './UpdateUserPreferences'
|
||||||
|
|
||||||
|
type Tab = 'perfil' | 'login'
|
||||||
|
|
||||||
|
const CuentaTabs: FC = () => {
|
||||||
|
useSession('/login')
|
||||||
|
const [currentTab, setCurrentTab] = useState<Tab>('perfil')
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ButtonGroup
|
||||||
|
fullWidth={true}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
fullWidth
|
||||||
|
onClick={() => { setCurrentTab('perfil') }}
|
||||||
|
disabled={currentTab === 'perfil'}
|
||||||
|
>
|
||||||
|
Perfil
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
fullWidth
|
||||||
|
onClick={() => { setCurrentTab('login') }}
|
||||||
|
disabled={currentTab === 'login'}
|
||||||
|
>
|
||||||
|
Login
|
||||||
|
</Button>
|
||||||
|
</ButtonGroup>
|
||||||
|
<div
|
||||||
|
className={css({
|
||||||
|
overflow: 'hidden',
|
||||||
|
marginTop: 'medium'
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
<AnimatePresence
|
||||||
|
mode='wait'
|
||||||
|
>
|
||||||
|
{currentTab === 'login' && (
|
||||||
|
<motion.div
|
||||||
|
transition={{ duration: 0.15, ease: 'easeInOut' }}
|
||||||
|
initial={{ opacity: 0, x: '-100%' }}
|
||||||
|
animate={{ opacity: 1, x: 0 }}
|
||||||
|
exit={{ opacity: 0, x: '100%' }}
|
||||||
|
key="login">
|
||||||
|
<UpdateEmail />
|
||||||
|
<UpdatePassword />
|
||||||
|
</motion.div>
|
||||||
|
)}
|
||||||
|
{currentTab === 'perfil' && (
|
||||||
|
<motion.div
|
||||||
|
transition={{ duration: 0.15, ease: 'easeInOut' }}
|
||||||
|
initial={{ opacity: 0, x: '-100%' }}
|
||||||
|
animate={{ opacity: 1, x: 0 }}
|
||||||
|
exit={{ opacity: 0, x: '100%' }}
|
||||||
|
key="perfil">
|
||||||
|
<UpdateUserName />
|
||||||
|
<UpdateUserPreferences />
|
||||||
|
</motion.div>
|
||||||
|
)}
|
||||||
|
</AnimatePresence>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CuentaTabs
|
||||||
@@ -61,7 +61,7 @@ const UpdateEmail: FC = () => {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
validationSchema: updateEmailSchema,
|
validationSchema: updateEmailSchema,
|
||||||
isInitialValid: false
|
validateOnMount: true
|
||||||
})
|
})
|
||||||
|
|
||||||
if (status !== 'idle' || session === undefined) {
|
if (status !== 'idle' || session === undefined) {
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ const UpdatePassword: FC = () => {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
validationSchema: updatePasswordSchema,
|
validationSchema: updatePasswordSchema,
|
||||||
isInitialValid: false
|
validateOnMount: true
|
||||||
})
|
})
|
||||||
|
|
||||||
if (status !== 'idle' || session === undefined) {
|
if (status !== 'idle' || session === undefined) {
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import { nanoid } from '@reduxjs/toolkit'
|
|||||||
import { AppwriteException } from 'appwrite'
|
import { AppwriteException } from 'appwrite'
|
||||||
import { updateName } from 'entgamers-database/frontend/session'
|
import { updateName } from 'entgamers-database/frontend/session'
|
||||||
import { useFormik } from 'formik'
|
import { useFormik } from 'formik'
|
||||||
import { type FC } from 'react'
|
import { useEffect, type FC } from 'react'
|
||||||
import { object, string } from 'yup'
|
import { object, string } from 'yup'
|
||||||
|
|
||||||
interface UpdateUserNameData {
|
interface UpdateUserNameData {
|
||||||
@@ -22,7 +22,7 @@ const UpdateUserNameSchema = object({
|
|||||||
})
|
})
|
||||||
|
|
||||||
const UpdateUserName: FC = () => {
|
const UpdateUserName: FC = () => {
|
||||||
const { status, session } = useSession('/login')
|
const { status, session, user } = useSession('/login')
|
||||||
const dispatch = useAppDispatch()
|
const dispatch = useAppDispatch()
|
||||||
|
|
||||||
const formik = useFormik<UpdateUserNameData>({
|
const formik = useFormik<UpdateUserNameData>({
|
||||||
@@ -57,9 +57,19 @@ const UpdateUserName: FC = () => {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
validationSchema: UpdateUserNameSchema,
|
validationSchema: UpdateUserNameSchema,
|
||||||
isInitialValid: false
|
validateOnMount: true,
|
||||||
|
initialTouched: { name: true }
|
||||||
})
|
})
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (status !== 'idle' && session !== undefined) {
|
||||||
|
formik.setValues({
|
||||||
|
name: user?.name ?? ''
|
||||||
|
})
|
||||||
|
.catch(console.error)
|
||||||
|
}
|
||||||
|
}, [status, session])
|
||||||
|
|
||||||
if (status !== 'idle' || session === undefined) {
|
if (status !== 'idle' || session === undefined) {
|
||||||
// TODO: Replace with Skeleton
|
// TODO: Replace with Skeleton
|
||||||
return null
|
return null
|
||||||
|
|||||||
@@ -0,0 +1,106 @@
|
|||||||
|
'use client'
|
||||||
|
import Button from '@/components/ui/Button'
|
||||||
|
import Typography from '@/components/ui/Typography'
|
||||||
|
import FormGroup from '@/components/ui/form/FormGroup'
|
||||||
|
import TextArea from '@/components/ui/form/TextArea'
|
||||||
|
import { useAppDispatch } from '@/hooks/useAppDispatch'
|
||||||
|
import useManageError from '@/hooks/useManageError'
|
||||||
|
import useSession from '@/hooks/useSession'
|
||||||
|
import { setCurrentUser } from '@/state/sessionSlice'
|
||||||
|
import { updatePreferences, type UserPreferences } from 'entgamers-database/frontend/session'
|
||||||
|
import { useFormik } from 'formik'
|
||||||
|
import { useEffect, type FC } from 'react'
|
||||||
|
import { array, object, string, type ObjectSchema } from 'yup'
|
||||||
|
|
||||||
|
const socialLinksSchema: ObjectSchema<UserPreferences> = object({
|
||||||
|
bio: string().max(280, 'La descripción debe tener menos de 280 caracteres'),
|
||||||
|
profilePicture: string().url('La imagen debe ser una URL'),
|
||||||
|
socialLinks: array().of(
|
||||||
|
object({
|
||||||
|
label: string().required('La etiqueta es requerida'),
|
||||||
|
url: string().url('La URL debe ser una URL').required('La URL es requerida')
|
||||||
|
})
|
||||||
|
).min(0)
|
||||||
|
})
|
||||||
|
|
||||||
|
const UpdateUserPreferences: FC = () => {
|
||||||
|
const { status, session, user } = useSession('/login')
|
||||||
|
const dispatch = useAppDispatch()
|
||||||
|
const { manageError } = useManageError()
|
||||||
|
|
||||||
|
const formik = useFormik<UserPreferences>({
|
||||||
|
initialValues: {
|
||||||
|
bio: '',
|
||||||
|
profilePicture: '',
|
||||||
|
socialLinks: []
|
||||||
|
},
|
||||||
|
onSubmit: async ({ bio, profilePicture, socialLinks }) => {
|
||||||
|
try {
|
||||||
|
const updatedUserWithPreferences = await updatePreferences({ bio, profilePicture, socialLinks })
|
||||||
|
dispatch(setCurrentUser(updatedUserWithPreferences))
|
||||||
|
} catch (error) {
|
||||||
|
manageError(error, 'Error mientras se actualizaba las preferencias', ' Error desconocido mientras se actualizaba las preferencias', 'error')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
validationSchema: socialLinksSchema,
|
||||||
|
validateOnMount: true
|
||||||
|
})
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (status === 'idle' && session !== undefined) {
|
||||||
|
formik.setValues({
|
||||||
|
bio: user?.prefs.bio ?? '',
|
||||||
|
profilePicture: user?.prefs.profilePicture ?? '',
|
||||||
|
socialLinks: user?.prefs.socialLinks ?? []
|
||||||
|
})
|
||||||
|
.catch(console.error)
|
||||||
|
}
|
||||||
|
}, [status, session])
|
||||||
|
|
||||||
|
if (status !== 'idle' || session === undefined) {
|
||||||
|
// TODO: Replace with Skeleton
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Typography
|
||||||
|
variant='h3'
|
||||||
|
>
|
||||||
|
Preferencias
|
||||||
|
</Typography>
|
||||||
|
<form
|
||||||
|
onSubmit={formik.handleSubmit}
|
||||||
|
>
|
||||||
|
<FormGroup>
|
||||||
|
<label
|
||||||
|
htmlFor='bio'
|
||||||
|
>
|
||||||
|
Biografia
|
||||||
|
</label>
|
||||||
|
<TextArea
|
||||||
|
id='bio'
|
||||||
|
name='bio'
|
||||||
|
value={formik.values.bio}
|
||||||
|
onChange={formik.handleChange}
|
||||||
|
onBlur={formik.handleBlur}
|
||||||
|
disabled={formik.isSubmitting}
|
||||||
|
status={formik.touched.bio !== undefined && formik.errors.bio !== undefined ? 'danger' : undefined}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
{/* TODO: Add Profile Picture and Social Links fields */}
|
||||||
|
<FormGroup>
|
||||||
|
<Button
|
||||||
|
type='submit'
|
||||||
|
disabled={formik.isSubmitting || !formik.isValid}
|
||||||
|
fullWidth
|
||||||
|
>
|
||||||
|
Actualizar
|
||||||
|
</Button>
|
||||||
|
</FormGroup>
|
||||||
|
</form>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default UpdateUserPreferences
|
||||||
@@ -1,17 +1,18 @@
|
|||||||
import UpdateEmail from '@/app/cuenta/UpdateEmail'
|
|
||||||
import UpdatePassword from '@/app/cuenta/UpdatePassword'
|
|
||||||
import UpdateUserName from '@/app/cuenta/UpdateUserName'
|
|
||||||
import Typography from '@/components/ui/Typography'
|
import Typography from '@/components/ui/Typography'
|
||||||
import { Container } from '@/styled-system/jsx'
|
import { Container } from '@/styled-system/jsx'
|
||||||
import { type FC } from 'react'
|
import { type FC } from 'react'
|
||||||
|
import CuentaTabs from './CuentaTabs'
|
||||||
|
|
||||||
const CuentaPage: FC = () => {
|
const CuentaPage: FC = () => {
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
<Typography variant="h1" align="center">Cuenta</Typography>
|
<Typography variant="h1" align="center">Cuenta</Typography>
|
||||||
<UpdateUserName />
|
<Typography variant="body1">
|
||||||
<UpdatePassword />
|
Aquí puedes actualizar el nombre de usuario de tu cuenta.
|
||||||
<UpdateEmail />
|
</Typography>
|
||||||
|
<CuentaTabs
|
||||||
|
|
||||||
|
/>
|
||||||
</Container>
|
</Container>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user