@@ -3,14 +3,31 @@ import { useRef, useCallback } from 'react';
33import { FormHandles } from '@unform/core' ;
44import * as Yup from 'yup' ;
55import { Form } from '@unform/web' ;
6- import { FiAtSign , FiCheck , FiLock , FiPlus } from 'react-icons/fi' ;
6+ import {
7+ FiAtSign ,
8+ FiCheck ,
9+ FiFileText ,
10+ FiLock ,
11+ FiLogOut ,
12+ FiPlus ,
13+ FiRefreshCcw ,
14+ FiUserX ,
15+ } from 'react-icons/fi' ;
16+ import { useNavigate } from 'react-router' ;
717import getValidationErrors from '../../utils/getValidationErrors' ;
818import Input from '../../components/Input' ;
919import { Container , AnimationContainer } from './styles' ;
1020import api from '../../services/api' ;
1121
22+ interface PasswordUpdateFormData {
23+ oldPassword : string ;
24+ newPassword : string ;
25+ newPasswordConfirmation : string ;
26+ }
27+
1228export default function Account ( ) {
1329 const formRef = useRef < FormHandles > ( null ) ;
30+ const navigate = useNavigate ( ) ;
1431
1532 const handleDataExport = async ( ) => {
1633 // GET request + bearer token to data export endpoint
@@ -51,21 +68,108 @@ export default function Account() {
5168 ) ,
5269 } ) ;
5370
54- await schema . validate ( data , {
55- abortEarly : false ,
56- } ) ;
57- } catch ( err ) {
58- if ( err instanceof Yup . ValidationError ) {
59- const errors = getValidationErrors ( err ) ;
60- formRef . current ?. setErrors ( errors ) ;
61- } else throw err ;
71+ // Delete user info from localStorage and redirect user to login page
72+ const handleLogout = ( ) => {
73+ // Delete user token from localStorage
74+ localStorage . removeItem ( '@AlertaDoTesouro:token' ) ;
75+ localStorage . removeItem ( '@AlertaDoTesouro:user' ) ;
76+
77+
78+ // Redirect user to login page
79+ navigate ( '/login' ) ;
80+ } ;
81+
82+ const handleDeleteAccount = async ( ) => {
83+ if (
84+ window . confirm (
85+ 'Você realmente quer deletar sua conta? Esta ação é irreversível!' ,
86+ )
87+ ) {
88+ // Send DELETE request to API to delete user account, along with bearer token
89+ const userToken : string | null = localStorage . getItem (
90+ '@AlertaDoTesouro:token' ,
91+ ) ;
92+ if ( userToken ) {
93+ await api . delete ( '/users' , {
94+ headers : {
95+ Authorization : `Bearer ${ userToken } ` ,
96+ } ,
97+ } ) ;
98+
99+ // Simulate logout
100+ handleLogout ( ) ;
101+ }
62102 }
63- } , [ ] ) ;
103+ } ;
104+
105+ const getUserEmail = ( ) : string | undefined => {
106+ try {
107+ const userDataString : string | null = localStorage . getItem (
108+ '@AlertaDoTesouro:user' ,
109+ ) ;
110+ if ( userDataString ) {
111+ const user : Record < string , string > = JSON . parse (
112+ userDataString ,
113+ ) as Record < string , string > ;
114+ if ( user ) {
115+ const userEmail : string = user . email ;
116+ return userEmail ;
117+ }
118+ }
119+ } catch ( error ) {
120+ if ( error instanceof Error ) {
121+ console . log ( error ) ;
122+ }
123+ }
124+
125+ return '' ;
126+ } ;
127+
128+ const handlePasswordUpdate = useCallback (
129+ async ( data : PasswordUpdateFormData ) => {
130+ try {
131+ formRef . current ?. setErrors ( { } ) ;
132+
133+ // Redundant validation, but surely is a validation.
134+ const schema = Yup . object ( ) . shape ( {
135+ oldPassword : Yup . string ( ) . min ( 8 , 'Mínimo de 8 caracteres' ) ,
136+ newPassword : Yup . string ( ) . min ( 8 , 'Mínimo de 8 caracteres' ) ,
137+ newPasswordConfirmation : Yup . string ( ) . when (
138+ 'password' ,
139+ ( password : string , field : Yup . StringSchema ) =>
140+ password
141+ ? field
142+ . required ( 'Senhas devem ser iguais' )
143+ . oneOf ( [ Yup . ref ( 'password' ) ] , 'Senhas devem ser iguais' )
144+ : field ,
145+ ) ,
146+ } ) ;
147+
148+ await schema . validate ( data , {
149+ abortEarly : false ,
150+ } ) ;
151+
152+ await api . put ( '/users' , data ) ;
153+
154+ console . log ( 'Senha atualizada com sucesso.' ) ;
155+ } catch ( err ) {
156+ if ( err instanceof Yup . ValidationError ) {
157+ const errors = getValidationErrors ( err ) ;
158+ formRef . current ?. setErrors ( errors ) ;
159+ } else {
160+ console . log (
161+ 'Ocorreu um erro ao atualizar a senha. Tente novamente mais tarde.' ,
162+ ) ;
163+ }
164+ }
165+ } ,
166+ [ ] ,
167+ ) ;
64168
65169 return (
66170 < Container >
67171 < AnimationContainer >
68- < Form ref = { formRef } onSubmit = { handleSubmit } >
172+ < Form ref = { formRef } onSubmit = { handlePasswordUpdate } >
69173 < div id = "form-header" >
70174 < h1 > SUAS INFORMAÇÕES</ h1 >
71175 </ div >
@@ -77,6 +181,7 @@ export default function Account() {
77181 icon = { FiAtSign }
78182 name = "email"
79183 placeholder = "turing@inf.ufes.br"
184+ defaultValue = { getUserEmail ( ) }
80185 />
81186
82187 < div id = "input-header" >
@@ -101,20 +206,37 @@ export default function Account() {
101206 placeholder = "Confirmação de sua nova senha"
102207 />
103208
104- < button type = "submit" > Atualizar dados</ button >
105- < button id = "sair" type = "submit" >
106- Sair
107- </ button >
108- < button id = "deletar-conta" type = "submit" >
109- Deletar conta
209+ { /* 'Form' Submit */ }
210+ < button id = "atualizar-senha" type = "submit" >
211+ < FiRefreshCcw />
212+ Atualizar senha
110213 </ button >
214+
215+ { /* Data export */ }
111216 < button
112217 id = "exportar-dados"
113218 type = "button"
114219 onClick = { ( ) => handleDataExport ( ) }
115220 >
221+ < FiFileText />
116222 Exportar dados
117223 </ button >
224+
225+ { /* Logout */ }
226+ < button id = "sair" type = "button" onClick = { ( ) => handleLogout ( ) } >
227+ < FiLogOut />
228+ Sair
229+ </ button >
230+
231+ { /* Account deletion */ }
232+ < button
233+ id = "deletar-conta"
234+ type = "button"
235+ onClick = { ( ) => handleDeleteAccount ( ) }
236+ >
237+ < FiUserX />
238+ Deletar conta
239+ </ button >
118240 </ Form >
119241 </ AnimationContainer >
120242 </ Container >
0 commit comments