Revert "Feature/VAN-16-view-create-itinerary"
This commit is contained in:
@@ -1,7 +1 @@
|
|||||||
# tcc-vamos-frontend
|
# tcc-vamos-frontend
|
||||||
|
|
||||||
# Primeiros passos para iniciar o desenvolvimento
|
|
||||||
|
|
||||||
- Rode o comando ```yarn``` para instalar as dependencias do projeto
|
|
||||||
- Para iniciar o desenvolvimento de uma nova funcionalidade crie uma branch
|
|
||||||
- Ao terminar o desenvolvimento abra um pull request para a branch "develop" e resolva os conflitos caso tenha
|
|
||||||
|
|||||||
48515
package-lock.json
generated
Normal file
48515
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
14
package.json
14
package.json
@@ -9,15 +9,13 @@
|
|||||||
"@capacitor/keyboard": "1.2.2",
|
"@capacitor/keyboard": "1.2.2",
|
||||||
"@capacitor/status-bar": "1.0.8",
|
"@capacitor/status-bar": "1.0.8",
|
||||||
"@craco/craco": "^6.4.5",
|
"@craco/craco": "^6.4.5",
|
||||||
"@googlemaps/js-api-loader": "^1.14.3",
|
|
||||||
"@hookform/error-message": "^2.0.0",
|
"@hookform/error-message": "^2.0.0",
|
||||||
"@ionic-selectable/core": "^5.0.0-alpha.13",
|
"@ionic-selectable/core": "^5.0.0-alpha.13",
|
||||||
"@ionic/react": "^6.2.5",
|
"@ionic/react": "^6.0.0",
|
||||||
"@ionic/react-router": "^6.2.5",
|
"@ionic/react-router": "^6.0.0",
|
||||||
"@testing-library/jest-dom": "^5.11.9",
|
"@testing-library/jest-dom": "^5.11.9",
|
||||||
"@testing-library/react": "^11.2.5",
|
"@testing-library/react": "^11.2.5",
|
||||||
"@testing-library/user-event": "^12.6.3",
|
"@testing-library/user-event": "^12.6.3",
|
||||||
"@types/google.maps": "^3.50.0",
|
|
||||||
"@types/jest": "^26.0.20",
|
"@types/jest": "^26.0.20",
|
||||||
"@types/node": "^12.19.15",
|
"@types/node": "^12.19.15",
|
||||||
"@types/react": "^18.0.18",
|
"@types/react": "^18.0.18",
|
||||||
@@ -25,7 +23,6 @@
|
|||||||
"@types/react-router": "^5.1.11",
|
"@types/react-router": "^5.1.11",
|
||||||
"@types/react-router-dom": "^5.1.7",
|
"@types/react-router-dom": "^5.1.7",
|
||||||
"axios": "^0.26.1",
|
"axios": "^0.26.1",
|
||||||
"caniuse-lite": "1.0.30001393",
|
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
"ionicons": "^5.4.0",
|
"ionicons": "^5.4.0",
|
||||||
"lodash.isequal": "^4.5.0",
|
"lodash.isequal": "^4.5.0",
|
||||||
@@ -33,6 +30,7 @@
|
|||||||
"pullstate": "^1.24.0",
|
"pullstate": "^1.24.0",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
|
"react-google-places-autocomplete": "^3.4.0",
|
||||||
"react-hook-form": "^7.30.0",
|
"react-hook-form": "^7.30.0",
|
||||||
"react-router": "^5.2.0",
|
"react-router": "^5.2.0",
|
||||||
"react-router-dom": "^5.2.0",
|
"react-router-dom": "^5.2.0",
|
||||||
@@ -86,11 +84,7 @@
|
|||||||
"@types/lodash.isequal": "^4.5.6",
|
"@types/lodash.isequal": "^4.5.6",
|
||||||
"autoprefixer": "^9.8.8",
|
"autoprefixer": "^9.8.8",
|
||||||
"postcss": "^7.0.39",
|
"postcss": "^7.0.39",
|
||||||
"react-error-overlay": "6.0.9",
|
|
||||||
"tailwindcss": "npm:@tailwindcss/postcss7-compat@^2.2.17"
|
"tailwindcss": "npm:@tailwindcss/postcss7-compat@^2.2.17"
|
||||||
},
|
},
|
||||||
"description": "Projeto de conclusão de curso a fim de resolver a dificuldade de alunos universitários ao buscar vans para suas universidades",
|
"description": "Projeto de conclusão de curso a fim de resolver a dificuldade de alunos universitários ao buscar vans para suas universidades"
|
||||||
"resolutions": {
|
|
||||||
"react-error-overlay": "6.0.9"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
12
src/App.tsx
12
src/App.tsx
@@ -1,3 +1,4 @@
|
|||||||
|
import React, { useContext, useState } from "react";
|
||||||
import {
|
import {
|
||||||
IonApp,
|
IonApp,
|
||||||
IonIcon,
|
IonIcon,
|
||||||
@@ -9,7 +10,6 @@ import {
|
|||||||
setupIonicReact,
|
setupIonicReact,
|
||||||
} from "@ionic/react";
|
} from "@ionic/react";
|
||||||
import { IonReactRouter } from "@ionic/react-router";
|
import { IonReactRouter } from "@ionic/react-router";
|
||||||
import React, { useContext, useState } from "react";
|
|
||||||
import { Redirect, Route } from "react-router-dom";
|
import { Redirect, Route } from "react-router-dom";
|
||||||
|
|
||||||
import { home, person, search } from "ionicons/icons";
|
import { home, person, search } from "ionicons/icons";
|
||||||
@@ -25,14 +25,15 @@ import Login from "./pages/Login";
|
|||||||
import Perfil from "./pages/Perfil";
|
import Perfil from "./pages/Perfil";
|
||||||
import PerfilEditar from "./pages/PerfilEditar";
|
import PerfilEditar from "./pages/PerfilEditar";
|
||||||
|
|
||||||
|
import VeiculoCadastro from "./pages/VeiculoCadastro";
|
||||||
|
import MeusVeiculos from "./pages/MeusVeiculos";
|
||||||
import CadastrarItinerario from "./pages/CadastrarItinerario/CadastrarItinerario";
|
import CadastrarItinerario from "./pages/CadastrarItinerario/CadastrarItinerario";
|
||||||
import MeusItinerarios from "./pages/MeusItinerarios/MeusItinerarios";
|
import MeusItinerarios from "./pages/MeusItinerarios/MeusItinerarios";
|
||||||
import MeusVeiculos from "./pages/MeusVeiculos";
|
|
||||||
import VeiculoCadastro from "./pages/VeiculoCadastro";
|
|
||||||
|
|
||||||
|
import Buscas from "./pages/Buscas";
|
||||||
import BuscarItinerario from "./pages/BuscarItinerario";
|
import BuscarItinerario from "./pages/BuscarItinerario";
|
||||||
import BuscarPassageiro from "./pages/BuscarPassageiro/BuscarPassageiro";
|
import BuscarPassageiro from "./pages/BuscarPassageiro/BuscarPassageiro";
|
||||||
import ListaItinerarios from "./pages/ListaItinerarios";
|
import Transportes from "./pages/Transportes/Transportes";
|
||||||
|
|
||||||
/* Core CSS required for Ionic components to work properly */
|
/* Core CSS required for Ionic components to work properly */
|
||||||
import "@ionic/react/css/core.css";
|
import "@ionic/react/css/core.css";
|
||||||
@@ -55,7 +56,6 @@ import "./theme/variables.css";
|
|||||||
|
|
||||||
/* Tailwind styles */
|
/* Tailwind styles */
|
||||||
import "./theme/tailwind.css";
|
import "./theme/tailwind.css";
|
||||||
import Buscas from "./pages/Buscas";
|
|
||||||
|
|
||||||
setupIonicReact();
|
setupIonicReact();
|
||||||
|
|
||||||
@@ -93,7 +93,7 @@ const routes = (
|
|||||||
<Route exact path="/buscas" component={Buscas}></Route>
|
<Route exact path="/buscas" component={Buscas}></Route>
|
||||||
<Route exact path="/buscar/itinerario" component={BuscarItinerario}></Route>
|
<Route exact path="/buscar/itinerario" component={BuscarItinerario}></Route>
|
||||||
<Route exact path="/buscar/passageiro" component={BuscarPassageiro}></Route>
|
<Route exact path="/buscar/passageiro" component={BuscarPassageiro}></Route>
|
||||||
<Route exact path="/buscar/itinerario/lista" component={ListaItinerarios}></Route>
|
<Route exact path="/transportes" component={Transportes}></Route>
|
||||||
|
|
||||||
<Route exact path="/">
|
<Route exact path="/">
|
||||||
<Redirect to="/home" />
|
<Redirect to="/home" />
|
||||||
|
|||||||
@@ -1,21 +1,24 @@
|
|||||||
|
const tokenId = 'token';
|
||||||
|
const productDetails = '@productDetails';
|
||||||
|
|
||||||
const LocalStorage = {
|
const LocalStorage = {
|
||||||
getToken: (): string => {
|
getToken: (): string => {
|
||||||
const tokenId = localStorage.getItem("tokenId");
|
const tokenId = localStorage.getItem('tokenId')
|
||||||
|
|
||||||
if (!tokenId) {
|
if (!tokenId) {
|
||||||
return "";
|
return ''
|
||||||
}
|
}
|
||||||
|
|
||||||
return tokenId;
|
return tokenId
|
||||||
},
|
},
|
||||||
|
|
||||||
setToken: (token: string) => {
|
setToken: (token: string) => {
|
||||||
localStorage.setItem("tokenId", token);
|
localStorage.setItem('tokenId', token)
|
||||||
},
|
},
|
||||||
|
|
||||||
clearToken: () => {
|
clearToken: () => {
|
||||||
localStorage.removeItem("tokenId");
|
localStorage.removeItem('tokenId')
|
||||||
},
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
export default LocalStorage;
|
export default LocalStorage
|
||||||
@@ -1,103 +0,0 @@
|
|||||||
import { Loader } from "@googlemaps/js-api-loader";
|
|
||||||
import { InputHTMLAttributes, useEffect, useRef } from "react";
|
|
||||||
|
|
||||||
const apiKey = process.env.REACT_APP_KEY_API
|
|
||||||
? process.env.REACT_APP_KEY_API
|
|
||||||
: "";
|
|
||||||
|
|
||||||
const extractAddress = (place: any) => {
|
|
||||||
const address = {
|
|
||||||
formatted_address: "",
|
|
||||||
lat: 0,
|
|
||||||
lng: 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (place.formatted_address) {
|
|
||||||
address.formatted_address = place.formatted_address;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (place.geometry && place.geometry.location) {
|
|
||||||
address.lat = place.geometry.location.lat();
|
|
||||||
address.lng = place.geometry.location.lng();
|
|
||||||
}
|
|
||||||
|
|
||||||
return address;
|
|
||||||
};
|
|
||||||
|
|
||||||
interface AddressSelected {
|
|
||||||
formatted_address: string;
|
|
||||||
lat: number;
|
|
||||||
lng: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface AutoCompleteInputProps extends InputHTMLAttributes<HTMLInputElement> {
|
|
||||||
onAddressSelected: (address: AddressSelected) => void;
|
|
||||||
clearAfterSelect?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
function AutoCompleteInput(props: AutoCompleteInputProps) {
|
|
||||||
const searchInput = useRef(null);
|
|
||||||
const { onAddressSelected, clearAfterSelect, ...othersProps } = props;
|
|
||||||
|
|
||||||
// do something on address change
|
|
||||||
const onChangeAddress = (autocomplete: any) => {
|
|
||||||
const place = autocomplete.getPlace();
|
|
||||||
const extractedAddress = extractAddress(place);
|
|
||||||
props.onAddressSelected && props.onAddressSelected(extractedAddress);
|
|
||||||
};
|
|
||||||
|
|
||||||
// init autocomplete
|
|
||||||
const initAutocomplete = () => {
|
|
||||||
if (!searchInput.current) return;
|
|
||||||
|
|
||||||
const autocomplete = new window.google.maps.places.Autocomplete(
|
|
||||||
searchInput.current
|
|
||||||
);
|
|
||||||
autocomplete.setFields(["formatted_address", "geometry"]);
|
|
||||||
autocomplete.setComponentRestrictions({ country: "br" });
|
|
||||||
autocomplete.addListener("place_changed", () =>
|
|
||||||
onChangeAddress(autocomplete)
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
// load map script after mounted
|
|
||||||
useEffect(() => {
|
|
||||||
const init = async () => {
|
|
||||||
try {
|
|
||||||
if (
|
|
||||||
!window.google ||
|
|
||||||
!window.google.maps ||
|
|
||||||
!window.google.maps.places
|
|
||||||
) {
|
|
||||||
await new Loader({
|
|
||||||
apiKey,
|
|
||||||
version: "weekly",
|
|
||||||
libraries: ["places"],
|
|
||||||
language: "pt-BR",
|
|
||||||
}).load();
|
|
||||||
}
|
|
||||||
initAutocomplete();
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if (apiKey) init();
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<input
|
|
||||||
ref={searchInput}
|
|
||||||
type="text"
|
|
||||||
{...othersProps}
|
|
||||||
style={{
|
|
||||||
textIndent: "0.5rem",
|
|
||||||
width: "100%",
|
|
||||||
height: "2.5rem",
|
|
||||||
borderRadius: "0.25rem",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default AutoCompleteInput;
|
|
||||||
@@ -1,10 +1,4 @@
|
|||||||
import {
|
import { IonBackButton, IonButtons, IonHeader, IonTitle, IonToolbar } from "@ionic/react";
|
||||||
IonBackButton,
|
|
||||||
IonButtons,
|
|
||||||
IonHeader,
|
|
||||||
IonTitle,
|
|
||||||
IonToolbar,
|
|
||||||
} from "@ionic/react";
|
|
||||||
|
|
||||||
interface ComponentProps {
|
interface ComponentProps {
|
||||||
pageName: string;
|
pageName: string;
|
||||||
@@ -16,12 +10,7 @@ export const PageHeader = (props: ComponentProps) => (
|
|||||||
<IonToolbar>
|
<IonToolbar>
|
||||||
<IonTitle>{props.pageName}</IonTitle>
|
<IonTitle>{props.pageName}</IonTitle>
|
||||||
<IonButtons slot="start">
|
<IonButtons slot="start">
|
||||||
<IonBackButton
|
<IonBackButton text="" defaultHref={ props.backButtonPageUrl ? props.backButtonPageUrl : undefined } />
|
||||||
text=""
|
|
||||||
defaultHref={
|
|
||||||
props.backButtonPageUrl ? props.backButtonPageUrl : undefined
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</IonButtons>
|
</IonButtons>
|
||||||
</IonToolbar>
|
</IonToolbar>
|
||||||
</IonHeader>
|
</IonHeader>
|
||||||
|
|||||||
@@ -4,9 +4,15 @@ import {
|
|||||||
IonCardSubtitle,
|
IonCardSubtitle,
|
||||||
IonCol,
|
IonCol,
|
||||||
IonIcon,
|
IonIcon,
|
||||||
|
IonNote,
|
||||||
IonRow,
|
IonRow,
|
||||||
} from "@ionic/react";
|
} from "@ionic/react";
|
||||||
import { call, callOutline, navigateOutline } from "ionicons/icons";
|
import {
|
||||||
|
arrowForward,
|
||||||
|
call,
|
||||||
|
callOutline,
|
||||||
|
navigateOutline,
|
||||||
|
} from "ionicons/icons";
|
||||||
import "./UserSearchInfos.css";
|
import "./UserSearchInfos.css";
|
||||||
|
|
||||||
export const UserSearchInfos = (record: any) => {
|
export const UserSearchInfos = (record: any) => {
|
||||||
@@ -22,7 +28,7 @@ export const UserSearchInfos = (record: any) => {
|
|||||||
</IonBadge>
|
</IonBadge>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<IonIcon icon={navigateOutline} size="large" />
|
<IonIcon icon={navigateOutline} size='large' />
|
||||||
{record.record.address_to}
|
{record.record.address_to}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|||||||
@@ -6,8 +6,6 @@
|
|||||||
.button-search{
|
.button-search{
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|
||||||
margin-top: 50%;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.latest-searches{
|
.latest-searches{
|
||||||
|
|||||||
@@ -1,39 +1,49 @@
|
|||||||
import {
|
import {
|
||||||
|
IonBackButton,
|
||||||
IonButton,
|
IonButton,
|
||||||
|
IonButtons,
|
||||||
IonCard,
|
IonCard,
|
||||||
IonCardContent,
|
IonCardContent,
|
||||||
|
IonCardHeader,
|
||||||
|
IonCardSubtitle,
|
||||||
|
IonCardTitle,
|
||||||
IonContent,
|
IonContent,
|
||||||
|
IonHeader,
|
||||||
IonIcon,
|
IonIcon,
|
||||||
|
IonItem,
|
||||||
IonItemDivider,
|
IonItemDivider,
|
||||||
IonPage,
|
IonPage,
|
||||||
IonRow,
|
IonRow,
|
||||||
|
IonTitle,
|
||||||
IonToast,
|
IonToast,
|
||||||
|
IonToolbar,
|
||||||
} from "@ionic/react";
|
} from "@ionic/react";
|
||||||
import {
|
import {
|
||||||
arrowForwardOutline,
|
arrowForwardOutline,
|
||||||
|
cashOutline,
|
||||||
chevronForwardOutline,
|
chevronForwardOutline,
|
||||||
locateOutline,
|
locateOutline,
|
||||||
locationOutline,
|
locationOutline,
|
||||||
|
personOutline,
|
||||||
|
starOutline,
|
||||||
timeOutline,
|
timeOutline,
|
||||||
} from "ionicons/icons";
|
} from "ionicons/icons";
|
||||||
import "./BuscarItinerario.css";
|
import "./BuscarItinerario.css";
|
||||||
|
|
||||||
import { useState } from "react";
|
import itinerariesService from "../services/functions/itinerariesService";
|
||||||
|
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
import { useHistory } from "react-router";
|
import { useHistory } from "react-router";
|
||||||
|
|
||||||
import { PageHeader } from "../components/PageHeader";
|
import GooglePlacesAutocomplete, {
|
||||||
|
geocodeByAddress,
|
||||||
|
getLatLng,
|
||||||
|
} from "react-google-places-autocomplete";
|
||||||
import { Itinerary } from "../models/itinerary.model";
|
import { Itinerary } from "../models/itinerary.model";
|
||||||
|
import { PageHeader } from "../components/PageHeader";
|
||||||
import { closeToast } from "../services/utils";
|
import { closeToast } from "../services/utils";
|
||||||
|
|
||||||
import { Color } from "@ionic/core";
|
import { Color } from "@ionic/core";
|
||||||
import AutoCompleteInput from "../components/AutoCompleteInput";
|
|
||||||
import { searchItineraries } from "../services/functions/itinerariesService";
|
|
||||||
|
|
||||||
interface Address {
|
|
||||||
formatted_address: string;
|
|
||||||
lat: number;
|
|
||||||
lng: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
const BuscarItinerario: React.FC = () => {
|
const BuscarItinerario: React.FC = () => {
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
@@ -42,10 +52,13 @@ const BuscarItinerario: React.FC = () => {
|
|||||||
const [messageToast, setMessageToast] = useState("");
|
const [messageToast, setMessageToast] = useState("");
|
||||||
const [toastColor, setToastColor] = useState<Color>("primary");
|
const [toastColor, setToastColor] = useState<Color>("primary");
|
||||||
|
|
||||||
const [addressFrom, setAddressFrom] = useState<Address>();
|
const [addressFrom, setAddressFrom] = useState<any>("");
|
||||||
const [coordinatesFrom, setCoordinatesFrom] = useState<any>("");
|
const [coordinatesFrom, setCoordinatesFrom] = useState<any>("");
|
||||||
const [addressTo, setAddressTo] = useState<Address>();
|
const [addressTo, setAddressTo] = useState<any>("");
|
||||||
const [coordinatesTo, setCoordinatesTo] = useState<any>("");
|
const [coordinatesTo, setCoordinatesTo] = useState<any>("");
|
||||||
|
const [showModalEnd, setShowModalEnd] = useState(false);
|
||||||
|
const [addressResults, setAddressResults] = useState<any[]>([]);
|
||||||
|
const [inputActive, setInputActive] = useState("");
|
||||||
|
|
||||||
const [recentSearches, setRecentSearches] = useState<any[]>([]);
|
const [recentSearches, setRecentSearches] = useState<any[]>([]);
|
||||||
|
|
||||||
@@ -84,33 +97,46 @@ const BuscarItinerario: React.FC = () => {
|
|||||||
// setShowModalEnd(false);
|
// setShowModalEnd(false);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (addressFrom.label && addressFrom.label.length > 0) {
|
||||||
|
geocodeByAddress(addressFrom.label)
|
||||||
|
.then((results) => getLatLng(results[0]))
|
||||||
|
.then(({ lat, lng }) => setCoordinatesFrom({ lat, lng }));
|
||||||
|
}
|
||||||
|
}, [addressFrom]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (addressTo.label && addressTo.label.length > 0) {
|
||||||
|
geocodeByAddress(addressTo.label)
|
||||||
|
.then((results) => getLatLng(results[0]))
|
||||||
|
.then(({ lat, lng }) => setCoordinatesTo({ lat, lng }));
|
||||||
|
}
|
||||||
|
}, [addressTo]);
|
||||||
|
|
||||||
async function buscarItinerarios() {
|
async function buscarItinerarios() {
|
||||||
if (!addressFrom || !addressTo) {
|
if (!coordinatesFrom || !coordinatesTo || !addressFrom || !addressTo) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const maxRecentSearchesLength = 0;;
|
const maxRecentSearchesLength = 0
|
||||||
|
|
||||||
if (recentSearches.length >= maxRecentSearchesLength) {
|
if (recentSearches.length >= maxRecentSearchesLength) {
|
||||||
setRecentSearches(
|
setRecentSearches(recentSearches.slice(recentSearches.length - maxRecentSearchesLength));
|
||||||
|
|
||||||
recentSearches.slice(recentSearches.length - maxRecentSearchesLength)
|
|
||||||
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setRecentSearches((arr) => [
|
setRecentSearches((arr) => [
|
||||||
...arr,
|
...arr,
|
||||||
{
|
{
|
||||||
addressFrom: addressFrom.formatted_address,
|
addressFrom: addressFrom.label,
|
||||||
addressTo: addressTo.formatted_address,
|
addressTo: addressTo.label,
|
||||||
time: Date.now(),
|
time: Date.now(),
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
await searchItineraries({
|
await itinerariesService
|
||||||
coordinatesFrom: addressFrom,
|
.searchItineraries({
|
||||||
coordinatesTo: addressTo,
|
coordinatesFrom,
|
||||||
|
coordinatesTo,
|
||||||
})
|
})
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
// if (response.status === "error") {
|
// if (response.status === "error") {
|
||||||
@@ -121,18 +147,7 @@ const BuscarItinerario: React.FC = () => {
|
|||||||
// return;
|
// return;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
history.push({
|
setItinerariesList(response);
|
||||||
pathname: "/buscar/itinerario/lista",
|
|
||||||
state: {
|
|
||||||
coordinatesFrom,
|
|
||||||
coordinatesTo,
|
|
||||||
addressFrom,
|
|
||||||
addressTo,
|
|
||||||
itineraries: response,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
// setItinerariesList(response);
|
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
setToastColor("danger");
|
setToastColor("danger");
|
||||||
@@ -158,20 +173,40 @@ const BuscarItinerario: React.FC = () => {
|
|||||||
<IonCardContent>
|
<IonCardContent>
|
||||||
<div className="inputs-from-to">
|
<div className="inputs-from-to">
|
||||||
<IonIcon icon={locateOutline}></IonIcon>
|
<IonIcon icon={locateOutline}></IonIcon>
|
||||||
<AutoCompleteInput
|
{/* <IonSearchbar
|
||||||
placeholder="R. José Paulino, 1234"
|
showClearButton="never"
|
||||||
className="ml-2"
|
onClick={() => setInputActiveOpenModal("from")}
|
||||||
onAddressSelected={(address: Address) =>
|
value={addressFrom}
|
||||||
setAddressFrom(address)
|
placeholder="R. José Paulino, 1234 - Centro, Campinas - SP, 13013-001"
|
||||||
}
|
/> */}
|
||||||
|
<GooglePlacesAutocomplete
|
||||||
|
apiKey={process.env.REACT_APP_KEY_API}
|
||||||
|
apiOptions={{ language: "pt-br", region: "br" }}
|
||||||
|
selectProps={{
|
||||||
|
value: addressFrom,
|
||||||
|
onChange: setAddressFrom,
|
||||||
|
className: "input-autocomplete",
|
||||||
|
placeholder: "R. José Paulino, 1234",
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="inputs-from-to">
|
<div className="inputs-from-to">
|
||||||
<IonIcon icon={locationOutline}></IonIcon>
|
<IonIcon icon={locationOutline}></IonIcon>
|
||||||
<AutoCompleteInput
|
{/* <IonSearchbar
|
||||||
|
showClearButton="never"
|
||||||
|
onClick={() => setInputActiveOpenModal("to")}
|
||||||
|
value={addressTo}
|
||||||
placeholder="PUC Campinas"
|
placeholder="PUC Campinas"
|
||||||
className="ml-2"
|
/> */}
|
||||||
onAddressSelected={(address: Address) => setAddressTo(address)}
|
<GooglePlacesAutocomplete
|
||||||
|
apiKey={process.env.REACT_APP_KEY_API}
|
||||||
|
apiOptions={{ language: "pt-br", region: "br" }}
|
||||||
|
selectProps={{
|
||||||
|
value: addressTo,
|
||||||
|
onChange: setAddressTo,
|
||||||
|
className: "input-autocomplete",
|
||||||
|
placeholder: "PUC Campinas",
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="button-search">
|
<div className="button-search">
|
||||||
@@ -188,9 +223,9 @@ const BuscarItinerario: React.FC = () => {
|
|||||||
<IonRow class="latest-searches">
|
<IonRow class="latest-searches">
|
||||||
{recentSearches.map((search, index) => {
|
{recentSearches.map((search, index) => {
|
||||||
return (
|
return (
|
||||||
<div key={index}>
|
<>
|
||||||
<IonRow
|
<div>
|
||||||
|
<IonRow key={index}
|
||||||
class="latest-searches"
|
class="latest-searches"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
fillSearchBars(search.addressFrom, search.addressTo);
|
fillSearchBars(search.addressFrom, search.addressTo);
|
||||||
@@ -215,6 +250,7 @@ const BuscarItinerario: React.FC = () => {
|
|||||||
></IonIcon>
|
></IonIcon>
|
||||||
</IonRow>
|
</IonRow>
|
||||||
</div>
|
</div>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</IonRow>
|
</IonRow>
|
||||||
@@ -222,6 +258,102 @@ const BuscarItinerario: React.FC = () => {
|
|||||||
) : (
|
) : (
|
||||||
<></>
|
<></>
|
||||||
)}
|
)}
|
||||||
|
{/* <IonRow class="latest-searches">
|
||||||
|
<IonIcon
|
||||||
|
className="icon-align-vcenter"
|
||||||
|
size="large"
|
||||||
|
icon={timeOutline}
|
||||||
|
/>
|
||||||
|
<div className="div_from_to">
|
||||||
|
<span>Taquaral</span>
|
||||||
|
<IonIcon icon={arrowForwardOutline}></IonIcon>
|
||||||
|
<span>PUC-Campinas</span>
|
||||||
|
<br />
|
||||||
|
<small>Há 2 hora</small>
|
||||||
|
</div>
|
||||||
|
<IonIcon
|
||||||
|
className="icon-forward icon-align-vcenter"
|
||||||
|
size="large"
|
||||||
|
icon={chevronForwardOutline}
|
||||||
|
/>
|
||||||
|
</IonRow> */}
|
||||||
|
{/* <IonModal isOpen={showModalEnd}>
|
||||||
|
<IonContent>
|
||||||
|
<div className="header-search-modal">
|
||||||
|
<IonIcon
|
||||||
|
className="icon-return-modal"
|
||||||
|
icon={arrowBack}
|
||||||
|
onClick={() => setShowModalEnd(false)}
|
||||||
|
/>
|
||||||
|
<IonInput
|
||||||
|
onIonChange={(e) => optionsAddress(e.detail.value)}
|
||||||
|
placeholder="R. José Paulino, 1234 - Centro, Campinas - SP, 13013-001"
|
||||||
|
className="search-modal"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{addressResults.length > 0 ? (
|
||||||
|
addressResults.map((item: any) => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
key={item.value}
|
||||||
|
className="modal-search-results"
|
||||||
|
data-value={item.value}
|
||||||
|
data-label={item.label}
|
||||||
|
onClick={(e) => setAddress(e)}
|
||||||
|
>
|
||||||
|
{item.label}
|
||||||
|
<IonIcon
|
||||||
|
className="icon-results-modal"
|
||||||
|
icon={chevronForwardOutline}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<IonProgressBar type="indeterminate" />
|
||||||
|
<br />
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</IonContent>
|
||||||
|
</IonModal> */}
|
||||||
|
|
||||||
|
{itinerariesList && itinerariesList.length !== 0 ? (
|
||||||
|
<>
|
||||||
|
<IonItemDivider color="secondary">Resultados</IonItemDivider>
|
||||||
|
{itinerariesList.map((itinerary, index) => {
|
||||||
|
return (
|
||||||
|
<IonCard
|
||||||
|
button
|
||||||
|
key={index}
|
||||||
|
onClick={() => {
|
||||||
|
history.push(`/itinerary/${itinerary.id_itinerary}`);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<IonCardHeader>
|
||||||
|
<IonCardTitle>{itinerary.itinerary_nickname}</IonCardTitle>
|
||||||
|
<IonCardSubtitle>
|
||||||
|
<p>
|
||||||
|
<IonIcon icon={personOutline} /> Vagas disponíveis:{" "}
|
||||||
|
{itinerary.available_seats}
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<IonIcon icon={starOutline} /> Motorista:{" "}
|
||||||
|
{itinerary.price}
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<IonIcon icon={cashOutline} /> Valor:{" "}
|
||||||
|
{itinerary.vehicle_plate}
|
||||||
|
</p>
|
||||||
|
</IonCardSubtitle>
|
||||||
|
</IonCardHeader>
|
||||||
|
</IonCard>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<></>
|
||||||
|
)}
|
||||||
|
|
||||||
<IonToast
|
<IonToast
|
||||||
color={toastColor}
|
color={toastColor}
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import {
|
import {
|
||||||
IonContent,
|
IonContent,
|
||||||
|
IonPage,
|
||||||
IonFab,
|
IonFab,
|
||||||
IonFabButton,
|
IonFabButton,
|
||||||
IonIcon,
|
IonIcon,
|
||||||
IonPage,
|
|
||||||
} from "@ionic/react";
|
} from "@ionic/react";
|
||||||
import { search } from "ionicons/icons";
|
import { search } from "ionicons/icons";
|
||||||
import "./BuscarPassageiro.css";
|
import "./BuscarPassageiro.css";
|
||||||
@@ -12,11 +12,11 @@ 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 { PageHeader } from "../../components/PageHeader";
|
|
||||||
import { UserSearchInfos } from "../../components/UserSearchInfos/UserSearchInfos";
|
|
||||||
import { getUsersSearching } from "../../services/api/users";
|
|
||||||
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 { UserSearchInfos } from "../../components/UserSearchInfos/UserSearchInfos";
|
||||||
|
import { PageHeader } from "../../components/PageHeader";
|
||||||
|
|
||||||
const maptilerProvider = maptiler("d5JQJPLLuap8TkJJlTdJ", "streets");
|
const maptilerProvider = maptiler("d5JQJPLLuap8TkJJlTdJ", "streets");
|
||||||
|
|
||||||
@@ -52,7 +52,7 @@ const BuscarPassageiro: React.FC = () => {
|
|||||||
const [results, setResults] = useState([]);
|
const [results, setResults] = useState([]);
|
||||||
const [zoom, setZoom] = useState(14);
|
const [zoom, setZoom] = useState(14);
|
||||||
|
|
||||||
// const [ moveMode, setMoveMode ] = useState(false);
|
const [moveMode, setMoveMode] = useState(false);
|
||||||
|
|
||||||
// useEffect(() => {
|
// useEffect(() => {
|
||||||
|
|
||||||
|
|||||||
@@ -1,941 +1,55 @@
|
|||||||
import { Color } from "@ionic/core";
|
|
||||||
import {
|
import {
|
||||||
IonBackButton,
|
IonBackButton,
|
||||||
IonButton,
|
IonButton,
|
||||||
IonButtons,
|
IonButtons,
|
||||||
IonCheckbox,
|
|
||||||
IonContent,
|
IonContent,
|
||||||
IonDatetime,
|
|
||||||
IonHeader,
|
IonHeader,
|
||||||
IonIcon,
|
IonIcon,
|
||||||
IonInput,
|
|
||||||
IonItem,
|
|
||||||
IonLabel,
|
|
||||||
IonList,
|
|
||||||
IonPage,
|
IonPage,
|
||||||
IonSelect,
|
|
||||||
IonSelectOption,
|
|
||||||
IonSlide,
|
|
||||||
IonSlides,
|
|
||||||
IonTitle,
|
IonTitle,
|
||||||
IonToast,
|
|
||||||
IonToolbar,
|
IonToolbar,
|
||||||
} from "@ionic/react";
|
} from "@ionic/react";
|
||||||
import {
|
import { close, locateOutline, locationOutline } from "ionicons/icons";
|
||||||
addCircleOutline,
|
import GooglePlacesAutocomplete from "react-google-places-autocomplete";
|
||||||
arrowBack,
|
import { PageHeader } from "../../components/PageHeader";
|
||||||
arrowForward,
|
|
||||||
checkmark,
|
|
||||||
close,
|
|
||||||
informationCircle,
|
|
||||||
locateOutline,
|
|
||||||
locationOutline,
|
|
||||||
removeCircleOutline,
|
|
||||||
trash,
|
|
||||||
} from "ionicons/icons";
|
|
||||||
import { useEffect, useRef, useState } from "react";
|
|
||||||
import { useHistory } from "react-router";
|
|
||||||
import AutoCompleteInput from "../../components/AutoCompleteInput";
|
|
||||||
import { CreateItineraryRequest } from "../../services/api/itineraries";
|
|
||||||
import * as vehiclesRoutes from "../../services/api/vehicles";
|
|
||||||
import { createItinerary } from "../../services/functions/itinerariesService";
|
|
||||||
import sessionsService from "../../services/functions/sessionsService";
|
|
||||||
|
|
||||||
const slideOpts = {
|
|
||||||
initialSlide: 0,
|
|
||||||
allowTouchMove: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
interface VanInfo {
|
|
||||||
plate: string;
|
|
||||||
brand: string;
|
|
||||||
model: string;
|
|
||||||
seats_number: string;
|
|
||||||
document_status: boolean;
|
|
||||||
locator_name: string;
|
|
||||||
locator_address: string;
|
|
||||||
locator_complement: string;
|
|
||||||
locator_city: string;
|
|
||||||
locator_state: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Address {
|
|
||||||
formatted_address: string;
|
|
||||||
lat: number;
|
|
||||||
lng: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Destinations extends Address {
|
|
||||||
is_final?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function CadastrarItinerario() {
|
export default function CadastrarItinerario() {
|
||||||
const minDate = new Date();
|
|
||||||
|
|
||||||
const history = useHistory();
|
|
||||||
|
|
||||||
const [showToast, setShowToast] = useState<boolean>(false);
|
|
||||||
const [toastMessage, setToastMessage] = useState<string>("");
|
|
||||||
const [toastColor, setToastColor] = useState<Color>("primary");
|
|
||||||
|
|
||||||
const mySlides = useRef<any>(null);
|
|
||||||
const nextButton1 = useRef<HTMLIonButtonElement>(null);
|
|
||||||
const nextButton2 = useRef<HTMLIonButtonElement>(null);
|
|
||||||
const nextButton3 = useRef<HTMLIonButtonElement>(null);
|
|
||||||
const nextButton4 = useRef<HTMLIonButtonElement>(null);
|
|
||||||
const nextButton5 = useRef<HTMLIonButtonElement>(null);
|
|
||||||
const nextButton6 = useRef<HTMLIonButtonElement>(null);
|
|
||||||
|
|
||||||
const [specificDate, setSpecificDate] = useState<boolean>(false);
|
|
||||||
const [singleVacancy, setSingleVacancy] = useState<boolean>(false);
|
|
||||||
const [vans, setVans] = useState<VanInfo[]>();
|
|
||||||
|
|
||||||
//Infos
|
|
||||||
const [initialAddress, setInitialAddress] = useState<Address>();
|
|
||||||
const [neighborhoods, setNeighborhoods] = useState<Address[]>([]);
|
|
||||||
const [finalAddress, setFinalAddress] = useState<Address>();
|
|
||||||
const [destinations, setDestinations] = useState<Destinations[]>([]);
|
|
||||||
const [daysOfWeek, setDaysOfWeek] = useState<string>("0000000");
|
|
||||||
const [specificDay, setSpecificDay] = useState<string>("");
|
|
||||||
const [departureTime, setDepartureTime] = useState<string>("00:00");
|
|
||||||
const [arrivalTime, setArrivalTime] = useState<string>("00:00");
|
|
||||||
const [monthlyPrice, setMonthlyPrice] = useState<number>(100);
|
|
||||||
const [dailyPrice, setDailyPrice] = useState<number>(40);
|
|
||||||
const [van, setVan] = useState<string>("");
|
|
||||||
const [nickname, setNickname] = useState<string>("");
|
|
||||||
|
|
||||||
const redirectUserToLogin = () => {
|
|
||||||
history.push({ pathname: "/login" });
|
|
||||||
};
|
|
||||||
|
|
||||||
const onBtnClicked = async (direction: string) => {
|
|
||||||
const swiper = await mySlides.current.getSwiper();
|
|
||||||
if (direction === "next") {
|
|
||||||
swiper.slideNext();
|
|
||||||
} else if (direction === "prev") {
|
|
||||||
swiper.slidePrev();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function formatRange(rangeValue: number) {
|
|
||||||
switch (rangeValue) {
|
|
||||||
case 1:
|
|
||||||
return "Segunda";
|
|
||||||
case 2:
|
|
||||||
return "Terça";
|
|
||||||
case 3:
|
|
||||||
return "Quarta";
|
|
||||||
case 4:
|
|
||||||
return "Quinta";
|
|
||||||
case 5:
|
|
||||||
return "Sexta";
|
|
||||||
case 6:
|
|
||||||
return "Sabádo";
|
|
||||||
case 7:
|
|
||||||
return "Domingo";
|
|
||||||
|
|
||||||
default:
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const getUserVans = async () => {
|
|
||||||
let userId = "";
|
|
||||||
|
|
||||||
const refreshSessionRes = await sessionsService.refreshSession();
|
|
||||||
|
|
||||||
if (refreshSessionRes.error) {
|
|
||||||
redirectUserToLogin();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (refreshSessionRes.userId) {
|
|
||||||
userId = refreshSessionRes.userId;
|
|
||||||
}
|
|
||||||
|
|
||||||
await vehiclesRoutes
|
|
||||||
.getByUserId(userId)
|
|
||||||
.then((response: any) => {
|
|
||||||
if (response.status === "error") {
|
|
||||||
setToastColor("danger");
|
|
||||||
setToastMessage(response.message);
|
|
||||||
setShowToast(true);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
setVans(response.data);
|
|
||||||
})
|
|
||||||
.catch((err: any) => {
|
|
||||||
setToastColor("danger");
|
|
||||||
setToastMessage(err);
|
|
||||||
setShowToast(true);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
getUserVans();
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (initialAddress) {
|
|
||||||
nextButton1.current!.disabled = false;
|
|
||||||
} else {
|
|
||||||
nextButton1.current!.disabled = true;
|
|
||||||
}
|
|
||||||
}, [initialAddress]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (finalAddress) {
|
|
||||||
nextButton3.current!.disabled = false;
|
|
||||||
} else {
|
|
||||||
nextButton3.current!.disabled = true;
|
|
||||||
}
|
|
||||||
}, [finalAddress]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (van) {
|
|
||||||
nextButton6.current!.disabled = false;
|
|
||||||
} else {
|
|
||||||
nextButton6.current!.disabled = true;
|
|
||||||
}
|
|
||||||
}, [van]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
|
|
||||||
}, [destinations]);
|
|
||||||
|
|
||||||
function addNeighborhood(address: Address) {
|
|
||||||
setNeighborhoods((arr) => [...arr, address]);
|
|
||||||
nextButton2.current!.disabled = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function removeNeighborhood(index: number) {
|
|
||||||
const newNeighborhoods = [...neighborhoods];
|
|
||||||
newNeighborhoods.splice(index, 1);
|
|
||||||
setNeighborhoods(newNeighborhoods);
|
|
||||||
if (newNeighborhoods.length === 0) {
|
|
||||||
nextButton2.current!.disabled = true;
|
|
||||||
} else {
|
|
||||||
nextButton2.current!.disabled = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function removeDestionation(index: number) {
|
|
||||||
const newDestionations = [...destinations];
|
|
||||||
newDestionations.splice(index, 1);
|
|
||||||
setDestinations(newDestionations);
|
|
||||||
}
|
|
||||||
|
|
||||||
function setDayOfWeekSeleted(day: string, checked: boolean) {
|
|
||||||
switch (day) {
|
|
||||||
case "Domingo":
|
|
||||||
setDaysOfWeek((value) => {
|
|
||||||
if (checked) {
|
|
||||||
let newDaysOfWeek = value.split("");
|
|
||||||
newDaysOfWeek[0] = "1";
|
|
||||||
let finalString = newDaysOfWeek.join("");
|
|
||||||
return finalString;
|
|
||||||
} else {
|
|
||||||
let newDaysOfWeek = value.split("");
|
|
||||||
newDaysOfWeek[0] = "0";
|
|
||||||
let finalString = newDaysOfWeek.join("");
|
|
||||||
return finalString;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case "Segunda":
|
|
||||||
setDaysOfWeek((value) => {
|
|
||||||
if (checked) {
|
|
||||||
let newDaysOfWeek = value.split("");
|
|
||||||
newDaysOfWeek[1] = "1";
|
|
||||||
let finalString = newDaysOfWeek.join("");
|
|
||||||
return finalString;
|
|
||||||
} else {
|
|
||||||
let newDaysOfWeek = value.split("");
|
|
||||||
newDaysOfWeek[1] = "0";
|
|
||||||
let finalString = newDaysOfWeek.join("");
|
|
||||||
return finalString;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case "Terça":
|
|
||||||
setDaysOfWeek((value) => {
|
|
||||||
if (checked) {
|
|
||||||
let newDaysOfWeek = value.split("");
|
|
||||||
newDaysOfWeek[2] = "1";
|
|
||||||
let finalString = newDaysOfWeek.join("");
|
|
||||||
return finalString;
|
|
||||||
} else {
|
|
||||||
let newDaysOfWeek = value.split("");
|
|
||||||
newDaysOfWeek[2] = "0";
|
|
||||||
let finalString = newDaysOfWeek.join("");
|
|
||||||
return finalString;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case "Quarta":
|
|
||||||
setDaysOfWeek((value) => {
|
|
||||||
if (checked) {
|
|
||||||
let newDaysOfWeek = value.split("");
|
|
||||||
newDaysOfWeek[3] = "1";
|
|
||||||
let finalString = newDaysOfWeek.join("");
|
|
||||||
return finalString;
|
|
||||||
} else {
|
|
||||||
let newDaysOfWeek = value.split("");
|
|
||||||
newDaysOfWeek[3] = "0";
|
|
||||||
let finalString = newDaysOfWeek.join("");
|
|
||||||
return finalString;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case "Quinta":
|
|
||||||
setDaysOfWeek((value) => {
|
|
||||||
if (checked) {
|
|
||||||
let newDaysOfWeek = value.split("");
|
|
||||||
newDaysOfWeek[4] = "1";
|
|
||||||
let finalString = newDaysOfWeek.join("");
|
|
||||||
return finalString;
|
|
||||||
} else {
|
|
||||||
let newDaysOfWeek = value.split("");
|
|
||||||
newDaysOfWeek[4] = "0";
|
|
||||||
let finalString = newDaysOfWeek.join("");
|
|
||||||
return finalString;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case "Sexta":
|
|
||||||
setDaysOfWeek((value) => {
|
|
||||||
if (checked) {
|
|
||||||
let newDaysOfWeek = value.split("");
|
|
||||||
newDaysOfWeek[5] = "1";
|
|
||||||
let finalString = newDaysOfWeek.join("");
|
|
||||||
return finalString;
|
|
||||||
} else {
|
|
||||||
let newDaysOfWeek = value.split("");
|
|
||||||
newDaysOfWeek[5] = "0";
|
|
||||||
let finalString = newDaysOfWeek.join("");
|
|
||||||
return finalString;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case "Sábado":
|
|
||||||
setDaysOfWeek((value) => {
|
|
||||||
if (checked) {
|
|
||||||
let newDaysOfWeek = value.split("");
|
|
||||||
newDaysOfWeek[6] = "1";
|
|
||||||
let finalString = newDaysOfWeek.join("");
|
|
||||||
return finalString;
|
|
||||||
} else {
|
|
||||||
let newDaysOfWeek = value.split("");
|
|
||||||
newDaysOfWeek[6] = "0";
|
|
||||||
let finalString = newDaysOfWeek.join("");
|
|
||||||
return finalString;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
useEffect(() => {}, [daysOfWeek]);
|
|
||||||
|
|
||||||
async function cadastrar() {
|
|
||||||
let newDestinations: Destinations[] = [{...finalAddress!, is_final: true}];
|
|
||||||
newDestinations = newDestinations.concat(destinations);
|
|
||||||
|
|
||||||
let itinerary: CreateItineraryRequest = {
|
|
||||||
vehicle_plate: van,
|
|
||||||
days_of_week: daysOfWeek,
|
|
||||||
specific_day: specificDate ? specificDay : undefined,
|
|
||||||
estimated_departure_time: departureTime,
|
|
||||||
estimated_arrival_time: arrivalTime,
|
|
||||||
monthly_price: monthlyPrice,
|
|
||||||
daily_price: dailyPrice,
|
|
||||||
accept_daily: singleVacancy,
|
|
||||||
itinerary_nickname: nickname,
|
|
||||||
estimated_departure_address: initialAddress!.formatted_address,
|
|
||||||
departure_latitude: initialAddress!.lat,
|
|
||||||
departure_longitude: initialAddress!.lng,
|
|
||||||
neighborhoods_served: neighborhoods,
|
|
||||||
destinations: newDestinations,
|
|
||||||
};
|
|
||||||
|
|
||||||
await createItinerary(itinerary)
|
|
||||||
.then((response: any) => {
|
|
||||||
if (response.status === "error") {
|
|
||||||
setToastColor("danger");
|
|
||||||
setToastMessage(response.message);
|
|
||||||
setShowToast(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
setToastColor("success");
|
|
||||||
setToastMessage(response.message);
|
|
||||||
setShowToast(true);
|
|
||||||
|
|
||||||
history.push({
|
|
||||||
pathname: "/meus-itinerarios",
|
|
||||||
// state: {
|
|
||||||
// redirectData: {
|
|
||||||
// showToastMessage: true,
|
|
||||||
// toastColor: "success",
|
|
||||||
// toastMessage: "Itinerário cadastrado com sucesso!",
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.catch((err: any) => {
|
|
||||||
setToastColor("danger");
|
|
||||||
setToastMessage(err);
|
|
||||||
setShowToast(true);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<IonPage>
|
<IonPage>
|
||||||
<IonHeader>
|
<PageHeader
|
||||||
<IonToolbar>
|
pageName="Cadastrar itinerário"
|
||||||
<IonTitle>Cadastrar Itinerário</IonTitle>
|
backButtonPageUrl="/perfil"
|
||||||
<IonButtons slot="start">
|
></PageHeader>
|
||||||
<IonBackButton icon={close} text="" defaultHref="/perfil" />
|
|
||||||
</IonButtons>
|
|
||||||
</IonToolbar>
|
|
||||||
</IonHeader>
|
|
||||||
|
|
||||||
<IonContent fullscreen>
|
<IonContent fullscreen>
|
||||||
<IonSlides ref={mySlides} options={slideOpts}>
|
|
||||||
<IonSlide>
|
|
||||||
<div className="m-3">
|
<div className="m-3">
|
||||||
<h1 className="mb-3 text-xl">
|
<h1>Digite o endereço de onde você iniciará a rota do itinerário</h1>
|
||||||
Digite o endereço de onde você iniciará a rota do itinerário
|
<div className="inputs-from-to">
|
||||||
</h1>
|
|
||||||
<div className="flex items-center mb-3">
|
|
||||||
<IonIcon icon={locateOutline}></IonIcon>
|
<IonIcon icon={locateOutline}></IonIcon>
|
||||||
<AutoCompleteInput
|
<GooglePlacesAutocomplete
|
||||||
placeholder="R. José Paulino, 1234"
|
apiKey={process.env.REACT_APP_KEY_API}
|
||||||
className="ml-2"
|
apiOptions={{ language: "pt-br", region: "br" }}
|
||||||
onAddressSelected={(address: Address) =>
|
selectProps={{
|
||||||
setInitialAddress(address)
|
className: "input-autocomplete",
|
||||||
}
|
placeholder: "R. José Paulino, 1234",
|
||||||
onChange={(e: any) => {
|
|
||||||
nextButton1.current!.disabled = true;
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex justify-end mb-3">
|
<div className="inputs-from-to">
|
||||||
<IonButton
|
|
||||||
ref={nextButton1}
|
|
||||||
disabled
|
|
||||||
onClick={() => onBtnClicked("next")}
|
|
||||||
color="primary"
|
|
||||||
>
|
|
||||||
<IonIcon icon={arrowForward} />
|
|
||||||
</IonButton>
|
|
||||||
</div>
|
|
||||||
<div className="flex items-center">
|
|
||||||
<IonIcon
|
|
||||||
icon={informationCircle}
|
|
||||||
size="large"
|
|
||||||
className="mr-4"
|
|
||||||
/>
|
|
||||||
<small className="text-gray-500">
|
|
||||||
Essa informação é importante para que possamos informar aos
|
|
||||||
passageiros um horário aproximado que você passará para
|
|
||||||
pegá-lo.
|
|
||||||
</small>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</IonSlide>
|
|
||||||
<IonSlide>
|
|
||||||
<div className="m-3">
|
|
||||||
<h1 className="mb-3 text-xl">
|
|
||||||
Adicione os bairros que você atenderá
|
|
||||||
</h1>
|
|
||||||
<div className="flex items-center mb-3">
|
|
||||||
<IonIcon icon={locationOutline}></IonIcon>
|
<IonIcon icon={locationOutline}></IonIcon>
|
||||||
<AutoCompleteInput
|
<GooglePlacesAutocomplete
|
||||||
placeholder="R. José Paulino, 1234"
|
apiKey={process.env.REACT_APP_KEY_API}
|
||||||
className="ml-2"
|
apiOptions={{ language: "pt-br", region: "br" }}
|
||||||
onAddressSelected={(address: Address) =>
|
selectProps={{
|
||||||
addNeighborhood(address)
|
className: "input-autocomplete",
|
||||||
}
|
placeholder: "PUC Campinas",
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="mb-3">
|
<div className="button-search">
|
||||||
<IonList class="w-screen">
|
<IonButton color="primary">Cadastrar</IonButton>
|
||||||
{neighborhoods.map((neighborhood, index) => (
|
|
||||||
<IonItem key={index}>
|
|
||||||
<IonButton
|
|
||||||
slot="end"
|
|
||||||
color={"light"}
|
|
||||||
onClick={() => removeNeighborhood(index)}
|
|
||||||
>
|
|
||||||
<IonIcon icon={trash} />
|
|
||||||
</IonButton>
|
|
||||||
<IonLabel>{neighborhood.formatted_address}</IonLabel>
|
|
||||||
</IonItem>
|
|
||||||
))}
|
|
||||||
</IonList>
|
|
||||||
</div>
|
|
||||||
<div className="flex justify-between mb-3">
|
|
||||||
<IonButton onClick={() => onBtnClicked("prev")} color="primary">
|
|
||||||
<IonIcon icon={arrowBack} />
|
|
||||||
</IonButton>
|
|
||||||
<IonButton
|
|
||||||
ref={nextButton2}
|
|
||||||
disabled
|
|
||||||
onClick={() => onBtnClicked("next")}
|
|
||||||
color="primary"
|
|
||||||
>
|
|
||||||
<IonIcon icon={arrowForward} />
|
|
||||||
</IonButton>
|
|
||||||
</div>
|
|
||||||
<div className="flex items-center">
|
|
||||||
<IonIcon
|
|
||||||
icon={informationCircle}
|
|
||||||
size="large"
|
|
||||||
className="mr-4"
|
|
||||||
/>
|
|
||||||
<small className="text-gray-500">
|
|
||||||
Não se preocupe, você poderá adicionar ou remover bairros
|
|
||||||
posteriormente caso precise editando o itinerário.
|
|
||||||
</small>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</IonSlide>
|
|
||||||
<IonSlide>
|
|
||||||
<div className="m-3">
|
|
||||||
<h1 className="mb-3 text-xl">
|
|
||||||
Digite o endereço de destino final do itinerário
|
|
||||||
</h1>
|
|
||||||
<div className="flex items-center mb-3">
|
|
||||||
<IonIcon icon={locationOutline}></IonIcon>
|
|
||||||
<AutoCompleteInput
|
|
||||||
placeholder="R. José Paulino, 1234"
|
|
||||||
className="ml-2"
|
|
||||||
onAddressSelected={(address: Address) =>
|
|
||||||
setFinalAddress(address)
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="flex justify-between mb-3">
|
|
||||||
<IonButton onClick={() => onBtnClicked("prev")} color="primary">
|
|
||||||
<IonIcon icon={arrowBack} />
|
|
||||||
</IonButton>
|
|
||||||
<IonButton
|
|
||||||
ref={nextButton3}
|
|
||||||
disabled
|
|
||||||
onClick={() => onBtnClicked("next")}
|
|
||||||
color="primary"
|
|
||||||
>
|
|
||||||
<IonIcon icon={arrowForward} />
|
|
||||||
</IonButton>
|
|
||||||
</div>
|
|
||||||
<div className="flex items-center">
|
|
||||||
<IonIcon
|
|
||||||
icon={informationCircle}
|
|
||||||
size="large"
|
|
||||||
className="mr-4"
|
|
||||||
/>
|
|
||||||
<small className="text-gray-500">
|
|
||||||
Não se preocupe, você poderá adicionar paradas.
|
|
||||||
</small>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</IonSlide>
|
|
||||||
<IonSlide>
|
|
||||||
<div className="m-3">
|
|
||||||
<h1 className="mb-3 text-xl">
|
|
||||||
Adicione paradas durante o trajeto do itinerário para encontrar
|
|
||||||
mais passageiros
|
|
||||||
</h1>
|
|
||||||
<div className="flex items-center mb-3">
|
|
||||||
<IonIcon icon={locationOutline}></IonIcon>
|
|
||||||
<AutoCompleteInput
|
|
||||||
placeholder="R. José Paulino, 1234"
|
|
||||||
className="ml-2"
|
|
||||||
onAddressSelected={(address: Address) =>
|
|
||||||
setDestinations((arr) => [...arr, address])
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="mb-3">
|
|
||||||
<IonList class="w-screen">
|
|
||||||
{destinations.map((destination, index) => (
|
|
||||||
<IonItem key={index}>
|
|
||||||
<IonButton
|
|
||||||
slot="end"
|
|
||||||
color={"light"}
|
|
||||||
onClick={() => removeDestionation(index)}
|
|
||||||
>
|
|
||||||
<IonIcon icon={trash} />
|
|
||||||
</IonButton>
|
|
||||||
<IonLabel>{destination.formatted_address}</IonLabel>
|
|
||||||
</IonItem>
|
|
||||||
))}
|
|
||||||
</IonList>
|
|
||||||
</div>
|
|
||||||
<div className="flex justify-between mb-3">
|
|
||||||
<IonButton onClick={() => onBtnClicked("prev")} color="primary">
|
|
||||||
<IonIcon icon={arrowBack} />
|
|
||||||
</IonButton>
|
|
||||||
<IonButton onClick={() => onBtnClicked("next")} color="primary">
|
|
||||||
<IonIcon icon={arrowForward} />
|
|
||||||
</IonButton>
|
|
||||||
</div>
|
|
||||||
<div className="flex items-center">
|
|
||||||
<IonIcon
|
|
||||||
icon={informationCircle}
|
|
||||||
size="large"
|
|
||||||
className="mr-4"
|
|
||||||
/>
|
|
||||||
<small className="text-gray-500">
|
|
||||||
Não se preocupe, você poderá adicionar ou remover paradas
|
|
||||||
posteriormente caso precise editando o itinerário.
|
|
||||||
</small>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</IonSlide>
|
|
||||||
<IonSlide>
|
|
||||||
<div className="m-3">
|
|
||||||
<h1 className="mb-3 text-xl">
|
|
||||||
Escolha o(s) dia(s) da semana ou um dia específico que o
|
|
||||||
itinerário será realizado
|
|
||||||
</h1>
|
|
||||||
<div hidden={specificDate} className="mb-3">
|
|
||||||
<div className="grid grid-cols-7 gap-4">
|
|
||||||
<div>
|
|
||||||
<IonLabel>D</IonLabel>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<IonLabel>S</IonLabel>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<IonLabel>T</IonLabel>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<IonLabel>Q</IonLabel>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<IonLabel>Q</IonLabel>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<IonLabel>S</IonLabel>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<IonLabel>S</IonLabel>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="grid grid-cols-7 gap-4">
|
|
||||||
<div>
|
|
||||||
<IonCheckbox
|
|
||||||
onIonChange={(e) =>
|
|
||||||
setDayOfWeekSeleted("Domingo", e.target.checked)
|
|
||||||
}
|
|
||||||
></IonCheckbox>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<IonCheckbox
|
|
||||||
onIonChange={(e) =>
|
|
||||||
setDayOfWeekSeleted("Segunda", e.target.checked)
|
|
||||||
}
|
|
||||||
></IonCheckbox>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<IonCheckbox
|
|
||||||
onIonChange={(e) =>
|
|
||||||
setDayOfWeekSeleted("Terça", e.target.checked)
|
|
||||||
}
|
|
||||||
></IonCheckbox>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<IonCheckbox
|
|
||||||
onIonChange={(e) =>
|
|
||||||
setDayOfWeekSeleted("Quarta", e.target.checked)
|
|
||||||
}
|
|
||||||
></IonCheckbox>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<IonCheckbox
|
|
||||||
onIonChange={(e) =>
|
|
||||||
setDayOfWeekSeleted("Quinta", e.target.checked)
|
|
||||||
}
|
|
||||||
></IonCheckbox>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<IonCheckbox
|
|
||||||
onIonChange={(e) =>
|
|
||||||
setDayOfWeekSeleted("Sexta", e.target.checked)
|
|
||||||
}
|
|
||||||
></IonCheckbox>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<IonCheckbox
|
|
||||||
onIonChange={(e) =>
|
|
||||||
setDayOfWeekSeleted("Sábado", e.target.checked)
|
|
||||||
}
|
|
||||||
></IonCheckbox>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="mb-3">
|
|
||||||
<IonItem className="mb-3">
|
|
||||||
<IonLabel>Dia Específico ?</IonLabel>
|
|
||||||
<IonCheckbox
|
|
||||||
onIonChange={(event) =>
|
|
||||||
event.detail.checked
|
|
||||||
? setSpecificDate(true)
|
|
||||||
: setSpecificDate(false)
|
|
||||||
}
|
|
||||||
></IonCheckbox>
|
|
||||||
</IonItem>
|
|
||||||
<IonDatetime
|
|
||||||
min={minDate.toISOString()}
|
|
||||||
presentation="date"
|
|
||||||
hidden={!specificDate}
|
|
||||||
value={specificDay}
|
|
||||||
onIonChange={(e) =>
|
|
||||||
setSpecificDay(
|
|
||||||
typeof e.detail.value === "string" ? e.detail.value : ""
|
|
||||||
)
|
|
||||||
}
|
|
||||||
></IonDatetime>
|
|
||||||
</div>
|
|
||||||
<div className="flex justify-between mb-3">
|
|
||||||
<IonButton onClick={() => onBtnClicked("prev")} color="primary">
|
|
||||||
<IonIcon icon={arrowBack} />
|
|
||||||
</IonButton>
|
|
||||||
<IonButton onClick={() => onBtnClicked("next")} color="primary">
|
|
||||||
<IonIcon icon={arrowForward} />
|
|
||||||
</IonButton>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</IonSlide>
|
|
||||||
<IonSlide>
|
|
||||||
<div className="m-3">
|
|
||||||
<h1 className="mb-3 text-xl">
|
|
||||||
Qual o horário estimado de ínicio do itinerário ?
|
|
||||||
</h1>
|
|
||||||
<div className="mb-3">
|
|
||||||
<IonDatetime
|
|
||||||
presentation="time"
|
|
||||||
value={departureTime}
|
|
||||||
onIonChange={(event) =>
|
|
||||||
setDepartureTime(
|
|
||||||
typeof event.detail.value === "string"
|
|
||||||
? event.detail.value
|
|
||||||
: "00:00"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
></IonDatetime>
|
|
||||||
</div>
|
|
||||||
<div className="flex justify-between mb-3">
|
|
||||||
<IonButton onClick={() => onBtnClicked("prev")} color="primary">
|
|
||||||
<IonIcon icon={arrowBack} />
|
|
||||||
</IonButton>
|
|
||||||
<IonButton onClick={() => onBtnClicked("next")} color="primary">
|
|
||||||
<IonIcon icon={arrowForward} />
|
|
||||||
</IonButton>
|
|
||||||
</div>
|
|
||||||
<div className="flex items-center">
|
|
||||||
<IonIcon
|
|
||||||
icon={informationCircle}
|
|
||||||
size="large"
|
|
||||||
className="mr-4"
|
|
||||||
/>
|
|
||||||
<small className="text-gray-500">
|
|
||||||
Não se preocupe, é apenas um horário estimado.
|
|
||||||
</small>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</IonSlide>
|
|
||||||
<IonSlide>
|
|
||||||
<div className="m-3">
|
|
||||||
<h1 className="mb-3 text-xl">
|
|
||||||
Qual o horário estimado de chegado no último destino do
|
|
||||||
itinerário ?
|
|
||||||
</h1>
|
|
||||||
<div className="mb-3">
|
|
||||||
<IonDatetime
|
|
||||||
presentation="time"
|
|
||||||
value={arrivalTime}
|
|
||||||
onIonChange={(event) =>
|
|
||||||
setArrivalTime(
|
|
||||||
typeof event.detail.value === "string"
|
|
||||||
? event.detail.value
|
|
||||||
: "00:00"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
></IonDatetime>
|
|
||||||
</div>
|
|
||||||
<div className="flex justify-between mb-3">
|
|
||||||
<IonButton onClick={() => onBtnClicked("prev")} color="primary">
|
|
||||||
<IonIcon icon={arrowBack} />
|
|
||||||
</IonButton>
|
|
||||||
<IonButton onClick={() => onBtnClicked("next")} color="primary">
|
|
||||||
<IonIcon icon={arrowForward} />
|
|
||||||
</IonButton>
|
|
||||||
</div>
|
|
||||||
<div className="flex items-center">
|
|
||||||
<IonIcon
|
|
||||||
icon={informationCircle}
|
|
||||||
size="large"
|
|
||||||
className="mr-4"
|
|
||||||
/>
|
|
||||||
<small className="text-gray-500">
|
|
||||||
Não se preocupe, é apenas um horário estimado.
|
|
||||||
</small>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</IonSlide>
|
|
||||||
<IonSlide>
|
|
||||||
<div className="m-3">
|
|
||||||
<h1 className="mb-3 text-xl">
|
|
||||||
Preencha as informações de pagamento
|
|
||||||
</h1>
|
|
||||||
<IonLabel>Valor cobrado mensalmente</IonLabel>
|
|
||||||
<div className="flex justify-between items-center mb-3">
|
|
||||||
<IonIcon
|
|
||||||
size="large"
|
|
||||||
onClick={() => setMonthlyPrice(monthlyPrice - 1)}
|
|
||||||
icon={removeCircleOutline}
|
|
||||||
/>
|
|
||||||
<h1 className="text-xl">R$ {monthlyPrice}</h1>
|
|
||||||
<IonIcon
|
|
||||||
className="text-4xl"
|
|
||||||
size="large"
|
|
||||||
onClick={() => setMonthlyPrice(monthlyPrice + 1)}
|
|
||||||
icon={addCircleOutline}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="mb-3">
|
|
||||||
<IonItem className="mb-3">
|
|
||||||
<IonLabel>Aceitar pedidos para vagas avulsa ?</IonLabel>
|
|
||||||
<IonCheckbox
|
|
||||||
onIonChange={(event) =>
|
|
||||||
setSingleVacancy(event.detail.checked)
|
|
||||||
}
|
|
||||||
></IonCheckbox>
|
|
||||||
</IonItem>
|
|
||||||
<div hidden={!singleVacancy}>
|
|
||||||
<IonLabel>Valor cobrado por dia (vaga avulsa)</IonLabel>
|
|
||||||
<div className="flex justify-between items-center">
|
|
||||||
<IonIcon
|
|
||||||
size="large"
|
|
||||||
onClick={() => setDailyPrice(dailyPrice - 1)}
|
|
||||||
icon={removeCircleOutline}
|
|
||||||
/>
|
|
||||||
<h1 className="text-xl">R$ {dailyPrice}</h1>
|
|
||||||
<IonIcon
|
|
||||||
className="text-4xl"
|
|
||||||
size="large"
|
|
||||||
onClick={() => setDailyPrice(dailyPrice + 1)}
|
|
||||||
icon={addCircleOutline}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="flex justify-between mb-3">
|
|
||||||
<IonButton onClick={() => onBtnClicked("prev")} color="primary">
|
|
||||||
<IonIcon icon={arrowBack} />
|
|
||||||
</IonButton>
|
|
||||||
<IonButton onClick={() => onBtnClicked("next")} color="primary">
|
|
||||||
<IonIcon icon={arrowForward} />
|
|
||||||
</IonButton>
|
|
||||||
</div>
|
|
||||||
<div className="flex items-center">
|
|
||||||
<IonIcon
|
|
||||||
icon={informationCircle}
|
|
||||||
size="large"
|
|
||||||
className="mr-4"
|
|
||||||
/>
|
|
||||||
<small className="text-gray-500">
|
|
||||||
Lembre-se esse valor será cobrado independente do destino do
|
|
||||||
passageiro.
|
|
||||||
<br />
|
|
||||||
<b>
|
|
||||||
Em breve será possível cobrar valores diferentes para cada
|
|
||||||
destino.
|
|
||||||
</b>
|
|
||||||
</small>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</IonSlide>
|
|
||||||
<IonSlide>
|
|
||||||
<div className="m-3">
|
|
||||||
<h1 className="mb-3 text-xl">
|
|
||||||
Escolha o veículo que será utilizado no itinerário
|
|
||||||
</h1>
|
|
||||||
<div className="mb-3">
|
|
||||||
<IonSelect
|
|
||||||
interface="action-sheet"
|
|
||||||
placeholder="Selecione o veículo"
|
|
||||||
onIonChange={(event) => setVan(event.detail.value)}
|
|
||||||
className="w-screen"
|
|
||||||
>
|
|
||||||
{vans ? (
|
|
||||||
vans.map((van, index) => {
|
|
||||||
return (
|
|
||||||
<IonSelectOption key={index} value={van.plate}>
|
|
||||||
{van.brand +
|
|
||||||
" - " +
|
|
||||||
van.model +
|
|
||||||
" | Placa: " +
|
|
||||||
van.plate}
|
|
||||||
</IonSelectOption>
|
|
||||||
);
|
|
||||||
})
|
|
||||||
) : (
|
|
||||||
<></>
|
|
||||||
)}
|
|
||||||
</IonSelect>
|
|
||||||
</div>
|
|
||||||
<div className="flex justify-between mb-3">
|
|
||||||
<IonButton onClick={() => onBtnClicked("prev")} color="primary">
|
|
||||||
<IonIcon icon={arrowBack} />
|
|
||||||
</IonButton>
|
|
||||||
<IonButton
|
|
||||||
ref={nextButton6}
|
|
||||||
disabled
|
|
||||||
onClick={() => onBtnClicked("next")}
|
|
||||||
color="primary"
|
|
||||||
>
|
|
||||||
<IonIcon icon={arrowForward} />
|
|
||||||
</IonButton>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</IonSlide>
|
|
||||||
<IonSlide>
|
|
||||||
<div className="m-3">
|
|
||||||
<h1 className="mb-3 text-xl">
|
|
||||||
Escolha um apelido para o itinerário
|
|
||||||
</h1>
|
|
||||||
<div className="mb-3">
|
|
||||||
<IonInput
|
|
||||||
value={nickname}
|
|
||||||
onIonChange={(event) => setNickname(event.detail.value!)}
|
|
||||||
placeholder="Manhã - Centro"
|
|
||||||
></IonInput>
|
|
||||||
</div>
|
|
||||||
<div className="flex justify-between mb-3">
|
|
||||||
<IonButton onClick={() => onBtnClicked("prev")} color="primary">
|
|
||||||
<IonIcon icon={arrowBack} />
|
|
||||||
</IonButton>
|
|
||||||
<IonButton onClick={() => cadastrar()} color="primary">
|
|
||||||
<IonIcon icon={checkmark} />
|
|
||||||
Cadastrar
|
|
||||||
</IonButton>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</IonSlide>
|
|
||||||
</IonSlides>
|
|
||||||
<IonToast
|
|
||||||
position="top"
|
|
||||||
color={toastColor}
|
|
||||||
isOpen={showToast}
|
|
||||||
onDidDismiss={() => setShowToast(false)}
|
|
||||||
message={toastMessage}
|
|
||||||
duration={2500}
|
|
||||||
/>
|
|
||||||
</IonContent>
|
</IonContent>
|
||||||
</IonPage>
|
</IonPage>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,26 +1,16 @@
|
|||||||
import { Color } from "@ionic/core";
|
import { IonToast, IonProgressBar, IonItem, IonLabel, IonInput, IonBackButton, IonButton, IonButtons, IonCardTitle, IonCol, IonContent, IonGrid, IonHeader, IonPage, IonRow, IonToolbar } from '@ionic/react';
|
||||||
import {
|
import { arrowBack, logoFacebook, mail } from 'ionicons/icons';
|
||||||
IonButton,
|
import { Action } from '../../components/Action';
|
||||||
IonCardTitle,
|
import { useContext, useEffect, useState } from 'react';
|
||||||
IonCol,
|
import { useHistory, useParams } from 'react-router';
|
||||||
IonContent,
|
import './Cadastro.css';
|
||||||
IonGrid,
|
import ModalExample from '../../components/Email';
|
||||||
IonInput,
|
import * as UsersService from '../../services/api/users'
|
||||||
IonItem,
|
import LocalStorage from '../../LocalStorage';
|
||||||
IonLabel,
|
import { UserContext } from '../../App';
|
||||||
IonPage,
|
import { Color } from '@ionic/core';
|
||||||
IonRow,
|
import { closeToast } from '../../services/utils';
|
||||||
IonToast,
|
import { PageHeader } from '../../components/PageHeader';
|
||||||
} from "@ionic/react";
|
|
||||||
import { useContext, useState } from "react";
|
|
||||||
import { useHistory, useParams } from "react-router";
|
|
||||||
import { UserContext } from "../../App";
|
|
||||||
import { Action } from "../../components/Action";
|
|
||||||
import { PageHeader } from "../../components/PageHeader";
|
|
||||||
import LocalStorage from "../../LocalStorage";
|
|
||||||
import * as UsersService from "../../services/api/users";
|
|
||||||
import { closeToast } from "../../services/utils";
|
|
||||||
import "./Cadastro.css";
|
|
||||||
|
|
||||||
const Cadastro: React.FC = () => {
|
const Cadastro: React.FC = () => {
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
@@ -28,35 +18,34 @@ const Cadastro: React.FC = () => {
|
|||||||
const user = useContext(UserContext);
|
const user = useContext(UserContext);
|
||||||
|
|
||||||
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 [email, setEmail] = useState<string>("");
|
const [email, setEmail] = useState<string>('');
|
||||||
const [password, setPassword] = useState<string>("");
|
const [password, setPassword] = useState<string>('');
|
||||||
const [confirmPassword, setConfirmPassword] = useState<string>("");
|
const [confirmPassword, setConfirmPassword] = useState<string>('');
|
||||||
const [firstName, setFirstName] = useState<string>("");
|
const [firstName, setFirstName] = useState<string>('');
|
||||||
const [lastName, setLastName] = useState<string>("");
|
const [lastName, setLastName] = useState<string>('');
|
||||||
const [birthDate, setBirthDate] = useState<string>("");
|
const [birthDate, setBirthDate] = useState<string>('');
|
||||||
const [lResult, setlResult] = useState({
|
const [lResult, setlResult] = useState({
|
||||||
error: "",
|
error: '',
|
||||||
success: true,
|
success: true
|
||||||
});
|
});
|
||||||
|
|
||||||
const emailValidate = () => {
|
const emailValidate = () => {
|
||||||
var usuario = email.substring(0, email.indexOf("@"));
|
var usuario = email.substring(0, email.indexOf("@"));
|
||||||
var dominio = email.substring(email.indexOf("@") + 1, email.length);
|
var dominio = email.substring(email.indexOf("@") + 1, email.length);
|
||||||
|
|
||||||
if (
|
if ((usuario.length >= 1) &&
|
||||||
usuario.length >= 1 &&
|
(dominio.length >= 3) &&
|
||||||
dominio.length >= 3 &&
|
(usuario.search("@") == -1) &&
|
||||||
usuario.search("@") === -1 &&
|
(dominio.search("@") == -1) &&
|
||||||
dominio.search("@") === -1 &&
|
(usuario.search(" ") == -1) &&
|
||||||
usuario.search(" ") === -1 &&
|
(dominio.search(" ") == -1) &&
|
||||||
dominio.search(" ") === -1 &&
|
(dominio.search(".") != -1) &&
|
||||||
dominio.search(".") !== -1 &&
|
(dominio.indexOf(".") >= 1) &&
|
||||||
dominio.indexOf(".") >= 1 &&
|
(dominio.lastIndexOf(".") < dominio.length - 1))
|
||||||
dominio.lastIndexOf(".") < dominio.length - 1
|
{
|
||||||
) {
|
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
@@ -64,20 +53,19 @@ const Cadastro: React.FC = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const clearResult = () => {
|
const clearResult = () => {
|
||||||
lResult.error = "";
|
lResult.error = '';
|
||||||
lResult.success = true;
|
lResult.success = true;
|
||||||
};
|
}
|
||||||
|
|
||||||
const fieldValidate = async () => {
|
const fieldValidate = async () => {
|
||||||
clearResult();
|
clearResult();
|
||||||
|
|
||||||
if (!emailValidate()) {
|
if(!emailValidate()) {
|
||||||
lResult.error = "E-mail inválido!";
|
lResult.error = 'E-mail inválido!';
|
||||||
lResult.success = false;
|
lResult.success = false;
|
||||||
return lResult;
|
return lResult;
|
||||||
} else if (password.length < 7 || password.length > 12) {
|
} else if(password.length < 7 || password.length > 12) { //TODO: validar de acordo com a documentação
|
||||||
//TODO: validar de acordo com a documentação
|
lResult.error = 'A senha deve ter de 7 a 12 caracteres!';
|
||||||
lResult.error = "A senha deve ter de 7 a 12 caracteres!";
|
|
||||||
lResult.success = false;
|
lResult.success = false;
|
||||||
return lResult;
|
return lResult;
|
||||||
}
|
}
|
||||||
@@ -86,24 +74,18 @@ const Cadastro: React.FC = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleSubmit = async () => {
|
const handleSubmit = async () => {
|
||||||
if (
|
if(name === '' || email === '' || birthDate === '' || password === '' || confirmPassword === '') {
|
||||||
name === "" ||
|
setToastColor("warning")
|
||||||
email === "" ||
|
setMessageToast('Nenhum campo pode estar vazio!');
|
||||||
birthDate === "" ||
|
|
||||||
password === "" ||
|
|
||||||
confirmPassword === ""
|
|
||||||
) {
|
|
||||||
setToastColor("warning");
|
|
||||||
setMessageToast("Nenhum campo pode estar vazio!");
|
|
||||||
setShowToast(true);
|
setShowToast(true);
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (password !== confirmPassword) {
|
if(password !== confirmPassword) {
|
||||||
setToastColor("warning");
|
setToastColor("warning")
|
||||||
setMessageToast("As senhas devem ser iguais!");
|
setMessageToast('As senhas devem ser iguais!');
|
||||||
setShowToast(true);
|
setShowToast(true);
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const signUpForm = {
|
const signUpForm = {
|
||||||
@@ -111,47 +93,47 @@ const Cadastro: React.FC = () => {
|
|||||||
lastname: lastName,
|
lastname: lastName,
|
||||||
email: email,
|
email: email,
|
||||||
birth_date: birthDate,
|
birth_date: birthDate,
|
||||||
password: password,
|
password: password
|
||||||
};
|
}
|
||||||
|
|
||||||
let result = fieldValidate();
|
let result = fieldValidate();
|
||||||
if (!(await result).success) {
|
if(!(await result).success) {
|
||||||
setToastColor("warning");
|
setToastColor("warning")
|
||||||
setMessageToast(lResult.error);
|
setMessageToast(lResult.error);
|
||||||
setShowToast(true);
|
setShowToast(true);
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let retorno = await UsersService.create(signUpForm);
|
let retorno = await UsersService.create(signUpForm);
|
||||||
|
|
||||||
if (!retorno.token) {
|
if(!retorno.token) {
|
||||||
setToastColor("danger");
|
setToastColor('danger')
|
||||||
setMessageToast(retorno.message);
|
setMessageToast(retorno.message);
|
||||||
setShowToast(true);
|
setShowToast(true);
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
LocalStorage.setToken(retorno.token.token);
|
LocalStorage.setToken(retorno.token.token);
|
||||||
|
|
||||||
user.setIsLoggedIn(true);
|
user.setIsLoggedIn(true);
|
||||||
|
|
||||||
history.push({
|
history.push({ pathname: '/home', state: {
|
||||||
pathname: "/home",
|
|
||||||
state: {
|
|
||||||
redirectData: {
|
redirectData: {
|
||||||
showToastMessage: true,
|
showToastMessage: true,
|
||||||
toastColor: "success",
|
toastColor: "success",
|
||||||
toastMessage: "Usuário cadastrado com sucesso!",
|
toastMessage: "Usuário cadastrado com sucesso!",
|
||||||
},
|
}
|
||||||
},
|
}})
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const { name } = useParams<{ name: string }>();
|
const { name } = useParams<{ name: string; }>();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<IonPage>
|
<IonPage>
|
||||||
<PageHeader pageName="Cadastro" backButtonPageUrl="/login"></PageHeader>
|
<PageHeader
|
||||||
|
pageName="Cadastro"
|
||||||
|
backButtonPageUrl="/login"
|
||||||
|
></PageHeader>
|
||||||
|
|
||||||
<IonContent fullscreen>
|
<IonContent fullscreen>
|
||||||
<IonGrid className="ion-padding">
|
<IonGrid className="ion-padding">
|
||||||
@@ -163,73 +145,69 @@ const Cadastro: React.FC = () => {
|
|||||||
</IonRow>
|
</IonRow>
|
||||||
<IonRow>
|
<IonRow>
|
||||||
<IonCol size="12">
|
<IonCol size="12">
|
||||||
<div id="nome-sobrenome">
|
<div id='nome-sobrenome'>
|
||||||
<IonItem>
|
<IonItem>
|
||||||
<IonLabel position="floating">Nome</IonLabel>
|
<IonLabel position='floating'>Nome</IonLabel>
|
||||||
<IonInput
|
<IonInput
|
||||||
type="text"
|
type='text'
|
||||||
clearInput
|
clearInput
|
||||||
onIonInput={(e: any) => setFirstName(e.target.value)}
|
onIonInput={(e: any) => setFirstName(e.target.value)}
|
||||||
// error={isError}
|
// error={isError}
|
||||||
// onIonChange={(e: any) => setFirstName(e.detail.value)}
|
// onIonChange={(e: any) => setFirstName(e.detail.value)}
|
||||||
></IonInput>
|
>
|
||||||
|
</IonInput>
|
||||||
</IonItem>
|
</IonItem>
|
||||||
<IonItem>
|
<IonItem>
|
||||||
<IonLabel position="floating">Sobrenome</IonLabel>
|
<IonLabel position='floating'>Sobrenome</IonLabel>
|
||||||
<IonInput
|
<IonInput
|
||||||
clearInput
|
clearInput
|
||||||
onIonChange={(e: any) => setLastName(e.target.value)}
|
onIonChange={(e: any) => setLastName(e.target.value)}
|
||||||
></IonInput>
|
>
|
||||||
|
</IonInput>
|
||||||
</IonItem>
|
</IonItem>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<IonItem>
|
<IonItem>
|
||||||
<IonLabel position="floating">E-mail</IonLabel>
|
<IonLabel position='floating'>E-mail</IonLabel>
|
||||||
<IonInput
|
<IonInput
|
||||||
clearInput
|
clearInput
|
||||||
type="email"
|
type='email'
|
||||||
onIonChange={(e: any) => setEmail(e.target.value)}
|
onIonChange={(e: any) => setEmail(e.target.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'
|
||||||
onIonChange={(e: any) => setBirthDate(e.target.value)}
|
onIonChange={(e: any) => setBirthDate(e.target.value)}
|
||||||
></IonInput>
|
>
|
||||||
|
</IonInput>
|
||||||
</IonItem>
|
</IonItem>
|
||||||
|
|
||||||
<IonItem>
|
<IonItem>
|
||||||
<IonLabel position="floating">Senha</IonLabel>
|
<IonLabel position='floating'>Senha</IonLabel>
|
||||||
<IonInput
|
<IonInput
|
||||||
clearInput
|
clearInput
|
||||||
type="password"
|
type='password'
|
||||||
onIonChange={(e: any) => setPassword(e.target.value)}
|
onIonChange={(e: any) => setPassword(e.target.value)}
|
||||||
></IonInput>
|
></IonInput>
|
||||||
</IonItem>
|
</IonItem>
|
||||||
<IonItem>
|
<IonItem>
|
||||||
<IonLabel position="floating">Confirme a senha</IonLabel>
|
<IonLabel position='floating'>Confirme a senha</IonLabel>
|
||||||
<IonInput
|
<IonInput
|
||||||
clearInput
|
clearInput
|
||||||
type="password"
|
type='password'
|
||||||
onIonChange={(e: any) => setConfirmPassword(e.target.value)}
|
onIonChange={(e: any) => setConfirmPassword(e.target.value)}
|
||||||
></IonInput>
|
></IonInput>
|
||||||
</IonItem>
|
</IonItem>
|
||||||
|
|
||||||
<IonButton
|
<IonButton className="ion-margin-top" expand="block" onClick={ handleSubmit }>Cadastrar-se</IonButton>
|
||||||
className="ion-margin-top"
|
|
||||||
expand="block"
|
|
||||||
onClick={handleSubmit}
|
|
||||||
>
|
|
||||||
Cadastrar-se
|
|
||||||
</IonButton>
|
|
||||||
</IonCol>
|
</IonCol>
|
||||||
</IonRow>
|
</IonRow>
|
||||||
<small className="ion-margin-top">
|
<small className='ion-margin-top'>
|
||||||
Ao se cadastrar, você aceita nossos{" "}
|
Ao se cadastrar, você aceita nossos <a href="">Termos e Condições</a> e nossa <a href=""> Política de Privacidade</a>.
|
||||||
<a href="">Termos e Condições</a> e nossa{" "}
|
|
||||||
<a href=""> Política de Privacidade</a>.
|
|
||||||
</small>
|
</small>
|
||||||
<Action message="Já tem conta?" text="Login" link="/login" />
|
<Action message="Já tem conta?" text="Login" link="/login" />
|
||||||
</IonGrid>
|
</IonGrid>
|
||||||
|
|||||||
@@ -1,22 +1,28 @@
|
|||||||
import {
|
import {
|
||||||
IonCard,
|
IonBackButton,
|
||||||
IonCardContent,
|
IonButtons,
|
||||||
IonContent,
|
IonCard,
|
||||||
IonIcon,
|
IonCardContent,
|
||||||
IonItem,
|
IonContent,
|
||||||
IonLabel,
|
IonHeader,
|
||||||
IonPage,
|
IonIcon,
|
||||||
IonToast,
|
IonItem,
|
||||||
|
IonLabel,
|
||||||
|
IonPage,
|
||||||
|
IonTitle,
|
||||||
|
IonToast,
|
||||||
|
IonToolbar
|
||||||
} from "@ionic/react";
|
} from "@ionic/react";
|
||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useReducer, useState } from "react";
|
||||||
|
|
||||||
import { callOutline, documentTextOutline } from "ionicons/icons";
|
import '../Perfil.css'
|
||||||
import { useHistory, useLocation } from "react-router";
|
import { useHistory, useLocation } from "react-router";
|
||||||
import "../Perfil.css";
|
import { callOutline, documentTextOutline } from "ionicons/icons";
|
||||||
|
|
||||||
|
import '../Cadastro/Cadastro.css'
|
||||||
import { Color } from "@ionic/core";
|
import { Color } from "@ionic/core";
|
||||||
import { PageHeader } from "../../components/PageHeader";
|
|
||||||
import { closeToast } from "../../services/utils";
|
import { closeToast } from "../../services/utils";
|
||||||
|
import { PageHeader } from "../../components/PageHeader";
|
||||||
|
|
||||||
interface cardItem {
|
interface cardItem {
|
||||||
icon: string;
|
icon: string;
|
||||||
@@ -44,62 +50,57 @@ interface LocationState {
|
|||||||
showToastMessage: boolean;
|
showToastMessage: boolean;
|
||||||
toastColor: Color;
|
toastColor: Color;
|
||||||
toastMessage: string;
|
toastMessage: string;
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let items: cardItem[] = [
|
let items: cardItem[] = [
|
||||||
{
|
{
|
||||||
icon: documentTextOutline,
|
icon: documentTextOutline,
|
||||||
label: "Documento",
|
label: 'Documento',
|
||||||
description:
|
description: 'Cadastre seu documento para que seu perfil possa ser verificado',
|
||||||
"Cadastre seu documento para que seu perfil possa ser verificado",
|
url: '/perfil/completar/documento',
|
||||||
url: "/perfil/completar/documento",
|
required: false
|
||||||
required: false,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: callOutline,
|
icon: callOutline,
|
||||||
label: "Informações de contato",
|
label: 'Informações de contato',
|
||||||
description:
|
description: 'Cadastre seu número de telefone celular que para possam contatar você',
|
||||||
"Cadastre seu número de telefone celular que para possam contatar você",
|
url: '/perfil/completar/telefone',
|
||||||
url: "/perfil/completar/telefone",
|
required: false
|
||||||
required: false,
|
}
|
||||||
},
|
]
|
||||||
];
|
|
||||||
|
|
||||||
const CadastroCompletar: React.FC = () => {
|
const CadastroCompletar: React.FC = () => {
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
const location = useLocation<LocationState>();
|
const location = useLocation<LocationState>();
|
||||||
|
|
||||||
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 handleCardClick = (item: cardItem) => {
|
const handleCardClick = (item: cardItem) => {
|
||||||
if (!item.required) return;
|
if (!item.required) return
|
||||||
|
|
||||||
history.push({
|
history.push({ pathname: item.url, state: { userData: location.state.userData } });
|
||||||
pathname: item.url,
|
}
|
||||||
state: { userData: location.state.userData },
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!location.state || !location.state.userData) {
|
if (!location.state || !location.state.userData) {
|
||||||
history.push({ pathname: "/perfil" });
|
history.push({ pathname: '/perfil' })
|
||||||
}
|
}
|
||||||
|
|
||||||
if (location.state && location.state.redirectData) {
|
if (location.state && location.state.redirectData) {
|
||||||
const redirectData = location.state.redirectData;
|
const redirectData = location.state.redirectData
|
||||||
|
|
||||||
if (redirectData.showToastMessage) {
|
if (redirectData.showToastMessage) {
|
||||||
setToastColor(redirectData.toastColor);
|
setToastColor(redirectData.toastColor)
|
||||||
setToastMessage(redirectData.toastMessage);
|
setToastMessage(redirectData.toastMessage)
|
||||||
setShowToast(true);
|
setShowToast(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!location.state.userData.document) items[0].required = true;
|
if (!location.state.userData.document) items[0].required = true
|
||||||
if (!location.state.userData.phone_number) items[1].required = true;
|
if (!location.state.userData.phone_number) items[1].required = true
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -110,15 +111,9 @@ const CadastroCompletar: React.FC = () => {
|
|||||||
></PageHeader>
|
></PageHeader>
|
||||||
|
|
||||||
<IonContent>
|
<IonContent>
|
||||||
{items.map((item, index) => {
|
{ items.map((item, index) => {
|
||||||
return (
|
return (
|
||||||
<IonCard
|
<IonCard button={item.required} key={index} onClick={() => { handleCardClick(item) }}>
|
||||||
button={item.required}
|
|
||||||
key={index}
|
|
||||||
onClick={() => {
|
|
||||||
handleCardClick(item);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<IonItem>
|
<IonItem>
|
||||||
<IonIcon icon={item.icon} slot="start" />
|
<IonIcon icon={item.icon} slot="start" />
|
||||||
<IonLabel>{item.label}</IonLabel>
|
<IonLabel>{item.label}</IonLabel>
|
||||||
@@ -126,7 +121,7 @@ const CadastroCompletar: React.FC = () => {
|
|||||||
|
|
||||||
<IonCardContent>{item.description}</IonCardContent>
|
<IonCardContent>{item.description}</IonCardContent>
|
||||||
</IonCard>
|
</IonCard>
|
||||||
);
|
)
|
||||||
})}
|
})}
|
||||||
|
|
||||||
<IonToast
|
<IonToast
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ const Home: React.FC = () => {
|
|||||||
// 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')
|
||||||
history.push(`/login`)
|
history.push(`/login`)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,259 +0,0 @@
|
|||||||
import {
|
|
||||||
IonContent,
|
|
||||||
IonPage,
|
|
||||||
IonFab,
|
|
||||||
IonFabButton,
|
|
||||||
IonIcon,
|
|
||||||
IonCard,
|
|
||||||
IonButton,
|
|
||||||
IonHeader,
|
|
||||||
IonToolbar,
|
|
||||||
IonLabel,
|
|
||||||
IonModal,
|
|
||||||
IonRadioGroup,
|
|
||||||
IonItem,
|
|
||||||
IonRadio,
|
|
||||||
IonCheckbox,
|
|
||||||
IonFooter,
|
|
||||||
IonToast,
|
|
||||||
IonCardHeader,
|
|
||||||
IonCardSubtitle,
|
|
||||||
IonCardTitle,
|
|
||||||
IonItemDivider,
|
|
||||||
IonCardContent,
|
|
||||||
IonChip,
|
|
||||||
IonGrid,
|
|
||||||
IonRow,
|
|
||||||
IonCol,
|
|
||||||
IonList,
|
|
||||||
IonListHeader,
|
|
||||||
IonTitle,
|
|
||||||
IonBackButton,
|
|
||||||
IonButtons,
|
|
||||||
} from "@ionic/react";
|
|
||||||
import {
|
|
||||||
arrowForwardOutline,
|
|
||||||
cashOutline,
|
|
||||||
closeOutline,
|
|
||||||
personOutline,
|
|
||||||
starOutline,
|
|
||||||
} from "ionicons/icons";
|
|
||||||
import { useEffect, useState } from "react";
|
|
||||||
import { useHistory, useLocation } from "react-router";
|
|
||||||
import { createUserSearch } from "../services/api/users";
|
|
||||||
import "./ListaItinerarios.css";
|
|
||||||
import { closeToast, convertNumberToPrice } from "../services/utils";
|
|
||||||
import { Itinerary } from "../models/itinerary.model";
|
|
||||||
import { PageHeader } from "../components/PageHeader";
|
|
||||||
|
|
||||||
interface InfoBusca {
|
|
||||||
addressFrom: any;
|
|
||||||
addressTo: any;
|
|
||||||
coordinatesFrom: any;
|
|
||||||
coordinatesTo: any;
|
|
||||||
|
|
||||||
itineraries: Itinerary[];
|
|
||||||
}
|
|
||||||
|
|
||||||
const ListaItinerarios: React.FC = () => {
|
|
||||||
const history = useHistory();
|
|
||||||
const location = useLocation();
|
|
||||||
const props = location.state as InfoBusca;
|
|
||||||
const [itinerariesList, setItinerariesList] = useState<Itinerary[]>([]);
|
|
||||||
const [showModalFilters, setShowModalFilters] = useState(true);
|
|
||||||
const [showToast, setShowToast] = useState(false);
|
|
||||||
const [messageToast, setMessageToast] = useState("");
|
|
||||||
const [toastColor, setToastColor] = useState("success");
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (props.itineraries) {
|
|
||||||
setItinerariesList(props.itineraries);
|
|
||||||
}
|
|
||||||
}, [props]);
|
|
||||||
|
|
||||||
function criaAlerta() {
|
|
||||||
createUserSearch(
|
|
||||||
props.coordinatesFrom.lat,
|
|
||||||
props.coordinatesFrom.lng,
|
|
||||||
props.addressTo.label
|
|
||||||
)
|
|
||||||
.then(() => {
|
|
||||||
setMessageToast("Alerta criado com sucesso!");
|
|
||||||
setShowToast(true);
|
|
||||||
})
|
|
||||||
.catch((err: any) => {
|
|
||||||
setMessageToast("Não foi possível criar o alerta!");
|
|
||||||
setToastColor("danger");
|
|
||||||
setShowToast(true);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<IonPage>
|
|
||||||
<PageHeader
|
|
||||||
pageName="Resultados da busca"
|
|
||||||
backButtonPageUrl="/buscar/itinerario"
|
|
||||||
/>
|
|
||||||
<IonContent fullscreen>
|
|
||||||
<IonCard color="light">
|
|
||||||
<IonCardHeader>
|
|
||||||
<IonCardSubtitle>Origem: {props.addressFrom.label}</IonCardSubtitle>
|
|
||||||
</IonCardHeader>
|
|
||||||
</IonCard>
|
|
||||||
<IonCard color="light">
|
|
||||||
<IonCardHeader>
|
|
||||||
<IonCardSubtitle>Destino: {props.addressTo.label}</IonCardSubtitle>
|
|
||||||
</IonCardHeader>
|
|
||||||
</IonCard>
|
|
||||||
|
|
||||||
{itinerariesList && itinerariesList.length !== 0 ? (
|
|
||||||
<>
|
|
||||||
<IonItemDivider color="secondary">Resultados</IonItemDivider>
|
|
||||||
{itinerariesList.map((itinerary, index) => {
|
|
||||||
return (
|
|
||||||
<IonCard
|
|
||||||
button
|
|
||||||
key={index}
|
|
||||||
onClick={() => {
|
|
||||||
history.push(`/itinerary/${itinerary.id_itinerary}`);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<IonCardHeader>
|
|
||||||
<IonCardTitle>{itinerary.itinerary_nickname}</IonCardTitle>
|
|
||||||
<IonCardContent>
|
|
||||||
<p>
|
|
||||||
<IonIcon icon={personOutline} /> Vagas disponíveis:{" "}
|
|
||||||
{itinerary.available_seats}
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<IonIcon icon={starOutline} /> Motorista:{" "}
|
|
||||||
{itinerary.price}
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<IonIcon icon={cashOutline} /> Valor:{" "}
|
|
||||||
{convertNumberToPrice(itinerary.price)}
|
|
||||||
</p>
|
|
||||||
</IonCardContent>
|
|
||||||
</IonCardHeader>
|
|
||||||
</IonCard>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<>
|
|
||||||
<div className="msg-not-found">
|
|
||||||
<IonCard>
|
|
||||||
<IonCardContent>
|
|
||||||
<span>
|
|
||||||
Não foi encontrado nenhum itinerário que atenda essa rota.
|
|
||||||
</span>
|
|
||||||
</IonCardContent>
|
|
||||||
</IonCard>
|
|
||||||
<IonCard>
|
|
||||||
<IonCardContent>
|
|
||||||
<span>
|
|
||||||
Deseja criar um alerta para ser notificado caso haja
|
|
||||||
itinerário para essa origem e destino?
|
|
||||||
</span>
|
|
||||||
<div className="button-criar-alerta">
|
|
||||||
<IonButton onClick={() => criaAlerta()}>
|
|
||||||
Criar Alerta
|
|
||||||
</IonButton>
|
|
||||||
</div>
|
|
||||||
</IonCardContent>
|
|
||||||
</IonCard>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<IonFab
|
|
||||||
onClick={() => setShowModalFilters(true)}
|
|
||||||
vertical="bottom"
|
|
||||||
horizontal="center"
|
|
||||||
slot="fixed"
|
|
||||||
>
|
|
||||||
<IonFabButton>Filtros</IonFabButton>
|
|
||||||
</IonFab>
|
|
||||||
<IonModal isOpen={showModalFilters}>
|
|
||||||
<IonHeader translucent>
|
|
||||||
<IonToolbar>
|
|
||||||
<IonTitle>Filtros</IonTitle>
|
|
||||||
<IonButtons slot="start">
|
|
||||||
<IonIcon
|
|
||||||
size="large"
|
|
||||||
icon={closeOutline}
|
|
||||||
onClick={() => setShowModalFilters(false)}
|
|
||||||
/>
|
|
||||||
</IonButtons>
|
|
||||||
</IonToolbar>
|
|
||||||
</IonHeader>
|
|
||||||
|
|
||||||
<IonContent>
|
|
||||||
<IonList>
|
|
||||||
<IonListHeader>Ordenar por</IonListHeader>
|
|
||||||
<IonRadioGroup>
|
|
||||||
<IonItem>
|
|
||||||
<IonLabel>Sem filtro</IonLabel>
|
|
||||||
<IonRadio value="sem_filtro" />
|
|
||||||
</IonItem>
|
|
||||||
|
|
||||||
<IonItem>
|
|
||||||
<IonLabel>Menor preço</IonLabel>
|
|
||||||
<IonRadio value="menor_preco" />
|
|
||||||
</IonItem>
|
|
||||||
|
|
||||||
<IonItem>
|
|
||||||
<IonLabel>Avaliação</IonLabel>
|
|
||||||
<IonRadio value="avaliacao" />
|
|
||||||
</IonItem>
|
|
||||||
|
|
||||||
<IonItem>
|
|
||||||
<IonLabel>Lugares disponíveis</IonLabel>
|
|
||||||
<IonRadio value="lugares_disponiveis" />
|
|
||||||
</IonItem>
|
|
||||||
</IonRadioGroup>
|
|
||||||
</IonList>
|
|
||||||
|
|
||||||
<IonItemDivider />
|
|
||||||
|
|
||||||
<IonList>
|
|
||||||
<IonListHeader>Preferências</IonListHeader>
|
|
||||||
<IonItem>
|
|
||||||
<IonLabel>Vaga avulsa</IonLabel>
|
|
||||||
<IonCheckbox value="vaga_avulsa" />
|
|
||||||
</IonItem>
|
|
||||||
<IonItem>
|
|
||||||
<IonLabel>Ar condicionado</IonLabel>
|
|
||||||
<IonCheckbox value="ar_condicionado" />
|
|
||||||
</IonItem>
|
|
||||||
<IonItem>
|
|
||||||
<IonLabel>Assento preferencial</IonLabel>
|
|
||||||
<IonCheckbox value="assento_preferencial" />
|
|
||||||
</IonItem>
|
|
||||||
</IonList>
|
|
||||||
</IonContent>
|
|
||||||
|
|
||||||
<IonFooter>
|
|
||||||
<IonButton
|
|
||||||
expand="block"
|
|
||||||
onClick={() => setShowModalFilters(false)}
|
|
||||||
>
|
|
||||||
Aplicar Filtros
|
|
||||||
</IonButton>
|
|
||||||
</IonFooter>
|
|
||||||
</IonModal>
|
|
||||||
|
|
||||||
<IonToast
|
|
||||||
// cssClass={"toast-notification"}
|
|
||||||
color={toastColor}
|
|
||||||
isOpen={showToast}
|
|
||||||
onDidDismiss={() => closeToast(setShowToast)}
|
|
||||||
message={messageToast}
|
|
||||||
duration={2500}
|
|
||||||
/>
|
|
||||||
</IonContent>
|
|
||||||
</IonPage>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default ListaItinerarios;
|
|
||||||
@@ -105,7 +105,7 @@ const Page: React.FC = () => {
|
|||||||
// 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");
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -15,46 +15,82 @@ import {
|
|||||||
IonToolbar,
|
IonToolbar,
|
||||||
} from "@ionic/react";
|
} from "@ionic/react";
|
||||||
import { add, locateOutline, locationOutline } from "ionicons/icons";
|
import { add, locateOutline, locationOutline } from "ionicons/icons";
|
||||||
import { useEffect, useState } from "react";
|
import { useState } from "react";
|
||||||
import { getItineraries } from "../../services/api/itineraries";
|
|
||||||
import { PageHeader } from "../../components/PageHeader";
|
import { PageHeader } from "../../components/PageHeader";
|
||||||
import "./MeusItinerarios.css";
|
import "./MeusItinerarios.css";
|
||||||
|
|
||||||
interface Address {
|
|
||||||
formatted_address: string;
|
|
||||||
lat: number;
|
|
||||||
lng: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Destination extends Address {
|
|
||||||
is_final?: boolean;
|
|
||||||
}
|
|
||||||
interface ItineraryInfo {
|
interface ItineraryInfo {
|
||||||
id_itinerary: number;
|
id_itinerary: number;
|
||||||
vehicle_plate: string;
|
vehicle_plate: string;
|
||||||
days_of_week?: string;
|
days_of_week: number;
|
||||||
specific_day?: string;
|
specific_day: string;
|
||||||
estimated_departure_time: string;
|
estimated_departure_time: string;
|
||||||
estimated_arrival_time: string;
|
estimated_arrival_time: string;
|
||||||
monthly_price: number;
|
available_seats: number;
|
||||||
daily_price?: number;
|
price: number;
|
||||||
accept_daily: boolean;
|
|
||||||
itinerary_nickname: string;
|
itinerary_nickname: string;
|
||||||
estimated_departure_address: string;
|
|
||||||
departure_latitude: number;
|
|
||||||
departure_longitude: number;
|
|
||||||
neighborhoods_served: Address[];
|
|
||||||
destinations: Destination[];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function MeusItinerarios() {
|
export default function MeusItinerarios() {
|
||||||
const [routes, setRoutes] = useState<ItineraryInfo[]>([]);
|
const [routes, setRoutes] = useState<ItineraryInfo[]>(
|
||||||
|
[
|
||||||
useEffect(() => {
|
{
|
||||||
getItineraries().then((response) => {
|
id_itinerary: 1,
|
||||||
setRoutes(response.data);
|
vehicle_plate: 'FSS1918',
|
||||||
});
|
days_of_week: 3,
|
||||||
}, [])
|
specific_day: '24/08/2022',
|
||||||
|
estimated_departure_time: '10:00',
|
||||||
|
estimated_arrival_time: '12:00',
|
||||||
|
available_seats: 20,
|
||||||
|
price: 108.20,
|
||||||
|
itinerary_nickname: 'Itinerário teste',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id_itinerary: 1,
|
||||||
|
vehicle_plate: 'FSS1918',
|
||||||
|
days_of_week: 3,
|
||||||
|
specific_day: '24/08/2022',
|
||||||
|
estimated_departure_time: '10:00',
|
||||||
|
estimated_arrival_time: '12:00',
|
||||||
|
available_seats: 20,
|
||||||
|
price: 108.20,
|
||||||
|
itinerary_nickname: 'Itinerário teste 2',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id_itinerary: 1,
|
||||||
|
vehicle_plate: 'FSS1918',
|
||||||
|
days_of_week: 3,
|
||||||
|
specific_day: '24/08/2022',
|
||||||
|
estimated_departure_time: '10:00',
|
||||||
|
estimated_arrival_time: '12:00',
|
||||||
|
available_seats: 20,
|
||||||
|
price: 108.20,
|
||||||
|
itinerary_nickname: 'Itinerário teste',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id_itinerary: 1,
|
||||||
|
vehicle_plate: 'FSS1918',
|
||||||
|
days_of_week: 3,
|
||||||
|
specific_day: '24/08/2022',
|
||||||
|
estimated_departure_time: '10:00',
|
||||||
|
estimated_arrival_time: '12:00',
|
||||||
|
available_seats: 20,
|
||||||
|
price: 108.20,
|
||||||
|
itinerary_nickname: 'Itinerário teste',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id_itinerary: 1,
|
||||||
|
vehicle_plate: 'FSS1918',
|
||||||
|
days_of_week: 3,
|
||||||
|
specific_day: '24/08/2022',
|
||||||
|
estimated_departure_time: '10:00',
|
||||||
|
estimated_arrival_time: '12:00',
|
||||||
|
available_seats: 20,
|
||||||
|
price: 108.20,
|
||||||
|
itinerary_nickname: 'Itinerário teste',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<IonPage>
|
<IonPage>
|
||||||
@@ -73,23 +109,15 @@ export default function MeusItinerarios() {
|
|||||||
</IonCardHeader>
|
</IonCardHeader>
|
||||||
<IonCardContent>
|
<IonCardContent>
|
||||||
<div className="addresses-itinerary">
|
<div className="addresses-itinerary">
|
||||||
<IonIcon icon={locateOutline} className="mr-1"></IonIcon>
|
<IonIcon icon={locateOutline}></IonIcon>
|
||||||
{itinerary.estimated_departure_address}
|
Rua Francisco Glicerio, nº 100, Vila Novam aaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||||
</div>
|
</div>
|
||||||
<div className="icons-location-divider">
|
<div className="icons-location-divider">
|
||||||
|
|
|
|
||||||
</div>
|
</div>
|
||||||
<div className="addresses-itinerary">
|
<div className="addresses-itinerary">
|
||||||
<IonIcon icon={locationOutline} className="mr-1"></IonIcon>
|
<IonIcon icon={locationOutline}></IonIcon>
|
||||||
{itinerary.destinations.map((destination) => {
|
PUC Campinas H15 Campus 1 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||||
if (destination.is_final) {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{destination.formatted_address}
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
})}
|
|
||||||
</div>
|
</div>
|
||||||
</IonCardContent>
|
</IonCardContent>
|
||||||
</IonCard>
|
</IonCard>
|
||||||
|
|||||||
@@ -1,19 +1,26 @@
|
|||||||
import {
|
import {
|
||||||
|
IonBackButton,
|
||||||
IonBadge,
|
IonBadge,
|
||||||
|
IonButtons,
|
||||||
IonCard,
|
IonCard,
|
||||||
IonCardContent,
|
IonCardContent,
|
||||||
IonCardHeader,
|
IonCardHeader,
|
||||||
IonCardTitle,
|
IonCardTitle,
|
||||||
IonChip,
|
IonChip,
|
||||||
IonContent,
|
IonContent,
|
||||||
|
IonHeader,
|
||||||
IonIcon,
|
IonIcon,
|
||||||
IonItem,
|
IonItem,
|
||||||
IonLabel,
|
IonLabel,
|
||||||
IonList,
|
IonList,
|
||||||
IonListHeader,
|
IonListHeader,
|
||||||
IonPage,
|
IonPage,
|
||||||
|
IonTitle,
|
||||||
IonToast,
|
IonToast,
|
||||||
|
IonToolbar,
|
||||||
} from "@ionic/react";
|
} from "@ionic/react";
|
||||||
|
import { useHistory, useLocation } from "react-router-dom";
|
||||||
|
import React, { useState, useEffect, useReducer, useContext } from "react";
|
||||||
import {
|
import {
|
||||||
callOutline,
|
callOutline,
|
||||||
cardOutline,
|
cardOutline,
|
||||||
@@ -25,21 +32,16 @@ import {
|
|||||||
shieldCheckmarkOutline,
|
shieldCheckmarkOutline,
|
||||||
starOutline,
|
starOutline,
|
||||||
} from "ionicons/icons";
|
} from "ionicons/icons";
|
||||||
import React, { useContext, useEffect, useReducer, useState } from "react";
|
|
||||||
import { useHistory, useLocation } from "react-router-dom";
|
|
||||||
|
|
||||||
import LocalStorage from "../LocalStorage";
|
|
||||||
import "./Perfil.css";
|
import "./Perfil.css";
|
||||||
|
import LocalStorage from "../LocalStorage";
|
||||||
|
|
||||||
import { Color } from "@ionic/core";
|
|
||||||
import { UserContext } from "../App";
|
|
||||||
import { PageHeader } from "../components/PageHeader";
|
|
||||||
import sessionsService from "../services/functions/sessionsService";
|
import sessionsService from "../services/functions/sessionsService";
|
||||||
import {
|
import usersService from "../services/functions/usersService";
|
||||||
checkIfUserIsDriver,
|
import { UserContext } from "../App";
|
||||||
getById,
|
import { Color } from "@ionic/core";
|
||||||
} from "../services/functions/usersService";
|
|
||||||
import { closeToast } from "../services/utils";
|
import { closeToast } from "../services/utils";
|
||||||
|
import { PageHeader } from "../components/PageHeader";
|
||||||
|
|
||||||
interface ScanNewProps {
|
interface ScanNewProps {
|
||||||
match: {
|
match: {
|
||||||
@@ -131,7 +133,7 @@ const Perfil: React.FC<ScanNewProps> = (props) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// get user info by ID
|
// get user info by ID
|
||||||
const getByIdRes = await getById(userId);
|
const getByIdRes = await usersService.getById(userId);
|
||||||
|
|
||||||
if (getByIdRes.error) {
|
if (getByIdRes.error) {
|
||||||
if (isVisitor && props.match.params.id) {
|
if (isVisitor && props.match.params.id) {
|
||||||
@@ -146,8 +148,8 @@ const Perfil: React.FC<ScanNewProps> = (props) => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if user is driver (if they have vans)
|
// check if user is driver (if they have vehicles)
|
||||||
const userIsDriverRes = await checkIfUserIsDriver(userId);
|
const userIsDriverRes = await usersService.checkIfUserIsDriver(userId);
|
||||||
|
|
||||||
// if (userIsDriverRes.error) {
|
// if (userIsDriverRes.error) {
|
||||||
// setToastColor('warning')
|
// setToastColor('warning')
|
||||||
@@ -345,15 +347,6 @@ const Perfil: React.FC<ScanNewProps> = (props) => {
|
|||||||
<IonIcon icon={personOutline} slot="start" />
|
<IonIcon icon={personOutline} slot="start" />
|
||||||
<IonLabel>Buscar passageiros</IonLabel>
|
<IonLabel>Buscar passageiros</IonLabel>
|
||||||
</IonItem>
|
</IonItem>
|
||||||
<IonItem
|
|
||||||
button
|
|
||||||
onClick={() =>
|
|
||||||
history.push({ pathname: "/cadastrar-itinerario" })
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<IonIcon icon={mapOutline} slot="start" />
|
|
||||||
<IonLabel>Cadastrar itinerário</IonLabel>
|
|
||||||
</IonItem>
|
|
||||||
<IonItem
|
<IonItem
|
||||||
button
|
button
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
|
|||||||
@@ -70,14 +70,9 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
/* margin: 1rem 0 5.5rem 0; */
|
margin: 1rem 0 5.5rem 0;
|
||||||
margin-top: 20px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.msg-not-found{
|
.msg-not-found{
|
||||||
margin: 1.5rem;
|
margin: 1.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.msg-not-found span {
|
|
||||||
font-size: 120%;
|
|
||||||
}
|
|
||||||
224
src/pages/Transportes/Transportes.tsx
Normal file
224
src/pages/Transportes/Transportes.tsx
Normal file
@@ -0,0 +1,224 @@
|
|||||||
|
import {
|
||||||
|
IonContent,
|
||||||
|
IonPage,
|
||||||
|
IonFab,
|
||||||
|
IonFabButton,
|
||||||
|
IonIcon,
|
||||||
|
IonCard,
|
||||||
|
IonInput,
|
||||||
|
IonRow,
|
||||||
|
IonCol,
|
||||||
|
IonCardContent,
|
||||||
|
IonButton,
|
||||||
|
IonHeader,
|
||||||
|
IonToolbar,
|
||||||
|
IonButtons,
|
||||||
|
IonBackButton,
|
||||||
|
IonTabs,
|
||||||
|
IonTabBar,
|
||||||
|
IonTabButton,
|
||||||
|
IonLabel,
|
||||||
|
IonBadge,
|
||||||
|
IonRouterOutlet,
|
||||||
|
IonSlides,
|
||||||
|
IonSlide,
|
||||||
|
IonModal,
|
||||||
|
IonList,
|
||||||
|
IonRadioGroup,
|
||||||
|
IonListHeader,
|
||||||
|
IonItem,
|
||||||
|
IonRadio,
|
||||||
|
IonCheckbox,
|
||||||
|
IonFooter,
|
||||||
|
IonToast,
|
||||||
|
} from "@ionic/react";
|
||||||
|
import {
|
||||||
|
arrowBack,
|
||||||
|
arrowBackOutline,
|
||||||
|
arrowForwardOutline,
|
||||||
|
chevronBackOutline,
|
||||||
|
chevronForwardOutline,
|
||||||
|
closeOutline,
|
||||||
|
locateOutline,
|
||||||
|
locationOutline,
|
||||||
|
timeOutline,
|
||||||
|
} from "ionicons/icons";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { useHistory, useLocation } from "react-router";
|
||||||
|
import itinerariesService from "../../services/functions/itinerariesService";
|
||||||
|
import { createUserSearch } from "../../services/api/users";
|
||||||
|
import "./Transportes.css";
|
||||||
|
import { closeToast } from "../../services/utils";
|
||||||
|
|
||||||
|
interface InfoBusca {
|
||||||
|
addressFrom: any;
|
||||||
|
addressTo: any;
|
||||||
|
coordinatesFrom: any;
|
||||||
|
coordinatesTo: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Transportes: React.FC = () => {
|
||||||
|
const history = useHistory();
|
||||||
|
const location = useLocation();
|
||||||
|
const props = location.state as InfoBusca;
|
||||||
|
const [itinerarios, setItinerarios] = useState([]);
|
||||||
|
const [showModalFilters, setShowModalFilters] = useState(false);
|
||||||
|
const [showToast, setShowToast] = useState(false);
|
||||||
|
const [messageToast, setMessageToast ] = useState('');
|
||||||
|
const [toastColor, setToastColor] = useState('success');
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (props) {
|
||||||
|
buscaItinerarios();
|
||||||
|
}
|
||||||
|
}, [props]);
|
||||||
|
|
||||||
|
async function buscaItinerarios() {
|
||||||
|
let data = (await itinerariesService.searchItineraries(props)) as any;
|
||||||
|
setItinerarios(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
function criaAlerta(){
|
||||||
|
createUserSearch(props.coordinatesFrom.lat, props.coordinatesFrom.lng, props.addressTo.label).then(() => {
|
||||||
|
setMessageToast('Alerta criado com sucesso!');
|
||||||
|
setShowToast(true);
|
||||||
|
}).catch((err:any) => {
|
||||||
|
setMessageToast('Não foi possível criar o alerta!');
|
||||||
|
setToastColor('danger');
|
||||||
|
setShowToast(true);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<IonPage>
|
||||||
|
{/* TODO, componentizar Header */}
|
||||||
|
<IonHeader>
|
||||||
|
<div className="header-page">
|
||||||
|
{/* <IonButtons slot="start">
|
||||||
|
<IonBackButton text={'aaaa'} icon={arrowBack} defaultHref='buscar-transporte' />
|
||||||
|
</IonButtons> */}
|
||||||
|
<span className="span-info-back" onClick={history.goBack}>
|
||||||
|
<IonIcon className="icon-return" icon={chevronBackOutline} />
|
||||||
|
<div className="address-from-to">
|
||||||
|
<span>{props.addressFrom.label}</span>
|
||||||
|
<IonIcon icon={arrowForwardOutline} />
|
||||||
|
<span>{props.addressTo.label}</span>
|
||||||
|
<small>Hoje</small>
|
||||||
|
</div>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</IonHeader>
|
||||||
|
<IonContent fullscreen>
|
||||||
|
{itinerarios && itinerarios.length > 0? (
|
||||||
|
<div className="header-tabs">
|
||||||
|
<IonSlides>
|
||||||
|
<IonSlide>
|
||||||
|
<h5>Mais barata</h5>
|
||||||
|
<IonCard className="card-transporte">
|
||||||
|
<IonCardContent>Seu João</IonCardContent>
|
||||||
|
</IonCard>
|
||||||
|
</IonSlide>
|
||||||
|
<IonSlide>
|
||||||
|
<h5>Melhor avaliação</h5>
|
||||||
|
<IonCard className="card-transporte">
|
||||||
|
<IonCardContent>Seu Zé</IonCardContent>
|
||||||
|
</IonCard>
|
||||||
|
</IonSlide>
|
||||||
|
</IonSlides>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
:
|
||||||
|
(<h1 className="msg-not-found">Não foi encontrado nenhum transporte que atenda essa rota.</h1>)}
|
||||||
|
{itinerarios &&
|
||||||
|
itinerarios.map((record: any, index: any) => {
|
||||||
|
return (
|
||||||
|
<IonCard className="card-transporte" key={index}>
|
||||||
|
<IonCardContent>
|
||||||
|
<h1>Motorista: {record.motorista}</h1>
|
||||||
|
<div>Avaliação: {record.avaliacao}</div>
|
||||||
|
<div>Valor: {record.valor}</div>
|
||||||
|
<div>Lugares disponíveis: {record.lugares}</div>
|
||||||
|
</IonCardContent>
|
||||||
|
</IonCard>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
|
||||||
|
<div className="button-criar-alerta">
|
||||||
|
<IonButton onClick={() => criaAlerta()}>Criar Alerta</IonButton>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<IonFab
|
||||||
|
onClick={() => setShowModalFilters(true)}
|
||||||
|
vertical="bottom"
|
||||||
|
horizontal="center"
|
||||||
|
slot="fixed"
|
||||||
|
>
|
||||||
|
<IonFabButton>Filtros</IonFabButton>
|
||||||
|
</IonFab>
|
||||||
|
<IonModal isOpen={showModalFilters}>
|
||||||
|
<IonToolbar>
|
||||||
|
<div className="header-filter-modal">
|
||||||
|
<IonIcon
|
||||||
|
size="large"
|
||||||
|
icon={closeOutline}
|
||||||
|
onClick={() => setShowModalFilters(false)}
|
||||||
|
/>
|
||||||
|
<h4>
|
||||||
|
<b>Limpar</b>
|
||||||
|
</h4>
|
||||||
|
</div>
|
||||||
|
</IonToolbar>
|
||||||
|
<IonContent>
|
||||||
|
<div className="content-filter-modal">
|
||||||
|
<h1>Filtrar</h1>
|
||||||
|
<h3>Ordernar por</h3>
|
||||||
|
<IonRadioGroup>
|
||||||
|
<IonItem>
|
||||||
|
<IonLabel>Menor preço</IonLabel>
|
||||||
|
<IonRadio value="menor_preco" />
|
||||||
|
</IonItem>
|
||||||
|
|
||||||
|
<IonItem>
|
||||||
|
<IonLabel>Avaliação</IonLabel>
|
||||||
|
<IonRadio value="avaliacao" />
|
||||||
|
</IonItem>
|
||||||
|
|
||||||
|
<IonItem>
|
||||||
|
<IonLabel>Lugares disponíveis</IonLabel>
|
||||||
|
<IonRadio value="lugares_disponiveis" />
|
||||||
|
</IonItem>
|
||||||
|
</IonRadioGroup>
|
||||||
|
<h3>Preferências</h3>
|
||||||
|
<IonItem>
|
||||||
|
<IonLabel>Vaga avulsa</IonLabel>
|
||||||
|
<IonCheckbox value="vaga_avulsa" />
|
||||||
|
</IonItem>
|
||||||
|
<IonItem>
|
||||||
|
<IonLabel>Ar condicionado</IonLabel>
|
||||||
|
<IonCheckbox value="ar_condicionado" />
|
||||||
|
</IonItem>
|
||||||
|
</div>
|
||||||
|
</IonContent>
|
||||||
|
<IonFooter>
|
||||||
|
<IonButton
|
||||||
|
expand="block"
|
||||||
|
onClick={() => setShowModalFilters(false)}
|
||||||
|
>
|
||||||
|
Aplicar Filtros
|
||||||
|
</IonButton>
|
||||||
|
</IonFooter>
|
||||||
|
</IonModal>
|
||||||
|
<IonToast
|
||||||
|
// cssClass={"toast-notification"}
|
||||||
|
color={toastColor}
|
||||||
|
isOpen={showToast}
|
||||||
|
onDidDismiss={() => closeToast(setShowToast)}
|
||||||
|
message={messageToast}
|
||||||
|
duration={2500}
|
||||||
|
/>
|
||||||
|
</IonContent>
|
||||||
|
</IonPage>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Transportes;
|
||||||
@@ -1,16 +1,22 @@
|
|||||||
import {
|
import {
|
||||||
IonButton,
|
IonToast,
|
||||||
IonCheckbox,
|
|
||||||
IonContent,
|
|
||||||
IonInput,
|
|
||||||
IonItem,
|
IonItem,
|
||||||
IonItemDivider,
|
|
||||||
IonLabel,
|
IonLabel,
|
||||||
IonList,
|
IonInput,
|
||||||
|
IonBackButton,
|
||||||
|
IonButton,
|
||||||
|
IonButtons,
|
||||||
|
IonContent,
|
||||||
|
IonHeader,
|
||||||
IonPage,
|
IonPage,
|
||||||
|
IonToolbar,
|
||||||
|
IonTitle,
|
||||||
|
IonList,
|
||||||
|
IonCheckbox,
|
||||||
|
IonListHeader,
|
||||||
IonSelect,
|
IonSelect,
|
||||||
IonSelectOption,
|
IonSelectOption,
|
||||||
IonToast,
|
IonItemDivider,
|
||||||
} from "@ionic/react";
|
} from "@ionic/react";
|
||||||
|
|
||||||
import React, { useEffect, useReducer, useState } from "react";
|
import React, { useEffect, useReducer, useState } from "react";
|
||||||
@@ -22,10 +28,10 @@ import carsService from "../services/functions/carsService";
|
|||||||
|
|
||||||
import * as vehiclesRoutes from "../services/api/vehicles";
|
import * as vehiclesRoutes from "../services/api/vehicles";
|
||||||
|
|
||||||
import { Color } from "@ionic/core";
|
|
||||||
import { PageHeader } from "../components/PageHeader";
|
|
||||||
import { closeToast } from "../services/utils";
|
|
||||||
import "./VeiculoCadastro.css";
|
import "./VeiculoCadastro.css";
|
||||||
|
import { Color } from "@ionic/core";
|
||||||
|
import { closeToast } from "../services/utils";
|
||||||
|
import { PageHeader } from "../components/PageHeader";
|
||||||
|
|
||||||
const VeiculoCadastro: React.FC = () => {
|
const VeiculoCadastro: React.FC = () => {
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
@@ -203,7 +209,7 @@ const VeiculoCadastro: React.FC = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
history.push({
|
history.push({
|
||||||
pathname: "/veiculos/meus",
|
pathname: "/minhas-vehicles",
|
||||||
state: {
|
state: {
|
||||||
redirectData: {
|
redirectData: {
|
||||||
showToastMessage: true,
|
showToastMessage: true,
|
||||||
@@ -256,9 +262,7 @@ const VeiculoCadastro: React.FC = () => {
|
|||||||
|
|
||||||
<IonContent>
|
<IonContent>
|
||||||
<IonList lines="full" class="ion-no-margin">
|
<IonList lines="full" class="ion-no-margin">
|
||||||
<IonItemDivider color={"primary"}>
|
<IonItemDivider color={"primary"}>Informações do veículo</IonItemDivider>
|
||||||
Informações do veículo
|
|
||||||
</IonItemDivider>
|
|
||||||
<IonItem>
|
<IonItem>
|
||||||
<IonLabel position="fixed">Placa </IonLabel>
|
<IonLabel position="fixed">Placa </IonLabel>
|
||||||
<IonInput
|
<IonInput
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
import instance from "./api";
|
import instance from './api';
|
||||||
// import LocalStorage from '../LocalStorage';
|
// import LocalStorage from '../LocalStorage';
|
||||||
|
|
||||||
import { AxiosRequestHeaders } from "axios";
|
import transportsRoutes from '../../constants/routes/itinerariesRoutes';
|
||||||
import transportsRoutes from "../../constants/routes/itinerariesRoutes";
|
import { AxiosRequestHeaders } from 'axios';
|
||||||
import LocalStorage from "../../LocalStorage";
|
import LocalStorage from '../../LocalStorage';
|
||||||
|
import { setStore } from '../../store/RecordsStore';
|
||||||
|
|
||||||
let token: string;
|
let token: string;
|
||||||
let header: AxiosRequestHeaders;
|
let header: AxiosRequestHeaders;
|
||||||
@@ -12,68 +13,27 @@ 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 Coordinates {
|
export interface Coordinates {
|
||||||
lat: number;
|
lat: number,
|
||||||
lng: number;
|
lng: number
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Address {
|
export async function get() {
|
||||||
formatted_address: string;
|
|
||||||
lat: number;
|
|
||||||
lng: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface CreateItineraryRequest {
|
|
||||||
vehicle_plate: string;
|
|
||||||
days_of_week?: string;
|
|
||||||
specific_day?: string;
|
|
||||||
estimated_departure_time: string;
|
|
||||||
estimated_arrival_time: string;
|
|
||||||
monthly_price: number;
|
|
||||||
daily_price?: number;
|
|
||||||
accept_daily: boolean;
|
|
||||||
itinerary_nickname: string;
|
|
||||||
estimated_departure_address: string;
|
|
||||||
departure_latitude: number;
|
|
||||||
departure_longitude: number;
|
|
||||||
neighborhoods_served: Array<Address>;
|
|
||||||
destinations: Array<Address>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function getItineraries() {
|
|
||||||
updateHeader();
|
updateHeader();
|
||||||
|
|
||||||
const response = await instance.get(transportsRoutes.get.url, {
|
const response = await instance.get(transportsRoutes.get.url, { headers: header });
|
||||||
headers: header,
|
|
||||||
});
|
|
||||||
return response.data;
|
return response.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function create(itinerary: CreateItineraryRequest) {
|
export async function search(coordinatesOrigin: Coordinates, coordinatesDestination: Coordinates) {
|
||||||
updateHeader();
|
updateHeader();
|
||||||
|
|
||||||
const response = await instance.post(transportsRoutes.create.url, itinerary, {
|
const response = await instance.post(transportsRoutes.search.url, { coordinatesOrigin, coordinatesDestination }, { headers: header });
|
||||||
headers: header,
|
|
||||||
});
|
|
||||||
return response.data;
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function search(
|
|
||||||
coordinatesOrigin: Coordinates,
|
|
||||||
coordinatesDestination: Coordinates
|
|
||||||
) {
|
|
||||||
updateHeader();
|
|
||||||
|
|
||||||
const response = await instance.post(
|
|
||||||
transportsRoutes.search.url,
|
|
||||||
{ coordinatesOrigin, coordinatesDestination },
|
|
||||||
{ headers: header }
|
|
||||||
);
|
|
||||||
return response.data;
|
return response.data;
|
||||||
}
|
}
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
import instance from "./api";
|
import instance from './api';
|
||||||
// import LocalStorage from '../LocalStorage';
|
// import LocalStorage from '../LocalStorage';
|
||||||
|
|
||||||
import { AxiosRequestHeaders } from "axios";
|
import userRoutes from '../../constants/routes/usersRoutes';
|
||||||
import userRoutes from "../../constants/routes/usersRoutes";
|
import { AxiosRequestHeaders } from 'axios';
|
||||||
import LocalStorage from "../../LocalStorage";
|
import LocalStorage from '../../LocalStorage';
|
||||||
import { setStore } from "../../store/RecordsStore";
|
import { setStore } from '../../store/RecordsStore';
|
||||||
|
|
||||||
let token: string;
|
let token: string;
|
||||||
let header: AxiosRequestHeaders;
|
let header: AxiosRequestHeaders;
|
||||||
@@ -13,10 +13,10 @@ 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 {
|
||||||
@@ -63,28 +63,21 @@ export async function create(CadastroRequest: any) {
|
|||||||
export async function getById(userId: string) {
|
export async function getById(userId: string) {
|
||||||
updateHeader();
|
updateHeader();
|
||||||
|
|
||||||
const response = await instance.get(userRoutes.get.url + `/${userId}`, {
|
const response = await instance.get(userRoutes.get.url + `/${userId}`, { headers: header });
|
||||||
headers: header,
|
|
||||||
});
|
|
||||||
return response.data;
|
return response.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function update(userData: UpdateUserRequest) {
|
export async function update(userData: UpdateUserRequest) {
|
||||||
updateHeader();
|
updateHeader();
|
||||||
|
|
||||||
const response = await instance.patch(userRoutes.update.url, userData, {
|
const response = await instance.patch(userRoutes.update.url, userData, { headers: header });
|
||||||
headers: header,
|
|
||||||
});
|
|
||||||
return response.data;
|
return response.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function checkIfUserIsDriver(id_user: string) {
|
export async function checkIfUserIsDriver(id_user: string) {
|
||||||
updateHeader();
|
updateHeader();
|
||||||
|
|
||||||
const response = await instance.get(
|
const response = await instance.get(userRoutes.checkIfUserIsDriver.url + `/${id_user}`, { headers: header });
|
||||||
userRoutes.checkIfUserIsDriver.url + `/${id_user}`,
|
|
||||||
{ headers: header }
|
|
||||||
);
|
|
||||||
return response.data;
|
return response.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,10 +85,7 @@ export async function checkIfUserIsDriver(id_user: string) {
|
|||||||
export async function getSocialInfo(userId: string) {
|
export async function getSocialInfo(userId: string) {
|
||||||
updateHeader();
|
updateHeader();
|
||||||
|
|
||||||
const response = await instance.get(
|
const response = await instance.get(userRoutes.getSocialInfo.url + `/${userId}`, { headers: header });
|
||||||
userRoutes.getSocialInfo.url + `/${userId}`,
|
|
||||||
{ headers: header }
|
|
||||||
);
|
|
||||||
return response.data;
|
return response.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,28 +93,17 @@ export async function getUsersSearching(currentPoint: any) {
|
|||||||
// Replace lat/long with values from get current location.
|
// Replace lat/long with values from get current location.
|
||||||
// Allow choosing of radius?
|
// Allow choosing of radius?
|
||||||
// Offset could = amount loaded in an infinite scroll?
|
// Offset could = amount loaded in an infinite scroll?
|
||||||
// var latitude = currentPoint.latitude, longitude = currentPoint.longitude, radius = 3000, offset = 0;
|
var latitude = currentPoint.latitude, longitude = currentPoint.longitude, radius = 3000, offset = 0;
|
||||||
// const response = await fetch(`http://localhost:4000/get-records?latitude=${ latitude }&longitude=${ longitude }&radius=${ radius }&offset=${ offset }`);
|
// const response = await fetch(`http://localhost:4000/get-records?latitude=${ latitude }&longitude=${ longitude }&radius=${ radius }&offset=${ offset }`);
|
||||||
const response = await instance.post(
|
const response = await instance.post(`${userRoutes.getUsersSearching.url}`, currentPoint)
|
||||||
`${userRoutes.getUsersSearching.url}`,
|
|
||||||
currentPoint
|
|
||||||
);
|
|
||||||
// const data = await response.json();
|
// const data = await response.json();
|
||||||
console.log(response.data);
|
console.log(response.data)
|
||||||
setStore(response.data);
|
setStore(response.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function createUserSearch(
|
export async function createUserSearch(latitude_from: any, longitude_from: any, addres_to: any) {
|
||||||
latitude_from: any,
|
const response = await instance.post(`${userRoutes.createUserSearch.url}`, { latitude_from, longitude_from, addres_to });
|
||||||
longitude_from: any,
|
|
||||||
addres_to: any
|
|
||||||
) {
|
|
||||||
const response = await instance.post(`${userRoutes.createUserSearch.url}`, {
|
|
||||||
latitude_from,
|
|
||||||
longitude_from,
|
|
||||||
addres_to,
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log(response);
|
console.log(response)
|
||||||
setStore(response);
|
setStore(response);
|
||||||
}
|
}
|
||||||
@@ -10,13 +10,13 @@ interface getAllCarBrandsReturn {
|
|||||||
|
|
||||||
error?: {
|
error?: {
|
||||||
errorMessage: string;
|
errorMessage: string;
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface getAllCarBrandsRes {
|
interface getAllCarBrandsRes {
|
||||||
status?: string;
|
status?: string;
|
||||||
|
|
||||||
message: string;
|
message: string
|
||||||
|
|
||||||
data?: CarObject[];
|
data?: CarObject[];
|
||||||
}
|
}
|
||||||
@@ -45,9 +45,7 @@ const getAllCarBrands = async (): Promise<getAllCarBrandsReturn> => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const getCarModels = async (
|
const getCarModels = async (carBrandId: string): Promise<getAllCarBrandsReturn> => {
|
||||||
carBrandId: string
|
|
||||||
): Promise<getAllCarBrandsReturn> => {
|
|
||||||
try {
|
try {
|
||||||
let res: getAllCarBrandsRes = await carsRoutes.listCarModels(carBrandId);
|
let res: getAllCarBrandsRes = await carsRoutes.listCarModels(carBrandId);
|
||||||
|
|
||||||
|
|||||||
@@ -1,50 +1,38 @@
|
|||||||
import * as itinerariesRoutes from "../api/itineraries";
|
import * as itinerariesRoutes from '../api/itineraries';
|
||||||
|
|
||||||
interface CoordinatesRequest {
|
interface CoordinatesRequest {
|
||||||
coordinatesFrom: {
|
coordinatesFrom: {
|
||||||
formatted_address: string;
|
lat: number,
|
||||||
lat: number;
|
lng: number
|
||||||
lng: number;
|
},
|
||||||
};
|
|
||||||
coordinatesTo: {
|
coordinatesTo: {
|
||||||
formatted_address: string;
|
lat: number,
|
||||||
lat: number;
|
lng: number
|
||||||
lng: number;
|
}
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getAllItineraries(): Promise<any> {
|
export async function getAllItineraries(): Promise<any> {
|
||||||
let res: any;
|
let res: any;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
res = await itinerariesRoutes.getItineraries();
|
res = await itinerariesRoutes.get();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
return res.data;
|
return res.data
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function searchItineraries({
|
|
||||||
coordinatesFrom,
|
export async function searchItineraries({ coordinatesFrom, coordinatesTo }: CoordinatesRequest): Promise<any> {
|
||||||
coordinatesTo,
|
let res: any
|
||||||
}: CoordinatesRequest): Promise<any> {
|
|
||||||
let res: any;
|
|
||||||
try {
|
try {
|
||||||
res = await itinerariesRoutes.search(coordinatesFrom, coordinatesTo);
|
res = await itinerariesRoutes.search(coordinatesFrom, coordinatesTo);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
return res.data;
|
return res.data
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function createItinerary(
|
export default { getAllItineraries, searchItineraries }
|
||||||
itinerary: itinerariesRoutes.CreateItineraryRequest
|
|
||||||
): Promise<any> {
|
|
||||||
let res: any;
|
|
||||||
|
|
||||||
res = await itinerariesRoutes.create(itinerary);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ interface refreshSessionResponse {
|
|||||||
|
|
||||||
const refreshSession = async (): Promise<refreshSessionReturn> => {
|
const refreshSession = async (): Promise<refreshSessionReturn> => {
|
||||||
try {
|
try {
|
||||||
let res: refreshSessionResponse = await sessionRoutes.refresh();
|
let res: refreshSessionResponse = await sessionRoutes.refresh()
|
||||||
|
|
||||||
if (res.status === "error") {
|
if (res.status === "error") {
|
||||||
return {
|
return {
|
||||||
@@ -26,7 +26,7 @@ const refreshSession = async (): Promise<refreshSessionReturn> => {
|
|||||||
return {
|
return {
|
||||||
userId: res.userId,
|
userId: res.userId,
|
||||||
};
|
};
|
||||||
} catch (err) {
|
} catch(err) {
|
||||||
return {
|
return {
|
||||||
error: true,
|
error: true,
|
||||||
errorMessage: "Por favor, autentique-se.",
|
errorMessage: "Por favor, autentique-se.",
|
||||||
@@ -40,11 +40,7 @@ const refreshSession = async (): Promise<refreshSessionReturn> => {
|
|||||||
// } else {
|
// } else {
|
||||||
// // Anything else
|
// // Anything else
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
};
|
};
|
||||||
|
|
||||||
const method = {
|
export default { refreshSession }
|
||||||
refreshSession,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default method;
|
|
||||||
@@ -10,10 +10,10 @@ interface getByIdReturn {
|
|||||||
bio: string;
|
bio: string;
|
||||||
document_type: string;
|
document_type: string;
|
||||||
document: string;
|
document: string;
|
||||||
};
|
},
|
||||||
error?: {
|
error?: {
|
||||||
errorMessage: string;
|
errorMessage: string;
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface getByIdRes {
|
interface getByIdRes {
|
||||||
@@ -29,67 +29,65 @@ interface getByIdRes {
|
|||||||
bio: string;
|
bio: string;
|
||||||
document_type: string;
|
document_type: string;
|
||||||
document: string;
|
document: string;
|
||||||
};
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getById = async (userId: string): Promise<getByIdReturn> => {
|
const getById = async (userId: string): Promise<getByIdReturn> => {
|
||||||
try {
|
try {
|
||||||
let res: getByIdRes = await usersRoutes.getById(userId);
|
let res: getByIdRes = await usersRoutes.getById(userId)
|
||||||
|
|
||||||
if (res.status === "error") {
|
if (res.status === "error") {
|
||||||
return {
|
return {
|
||||||
error: {
|
error: {
|
||||||
errorMessage: res.message,
|
errorMessage: res.message,
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
userData: res.data,
|
userData: res.data,
|
||||||
};
|
};
|
||||||
} catch (err) {
|
} catch(err) {
|
||||||
return {
|
return {
|
||||||
error: {
|
error: {
|
||||||
errorMessage: "Por favor, autentique-se.",
|
errorMessage: "Por favor, autentique-se.",
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
interface getByIdReturn {
|
interface getByIdReturn {
|
||||||
data?: {
|
data?: {
|
||||||
phone: "";
|
phone: '',
|
||||||
whatsapp: "";
|
whatsapp: '',
|
||||||
facebook: "";
|
facebook: '',
|
||||||
telegram: "";
|
telegram: '',
|
||||||
};
|
},
|
||||||
error?: {
|
error?: {
|
||||||
errorMessage: string;
|
errorMessage: string;
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getUserSocialInfo = async (
|
const getUserSocialInfo = async (userId: string): Promise<getByIdReturn> => {
|
||||||
userId: string
|
|
||||||
): Promise<getByIdReturn> => {
|
|
||||||
try {
|
try {
|
||||||
let res: getByIdRes = await usersRoutes.getSocialInfo(userId);
|
let res: getByIdRes = await usersRoutes.getSocialInfo(userId)
|
||||||
|
|
||||||
if (res.status === "error") {
|
if (res.status === "error") {
|
||||||
return {
|
return {
|
||||||
error: {
|
error: {
|
||||||
errorMessage: res.message,
|
errorMessage: res.message,
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
userData: res.data,
|
userData: res.data,
|
||||||
};
|
};
|
||||||
} catch (err) {
|
} catch(err) {
|
||||||
return {
|
return {
|
||||||
error: {
|
error: {
|
||||||
errorMessage: "Por favor, autentique-se.",
|
errorMessage: "Por favor, autentique-se.",
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -98,7 +96,7 @@ interface checkIfUserIsDriverReturn {
|
|||||||
result?: boolean;
|
result?: boolean;
|
||||||
error?: {
|
error?: {
|
||||||
errorMessage: string;
|
errorMessage: string;
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface checkIfUserIsDriverResponse {
|
interface checkIfUserIsDriverResponse {
|
||||||
@@ -107,32 +105,31 @@ interface checkIfUserIsDriverResponse {
|
|||||||
result?: boolean;
|
result?: boolean;
|
||||||
error?: {
|
error?: {
|
||||||
errorMessage: string;
|
errorMessage: string;
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const checkIfUserIsDriver = async (
|
const checkIfUserIsDriver = async (id_user: string): Promise<checkIfUserIsDriverReturn> => {
|
||||||
id_user: string
|
|
||||||
): Promise<checkIfUserIsDriverReturn> => {
|
|
||||||
try {
|
try {
|
||||||
let res: checkIfUserIsDriverResponse =
|
let res: checkIfUserIsDriverResponse = await usersRoutes.checkIfUserIsDriver(id_user)
|
||||||
await usersRoutes.checkIfUserIsDriver(id_user);
|
|
||||||
|
|
||||||
if (res.status === "error") {
|
if (res.status === "error") {
|
||||||
return {
|
return {
|
||||||
error: {
|
error: {
|
||||||
errorMessage: res.message,
|
errorMessage: res.message,
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
result: res.result,
|
result: res.result,
|
||||||
};
|
};
|
||||||
} catch (err) {
|
} catch(err) {
|
||||||
return {
|
return {
|
||||||
error: {
|
error: {
|
||||||
errorMessage: "Por favor, autentique-se.",
|
errorMessage: "Por favor, autentique-se.",
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export default { getById, getUserSocialInfo, checkIfUserIsDriver }
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import instance from '../services/api/api';
|
import instance from '../services/api/api';
|
||||||
|
|
||||||
export async function autoCompleteAddress(address: string) {
|
export async function autoCompleteAddress(address:string) {
|
||||||
|
|
||||||
const response = await instance.get(`https://api.geoapify.com/v1/geocode/autocomplete?text=${address}&apiKey=ee574aacff6f440a84378bbbf7e2f20d`);
|
const response = await instance.get(`https://api.geoapify.com/v1/geocode/autocomplete?text=${address}&apiKey=ee574aacff6f440a84378bbbf7e2f20d`);
|
||||||
return response.data.features;
|
return response.data.features;
|
||||||
@@ -10,13 +10,3 @@ export async function closeToast(setShowToast: React.Dispatch<React.SetStateActi
|
|||||||
setShowToast(false)
|
setShowToast(false)
|
||||||
window.history.replaceState({}, document.title)
|
window.history.replaceState({}, document.title)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function convertNumberToPrice(price: number) {
|
|
||||||
// Create our number formatter.
|
|
||||||
var formatter = new Intl.NumberFormat('pt-BR', {
|
|
||||||
style: 'currency',
|
|
||||||
currency: 'BRL',
|
|
||||||
});
|
|
||||||
|
|
||||||
return formatter.format(price);
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user