From 17955fa8a81dde87c90a264cef14756fc6f161f7 Mon Sep 17 00:00:00 2001 From: manugallegob Date: Sat, 5 Apr 2025 12:29:09 +0200 Subject: [PATCH 1/3] feature edit reset password ok --- .../api/edit-reset-password.api.ts | 7 ++ .../users/edit-reset-password/api/index.ts | 1 + .../alerts-reset-password.componet.tsx | 25 +++++ .../confirm-reset-dialog.component.tsx | 44 +++++---- .../edit-reset-password/components/index.ts | 1 + .../edit-reset-password.component.tsx | 97 ++++++++++++------- .../edit-reset-password.pod.tsx | 7 +- .../edit-reset-password.query.hook.ts | 32 ++++++ 8 files changed, 155 insertions(+), 59 deletions(-) create mode 100644 src/modules/users/edit-reset-password/api/edit-reset-password.api.ts create mode 100644 src/modules/users/edit-reset-password/api/index.ts create mode 100644 src/modules/users/edit-reset-password/components/alerts-reset-password.componet.tsx create mode 100644 src/modules/users/edit-reset-password/edit-reset-password.query.hook.ts diff --git a/src/modules/users/edit-reset-password/api/edit-reset-password.api.ts b/src/modules/users/edit-reset-password/api/edit-reset-password.api.ts new file mode 100644 index 0000000..9ffd7f2 --- /dev/null +++ b/src/modules/users/edit-reset-password/api/edit-reset-password.api.ts @@ -0,0 +1,7 @@ +import axios from 'axios'; + +export const updatePassword = async (password: string, id: string): Promise => { + const response = await axios.put(`/api/user/${id}`, { contraseña: password }); + + return response.data; +}; diff --git a/src/modules/users/edit-reset-password/api/index.ts b/src/modules/users/edit-reset-password/api/index.ts new file mode 100644 index 0000000..8da65fa --- /dev/null +++ b/src/modules/users/edit-reset-password/api/index.ts @@ -0,0 +1 @@ +export * from './edit-reset-password.api'; diff --git a/src/modules/users/edit-reset-password/components/alerts-reset-password.componet.tsx b/src/modules/users/edit-reset-password/components/alerts-reset-password.componet.tsx new file mode 100644 index 0000000..bb04279 --- /dev/null +++ b/src/modules/users/edit-reset-password/components/alerts-reset-password.componet.tsx @@ -0,0 +1,25 @@ +import React from 'react'; +import { Alert } from '@mui/material'; +import CheckIcon from '@mui/icons-material/Check'; + +interface Props { + handleClose: () => void; +} + +export const SuccessAlertResetPassword: React.FC = props => { + const { handleClose } = props; + return ( + } severity="success" onClose={handleClose}> + Contraseña reseteada exitosamente. + + ); +}; + +export const ErrorAlertResetPassword: React.FC = props => { + const { handleClose } = props; + return ( + } severity="error" onClose={handleClose}> + Error: La contraseña no ha podido ser cambiada. Intente de nuevo. + + ); +}; diff --git a/src/modules/users/edit-reset-password/components/confirm-reset-dialog.component.tsx b/src/modules/users/edit-reset-password/components/confirm-reset-dialog.component.tsx index 0a0aaa7..b9615d5 100644 --- a/src/modules/users/edit-reset-password/components/confirm-reset-dialog.component.tsx +++ b/src/modules/users/edit-reset-password/components/confirm-reset-dialog.component.tsx @@ -5,33 +5,39 @@ import DialogActions from '@mui/material/DialogActions'; import DialogContent from '@mui/material/DialogContent'; import DialogContentText from '@mui/material/DialogContentText'; import DialogTitle from '@mui/material/DialogTitle'; +import { Spinner } from '#common/components/spinner/spinner.component.tsx'; interface Props { open: boolean; handleClose: () => void; + onConfirm: () => void; + isLoading: boolean; } export const ConfirmResetDialog: React.FC = props => { - const { open, handleClose } = props; + const { open, handleClose, onConfirm, isLoading } = props; return ( - - - - {'¿Está seguro que desea resetear la contraseña de este usuario?'} - - - - Si está seguro de cambiar la contraseña presiona CONFIRMAR, de lo contrario presiona CANCELAR - - - - - - - - + <> + + + + + {'¿Está seguro que desea resetear la contraseña de este usuario?'} + + + + Si está seguro de cambiar la contraseña presiona CONFIRMAR, de lo contrario presiona CANCELAR + + + + + + + + + ); }; diff --git a/src/modules/users/edit-reset-password/components/index.ts b/src/modules/users/edit-reset-password/components/index.ts index ef7033a..5ba459f 100644 --- a/src/modules/users/edit-reset-password/components/index.ts +++ b/src/modules/users/edit-reset-password/components/index.ts @@ -1 +1,2 @@ export * from './confirm-reset-dialog.component'; +export * from './alerts-reset-password.componet'; diff --git a/src/modules/users/edit-reset-password/edit-reset-password.component.tsx b/src/modules/users/edit-reset-password/edit-reset-password.component.tsx index 4212189..b585903 100644 --- a/src/modules/users/edit-reset-password/edit-reset-password.component.tsx +++ b/src/modules/users/edit-reset-password/edit-reset-password.component.tsx @@ -10,11 +10,25 @@ import { ConfirmResetDialog } from './components'; import { handleCopyPassword } from './edit-reset-password.business'; import { createEmptyInitialResetPassword } from './edit-reset-password.vm'; import * as classes from './edit-reset-password.styles'; +import { useUpdateUserPasswordMutation } from './edit-reset-password.query.hook'; +import { ErrorAlertResetPassword, SuccessAlertResetPassword } from './components/alerts-reset-password.componet'; -export const EditResetPasswordComponent: React.FC = () => { +interface Props { + userId: string; +} + +export const EditResetPasswordComponent: React.FC = (props: Props) => { + const { userId } = props; const { showPassword, toggleShowPassword } = usePassword(); + const { isOpen: isOpenDialog, onToggle: onToggleDialog } = useToggle(false); + const { isOpen: isOpenAlert, onToggle: onToggleAlert } = useToggle(false); + const { savePassword, isPending, isSuccess, isError } = useUpdateUserPasswordMutation(); - const { isOpen, onToggle } = useToggle(false); + const handleConfirmPassword = (newPassword: string, userId: string) => { + savePassword({ password: newPassword, id: userId }); + onToggleDialog(); + onToggleAlert(); + }; return (
@@ -25,43 +39,54 @@ export const EditResetPasswordComponent: React.FC = () => { validate={formValidation.validateForm} onSubmit={() => {}} > - {({ values, isValid, dirty }) => ( -
-
- - {showPassword ? : } - - ), - }, - }} - /> - { - handleCopyPassword(values.contraseña || ''); - }} - className={classes.icon} - > - - -
+ {({ values, isValid, dirty, resetForm }) => ( + <> + +
+ + {showPassword ? : } + + ), + }, + }} + /> + { + handleCopyPassword(values.contraseña || ''); + }} + className={classes.icon} + > + + +
-
- -
-
+
+ +
+ + { + handleConfirmPassword(values.contraseña, userId); + resetForm(); + }} + /> + )} - - + {isSuccess && isOpenAlert && } + {isError && isOpenAlert && }
); diff --git a/src/modules/users/edit-reset-password/edit-reset-password.pod.tsx b/src/modules/users/edit-reset-password/edit-reset-password.pod.tsx index 1669ab7..a16857d 100644 --- a/src/modules/users/edit-reset-password/edit-reset-password.pod.tsx +++ b/src/modules/users/edit-reset-password/edit-reset-password.pod.tsx @@ -1,16 +1,15 @@ import React from 'react'; import { EditResetPasswordComponent } from './edit-reset-password.component'; -// TO DO: prop id se usará cuando el endpoint de reseteo de clave esté listo interface Props { id: string; } -export const EditResetPassword: React.FC = () => { - // const { id } = props; +export const EditResetPassword: React.FC = props => { + const { id } = props; return ( <> - + ); }; diff --git a/src/modules/users/edit-reset-password/edit-reset-password.query.hook.ts b/src/modules/users/edit-reset-password/edit-reset-password.query.hook.ts new file mode 100644 index 0000000..3a426dc --- /dev/null +++ b/src/modules/users/edit-reset-password/edit-reset-password.query.hook.ts @@ -0,0 +1,32 @@ +import { useMutation } from '@tanstack/react-query'; +import { updatePassword } from './api'; + +interface ParamsMutationPassword { + password: string; + id: string; +} + +interface UseSavePasswordMutationResult { + savePassword: (params: ParamsMutationPassword) => void; + isPending: boolean; + isSuccess: boolean; + isError: boolean; +} + +export const useUpdateUserPasswordMutation = (): UseSavePasswordMutationResult => { + const { + mutate: savePassword, + isPending, + isSuccess, + isError, + } = useMutation({ + mutationFn: ({ password, id }: ParamsMutationPassword) => updatePassword(password, id), + }); + + return { + savePassword, + isPending, + isSuccess, + isError, + }; +}; From 1fbec849d22392336788655ebc22fda6b3eaad76 Mon Sep 17 00:00:00 2001 From: manudous Date: Fri, 25 Apr 2025 10:16:00 +0200 Subject: [PATCH 2/3] feat: implement password reset functionality and integrate snackbar notifications --- mock-server/src/dals/user/user.repository.ts | 4 ++ mock-server/src/pods/user/user.rest-api.ts | 17 +++++++ src/common/components/index.ts | 1 + src/common/components/snackbar/index.ts | 4 ++ .../snackbar/snackbar.component.tsx | 35 +++++++++++++ .../components/snackbar/snackbar.context.tsx | 51 +++++++++++++++++++ .../components/snackbar/snackbar.hook.tsx | 13 +++++ .../components/snackbar/snackbar.styles.ts | 35 +++++++++++++ src/common/components/snackbar/snackbar.vm.ts | 6 +++ src/core/notification/index.ts | 2 + src/core/notification/notification.hooks.ts | 16 ++++++ .../notification/notification.provider.tsx | 17 +++++++ src/main.tsx | 7 ++- .../api/edit-reset-password.api.ts | 2 +- .../alerts-reset-password.componet.tsx | 25 --------- .../edit-reset-password/components/index.ts | 1 - .../edit-reset-password.component.tsx | 17 ++----- .../edit-reset-password.pod.tsx | 6 +-- .../edit-reset-password.query.hook.ts | 23 +++++---- 19 files changed, 225 insertions(+), 57 deletions(-) create mode 100644 src/common/components/snackbar/index.ts create mode 100644 src/common/components/snackbar/snackbar.component.tsx create mode 100644 src/common/components/snackbar/snackbar.context.tsx create mode 100644 src/common/components/snackbar/snackbar.hook.tsx create mode 100644 src/common/components/snackbar/snackbar.styles.ts create mode 100644 src/common/components/snackbar/snackbar.vm.ts create mode 100644 src/core/notification/index.ts create mode 100644 src/core/notification/notification.hooks.ts create mode 100644 src/core/notification/notification.provider.tsx delete mode 100644 src/modules/users/edit-reset-password/components/alerts-reset-password.componet.tsx diff --git a/mock-server/src/dals/user/user.repository.ts b/mock-server/src/dals/user/user.repository.ts index 71de253..6b28d15 100644 --- a/mock-server/src/dals/user/user.repository.ts +++ b/mock-server/src/dals/user/user.repository.ts @@ -27,4 +27,8 @@ export const userRepository = { } return index !== -1; }, + // resetPassword: async (id: string, password: string): Promise => { + // // reset password, el db.users[index].password = password; + // return true; + // }, }; diff --git a/mock-server/src/pods/user/user.rest-api.ts b/mock-server/src/pods/user/user.rest-api.ts index d03c788..0120412 100644 --- a/mock-server/src/pods/user/user.rest-api.ts +++ b/mock-server/src/pods/user/user.rest-api.ts @@ -63,4 +63,21 @@ userApi } catch (error) { next(error); } + }) + // TODO: Implementar la lógica para actualizar el password + .put('/resetPassword/:id', async (req, res, next) => { + try { + //const { id } = req.params; + //const { contraseña } = req.body; + // comporabar si existe el usuario sino mandamos un erro un 404 + //const estaActualizado = await userRepository.resetPassword(id, contraseña); + // if (usaarioexiste) { + // await userRepository.resetPassword(id, password); + // } else { + // res.sendStatus(404); + // } + //res.status(201).send(estaActualizado); + } catch (error) { + next(error); + } }); diff --git a/src/common/components/index.ts b/src/common/components/index.ts index 829e726..b2fbd6d 100644 --- a/src/common/components/index.ts +++ b/src/common/components/index.ts @@ -4,3 +4,4 @@ export * from './sidebar-menu'; export * from './navigation-button'; export * from './spinner'; export * from './form'; +export * from './snackbar'; diff --git a/src/common/components/snackbar/index.ts b/src/common/components/snackbar/index.ts new file mode 100644 index 0000000..52b0843 --- /dev/null +++ b/src/common/components/snackbar/index.ts @@ -0,0 +1,4 @@ +export * from './snackbar.component'; +export { SnackbarProvider } from './snackbar.context'; +export { useSnackbarContext } from './snackbar.hook'; +export * from './snackbar.vm'; diff --git a/src/common/components/snackbar/snackbar.component.tsx b/src/common/components/snackbar/snackbar.component.tsx new file mode 100644 index 0000000..69e7b4e --- /dev/null +++ b/src/common/components/snackbar/snackbar.component.tsx @@ -0,0 +1,35 @@ +import React from 'react'; +import Snackbar, { SnackbarOrigin } from '@mui/material/Snackbar'; +import SnackbarContent from '@mui/material/SnackbarContent'; +import IconButton from '@mui/material/IconButton'; +import CloseIcon from '@mui/icons-material/Close'; +import { useSnackbar } from './snackbar.context'; +import * as classes from './snackbar.styles'; + +interface Props { + autoHideDuration?: number; + position?: SnackbarOrigin; +} + +export const SnackbarComponent: React.FunctionComponent = props => { + const { position = { horizontal: 'right', vertical: 'top' }, autoHideDuration = 3000 } = props; + const { open, onClose, options } = useSnackbar(); + + return ( + + + + , + ]} + /> + + ); +}; diff --git a/src/common/components/snackbar/snackbar.context.tsx b/src/common/components/snackbar/snackbar.context.tsx new file mode 100644 index 0000000..7459a1b --- /dev/null +++ b/src/common/components/snackbar/snackbar.context.tsx @@ -0,0 +1,51 @@ +import React, { PropsWithChildren } from 'react'; +import { SnackbarOptions } from './snackbar.vm'; +import { SnackbarCloseReason } from '@mui/material'; + +interface Context { + open: boolean; + setOpen: (open: boolean) => void; + onClose: (event?: React.SyntheticEvent | Event, reason?: SnackbarCloseReason) => void; + options: SnackbarOptions; + setOptions: (options: SnackbarOptions) => void; +} + +export const SnackbarContext = React.createContext(null); + +export const SnackbarProvider: React.FC = props => { + const { children } = props; + const [open, setOpen] = React.useState(false); + const [options, setOptions] = React.useState({ + message: '', + variant: 'success', + }); + + const handleClose = (_?: React.SyntheticEvent | Event, reason?: SnackbarCloseReason) => { + if (reason === 'clickaway') { + return; + } + setOpen(false); + }; + + return ( + + {children} + + ); +}; + +export const useSnackbar = () => { + const context = React.useContext(SnackbarContext); + if (!context) { + throw new Error('useSnackbar must be used within a SnackbarProvider'); + } + return context; +}; diff --git a/src/common/components/snackbar/snackbar.hook.tsx b/src/common/components/snackbar/snackbar.hook.tsx new file mode 100644 index 0000000..48faede --- /dev/null +++ b/src/common/components/snackbar/snackbar.hook.tsx @@ -0,0 +1,13 @@ +import { useSnackbar } from './snackbar.context'; +import { Variant } from './snackbar.vm'; + +export const useSnackbarContext = () => { + const { setOptions, setOpen } = useSnackbar(); + + return { + showMessage: (message: string, variant: Variant) => { + setOptions({ message, variant }); + setOpen(true); + }, + }; +}; diff --git a/src/common/components/snackbar/snackbar.styles.ts b/src/common/components/snackbar/snackbar.styles.ts new file mode 100644 index 0000000..feb79d0 --- /dev/null +++ b/src/common/components/snackbar/snackbar.styles.ts @@ -0,0 +1,35 @@ +import { css } from '@emotion/css'; +import { theme } from '#core/theme'; + +export const success = css` + &.MuiSnackbarContent-root { + background-color: ${theme.palette.success.main}; + } +`; + +export const error = css` + &.MuiSnackbarContent-root { + background-color: ${theme.palette.error.dark}; + } +`; + +export const info = css` + &.MuiSnackbarContent-root { + background-color: ${theme.palette.info.main}; + } +`; + +export const warning = css` + &.MuiSnackbarContent-root { + background-color: ${theme.palette.warning.main}; + } +`; + +export const snackbarContent = css` + align-items: flex-start; +`; + +export const message = css` + align-self: center; + white-space: pre; +`; diff --git a/src/common/components/snackbar/snackbar.vm.ts b/src/common/components/snackbar/snackbar.vm.ts new file mode 100644 index 0000000..5adf446 --- /dev/null +++ b/src/common/components/snackbar/snackbar.vm.ts @@ -0,0 +1,6 @@ +export type Variant = 'success' | 'info' | 'warning' | 'error'; + +export interface SnackbarOptions { + message: string; + variant: Variant; +} diff --git a/src/core/notification/index.ts b/src/core/notification/index.ts new file mode 100644 index 0000000..527f422 --- /dev/null +++ b/src/core/notification/index.ts @@ -0,0 +1,2 @@ +export * from './notification.provider'; +export * from './notification.hooks'; diff --git a/src/core/notification/notification.hooks.ts b/src/core/notification/notification.hooks.ts new file mode 100644 index 0000000..f633e18 --- /dev/null +++ b/src/core/notification/notification.hooks.ts @@ -0,0 +1,16 @@ +import { Variant, useSnackbarContext } from '#common/components'; + +export type Notify = { + notify: (message: string, variant?: Variant) => void; +}; + +export const useNotification = (): Notify => { + const { showMessage } = useSnackbarContext(); + const notify = (message: string, variant: Variant = 'error') => { + showMessage(message, variant); + }; + + return { + notify, + }; +}; diff --git a/src/core/notification/notification.provider.tsx b/src/core/notification/notification.provider.tsx new file mode 100644 index 0000000..a4df3a8 --- /dev/null +++ b/src/core/notification/notification.provider.tsx @@ -0,0 +1,17 @@ +import React from 'react'; +import { SnackbarComponent, SnackbarProvider } from '#common/components'; + +interface Props { + children: React.ReactNode; +} + +export const NotificationProvider: React.FC = props => { + const { children } = props; + + return ( + + + {children} + + ); +}; diff --git a/src/main.tsx b/src/main.tsx index f824cb0..cb7060f 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -6,6 +6,7 @@ import { RouterProvider } from '@tanstack/react-router'; import { queryClient } from './core/react-query'; import { router } from './core/router'; import { ThemeProvider } from './core/theme'; +import { NotificationProvider } from './core/notification'; const App = () => { return ; @@ -15,8 +16,10 @@ createRoot(document.getElementById('root')!).render( - - + + + + diff --git a/src/modules/users/edit-reset-password/api/edit-reset-password.api.ts b/src/modules/users/edit-reset-password/api/edit-reset-password.api.ts index 9ffd7f2..7e37acb 100644 --- a/src/modules/users/edit-reset-password/api/edit-reset-password.api.ts +++ b/src/modules/users/edit-reset-password/api/edit-reset-password.api.ts @@ -1,7 +1,7 @@ import axios from 'axios'; export const updatePassword = async (password: string, id: string): Promise => { - const response = await axios.put(`/api/user/${id}`, { contraseña: password }); + const response = await axios.put(`/api/user/resetPassword/${id}`, { contraseña: password }); return response.data; }; diff --git a/src/modules/users/edit-reset-password/components/alerts-reset-password.componet.tsx b/src/modules/users/edit-reset-password/components/alerts-reset-password.componet.tsx deleted file mode 100644 index bb04279..0000000 --- a/src/modules/users/edit-reset-password/components/alerts-reset-password.componet.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import React from 'react'; -import { Alert } from '@mui/material'; -import CheckIcon from '@mui/icons-material/Check'; - -interface Props { - handleClose: () => void; -} - -export const SuccessAlertResetPassword: React.FC = props => { - const { handleClose } = props; - return ( - } severity="success" onClose={handleClose}> - Contraseña reseteada exitosamente. - - ); -}; - -export const ErrorAlertResetPassword: React.FC = props => { - const { handleClose } = props; - return ( - } severity="error" onClose={handleClose}> - Error: La contraseña no ha podido ser cambiada. Intente de nuevo. - - ); -}; diff --git a/src/modules/users/edit-reset-password/components/index.ts b/src/modules/users/edit-reset-password/components/index.ts index 5ba459f..ef7033a 100644 --- a/src/modules/users/edit-reset-password/components/index.ts +++ b/src/modules/users/edit-reset-password/components/index.ts @@ -1,2 +1 @@ export * from './confirm-reset-dialog.component'; -export * from './alerts-reset-password.componet'; diff --git a/src/modules/users/edit-reset-password/edit-reset-password.component.tsx b/src/modules/users/edit-reset-password/edit-reset-password.component.tsx index b585903..45e1861 100644 --- a/src/modules/users/edit-reset-password/edit-reset-password.component.tsx +++ b/src/modules/users/edit-reset-password/edit-reset-password.component.tsx @@ -4,14 +4,13 @@ import { Button, IconButton } from '@mui/material'; import { Visibility, VisibilityOff, ContentCopy } from '@mui/icons-material'; import { TextFieldForm } from '#common/components'; import { useToggle } from '#common/hooks'; +import { ConfirmResetDialog } from './components'; import { formValidation } from './validations'; import { usePassword } from '../create/use-password.hook'; -import { ConfirmResetDialog } from './components'; import { handleCopyPassword } from './edit-reset-password.business'; import { createEmptyInitialResetPassword } from './edit-reset-password.vm'; -import * as classes from './edit-reset-password.styles'; import { useUpdateUserPasswordMutation } from './edit-reset-password.query.hook'; -import { ErrorAlertResetPassword, SuccessAlertResetPassword } from './components/alerts-reset-password.componet'; +import * as classes from './edit-reset-password.styles'; interface Props { userId: string; @@ -21,14 +20,10 @@ export const EditResetPasswordComponent: React.FC = (props: Props) => { const { userId } = props; const { showPassword, toggleShowPassword } = usePassword(); const { isOpen: isOpenDialog, onToggle: onToggleDialog } = useToggle(false); - const { isOpen: isOpenAlert, onToggle: onToggleAlert } = useToggle(false); - const { savePassword, isPending, isSuccess, isError } = useUpdateUserPasswordMutation(); + const { savePassword, isPending } = useUpdateUserPasswordMutation(onToggleDialog); - const handleConfirmPassword = (newPassword: string, userId: string) => { + const handleConfirmPassword = (newPassword: string, userId: string) => savePassword({ password: newPassword, id: userId }); - onToggleDialog(); - onToggleAlert(); - }; return (
@@ -37,7 +32,7 @@ export const EditResetPasswordComponent: React.FC = (props: Props) => { initialValues={createEmptyInitialResetPassword()} enableReinitialize={true} validate={formValidation.validateForm} - onSubmit={() => {}} + onSubmit={onToggleDialog} > {({ values, isValid, dirty, resetForm }) => ( <> @@ -85,8 +80,6 @@ export const EditResetPasswordComponent: React.FC = (props: Props) => { )} - {isSuccess && isOpenAlert && } - {isError && isOpenAlert && }
); diff --git a/src/modules/users/edit-reset-password/edit-reset-password.pod.tsx b/src/modules/users/edit-reset-password/edit-reset-password.pod.tsx index a16857d..d7a2942 100644 --- a/src/modules/users/edit-reset-password/edit-reset-password.pod.tsx +++ b/src/modules/users/edit-reset-password/edit-reset-password.pod.tsx @@ -7,9 +7,5 @@ interface Props { export const EditResetPassword: React.FC = props => { const { id } = props; - return ( - <> - - - ); + return ; }; diff --git a/src/modules/users/edit-reset-password/edit-reset-password.query.hook.ts b/src/modules/users/edit-reset-password/edit-reset-password.query.hook.ts index 3a426dc..80fc783 100644 --- a/src/modules/users/edit-reset-password/edit-reset-password.query.hook.ts +++ b/src/modules/users/edit-reset-password/edit-reset-password.query.hook.ts @@ -1,4 +1,5 @@ import { useMutation } from '@tanstack/react-query'; +import { useNotification } from '#core/notification'; import { updatePassword } from './api'; interface ParamsMutationPassword { @@ -9,24 +10,24 @@ interface ParamsMutationPassword { interface UseSavePasswordMutationResult { savePassword: (params: ParamsMutationPassword) => void; isPending: boolean; - isSuccess: boolean; - isError: boolean; } -export const useUpdateUserPasswordMutation = (): UseSavePasswordMutationResult => { - const { - mutate: savePassword, - isPending, - isSuccess, - isError, - } = useMutation({ +export const useUpdateUserPasswordMutation = (onToggleDialog: () => void): UseSavePasswordMutationResult => { + const { notify } = useNotification(); + const { mutate: savePassword, isPending } = useMutation({ mutationFn: ({ password, id }: ParamsMutationPassword) => updatePassword(password, id), + onSuccess: () => { + onToggleDialog(); + notify('Contraseña actualizada correctamente', 'success'); + }, + onError: () => { + onToggleDialog(); + notify('Error al actualizar la contraseña', 'error'); + }, }); return { savePassword, isPending, - isSuccess, - isError, }; }; From c6577cb017943970fd4a52bf8b0e751358902d3e Mon Sep 17 00:00:00 2001 From: manugallegob Date: Sun, 18 May 2025 12:42:15 +0200 Subject: [PATCH 3/3] =?UTF-8?q?creaci=C3=B3n=20de=20endpoint=20para=20rese?= =?UTF-8?q?t=20password?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mock-server/src/dals/user/user.repository.ts | 11 +++++++---- mock-server/src/pods/user/user.rest-api.ts | 8 ++++++++ 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/mock-server/src/dals/user/user.repository.ts b/mock-server/src/dals/user/user.repository.ts index 6b28d15..5c50d93 100644 --- a/mock-server/src/dals/user/user.repository.ts +++ b/mock-server/src/dals/user/user.repository.ts @@ -27,8 +27,11 @@ export const userRepository = { } return index !== -1; }, - // resetPassword: async (id: string, password: string): Promise => { - // // reset password, el db.users[index].password = password; - // return true; - // }, + resetPassword: async (id: string, nuevaContraseña: string): Promise => { + const index = db.users.findIndex(user => user._id.toHexString() === id); + if (index !== -1) { + db.users[index].contraseña = nuevaContraseña; + } + return index !== -1; + }, }; diff --git a/mock-server/src/pods/user/user.rest-api.ts b/mock-server/src/pods/user/user.rest-api.ts index 0120412..aa784b3 100644 --- a/mock-server/src/pods/user/user.rest-api.ts +++ b/mock-server/src/pods/user/user.rest-api.ts @@ -77,6 +77,14 @@ userApi // res.sendStatus(404); // } //res.status(201).send(estaActualizado); + const { id } = req.params; + const { contraseña } = req.body; + const contraseñaEstaActualizada = await userRepository.resetPassword(id, contraseña); + if (contraseñaEstaActualizada) { + res.status(200).send(contraseñaEstaActualizada); + } else { + res.sendStatus(404); + } } catch (error) { next(error); }