Página de perfil mostra dados do banco de dados do usuário autenticado

This commit is contained in:
Matheus Albino Brunhara
2022-05-16 20:11:15 -05:00
parent f848e20492
commit 453c763f6d
9 changed files with 265 additions and 44 deletions

View File

@@ -29,7 +29,7 @@ import '@ionic/react/css/display.css';
/* Theme variables */ /* Theme variables */
import './theme/variables.css'; import './theme/variables.css';
// import Tabs from './components/Tabs'; import Perfil from './pages/Perfil';
setupIonicReact(); setupIonicReact();
@@ -41,6 +41,8 @@ const App: React.FC = () => (
<Route exact path="/mainpages" component={MainPages}></Route> <Route exact path="/mainpages" component={MainPages}></Route>
<Route exact path="/cadastro" component={Cadastro}></Route> <Route exact path="/cadastro" component={Cadastro}></Route>
<Route exact path="/login" component={Login}></Route> <Route exact path="/login" component={Login}></Route>
<Route exact path="/perfil" component={Perfil}></Route>
{/* <Route exact path="/perfil/edit" component={Perfil}></Route> TODO */}
<Route exact path="/"> <Route exact path="/">
<Redirect to="/cadastro" /> <Redirect to="/cadastro" />
</Route> </Route>

View File

@@ -2,16 +2,22 @@ const tokenId = 'token';
const productDetails = '@productDetails'; const productDetails = '@productDetails';
const LocalStorage = { const LocalStorage = {
getToken: (): string | null => { getToken: (): string => {
return localStorage.getItem(tokenId) const tokenId = localStorage.getItem('tokenId')
if (!tokenId) {
return ''
}
return tokenId
}, },
setToken: (token: string) => { setToken: (token: string) => {
localStorage.setItem(tokenId, token) localStorage.setItem('tokenId', token)
}, },
clearToken: () => { clearToken: () => {
localStorage.setItem(tokenId, ''); localStorage.removeItem('tokenId')
} }
} }

View File

@@ -0,0 +1,11 @@
const usersRoutesDefault = '/users';
const usersRoutes = {
create: {
url: `${usersRoutesDefault}/create`
},
get: {
url: `${usersRoutesDefault}`
}
}
export default usersRoutes;

View File

@@ -7,15 +7,12 @@ import {
} from "@ionic/react"; } from "@ionic/react";
import React, { useState } from "react"; import React, { useState } from "react";
import { IonGrid, IonRow, IonCol, IonToast } from "@ionic/react"; import { IonGrid, IonRow, IonCol, IonToast } from "@ionic/react";
import { personCircle } from "ionicons/icons";
import { useHistory } from "react-router-dom"; import { useHistory } from "react-router-dom";
import { import {
IonItem, IonItem,
IonLabel, IonLabel,
IonInput, IonInput,
IonButton, IonButton,
IonIcon,
IonAlert,
} from "@ionic/react"; } from "@ionic/react";
import * as sessionRoutes from '../services/session'; import * as sessionRoutes from '../services/session';
@@ -29,11 +26,10 @@ const Page: React.FC = () => {
const history = useHistory(); const history = useHistory();
const [email, setEmail] = useState<string>("matheusalb3213@gmail.com"); const [email, setEmail] = useState<string>("matheusalb3213@gmail.com");
const [password, setPassword] = useState<string>("123456"); const [password, setPassword] = useState<string>("123456");
const [isError, setIsError] = useState<boolean>(false);
const [message, setMessage] = useState<string>("");
function validateEmail(email: string) { function validateEmail(email: string) {
const re = const re =
// eslint-disable-next-line no-control-regex
/^((?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\]))$/; /^((?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\]))$/;
return re.test(String(email).toLowerCase()); return re.test(String(email).toLowerCase());
} }
@@ -107,15 +103,6 @@ const Page: React.FC = () => {
</IonToolbar> </IonToolbar>
</IonHeader> </IonHeader>
<IonRow>
<IonCol>
<IonIcon
style={{ fontSize: "70px", color: "#0040ff" }}
icon={personCircle}
/>
</IonCol>
</IonRow>
<IonContent fullscreen> <IonContent fullscreen>
<IonHeader collapse="condense"> <IonHeader collapse="condense">
<IonToolbar> <IonToolbar>
@@ -124,19 +111,6 @@ const Page: React.FC = () => {
</IonHeader> </IonHeader>
<IonGrid> <IonGrid>
<IonRow>
<IonCol>
<IonAlert
isOpen={isError}
onDidDismiss={() => setIsError(false)}
cssClass="my-custom-class"
header={"Error!"}
message={message}
buttons={["Dismiss"]}
/>
</IonCol>
</IonRow>
<IonRow> <IonRow>
<IonCol> <IonCol>
<IonItem> <IonItem>
@@ -165,10 +139,6 @@ const Page: React.FC = () => {
<IonRow> <IonRow>
<IonCol> <IonCol>
<p style={{ fontSize: "small" }}>
Clicando no botão de "Login", você concorda com a nossa{" "}
<a href="#">política de termos e serviços</a>
</p>
<IonButton expand="block" onClick={handleLogin}> <IonButton expand="block" onClick={handleLogin}>
Login Login
</IonButton> </IonButton>

3
src/pages/Perfil.css Normal file
View File

@@ -0,0 +1,3 @@
#avatar {
border-radius: 50%;
}

151
src/pages/Perfil.tsx Normal file
View File

@@ -0,0 +1,151 @@
import {
IonCard,
IonCardContent,
IonCardHeader,
IonCardTitle,
IonContent,
IonFab,
IonFabButton,
IonHeader,
IonIcon,
IonPage,
IonTitle,
IonToast,
IonToolbar,
} from "@ionic/react";
import { useHistory } from "react-router-dom";
import React, { useState, useEffect, useReducer } from "react";
import { IonRow, IonCol } from "@ionic/react";
import { createOutline } from "ionicons/icons";
import * as sessionRoutes from '../services/session';
import * as usersRoutes from '../services/users';
import './Perfil.css'
import LocalStorage from "../LocalStorage";
const Perfil: React.FC = () => {
const [showToast, setShowToast] = useState(false);
const [messageToast, setMessageToast ] = useState('');
const [inputValues, setInputValues] = useReducer(
(state: any, newState: any) => ({ ...state, ...newState }),
{
fullname: '',
bio: ''
}
);
const history = useHistory();
const loadUserData = async () => {
let userId = ''
await sessionRoutes.refresh().then(response => {
if (response.status === 'error') {
setMessageToast(response.message);
setShowToast(true);
return
}
userId = response.userId
}).catch(error => {
console.dir('Houve um erro: ', { error })
alert('Houve um erro')
})
await usersRoutes.getById(userId).then(response => {
if (response.status === 'error') {
setMessageToast(response.message.data)
setShowToast(true);
return
}
const userData = response.data
setInputValues({'fullname': userData.name, 'bio': userData.bio});
}).catch(error => {
console.dir('Houve um erro: ', { error })
alert('Houve um erro')
})
}
useEffect(() => {
const userToken = LocalStorage.getToken()
if (!userToken) {
// TODO, não impede o usuário de retornar a página de login
history.push({ pathname: '/login' });
setMessageToast("Por favor, autentique-se!");
setShowToast(true);
}
// const refreshResponse = refreshSession()
loadUserData()
}, []);
const handleEditProfile = () => {
alert('oi')
}
return (
<IonPage>
<IonHeader>
<IonToolbar>
<IonTitle>Seu perfil</IonTitle>
</IonToolbar>
</IonHeader>
<IonContent fullscreen>
<IonHeader collapse="condense">
<IonToolbar>
<IonTitle size="large">Seu perfil</IonTitle>
</IonToolbar>
</IonHeader>
<IonCard>
<IonCardContent>
<IonRow>
<IonCol></IonCol>
<IonCol>
<img src="https://static.generated.photos/vue-static/home/feed/adult.png" alt="avatar" className='avatar' id='avatar'/>
</IonCol>
<IonCol></IonCol>
</IonRow>
<IonCardHeader>
<IonCardTitle class="ion-text-center">{inputValues.fullname}</IonCardTitle>
</IonCardHeader>
</IonCardContent>
</IonCard>
<IonCard>
<IonCardHeader>
<IonCardTitle>Biografia</IonCardTitle>
</IonCardHeader>
<IonCardContent>
{inputValues.bio ? inputValues.bio : 'Sem biografia.'}
</IonCardContent>
</IonCard>
<IonFab vertical="bottom" horizontal="end" slot="fixed" onClick={handleEditProfile}>
<IonFabButton>
<IonIcon icon={createOutline} />
</IonFabButton>
</IonFab>
<IonToast
color='danger'
isOpen={showToast}
onDidDismiss={() => setShowToast(false)}
message={messageToast}
duration={2500}
/>
</IonContent>
</IonPage>
);
};
export default Perfil;

View File

@@ -0,0 +1,66 @@
import {
IonCard,
IonCardContent,
IonCardHeader,
IonCardTitle,
IonContent,
IonFab,
IonFabButton,
IonGrid,
IonHeader,
IonIcon,
IonInput,
IonItem,
IonLabel,
IonPage,
IonTitle,
IonToolbar
} from "@ionic/react";
import React, { useState } from "react";
import { IonRow, IonCol } from "@ionic/react";
import { createOutline } from "ionicons/icons";
import './Perfil.css'
const Perfil: React.FC = () => {
const [email, setEmail] = useState<string>("matheusalb3213@gmail.com");
const handleEditProfile = () => {
alert('oi')
}
return (
<IonPage>
<IonHeader>
<IonToolbar>
<IonTitle>Editar perfil</IonTitle>
</IonToolbar>
</IonHeader>
<IonContent fullscreen>
<IonHeader collapse="condense">
<IonToolbar>
<IonTitle size="large">Editar perfil</IonTitle>
</IonToolbar>
</IonHeader>
<IonGrid>
<IonRow>
<IonCol>
<IonItem>
<IonLabel position="floating"> Email</IonLabel>
<IonInput
type="email"
value={email}
onIonChange={(e) => setEmail(e.detail.value!)}
></IonInput>
</IonItem>
</IonCol>
</IonRow>
</IonGrid>
</IonContent>
</IonPage>
);
};
export default Perfil;

View File

@@ -14,8 +14,8 @@ interface createData {
function updateHeader() { function updateHeader() {
token = LocalStorage.getToken(); token = LocalStorage.getToken();
header = { header = {
Accept: 'application/json', "Accept": 'application/json',
'Content-Type': 'application/json', "Content-Type": 'application/json',
"Authorization": 'Bearer ' + token "Authorization": 'Bearer ' + token
} }
} }

View File

@@ -1,16 +1,21 @@
import instance from '../services/api'; import instance from '../services/api';
// import LocalStorage from '../LocalStorage'; // import LocalStorage from '../LocalStorage';
let token:string; import userRoutes from '../constants/routes/usersRoutes';
let header:string; import { AxiosRequestHeaders } from 'axios';
import LocalStorage from '../LocalStorage';
let token: string;
let header: AxiosRequestHeaders;
function updateHeader() { function updateHeader() {
// token = LocalStorage.getToken(); token = LocalStorage.getToken();
header = `{
header = {
"Accept": 'application/json', "Accept": 'application/json',
"Content-Type": 'application/json', "Content-Type": 'application/json',
"Authorization": 'Bearer ' + token "Authorization": 'Bearer ' + token
}` }
} }
export interface CadastroResponse { export interface CadastroResponse {
@@ -40,6 +45,13 @@ export interface CadastroRequest {
export async function create(CadastroRequest: any) { export async function create(CadastroRequest: any) {
updateHeader(); updateHeader();
const response = await instance.post("http://localhost:3333/users/", CadastroRequest); const response = await instance.post(userRoutes.create.url, CadastroRequest);
return response.data;
}
export async function getById(userId: string) {
updateHeader();
const response = await instance.get(userRoutes.get.url + `/${userId}`, { headers: header });
return response.data; return response.data;
} }