diff --git a/package-lock.json b/package-lock.json index a1e3220..a88aa24 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,11 +27,14 @@ "@types/react-router-dom": "^5.1.7", "axios": "^0.26.1", "ionicons": "^5.4.0", + "pigeon-maps": "^0.21.0", + "pullstate": "^1.24.0", "react": "^17.0.1", "react-dom": "^17.0.1", "react-hook-form": "^7.30.0", "react-router": "^5.2.0", "react-router-dom": "^5.2.0", + "reselect": "^4.1.5", "typescript": "^4.1.3", "web-vitals": "^0.2.4", "workbox-background-sync": "^5.1.4", @@ -7902,8 +7905,7 @@ "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "node_modules/fast-glob": { "version": "3.2.11", @@ -8955,7 +8957,6 @@ "version": "9.0.12", "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.12.tgz", "integrity": "sha512-lk7UNmSbAukB5B6dh9fnh5D0bJTOFKxVg2cyJWTYrWRfhLrLMBquONcUs3aFq507hNoIZEDDh8lb8UtOizSMhA==", - "dev": true, "funding": { "type": "opencollective", "url": "https://opencollective.com/immer" @@ -11655,6 +11656,14 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pigeon-maps": { + "version": "0.21.0", + "resolved": "https://registry.npmjs.org/pigeon-maps/-/pigeon-maps-0.21.0.tgz", + "integrity": "sha512-p3GaGday5nmufHVGZW/36LnSXfYVh6qfzYisqcC87nqFr0eXIKkqQcDuPP9g4F1OXL1JeJe4x6JEnAE9HB+zWQ==", + "peerDependencies": { + "react": "*" + } + }, "node_modules/pirates": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", @@ -13081,6 +13090,18 @@ "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", "dev": true }, + "node_modules/pullstate": { + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/pullstate/-/pullstate-1.24.0.tgz", + "integrity": "sha512-uKXQjGnZUNb3wg7STF3HvCDbGtYg7tju42QjVtaefMik6JpbadnmKgI8DgZL02SvtTNlFPosMQkAwuI/a9D8dg==", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "immer": "^9.0.12" + }, + "peerDependencies": { + "react": "^16.12.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", @@ -13661,6 +13682,11 @@ "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", "dev": true }, + "node_modules/reselect": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.5.tgz", + "integrity": "sha512-uVdlz8J7OO+ASpBYoz1Zypgx0KasCY20H+N8JD13oUMtPvSHQuscrHop4KbXrbsBcdB9Ds7lVK7eRkBIfO43vQ==" + }, "node_modules/resolve": { "version": "1.22.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", @@ -22491,8 +22517,7 @@ "fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "fast-glob": { "version": "3.2.11", @@ -23282,8 +23307,7 @@ "immer": { "version": "9.0.12", "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.12.tgz", - "integrity": "sha512-lk7UNmSbAukB5B6dh9fnh5D0bJTOFKxVg2cyJWTYrWRfhLrLMBquONcUs3aFq507hNoIZEDDh8lb8UtOizSMhA==", - "dev": true + "integrity": "sha512-lk7UNmSbAukB5B6dh9fnh5D0bJTOFKxVg2cyJWTYrWRfhLrLMBquONcUs3aFq507hNoIZEDDh8lb8UtOizSMhA==" }, "import-fresh": { "version": "3.3.0", @@ -25307,6 +25331,12 @@ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true }, + "pigeon-maps": { + "version": "0.21.0", + "resolved": "https://registry.npmjs.org/pigeon-maps/-/pigeon-maps-0.21.0.tgz", + "integrity": "sha512-p3GaGday5nmufHVGZW/36LnSXfYVh6qfzYisqcC87nqFr0eXIKkqQcDuPP9g4F1OXL1JeJe4x6JEnAE9HB+zWQ==", + "requires": {} + }, "pirates": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", @@ -26252,6 +26282,15 @@ "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", "dev": true }, + "pullstate": { + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/pullstate/-/pullstate-1.24.0.tgz", + "integrity": "sha512-uKXQjGnZUNb3wg7STF3HvCDbGtYg7tju42QjVtaefMik6JpbadnmKgI8DgZL02SvtTNlFPosMQkAwuI/a9D8dg==", + "requires": { + "fast-deep-equal": "^3.1.3", + "immer": "^9.0.12" + } + }, "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", @@ -26699,6 +26738,11 @@ "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", "dev": true }, + "reselect": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.5.tgz", + "integrity": "sha512-uVdlz8J7OO+ASpBYoz1Zypgx0KasCY20H+N8JD13oUMtPvSHQuscrHop4KbXrbsBcdB9Ds7lVK7eRkBIfO43vQ==" + }, "resolve": { "version": "1.22.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", diff --git a/package.json b/package.json index 39fd73e..6635922 100644 --- a/package.json +++ b/package.json @@ -22,11 +22,14 @@ "@types/react-router-dom": "^5.1.7", "axios": "^0.26.1", "ionicons": "^5.4.0", + "pigeon-maps": "^0.21.0", + "pullstate": "^1.24.0", "react": "^17.0.1", "react-dom": "^17.0.1", "react-hook-form": "^7.30.0", "react-router": "^5.2.0", "react-router-dom": "^5.2.0", + "reselect": "^4.1.5", "typescript": "^4.1.3", "web-vitals": "^0.2.4", "workbox-background-sync": "^5.1.4", diff --git a/src/pages/BuscarPassageiro/BuscarPassageiro.tsx b/src/pages/BuscarPassageiro/BuscarPassageiro.tsx index 9f9664c..605dd89 100644 --- a/src/pages/BuscarPassageiro/BuscarPassageiro.tsx +++ b/src/pages/BuscarPassageiro/BuscarPassageiro.tsx @@ -1,215 +1,113 @@ -import { IonToast, IonProgressBar, IonItem, IonLabel, IonInput, IonBackButton, IonButton, IonButtons, IonCardTitle, IonCol, IonContent, IonGrid, IonHeader, IonPage, IonRow, IonToolbar } from '@ionic/react'; -import { arrowBack, logoFacebook, mail } from 'ionicons/icons'; -import { Action } from '../../components/Action'; -import { useEffect, useState } from 'react'; -import { useHistory, useParams } from 'react-router'; +import { IonContent, IonPage, IonFab, IonFabButton, IonIcon } from '@ionic/react'; +import { search } from 'ionicons/icons'; import './BuscarPassageiro.css'; -import ModalExample from '../../components/Email'; -import * as UsersService from '../../services/users' + +import { Map, Marker, Overlay } from "pigeon-maps"; +import { maptiler } from 'pigeon-maps/providers'; +import { useEffect, useState } from 'react'; + +import RecordsStore from '../../store/RecordsStore'; +import { fetchRecords } from '../../store/Selectors'; +import { getUsersSearching } from '../../services/users'; + +const maptilerProvider = maptiler('d5JQJPLLuap8TkJJlTdJ', 'streets'); const BuscarPassageiro: React.FC = () => { - const history = useHistory(); - - const [showToast, setShowToast] = useState(false); - const [messageToast, setMessageToast ] = useState(''); - const [email, setEmail] = useState(''); - const [password, setPassword] = useState(''); - const [confirmPassword, setConfirmPassword] = useState(''); - const [firstName, setFirstName] = useState(''); - const [lastName, setLastName] = useState(''); - const [birthDate, setBirthDate] = useState(''); - const [lResult, setlResult] = useState({ - error: '', - success: true - }); + // UNCOMMENT THESE TO USE CURRENT LOCATION. - const emailValidate = () => { - var usuario = email.substring(0, email.indexOf("@")); - var dominio = email.substring(email.indexOf("@") + 1, email.length); + // const [ currentPoint, setCurrentPoint ] = useState(false); - if ((usuario.length >= 1) && - (dominio.length >= 3) && - (usuario.search("@") == -1) && - (dominio.search("@") == -1) && - (usuario.search(" ") == -1) && - (dominio.search(" ") == -1) && - (dominio.search(".") != -1) && - (dominio.indexOf(".") >= 1) && - (dominio.lastIndexOf(".") < dominio.length - 1)) - { - return true; - } else { - return false; - } - }; + // useEffect(() => { - const clearResult = () => { - lResult.error = ''; - lResult.success = true; + // const getCurrentLocation = async () => { + + // const fetchedLocation = await getLocation(); + // setCurrentPoint(fetchedLocation.currentLocation); + // } + + // getCurrentLocation(); + // }, []); + + // useIonViewWillEnter(() => { + + // getUsersSearching(currentPoint); + // }); + + const [ currentPoint, setCurrentPoint ] = useState({ latitude: 40.8264691, longitude: -73.9549618 }); + + const records = RecordsStore.useState(fetchRecords); + const center = { latitude: 40.8264691, longitude: -73.9549618 }; + + const [ results, setResults ] = useState([]); + const [ zoom, setZoom ] = useState(14); + + const [ moveMode, setMoveMode ] = useState(false); + + // useEffect(() => { + + // const getData = async () => { + + // await getUsersSearching(currentPoint); + // } + + // getData(); + // }, [ currentPoint ]); + + useEffect(() => { + + setResults(records); + }, [ records ]); + + const hideMarkers = () => { + console.log('entrou') + const tempRecords = JSON.parse(JSON.stringify(results)); + tempRecords.forEach((tempRecord:any) => tempRecord.showInfo = false); + console.log(tempRecords) + setResults(tempRecords); + } + + const handleMap = (e:any) => { + console.log(e) + setCurrentPoint({ latitude: e.center[0], longitude: e.center[1] }); + } + + const searchResults = async () => { + await getUsersSearching(currentPoint); } - const fieldValidate = async () => { - clearResult(); - - if(!emailValidate()) { - lResult.error = 'O EMAIL é inválido!'; - lResult.success = false; - return lResult; - } else if(password.length < 7 || password.length > 12) { //TODO: validar de acordo com a documentação - lResult.error = 'A senha deve ter de 7 a 12 caracteres!'; - lResult.success = false; - return lResult; - } - - return lResult; - }; - - const handleSubmit = async () => { - - if(name != '' && email != '' && birthDate != '' && password != '' && confirmPassword != '') { - if(password === confirmPassword){ - const signUpForm = { - name: firstName +' '+ lastName, - email: email, - birth_date: birthDate, - password: password - } - - let result = fieldValidate(); - if((await result).success) { - - let retorno = await UsersService.create(signUpForm); - console.log(retorno); - if(retorno.token) { - // let signIn = await Api.signIn(email, passwordField); - // if(signIn.token) { - // await AsyncStorage.setItem('token', signIn.token); - // await AsyncStorage.setItem('cpf', retorno.cpf); - history.push('home'); - - } else { - setMessageToast(retorno.message); - setShowToast(true); - } - } else{ - setMessageToast(lResult.error); - setShowToast(true); - } - } else { - setMessageToast('As senhas devem ser iguais!'); - setShowToast(true); - } - } else { - setMessageToast('Nenhum campo pode ser nulo!'); - setShowToast(true); - } - }; - - const { name } = useParams<{ name: string; }>(); - return ( - - - - - - - - - - - {/* Como você deseja se cadastrar? */} - BuscarPassageiro - - - {/* - - Continuar com Facebook - - - - Continuar com e-mail - */} - - -
- - Nome - setFirstName(e.target.value)} - // error={isError} - // onIonChange={(e: any) => setFirstName(e.detail.value)} - > - - - - Sobrenome - setLastName(e.target.value)} - > - - -
- - - E-mail - setEmail(e.target.value)} - > - - + {/* { results && + <> */} + handleMap(e)} defaultCenter={ [center.latitude, center.longitude] } defaultZoom={ zoom } provider={ maptilerProvider } touchEvents={ true }> - - Data de nascimento - setBirthDate(e.target.value)} - > - - - - - Senha - setPassword(e.target.value)} - > - - - Confirme a senha - setConfirmPassword(e.target.value)} - > - - - Cadastrar-se -
-
- - Ao se cadastrar, você aceita nossos Termos e Condições e nossa Política de Privacidade. - - -
- {/*
*/} - setShowToast(false)} - message={messageToast} - duration={2500} - /> + { results.map((record:{latitude:any, longitude:any}, index) => { + + return + })} + + { results.map((record:{showInfo:boolean, latitude:any, longitude:any}, index) => { + + if (record.showInfo) { + + return ( + + {/* */} + + ); + } + })} + + + + + + + + {/* */} + {/* } */}
); diff --git a/src/services/users.ts b/src/services/users.ts index e14e17d..ea70d95 100644 --- a/src/services/users.ts +++ b/src/services/users.ts @@ -1,4 +1,5 @@ import instance from '../services/api'; +import { setStore } from "../store/RecordsStore"; // import LocalStorage from '../LocalStorage'; // let token:string; @@ -42,4 +43,14 @@ export async function create(CadastroRequest: any) { const response = await instance.post("http://localhost:3333/users/", CadastroRequest); return response.data; +} + +export async function getUsersSearching(currentPoint: any) { + // Replace lat/long with values from get current location. + // Allow choosing of radius? + // Offset could = amount loaded in an infinite scroll? + var latitude = currentPoint.latitude, longitude = currentPoint.longitude, radius = 5000, offset = 0; + const response = await fetch(`http://localhost:4000/get-records?latitude=${ latitude }&longitude=${ longitude }&radius=${ radius }&offset=${ offset }`); + const data = await response.json(); + setStore(data); } \ No newline at end of file diff --git a/src/store/RecordsStore.js b/src/store/RecordsStore.js new file mode 100644 index 0000000..e6ba71e --- /dev/null +++ b/src/store/RecordsStore.js @@ -0,0 +1,15 @@ +import { Store } from 'pullstate'; + +const RecordsStore = new Store({ + + records: [], + center : [] +}); + +export default RecordsStore; + +export const setStore = records => { + + RecordsStore.update(state => { state.records = records.allRecords }); + RecordsStore.update(state => { state.center = records.center }); +} \ No newline at end of file diff --git a/src/store/Selectors.js b/src/store/Selectors.js new file mode 100644 index 0000000..c83e9f6 --- /dev/null +++ b/src/store/Selectors.js @@ -0,0 +1,15 @@ +import { createSelector } from 'reselect'; + +const getState = state => state; + +// General getters +export const fetchRecords = createSelector(getState, state => state.records); + +// More specific getters +export const fetchRecord = recordId => createSelector(getState, state => { + + return state.records.filter(record => record.id === recordId)[0]; +}); +// export const getPoll = pollId => createSelector(getState, state => state.polls.filter(poll => poll.id === parseInt(pollId))[0]); +// export const getChat = contactId => createSelector(getState, state => state.chats.filter(c => parseInt(c.contact_id) === parseInt(contactId))[0].chats); +// export const getContact = contactId => createSelector(getState, state => state.contacts.filter(c => parseInt(c.id) === parseInt(contactId))[0]);