Componentizando header

This commit is contained in:
Matheus Albino Brunhara
2022-09-03 16:38:13 -03:00
parent df4fe0ffef
commit c0b26741bb
20 changed files with 596 additions and 518 deletions

View File

@@ -1,17 +1,19 @@
import { IonCol, IonRouterLink, IonRow } from "@ionic/react"; import { IonCol, IonRouterLink, IonRow } from "@ionic/react";
interface ComponentProps { interface ComponentProps {
message: string, message: string;
link: string, link: string;
text: string text: string;
} }
export const Action = (props: ComponentProps) => ( export const Action = (props: ComponentProps) => (
<IonRow className="ion-text-center ion-justify-content-center">
<IonRow className="ion-text-center ion-justify-content-center"> <IonCol size="12">
<IonCol size="12"> {props.message}
{ props.message } <IonRouterLink className="custom-link" routerLink={props.link}>
<IonRouterLink className="custom-link" routerLink={ props.link }> { props.text } &rarr;</IonRouterLink> {" "}
</IonCol> {props.text} &rarr;
</IonRow> </IonRouterLink>
</IonCol>
</IonRow>
); );

View File

@@ -0,0 +1,17 @@
import { IonBackButton, IonButtons, IonHeader, IonTitle, IonToolbar } from "@ionic/react";
interface ComponentProps {
pageName: string;
backButtonPageUrl?: string;
}
export const PageHeader = (props: ComponentProps) => (
<IonHeader translucent>
<IonToolbar>
<IonTitle>{props.pageName}</IonTitle>
<IonButtons slot="start">
<IonBackButton text="" defaultHref={ props.backButtonPageUrl ? props.backButtonPageUrl : undefined } />
</IonButtons>
</IonToolbar>
</IonHeader>
);

View File

@@ -1,16 +1,21 @@
import { import {
IonBackButton,
IonButton, IonButton,
IonButtons,
IonCard, IonCard,
IonCardContent, IonCardContent,
IonCardHeader, IonCardHeader,
IonCardSubtitle, IonCardSubtitle,
IonCardTitle, IonCardTitle,
IonContent, IonContent,
IonHeader,
IonIcon, IonIcon,
IonItem, IonItem,
IonItemDivider, IonItemDivider,
IonPage, IonPage,
IonRow, IonRow,
IonTitle,
IonToolbar,
} from "@ionic/react"; } from "@ionic/react";
import { import {
arrowForwardOutline, arrowForwardOutline,
@@ -34,6 +39,7 @@ import GooglePlacesAutocomplete, {
getLatLng, getLatLng,
} from "react-google-places-autocomplete"; } from "react-google-places-autocomplete";
import { Itinerary } from "../models/itinerary.model"; import { Itinerary } from "../models/itinerary.model";
import { PageHeader } from "../components/PageHeader";
const BuscarItinerario: React.FC = () => { const BuscarItinerario: React.FC = () => {
const history = useHistory(); const history = useHistory();
@@ -108,6 +114,11 @@ const BuscarItinerario: React.FC = () => {
return ( return (
<IonPage> <IonPage>
<PageHeader
pageName="Buscar itinerários"
backButtonPageUrl="/buscas"
></PageHeader>
<IonContent fullscreen> <IonContent fullscreen>
<IonCard> <IonCard>
<IonCardContent> <IonCardContent>
@@ -156,7 +167,7 @@ const BuscarItinerario: React.FC = () => {
</div> </div>
</IonCardContent> </IonCardContent>
</IonCard> </IonCard>
<IonItemDivider>Pesquisas recentes</IonItemDivider> <IonItemDivider color="dark">Pesquisas recentes</IonItemDivider>
<IonRow class="latest-searches"> <IonRow class="latest-searches">
<IonIcon <IonIcon
className="icon-align-vcenter" className="icon-align-vcenter"
@@ -238,7 +249,7 @@ const BuscarItinerario: React.FC = () => {
{itinerariesList ? ( {itinerariesList ? (
<> <>
<IonItemDivider>Resultados</IonItemDivider> <IonItemDivider color="secondary">Resultados</IonItemDivider>
{itinerariesList.map((itinerary, index) => { {itinerariesList.map((itinerary, index) => {
return ( return (
<IonCard button key={index} onClick={() => { history.push(`/itinerary/${itinerary.id_itinerary}`) }}> <IonCard button key={index} onClick={() => { history.push(`/itinerary/${itinerary.id_itinerary}`) }}>

View File

@@ -25,6 +25,7 @@ import { cashOutline, personOutline, starOutline } from "ionicons/icons";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { useHistory } from "react-router"; import { useHistory } from "react-router";
import { PageHeader } from "../components/PageHeader";
interface coordinates { interface coordinates {
lat: number; lat: number;
@@ -109,14 +110,10 @@ const BuscarItinerario: React.FC = () => {
return ( return (
<IonPage> <IonPage>
<IonHeader translucent> <PageHeader
<IonToolbar> pageName="Buscar itinerários"
<IonTitle>Buscar itinerários</IonTitle> backButtonPageUrl="/buscas"
<IonButtons slot="start"> ></PageHeader>
<IonBackButton text="" defaultHref="/buscas" />
</IonButtons>
</IonToolbar>
</IonHeader>
<IonContent fullscreen> <IonContent fullscreen>
{/* <IonGrid> {/* <IonGrid>

View File

@@ -1,126 +1,162 @@
import { IonContent, IonPage, IonFab, IonFabButton, IonIcon } from '@ionic/react'; import {
import { search } from 'ionicons/icons'; IonContent,
import './BuscarPassageiro.css'; IonPage,
IonFab,
IonFabButton,
IonIcon,
} from "@ionic/react";
import { search } from "ionicons/icons";
import "./BuscarPassageiro.css";
import { Map, Marker, Overlay } from "pigeon-maps"; import { Map, Marker, Overlay } from "pigeon-maps";
import { maptiler } from 'pigeon-maps/providers'; import { maptiler } from "pigeon-maps/providers";
import { useEffect, useState } from 'react'; import { useEffect, useState } from "react";
import RecordsStore from '../../store/RecordsStore'; import RecordsStore from "../../store/RecordsStore";
import { fetchRecords } from '../../store/Selectors'; import { fetchRecords } from "../../store/Selectors";
import { getUsersSearching } from '../../services/api/users'; import { getUsersSearching } from "../../services/api/users";
import { UserSearchInfos } from '../../components/UserSearchInfos/UserSearchInfos'; import { UserSearchInfos } from "../../components/UserSearchInfos/UserSearchInfos";
import { PageHeader } from "../../components/PageHeader";
const maptilerProvider = maptiler('d5JQJPLLuap8TkJJlTdJ', 'streets'); const maptilerProvider = maptiler("d5JQJPLLuap8TkJJlTdJ", "streets");
const BuscarPassageiro: React.FC = () => { const BuscarPassageiro: React.FC = () => {
// UNCOMMENT THESE TO USE CURRENT LOCATION.
// UNCOMMENT THESE TO USE CURRENT LOCATION. // const [ currentPoint, setCurrentPoint ] = useState(false);
// const [ currentPoint, setCurrentPoint ] = useState(false); // useEffect(() => {
// useEffect(() => { // const getCurrentLocation = async () => {
// const getCurrentLocation = async () => { // const fetchedLocation = await getLocation();
// setCurrentPoint(fetchedLocation.currentLocation);
// }
// const fetchedLocation = await getLocation(); // getCurrentLocation();
// setCurrentPoint(fetchedLocation.currentLocation); // }, []);
// }
// getCurrentLocation(); // useIonViewWillEnter(() => {
// }, []);
// useIonViewWillEnter(() => { // getUsersSearching(currentPoint);
// });
// getUsersSearching(currentPoint); const [currentPoint, setCurrentPoint] = useState({
// }); latitude: -22.907829,
longitude: -47.062943,
});
const [ currentPoint, setCurrentPoint ] = useState({ latitude: -22.907829, longitude: -47.062943 }); const records = RecordsStore.useState(fetchRecords);
const center = { latitude: -22.907829, longitude: -47.062943 };
const records = RecordsStore.useState(fetchRecords); const [results, setResults] = useState([]);
const center = { latitude: -22.907829, longitude: -47.062943 }; const [zoom, setZoom] = useState(14);
const [ results, setResults ] = useState([]); const [moveMode, setMoveMode] = useState(false);
const [ zoom, setZoom ] = useState(14);
const [ moveMode, setMoveMode ] = useState(false); // useEffect(() => {
// useEffect(() => { // const getData = async () => {
// const getData = async () => { // await getUsersSearching(currentPoint);
// }
// await getUsersSearching(currentPoint); // getData();
// } // }, [ currentPoint ]);
// getData(); useEffect(() => {
// }, [ currentPoint ]); setResults(records);
}, [records]);
useEffect(() => { const hideMarkers = () => {
console.log("entrou");
const tempRecords = JSON.parse(JSON.stringify(results));
tempRecords.forEach((tempRecord: any) => (tempRecord.showInfo = false));
console.log(tempRecords);
setResults(tempRecords);
};
setResults(records); const handleMap = (e: any) => {
}, [ records ]);
const hideMarkers = () => {
console.log('entrou')
const tempRecords = JSON.parse(JSON.stringify(results));
tempRecords.forEach((tempRecord:any) => tempRecord.showInfo = false);
console.log(tempRecords)
setResults(tempRecords);
}
const handleMap = (e:any) => {
setCurrentPoint({ latitude: e.center[0], longitude: e.center[1] }); setCurrentPoint({ latitude: e.center[0], longitude: e.center[1] });
} };
const searchResults = async () => { const searchResults = async () => {
await getUsersSearching(currentPoint); await getUsersSearching(currentPoint);
} };
const showMarkerInfo = (e:any, index:any) => { const showMarkerInfo = (e: any, index: any) => {
const tempRecords = JSON.parse(JSON.stringify(results));
const tempRecords = JSON.parse(JSON.stringify(results)); // Hide all current marker infos
!tempRecords[index].showInfo &&
tempRecords.forEach((tempRecord: any) => (tempRecord.showInfo = false));
tempRecords[index].showInfo = !tempRecords[index].showInfo;
// Hide all current marker infos console.log(tempRecords);
!tempRecords[index].showInfo && tempRecords.forEach((tempRecord:any) => tempRecord.showInfo = false); setResults(tempRecords);
tempRecords[index].showInfo = !tempRecords[index].showInfo; };
console.log(tempRecords)
setResults(tempRecords);
}
return ( return (
<IonPage> <IonPage>
<IonContent fullscreen> <PageHeader
{/* { results && pageName="Buscar passageiros"
backButtonPageUrl="/buscas"
></PageHeader>
<IonContent fullscreen>
{/* { results &&
<> */} <> */}
<Map onBoundsChanged={e => handleMap(e)} defaultCenter={ [center.latitude, center.longitude] } defaultZoom={ zoom } provider={ maptilerProvider } touchEvents={ true }> <Map
onBoundsChanged={(e) => handleMap(e)}
defaultCenter={[center.latitude, center.longitude]}
defaultZoom={zoom}
provider={maptilerProvider}
touchEvents={true}
>
{results &&
results.map(
(record: { latitude_from: any; longitude_from: any }, index) => {
return (
<Marker
onClick={(e) => showMarkerInfo(e, index)}
key={index}
color="#3578e5"
width={50}
anchor={[
parseFloat(record.latitude_from),
parseFloat(record.longitude_from),
]}
/>
);
}
)}
{results && results.map((record:{latitude_from:any, longitude_from:any}, index) => { {results.map((record: any, index) => {
return <Marker onClick={ e => showMarkerInfo(e, index) } key={ index } color="#3578e5" width={ 50 } anchor={ [ parseFloat(record.latitude_from), parseFloat(record.longitude_from) ] } /> if (record.showInfo) {
})} return (
<Overlay
key={index}
anchor={[
parseFloat(record.latitude_from),
parseFloat(record.longitude_from),
]}
offset={[95, 304]}
>
<UserSearchInfos record={record} />
</Overlay>
);
}
})}
</Map>
{ results.map((record:any, index) => { <IonFab vertical="bottom" horizontal="end" slot="fixed">
<IonFabButton>
if (record.showInfo) { <IonIcon onClick={searchResults} icon={search} />
</IonFabButton>
return ( </IonFab>
<Overlay key={ index } anchor={ [ parseFloat(record.latitude_from), parseFloat(record.longitude_from) ] } offset={[95, 304]}> {/* </> */}
<UserSearchInfos record={ record } /> {/* } */}
</Overlay> </IonContent>
) </IonPage>
}
})}
</Map>
<IonFab vertical="bottom" horizontal="end" slot="fixed">
<IonFabButton>
<IonIcon onClick={searchResults} icon={search} />
</IonFabButton>
</IonFab>
{/* </> */}
{/* } */}
</IonContent>
</IonPage>
); );
}; };

View File

@@ -2,6 +2,7 @@ import { IonCard, IonCardContent, IonCardHeader, IonCardSubtitle, IonCardTitle,
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { useHistory } from "react-router"; import { useHistory } from "react-router";
import { PageHeader } from "../components/PageHeader";
const Buscas: React.FC = () => { const Buscas: React.FC = () => {
useEffect(() => {}, []); useEffect(() => {}, []);
@@ -9,11 +10,9 @@ const Buscas: React.FC = () => {
return ( return (
<IonPage> <IonPage>
<IonHeader> <PageHeader
<IonToolbar> pageName="Buscas"
<IonTitle>Buscas</IonTitle> ></PageHeader>
</IonToolbar>
</IonHeader>
<IonContent fullscreen> <IonContent fullscreen>
<IonCard button class="cardItem" onClick={ () => history.push({ pathname: "/buscar/itinerario"}) }> <IonCard button class="cardItem" onClick={ () => history.push({ pathname: "/buscar/itinerario"}) }>

View File

@@ -20,25 +20,19 @@ import {
import { close, locateOutline, locationOutline } from "ionicons/icons"; import { close, locateOutline, locationOutline } from "ionicons/icons";
import { useState } from "react"; import { useState } from "react";
import GooglePlacesAutocomplete from "react-google-places-autocomplete"; import GooglePlacesAutocomplete from "react-google-places-autocomplete";
import { PageHeader } from "../../components/PageHeader";
export default function CadastrarItinerario() { export default function CadastrarItinerario() {
const [selected, setSelected] = useState<any>(""); const [selected, setSelected] = useState<any>("");
return ( return (
<IonPage> <IonPage>
<IonHeader> <PageHeader
<IonToolbar> pageName="Cadastrar itinerário"
<IonButtons slot="start"> backButtonPageUrl="/perfil"
<IonBackButton icon={close} text="" defaultHref="/perfil" /> ></PageHeader>
</IonButtons>
</IonToolbar>
</IonHeader>
<IonContent fullscreen> <IonContent fullscreen>
<IonHeader collapse="condense">
<IonToolbar>
<IonTitle size="large">Cadastrar Itinerário</IonTitle>
</IonToolbar>
</IonHeader>
<IonCard> <IonCard>
<IonCardContent> <IonCardContent>
<div className="inputs-from-to"> <div className="inputs-from-to">

View File

@@ -10,6 +10,7 @@ import LocalStorage from '../../LocalStorage';
import { UserContext } from '../../App'; import { UserContext } from '../../App';
import { Color } from '@ionic/core'; import { Color } from '@ionic/core';
import { closeToast } from '../../services/utils'; import { closeToast } from '../../services/utils';
import { PageHeader } from '../../components/PageHeader';
const Cadastro: React.FC = () => { const Cadastro: React.FC = () => {
const history = useHistory(); const history = useHistory();
@@ -129,13 +130,11 @@ const Cadastro: React.FC = () => {
return ( return (
<IonPage> <IonPage>
<IonHeader> <PageHeader
<IonToolbar> pageName="Cadastro"
<IonButtons slot="start"> backButtonPageUrl="/login"
<IonBackButton text={''} icon={arrowBack} defaultHref='login' /> ></PageHeader>
</IonButtons>
</IonToolbar>
</IonHeader>
<IonContent fullscreen> <IonContent fullscreen>
<IonGrid className="ion-padding"> <IonGrid className="ion-padding">
<IonRow> <IonRow>

View File

@@ -22,6 +22,7 @@ import { callOutline, documentTextOutline } from "ionicons/icons";
import '../Cadastro/Cadastro.css' import '../Cadastro/Cadastro.css'
import { Color } from "@ionic/core"; import { Color } from "@ionic/core";
import { closeToast } from "../../services/utils"; import { closeToast } from "../../services/utils";
import { PageHeader } from "../../components/PageHeader";
interface cardItem { interface cardItem {
icon: string; icon: string;
@@ -104,14 +105,10 @@ const CadastroCompletar: React.FC = () => {
return ( return (
<IonPage> <IonPage>
<IonHeader> <PageHeader
<IonToolbar> pageName="Completar cadastro"
<IonTitle>Completar cadastro</IonTitle> backButtonPageUrl="/perfil"
<IonButtons slot="start"> ></PageHeader>
<IonBackButton defaultHref="/perfil" />
</IonButtons>
</IonToolbar>
</IonHeader>
<IonContent> <IonContent>
{ items.map((item, index) => { { items.map((item, index) => {

View File

@@ -29,6 +29,7 @@ import * as usersRoutes from '../../services/api/users';
import validateCpf from '../../services/validateCpf' import validateCpf from '../../services/validateCpf'
import { closeToast } from "../../services/utils"; import { closeToast } from "../../services/utils";
import { PageHeader } from "../../components/PageHeader";
interface documentTypesInterface { interface documentTypesInterface {
label: string; label: string;
@@ -155,22 +156,12 @@ const CompletarDocumento: React.FC = () => {
return ( return (
<IonPage> <IonPage>
<IonHeader> <PageHeader
<IonToolbar> pageName="Completar cadastro"
<IonTitle>Completar cadastro</IonTitle> backButtonPageUrl="/perfil/completar"
<IonButtons slot="start"> ></PageHeader>
<IonBackButton defaultHref="/perfil/completar" />
</IonButtons>
</IonToolbar>
</IonHeader>
<IonContent fullscreen> <IonContent fullscreen>
<IonHeader collapse="condense">
<IonToolbar>
<IonTitle size="large">Completar cadastro</IonTitle>
</IonToolbar>
</IonHeader>
<IonGrid> <IonGrid>
<IonRow> <IonRow>
<IonCol> <IonCol>

View File

@@ -26,6 +26,7 @@ import { saveOutline } from "ionicons/icons";
import * as usersRoutes from '../../services/api/users'; import * as usersRoutes from '../../services/api/users';
import { Color } from "@ionic/core"; import { Color } from "@ionic/core";
import { closeToast } from "../../services/utils"; import { closeToast } from "../../services/utils";
import { PageHeader } from "../../components/PageHeader";
interface documentTypesInterface { interface documentTypesInterface {
label: string; label: string;
@@ -113,22 +114,12 @@ const CompletarTelefone: React.FC = () => {
return ( return (
<IonPage> <IonPage>
<IonHeader> <PageHeader
<IonToolbar> pageName="Completar cadastro"
<IonTitle>Completar cadastro</IonTitle> backButtonPageUrl="/perfil/completar"
<IonButtons slot="start"> ></PageHeader>
<IonBackButton defaultHref="/perfil/completar" />
</IonButtons>
</IonToolbar>
</IonHeader>
<IonContent fullscreen> <IonContent fullscreen>
<IonHeader collapse="condense">
<IonToolbar>
<IonTitle size="large">Completar cadastro</IonTitle>
</IonToolbar>
</IonHeader>
<IonGrid> <IonGrid>
<IonRow> <IonRow>
<IonCol> <IonCol>

View File

@@ -30,6 +30,7 @@ import * as vansRoutes from '../services/api/vans';
import "./CadastroVan.css"; import "./CadastroVan.css";
import { Color } from "@ionic/core"; import { Color } from "@ionic/core";
import { closeToast } from "../services/utils"; import { closeToast } from "../services/utils";
import { PageHeader } from "../components/PageHeader";
const CadastroVan: React.FC = () => { const CadastroVan: React.FC = () => {
const history = useHistory(); const history = useHistory();
@@ -241,14 +242,10 @@ const CadastroVan: React.FC = () => {
return ( return (
<IonPage> <IonPage>
<IonHeader> <PageHeader
<IonToolbar> pageName="Cadastro de veículo"
<IonTitle>Cadastro de veículo</IonTitle> backButtonPageUrl="/perfil"
<IonButtons slot='start'> ></PageHeader>
<IonBackButton defaultHref='/perfil' />
</IonButtons>
</IonToolbar>
</IonHeader>
<IonContent> <IonContent>
<IonList lines="full" class="ion-no-margin"> <IonList lines="full" class="ion-no-margin">

View File

@@ -1,60 +1,58 @@
import { import {
IonContent, IonContent,
IonHeader, IonHeader,
IonPage, IonPage,
IonTitle, IonTitle,
IonToolbar IonToolbar,
} from "@ionic/react"; } from "@ionic/react";
import React, { useContext, useState } from "react"; import React, { useContext, useState } from "react";
import { IonGrid, IonRow, IonCol, IonToast } from "@ionic/react"; import { IonGrid, IonRow, IonCol, IonToast } from "@ionic/react";
import { useHistory } from "react-router-dom"; import { useHistory } from "react-router-dom";
import { import { IonItem, IonLabel, IonInput, IonButton } from "@ionic/react";
IonItem,
IonLabel,
IonInput,
IonButton,
} from "@ionic/react";
import { UserContext } from "../App"; import { UserContext } from "../App";
import { PageHeader } from "../components/PageHeader";
const Debug: React.FC = () => { const Debug: React.FC = () => {
const [input, setInput] = useState(''); const [input, setInput] = useState("");
return ( return (
<IonPage> <IonPage>
<IonHeader> <PageHeader pageName="Debug" backButtonPageUrl="/home"></PageHeader>
<IonContent fullscreen>
<IonHeader collapse="condense">
<IonToolbar> <IonToolbar>
<IonTitle>Debug</IonTitle> <IonTitle size="large">Debug</IonTitle>
</IonToolbar> </IonToolbar>
</IonHeader> </IonHeader>
<IonContent fullscreen> <IonGrid>
<IonHeader collapse="condense"> <IonRow>
<IonToolbar> <IonCol>
<IonTitle size="large">Debug</IonTitle> <IonItem>
</IonToolbar> <IonLabel position="floating"> Input</IonLabel>
</IonHeader> <IonInput
type="date"
value={input}
// onIonChange={(e) => { setInput(e.detail.value!) }}
></IonInput>
</IonItem>
<IonGrid> <IonButton
<IonRow> onClick={(e) => {
<IonCol> setInput("1994-12-15");
<IonItem> console.log(input);
<IonLabel position="floating"> Input</IonLabel> }}
<IonInput >
type="date" Enviar
value={input} </IonButton>
// onIonChange={(e) => { setInput(e.detail.value!) }} </IonCol>
></IonInput> </IonRow>
</IonItem> </IonGrid>
</IonContent>
<IonButton onClick={(e) => { setInput('1994-12-15'); console.log(input) }}>Enviar</IonButton> </IonPage>
</IonCol> );
</IonRow> };
</IonGrid>
</IonContent>
</IonPage>
);
};
export default Debug;
export default Debug;

View File

@@ -1,22 +1,40 @@
import { IonBackButton, IonButtons, IonCard, IonCardContent, IonCardHeader, IonCardSubtitle, IonCardTitle, IonContent, IonHeader, IonIcon, IonItem, IonLabel, IonPage, IonTitle, IonToast, IonToolbar } from '@ionic/react'; import {
import { Color } from '@ionic/core'; IonBackButton,
import { carOutline } from 'ionicons/icons'; IonButtons,
import { useContext, useEffect, useState } from 'react'; IonCard,
import { useHistory, useLocation } from 'react-router'; IonCardContent,
IonCardHeader,
IonCardSubtitle,
IonCardTitle,
IonContent,
IonHeader,
IonIcon,
IonItem,
IonLabel,
IonPage,
IonTitle,
IonToast,
IonToolbar,
} from "@ionic/react";
import { Color } from "@ionic/core";
import { carOutline } from "ionicons/icons";
import { useContext, useEffect, useState } from "react";
import { useHistory, useLocation } from "react-router";
import { UserContext } from '../App'; import { UserContext } from "../App";
import * as vansRoutes from '../services/api/vans'; import * as vansRoutes from "../services/api/vans";
import sessionsService from '../services/functions/sessionsService' import sessionsService from "../services/functions/sessionsService";
import { closeToast } from '../services/utils'; import { closeToast } from "../services/utils";
import { PageHeader } from "../components/PageHeader";
interface VanInfo { interface VanInfo {
plate: string; plate: string;
brand: string; brand: string;
model: string; model: string;
seats_number: string; seats_number: string;
document_status: boolean, document_status: boolean;
locator_name: string; locator_name: string;
locator_address: string; locator_address: string;
locator_complement: string; locator_complement: string;
@@ -28,90 +46,100 @@ const Itinerario: React.FC = () => {
const history = useHistory(); const history = useHistory();
const [showToast, setShowToast] = useState(false); const [showToast, setShowToast] = useState(false);
const [toastMessage, setToastMessage] = useState(''); const [toastMessage, setToastMessage] = useState("");
const [toastColor, setToastColor] = useState<Color>("primary"); const [toastColor, setToastColor] = useState<Color>("primary");
const [userVans, setUserVans] = useState<VanInfo[]>(); const [userVans, setUserVans] = useState<VanInfo[]>();
const redirectUserToLogin = () => { const redirectUserToLogin = () => {
history.push({ pathname: '/login' }); history.push({ pathname: "/login" });
} };
useEffect(() => { useEffect(() => {
const getUserVans = async () => { const getUserVans = async () => {
let userId = '' let userId = "";
const refreshSessionRes = await sessionsService.refreshSession() const refreshSessionRes = await sessionsService.refreshSession();
if (refreshSessionRes.error) { if (refreshSessionRes.error) {
redirectUserToLogin() redirectUserToLogin();
return return;
} }
if (refreshSessionRes.userId) { if (refreshSessionRes.userId) {
userId = refreshSessionRes.userId userId = refreshSessionRes.userId;
} }
vansRoutes.getByUserId(userId).then(response => { vansRoutes
if (response.status === 'error') { .getByUserId(userId)
setToastColor("danger") .then((response) => {
setToastMessage(response.message); if (response.status === "error") {
setToastColor("danger");
setToastMessage(response.message);
setShowToast(true);
return;
}
setUserVans(response.data);
})
.catch((err) => {
setToastColor("danger");
setToastMessage(err);
setShowToast(true); setShowToast(true);
});
};
return getUserVans();
} }, []);
setUserVans(response.data)
}).catch((err) => {
setToastColor("danger")
setToastMessage(err);
setShowToast(true);
})
}
getUserVans()
}, [])
return ( return (
<IonPage> <IonPage>
<IonHeader> <PageHeader
<IonToolbar> pageName="Minhas vans"
<IonTitle>Minhas vans</IonTitle> backButtonPageUrl="/perfil"
<IonButtons slot="start"> ></PageHeader>
<IonBackButton defaultHref="/perfil" />
</IonButtons>
</IonToolbar>
</IonHeader>
<IonContent> <IonContent>
{ userVans ? userVans.map((van, index) => { {userVans ? (
userVans.map((van, index) => {
return ( return (
<IonCard key={index}> <IonCard key={index}>
<IonCardHeader> <IonCardHeader>
<IonCardTitle>{van.plate}</IonCardTitle> <IonCardTitle>{van.plate}</IonCardTitle>
<IonCardSubtitle>{van.brand} - {van.model}</IonCardSubtitle> <IonCardSubtitle>
</IonCardHeader> {van.brand} - {van.model}
{ van.locator_name ? </IonCardSubtitle>
</IonCardHeader>
{van.locator_name ? (
<> <>
<IonCardContent>{van.seats_number} assentos - Locador: {van.locator_name}</IonCardContent> <IonCardContent>
</> : {van.seats_number} assentos - Locador: {van.locator_name}
<> </IonCardContent>
<IonCardContent>{van.seats_number} assentos - Não é alugado</IonCardContent>
</> </>
} ) : (
<>
<IonCardContent>
{van.seats_number} assentos - Não é alugado
</IonCardContent>
</>
)}
</IonCard> </IonCard>
) );
}) : <></>} })
) : (
<></>
)}
<IonToast <IonToast
position="top" position="top"
color={toastColor} color={toastColor}
isOpen={showToast} isOpen={showToast}
onDidDismiss={() => closeToast(setShowToast)} onDidDismiss={() => closeToast(setShowToast)}
message={toastMessage} message={toastMessage}
duration={2500} duration={2500}
/> />
</IonContent> </IonContent>
</IonPage> </IonPage>
); );
}; };

View File

@@ -3,31 +3,27 @@ import {
IonHeader, IonHeader,
IonPage, IonPage,
IonTitle, IonTitle,
IonToolbar IonToolbar,
} from "@ionic/react"; } from "@ionic/react";
import React, { useContext, useState } from "react"; import React, { useContext, useState } from "react";
import { IonGrid, IonRow, IonCol, IonToast } from "@ionic/react"; import { IonGrid, IonRow, IonCol, IonToast } from "@ionic/react";
import { useHistory } from "react-router-dom"; import { useHistory } from "react-router-dom";
import { import { IonItem, IonLabel, IonInput, IonButton } from "@ionic/react";
IonItem,
IonLabel,
IonInput,
IonButton,
} from "@ionic/react";
import * as sessionRoutes from '../services/api/session'; import * as sessionRoutes from "../services/api/session";
import LocalStorage from '../LocalStorage'; import LocalStorage from "../LocalStorage";
import { Action } from "../components/Action"; import { Action } from "../components/Action";
import { UserContext } from "../App"; import { UserContext } from "../App";
import { closeToast } from "../services/utils"; import { closeToast } from "../services/utils";
import { PageHeader } from "../components/PageHeader";
const Page: React.FC = () => { const Page: React.FC = () => {
const [showToast, setShowToast] = useState(false); const [showToast, setShowToast] = useState(false);
const [messageToast, setMessageToast ] = useState(''); const [messageToast, setMessageToast] = useState("");
const history = useHistory(); const history = useHistory();
const [email, setEmail] = useState(''); const [email, setEmail] = useState("");
const [password, setPassword] = useState(''); const [password, setPassword] = useState("");
const user = useContext(UserContext); const user = useContext(UserContext);
@@ -57,18 +53,18 @@ const Page: React.FC = () => {
return false; return false;
} }
if(password.length < 7 || password.length > 12) { if (password.length < 7 || password.length > 12) {
setMessageToast("A senha deve conter entre 7 e 12 dígitos"); setMessageToast("A senha deve conter entre 7 e 12 dígitos");
setShowToast(true); setShowToast(true);
return false; return false;
} }
return true; return true;
} };
const handleLogin = async () => { const handleLogin = async () => {
if (!validateForm()) { if (!validateForm()) {
return return;
} }
const singinForm = { const singinForm = {
@@ -76,50 +72,48 @@ const Page: React.FC = () => {
password: password, password: password,
}; };
await sessionRoutes.create(singinForm).then(response => { await sessionRoutes
if (response.status === 'error') { .create(singinForm)
setMessageToast(response.message); .then((response) => {
setShowToast(true); if (response.status === "error") {
setMessageToast(response.message);
setShowToast(true);
return return;
} }
const { token } = response.token const { token } = response.token;
LocalStorage.setToken(token); LocalStorage.setToken(token);
user.setIsLoggedIn(true); user.setIsLoggedIn(true);
history.push({ pathname: '/home', state: { redirectData: { history.push({
showToastMessage: true, pathname: "/home",
toastColor: "success", state: {
toastMessage: "Usuário autenticado com sucesso!", redirectData: {
}}}) showToastMessage: true,
}).catch(error => { toastColor: "success",
// if (!error.response) return toastMessage: "Usuário autenticado com sucesso!",
},
},
});
})
.catch((error) => {
// if (!error.response) return
// se o backend retornou uma mensagem de erro customizada // se o backend retornou uma mensagem de erro customizada
// if (error.response.data.message) { // if (error.response.data.message) {
console.dir('Houve um erro: ', { error }) console.dir("Houve um erro: ", { error });
alert('Houve um erro') alert("Houve um erro");
}) });
}; };
return ( return (
<IonPage> <IonPage>
<IonHeader> <PageHeader pageName="Login"></PageHeader>
<IonToolbar>
<IonTitle>Login</IonTitle>
</IonToolbar>
</IonHeader>
<IonContent fullscreen> <IonContent fullscreen>
<IonHeader collapse="condense">
<IonToolbar>
<IonTitle size="large">Login</IonTitle>
</IonToolbar>
</IonHeader>
<IonGrid> <IonGrid>
<IonRow> <IonRow>
<IonCol> <IonCol>
@@ -153,7 +147,11 @@ const Page: React.FC = () => {
Login Login
</IonButton> </IonButton>
<p style={{ fontSize: "medium" }}> <p style={{ fontSize: "medium" }}>
<Action message="Ainda não possui uma conta?" text="Cadastre-se aqui!" link="/cadastro" /> <Action
message="Ainda não possui uma conta?"
text="Cadastre-se aqui!"
link="/cadastro"
/>
</p> </p>
</IonCol> </IonCol>
</IonRow> </IonRow>
@@ -161,7 +159,7 @@ const Page: React.FC = () => {
<IonToast <IonToast
position="top" position="top"
color='danger' color="danger"
isOpen={showToast} isOpen={showToast}
onDidDismiss={() => closeToast(setShowToast)} onDidDismiss={() => closeToast(setShowToast)}
message={messageToast} message={messageToast}

View File

@@ -16,6 +16,7 @@ import {
} from "@ionic/react"; } from "@ionic/react";
import { add, locateOutline, locationOutline } from "ionicons/icons"; import { add, locateOutline, locationOutline } from "ionicons/icons";
import { useState } from "react"; import { useState } from "react";
import { PageHeader } from "../../components/PageHeader";
import "./MeusItinerarios.css"; import "./MeusItinerarios.css";
interface ItineraryInfo { interface ItineraryInfo {
@@ -93,20 +94,12 @@ export default function MeusItinerarios() {
return ( return (
<IonPage> <IonPage>
<IonHeader translucent> <PageHeader
<IonToolbar> pageName="Meus Itinerários"
<IonTitle>Meus Itinerários</IonTitle> backButtonPageUrl="/perfil"
<IonButtons slot="start"> ></PageHeader>
<IonBackButton text={""} defaultHref="/perfil" />
</IonButtons>
</IonToolbar>
</IonHeader>
<IonContent fullscreen> <IonContent fullscreen>
<IonHeader collapse="condense">
<IonToolbar>
<IonTitle size="large">Meus Itinerários</IonTitle>
</IonToolbar>
</IonHeader>
{routes ? ( {routes ? (
routes.map((itinerary, index) => { routes.map((itinerary, index) => {
return ( return (

View File

@@ -1,22 +1,40 @@
import { IonBackButton, IonButtons, IonCard, IonCardContent, IonCardHeader, IonCardSubtitle, IonCardTitle, IonContent, IonHeader, IonIcon, IonItem, IonLabel, IonPage, IonTitle, IonToast, IonToolbar } from '@ionic/react'; import {
import { Color } from '@ionic/core'; IonBackButton,
import { carOutline } from 'ionicons/icons'; IonButtons,
import { useContext, useEffect, useState } from 'react'; IonCard,
import { useHistory, useLocation } from 'react-router'; IonCardContent,
IonCardHeader,
IonCardSubtitle,
IonCardTitle,
IonContent,
IonHeader,
IonIcon,
IonItem,
IonLabel,
IonPage,
IonTitle,
IonToast,
IonToolbar,
} from "@ionic/react";
import { Color } from "@ionic/core";
import { carOutline } from "ionicons/icons";
import { useContext, useEffect, useState } from "react";
import { useHistory, useLocation } from "react-router";
import { UserContext } from '../App'; import { UserContext } from "../App";
import * as vansRoutes from '../services/api/vans'; import * as vansRoutes from "../services/api/vans";
import sessionsService from '../services/functions/sessionsService' import sessionsService from "../services/functions/sessionsService";
import { closeToast } from '../services/utils'; import { closeToast } from "../services/utils";
import { PageHeader } from "../components/PageHeader";
interface VanInfo { interface VanInfo {
plate: string; plate: string;
brand: string; brand: string;
model: string; model: string;
seats_number: string; seats_number: string;
document_status: boolean, document_status: boolean;
locator_name: string; locator_name: string;
locator_address: string; locator_address: string;
locator_complement: string; locator_complement: string;
@@ -28,90 +46,100 @@ const MinhasVans: React.FC = () => {
const history = useHistory(); const history = useHistory();
const [showToast, setShowToast] = useState(false); const [showToast, setShowToast] = useState(false);
const [toastMessage, setToastMessage] = useState(''); const [toastMessage, setToastMessage] = useState("");
const [toastColor, setToastColor] = useState<Color>("primary"); const [toastColor, setToastColor] = useState<Color>("primary");
const [userVans, setUserVans] = useState<VanInfo[]>(); const [userVans, setUserVans] = useState<VanInfo[]>();
const redirectUserToLogin = () => { const redirectUserToLogin = () => {
history.push({ pathname: '/login' }); history.push({ pathname: "/login" });
} };
useEffect(() => { useEffect(() => {
const getUserVans = async () => { const getUserVans = async () => {
let userId = '' let userId = "";
const refreshSessionRes = await sessionsService.refreshSession() const refreshSessionRes = await sessionsService.refreshSession();
if (refreshSessionRes.error) { if (refreshSessionRes.error) {
redirectUserToLogin() redirectUserToLogin();
return return;
} }
if (refreshSessionRes.userId) { if (refreshSessionRes.userId) {
userId = refreshSessionRes.userId userId = refreshSessionRes.userId;
} }
vansRoutes.getByUserId(userId).then(response => { vansRoutes
if (response.status === 'error') { .getByUserId(userId)
setToastColor("danger") .then((response) => {
setToastMessage(response.message); if (response.status === "error") {
setToastColor("danger");
setToastMessage(response.message);
setShowToast(true);
return;
}
setUserVans(response.data);
})
.catch((err) => {
setToastColor("danger");
setToastMessage(err);
setShowToast(true); setShowToast(true);
});
};
return getUserVans();
} }, []);
setUserVans(response.data)
}).catch((err) => {
setToastColor("danger")
setToastMessage(err);
setShowToast(true);
})
}
getUserVans()
}, [])
return ( return (
<IonPage> <IonPage>
<IonHeader> <PageHeader
<IonToolbar> pageName="Minhas vans"
<IonTitle>Minhas vans</IonTitle> backButtonPageUrl="/perfil"
<IonButtons slot="start"> ></PageHeader>
<IonBackButton defaultHref="/perfil" />
</IonButtons>
</IonToolbar>
</IonHeader>
<IonContent> <IonContent>
{ userVans ? userVans.map((van, index) => { {userVans ? (
userVans.map((van, index) => {
return ( return (
<IonCard key={index}> <IonCard key={index}>
<IonCardHeader> <IonCardHeader>
<IonCardTitle>{van.plate}</IonCardTitle> <IonCardTitle>{van.plate}</IonCardTitle>
<IonCardSubtitle>{van.brand} - {van.model}</IonCardSubtitle> <IonCardSubtitle>
</IonCardHeader> {van.brand} - {van.model}
{ van.locator_name ? </IonCardSubtitle>
</IonCardHeader>
{van.locator_name ? (
<> <>
<IonCardContent>{van.seats_number} assentos - Locador: {van.locator_name}</IonCardContent> <IonCardContent>
</> : {van.seats_number} assentos - Locador: {van.locator_name}
<> </IonCardContent>
<IonCardContent>{van.seats_number} assentos - Não é alugado</IonCardContent>
</> </>
} ) : (
<>
<IonCardContent>
{van.seats_number} assentos - Não é alugado
</IonCardContent>
</>
)}
</IonCard> </IonCard>
) );
}) : <></>} })
) : (
<></>
)}
<IonToast <IonToast
position="top" position="top"
color={toastColor} color={toastColor}
isOpen={showToast} isOpen={showToast}
onDidDismiss={() => closeToast(setShowToast)} onDidDismiss={() => closeToast(setShowToast)}
message={toastMessage} message={toastMessage}
duration={2500} duration={2500}
/> />
</IonContent> </IonContent>
</IonPage> </IonPage>
); );
}; };

View File

@@ -41,6 +41,7 @@ import usersService from "../services/functions/usersService";
import { UserContext } from "../App"; import { UserContext } from "../App";
import { Color } from "@ionic/core"; import { Color } from "@ionic/core";
import { closeToast } from "../services/utils"; import { closeToast } from "../services/utils";
import { PageHeader } from "../components/PageHeader";
interface ScanNewProps { interface ScanNewProps {
match: { match: {
@@ -212,22 +213,9 @@ const Perfil: React.FC<ScanNewProps> = (props) => {
return ( return (
<IonPage> <IonPage>
<IonHeader translucent> <PageHeader pageName="Meu perfil"></PageHeader>
<IonToolbar>
<IonTitle>Seu perfil</IonTitle>
<IonButtons slot="start">
<IonBackButton text="" defaultHref="/home" />
</IonButtons>
</IonToolbar>
</IonHeader>
<IonContent fullscreen> <IonContent fullscreen>
<IonHeader collapse="condense">
<IonToolbar>
<IonTitle size="large">Seu perfil</IonTitle>
</IonToolbar>
</IonHeader>
<IonCard> <IonCard>
<IonCardContent> <IonCardContent>
<img <img

View File

@@ -14,22 +14,23 @@ import {
IonTextarea, IonTextarea,
IonTitle, IonTitle,
IonToast, IonToast,
IonToolbar IonToolbar,
} from "@ionic/react"; } from "@ionic/react";
import React, { useEffect, useReducer, useState } from "react"; import React, { useEffect, useReducer, useState } from "react";
import { IonRow, IonCol } from "@ionic/react"; import { IonRow, IonCol } from "@ionic/react";
import './Perfil.css' import "./Perfil.css";
import { useHistory, useLocation } from "react-router"; import { useHistory, useLocation } from "react-router";
import { saveOutline } from "ionicons/icons"; import { saveOutline } from "ionicons/icons";
import isEqual from 'lodash.isequal'; import isEqual from "lodash.isequal";
import * as usersRoutes from '../services/api/users'; import * as usersRoutes from "../services/api/users";
import './Cadastro/Cadastro.css' import "./Cadastro/Cadastro.css";
import { Color } from "@ionic/core"; import { Color } from "@ionic/core";
import { closeToast } from "../services/utils"; import { closeToast } from "../services/utils";
import { PageHeader } from "../components/PageHeader";
interface userData { interface userData {
name: string; name: string;
@@ -40,7 +41,7 @@ interface userData {
} }
interface LocationState { interface LocationState {
userData: userData userData: userData;
} }
const PerfilEditar: React.FC = () => { const PerfilEditar: React.FC = () => {
@@ -48,97 +49,101 @@ const PerfilEditar: React.FC = () => {
const location = useLocation<LocationState>(); const location = useLocation<LocationState>();
const [showToast, setShowToast] = useState(false); const [showToast, setShowToast] = useState(false);
const [messageToast, setMessageToast] = useState(''); const [messageToast, setMessageToast] = useState("");
const [toastColor, setToastColor] = useState<Color>("primary"); const [toastColor, setToastColor] = useState<Color>("primary");
const [userData, setUserData] = useState({ const [userData, setUserData] = useState({
name: '', name: "",
lastname: '', lastname: "",
email: '', email: "",
birth_date: '', birth_date: "",
bio: '', bio: "",
}); });
const [inputValues, setInputValues] = useReducer( const [inputValues, setInputValues] = useReducer(
(state: any, newState: any) => ({ ...state, ...newState }), (state: any, newState: any) => ({ ...state, ...newState }),
{ {
name: '', name: "",
lastname: '', lastname: "",
email: '', email: "",
birth_date: '', birth_date: "",
bio: '', bio: "",
} }
); );
useEffect(() => { useEffect(() => {
if (!location.state) { if (!location.state) {
history.push({ pathname: '/perfil' }) history.push({ pathname: "/perfil" });
} }
let userData = location.state.userData let userData = location.state.userData;
setUserData(location.state.userData) setUserData(location.state.userData);
setInputValues({ setInputValues({
'name': userData.name, name: userData.name,
'lastname': userData.lastname, lastname: userData.lastname,
'email': userData.email, email: userData.email,
'birth_date': userData.birth_date, birth_date: userData.birth_date,
'bio': userData.bio bio: userData.bio,
}); });
console.log(inputValues) console.log(inputValues);
}, [userData]); }, [userData]);
const handleUpdateUserData = () => { const handleUpdateUserData = () => {
usersRoutes.update(inputValues).then(response => { usersRoutes
if (response.status === 'error') { .update(inputValues)
setToastColor("danger") .then((response) => {
setMessageToast(response.message); if (response.status === "error") {
setToastColor("danger");
setMessageToast(response.message);
setShowToast(true);
return;
}
history.push({
pathname: "/perfil",
state: {
redirectData: {
showToastMessage: true,
toastColor: "success",
toastMessage: response.message,
},
},
});
})
.catch((err) => {
setToastColor("danger");
setMessageToast(err);
setShowToast(true); setShowToast(true);
});
return };
}
history.push({ pathname: '/perfil', state: {
redirectData: {
showToastMessage: true,
toastColor: "success",
toastMessage: response.message,
},
}})
}).catch((err) => {
setToastColor("danger")
setMessageToast(err);
setShowToast(true);
})
}
const hasChangedSinceInitialState = () => { const hasChangedSinceInitialState = () => {
return isEqual(userData, inputValues) return isEqual(userData, inputValues);
} };
return ( return (
<IonPage> <IonPage>
<IonHeader> <PageHeader
<IonToolbar> pageName="Editar perfil"
<IonTitle>Editar perfil</IonTitle> backButtonPageUrl="/perfil"
<IonButtons slot="start"> ></PageHeader>
<IonBackButton defaultHref="/perfil" />
</IonButtons>
</IonToolbar>
</IonHeader>
<IonContent> <IonContent>
<IonGrid> <IonGrid>
<IonRow> <IonRow>
<IonCol size="12"> <IonCol size="12">
<div id='nome-sobrenome'> <div id="nome-sobrenome">
<IonItem> <IonItem>
<IonLabel position="stacked"> Nome</IonLabel> <IonLabel position="stacked"> Nome</IonLabel>
<IonInput <IonInput
type="text" type="text"
value={inputValues.name} value={inputValues.name}
onIonChange={(e) => setInputValues({'name': e.detail.value!})} onIonChange={(e) =>
setInputValues({ name: e.detail.value! })
}
></IonInput> ></IonInput>
</IonItem> </IonItem>
@@ -147,7 +152,9 @@ const PerfilEditar: React.FC = () => {
<IonInput <IonInput
type="text" type="text"
value={inputValues.lastname} value={inputValues.lastname}
onIonChange={(e) => setInputValues({'lastname': e.detail.value!})} onIonChange={(e) =>
setInputValues({ lastname: e.detail.value! })
}
></IonInput> ></IonInput>
</IonItem> </IonItem>
</div> </div>
@@ -157,25 +164,28 @@ const PerfilEditar: React.FC = () => {
<IonInput <IonInput
type="email" type="email"
value={inputValues.email} value={inputValues.email}
onIonChange={(e) => setInputValues({'email': e.detail.value!})} onIonChange={(e) =>
setInputValues({ email: e.detail.value! })
}
></IonInput> ></IonInput>
</IonItem> </IonItem>
<IonItem> <IonItem>
<IonLabel position='stacked'>Data de nascimento</IonLabel> <IonLabel position="stacked">Data de nascimento</IonLabel>
<IonInput <IonInput
type='date' type="date"
value={inputValues.birth_date} value={inputValues.birth_date}
onIonChange={(e) => setInputValues({'birth_date': e.detail.value!}) } onIonChange={(e) =>
> setInputValues({ birth_date: e.detail.value! })
</IonInput> }
></IonInput>
</IonItem> </IonItem>
<IonItem> <IonItem>
<IonLabel position="stacked"> Biografia</IonLabel> <IonLabel position="stacked"> Biografia</IonLabel>
<IonTextarea <IonTextarea
value={inputValues.bio} value={inputValues.bio}
onIonChange={(e) => setInputValues({'bio': e.detail.value!})} onIonChange={(e) => setInputValues({ bio: e.detail.value! })}
></IonTextarea> ></IonTextarea>
</IonItem> </IonItem>
</IonCol> </IonCol>
@@ -183,7 +193,10 @@ const PerfilEditar: React.FC = () => {
</IonGrid> </IonGrid>
<IonFab vertical="bottom" horizontal="end" slot="fixed"> <IonFab vertical="bottom" horizontal="end" slot="fixed">
<IonFabButton disabled={hasChangedSinceInitialState()} onClick={handleUpdateUserData}> <IonFabButton
disabled={hasChangedSinceInitialState()}
onClick={handleUpdateUserData}
>
<IonIcon icon={saveOutline} /> <IonIcon icon={saveOutline} />
</IonFabButton> </IonFabButton>
</IonFab> </IonFab>

View File

@@ -91,6 +91,7 @@ const Transportes: React.FC = () => {
return ( return (
<IonPage> <IonPage>
{/* TODO, componentizar Header */}
<IonHeader> <IonHeader>
<div className="header-page"> <div className="header-page">
{/* <IonButtons slot="start"> {/* <IonButtons slot="start">