diff --git a/-1 b/-1 deleted file mode 100644 index e69de29..0000000 diff --git a/package-lock.json b/package-lock.json index 971a0b1..520fafe 100644 --- a/package-lock.json +++ b/package-lock.json @@ -63,6 +63,7 @@ "react-dom": "^17.0.2", "react-leaflet": ">=3.1.0 <3.2.0 || ^3.2.1", "react-leaflet-drift-marker": "^3.0.0", + "react-moment": "^1.1.1", "react-native": "^0.64.1", "react-native-openalpr": "^2.2.0", "react-router": "^5.2.0", @@ -21588,6 +21589,16 @@ "react-leaflet": "3.x" } }, + "node_modules/react-moment": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/react-moment/-/react-moment-1.1.1.tgz", + "integrity": "sha512-WjwvxBSnmLMRcU33do0KixDB+9vP3e84eCse+rd+HNklAMNWyRgZTDEQlay/qK6lcXFPRuEIASJTpEt6pyK7Ww==", + "peerDependencies": { + "moment": "^2.29.0", + "prop-types": "^15.7.0", + "react": "^16.0 || ^17.0.0" + } + }, "node_modules/react-native": { "version": "0.64.2", "resolved": "https://registry.npmjs.org/react-native/-/react-native-0.64.2.tgz", @@ -44406,6 +44417,12 @@ "leaflet-drift-marker": "^2.0.0" } }, + "react-moment": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/react-moment/-/react-moment-1.1.1.tgz", + "integrity": "sha512-WjwvxBSnmLMRcU33do0KixDB+9vP3e84eCse+rd+HNklAMNWyRgZTDEQlay/qK6lcXFPRuEIASJTpEt6pyK7Ww==", + "requires": {} + }, "react-native": { "version": "0.64.2", "resolved": "https://registry.npmjs.org/react-native/-/react-native-0.64.2.tgz", diff --git a/package.json b/package.json index 2f68607..a91d75f 100644 --- a/package.json +++ b/package.json @@ -58,6 +58,7 @@ "react-dom": "^17.0.2", "react-leaflet": ">=3.1.0 <3.2.0 || ^3.2.1", "react-leaflet-drift-marker": "^3.0.0", + "react-moment": "^1.1.1", "react-native": "^0.64.1", "react-native-openalpr": "^2.2.0", "react-router": "^5.2.0", diff --git a/src/pages/AnimalDashboard.css b/src/pages/AnimalDashboard.css index 5fdc101..99b69ff 100644 --- a/src/pages/AnimalDashboard.css +++ b/src/pages/AnimalDashboard.css @@ -10,21 +10,35 @@ } .searchbar-input { - border: 0 !important; + /* border: 0 !important; */ box-shadow: none!important; - width: 800px; + width: 40vw; + max-width: 800px; + min-width: 300px; + text-align: left; + height: 100%; + + text-transform: none; } .calendarIcon { color: black; font-size: 64px; } + + .mapIcon { + color: #D8AB4C; + font-size: 15px; + position: absolute; + } + .animalCard { + color: #FFE162; + + } ion-toolbar.ion-padding { --background: white; - height: 50px; - box-shadow: none !important; - margin-bottom: 20px + padding-bottom: 0px !important; } /* plate selection stuff */ @@ -44,6 +58,9 @@ .reportLostPet { position: relative; width: 300px; + font-size: 20px; + text-transform: none; + color:crimson } .bottomItems { @@ -60,4 +77,33 @@ display: flex !important; align-items: center !important; flex-flow: column; - } \ No newline at end of file + } + + .mapButton { + position: absolute; + top: 8px; + right: 10px; + margin-bottom: 10px; + width: max-content center; + justify-content: flex-end; + display: flex !important; + align-items: center !important; + flex-flow: column; + } +/* + .mapButtonCircle { + background-color: #D8AB4C; + border-radius: 50%; + } */ + + /* .mapContainer { + position: absolute; + top: 0px; + width: 400px; + height: 100%; + z-index: -1; + } */ + + /* .contact-popover .popover-content{ width: 700px; } */ + + \ No newline at end of file diff --git a/src/pages/AnimalDashboard.tsx b/src/pages/AnimalDashboard.tsx index 8f0c25b..209db9a 100644 --- a/src/pages/AnimalDashboard.tsx +++ b/src/pages/AnimalDashboard.tsx @@ -26,32 +26,34 @@ import { IonInfiniteScrollContent, useIonViewWillEnter } from "@ionic/react"; -import React, {useState} from "react"; +import React, { useState, useEffect } from "react"; import "./AnimalDashboard.css"; import TopMenu from './../components/TopMenu'; +import moment from "moment"; /* GraphQL for API Calls */ -import {gql, NetworkStatus, useQuery} from "@apollo/client"; +import { gql, NetworkStatus, useQuery } from "@apollo/client"; // icons -import {cloudUploadOutline, calendar} from "ionicons/icons"; -import {MapContainer, Marker, Popup, TileLayer} from "react-leaflet"; +import { cloudUploadOutline, calendar, paw, locate, map, navigateCircleOutline } from "ionicons/icons"; +import { MapContainer, Marker, Popup, TileLayer } from "react-leaflet"; +import { getByDisplayValue } from "@testing-library/react"; -const AnimalDashboard : React.FC = () => { +const AnimalDashboard: React.FC = () => { const [selectedStartDate, - setSelectedStartDate] = useState < string > ("2021-06-01T13:47:20.789"); + setSelectedStartDate] = useState("2021-06-01T13:47:20.789"); const [selectedEndDate, - setSelectedEndDate] = useState < string > ("2021-06-01T13:47:20.789"); + setSelectedEndDate] = useState("2021-06-01T13:47:20.789"); // for USER input on dropdown menus const [pastTime, - setPastTime] = useState < string > (""); + setPastTime] = useState(""); // for the date and time selection const [advancedDate, - setAdvancedDate] = useState < boolean > (false); + setAdvancedDate] = useState(false); const [type, - setType] = useState < string > (""); + setType] = useState(""); const [present] = useIonPicker(); const [value, @@ -155,7 +157,7 @@ const AnimalDashboard : React.FC = () => { console.log(quickTimePicker); } - const ANIMAL_POST_QUERY = gql ` + const ANIMAL_POST_QUERY = gql` query Animals { animals { _id @@ -174,42 +176,60 @@ const AnimalDashboard : React.FC = () => { } `; - const {loading, data, error, refetch, networkStatus} = useQuery(ANIMAL_POST_QUERY, { + + const { loading, data, error, refetch, networkStatus } = useQuery(ANIMAL_POST_QUERY, { fetchPolicy: "no-cache", notifyOnNetworkStatusChange: true }); - if (networkStatus == NetworkStatus.refetch) + const [search, setSearch] = useState(data); + + useEffect(() => { + if(!error && !loading) { + setSearch(data); + } +}, [data, error, loading]); + + if (networkStatus == NetworkStatus.refetch) console.log("refetching!"); - if (loading) + if (loading) console.log("loading"); - if (error) + if (error) console.log("error: " + error.networkError); - + // for the map const [animalLat, - setAnimalLat] = useState < number > (0); + setAnimalLat] = useState(0); const [animalLon, - setAnimalLon] = useState < number > (0); + setAnimalLon] = useState(0); - const animalOnMap = (latitude : number, longitude : number) => { + const animalOnMap = (latitude: number, longitude: number) => { setAnimalLat(latitude); setAnimalLon(longitude); console.log(animalLat, ", ", animalLon); }; - + const [openMap, setOpenMap] = useState(false); // for number of animals being shown const [numCard, - setNumCard] = useState (data - ?.animals + setNumCard] = useState(data + ?.animals ?.length); // for getting live geolocation interface LocationError { - showError : boolean; + showError: boolean; message?: string; } + const onSearchChange= (e: any) => { + const value = e.target.value.toLowerCase(); + var temp = data.animals; + var result = temp.filter(function(animal: { breed: string; type: string; color: string; }) { + return animal.breed.toLowerCase().includes(value) || animal.type.toLowerCase().includes(value) || animal.color.toLowerCase().includes(value); + }) + setSearch({animals: result}); + }; + //TODO: Animal Dashboard Title needs to be centered //TODO: prepare collection of data for infinite scroll // can create a dictionary for the animal data @@ -217,25 +237,27 @@ const AnimalDashboard : React.FC = () => { // type User = typeof initUser; // const initUser = {name: 'Jon'} //... - // const [user, setUser] = useState(initUser); + // const [user, setUser] = useState(initUser); + + + // TODO: implement the search functin + // TODO: get the date picker to function + // TODO: screen size fitting using css and adjust colors a bit + // TODO: dark mode + // TODO: create data structure to store the animal card information + // TODO: clean up the code + // TODO: apply changes to the other web pages - // TODO: implement the search functin - // TODO: get the date picker to function - // TODO: screen size fitting using css and adjust colors a bit - // TODO: dark mode - // TODO: create data structure to store the animal card information - // TODO: clean up the code - // TODO: apply changes to the other web pages - + + // cardData and isInifiniteDisabled pertain to the infinite scroll + // a dictionary needs to be setup for storing the animal data attributes to push onto the data set + - // cardData and isInifiniteDisabled pertain to the infinite scroll - // a dictionary needs to be setup for storing the animal data attributes to push onto the data set - const [cardData, - setData] = useState < string[] > ([]); + setData] = useState([]); const [isInfiniteDisabled, setInfiniteDisabled] = useState(false); @@ -252,7 +274,7 @@ const AnimalDashboard : React.FC = () => { ...newData ]); } - const loadData = (animal : any) => { + const loadData = (animal: any) => { setTimeout(() => { pushData(); console.log('Loaded data'); @@ -269,8 +291,8 @@ const AnimalDashboard : React.FC = () => { return ( - - + + {/* generalized date string formats! */} {/* { @@ -303,105 +325,91 @@ const AnimalDashboard : React.FC = () => { {/* */} {/* Animal Dashboard */} - {animalLat != 0 && animalLon != 0 && ( - - - - Animal Location - - - )} - - -
- - - - - - - - - -
Report Lost Pet
-
- - present([ - { - - name: 'number', - options: [ + + + + + + + + + + + + Report Lost Pet + + + + + + present([ { - text: 'One', - value: 1 - }, { - text: 'Two', - value: 2, + + name: 'number', + options: [ + { + text: 'One', + value: 1 + }, { + text: 'Two', + value: 2, + }, { + text: 'Three', + value: 3 + }, + { + text: 'Four', + value: 4 + } + ] }, { - text: 'Three', - value: 3 - }, - { - text: 'Four', - value: 4 + name: 'time', + options: [ + { + text: 'Day(s)', + value: 'day' + }, { + text: 'Week(s)', + value: 'week' + }, { + text: 'Month(s)', + value: 'month' + }, + { + text: 'Year(s)', + value: 'year' + + } + + ] } - ] - }, { - name: 'time', - options: [ - { - text: 'Day(s)', - value: 'day' - }, { - text: 'Week(s)', - value: 'week' - }, { - text: 'Month(s)', - value: 'month' - }, + ], [ { - text: 'Year(s)', - value: 'year' - + text: 'Confirm', + handler: (selected) => { + setValue(`${selected.number.value}, ${selected.time.value}`) + } } - - ] - } - ], [ - { - text: 'Confirm', - handler: (selected) => { - setValue(`${selected.number.value}, ${selected.time.value}`) - } - } - ])}> - - - - - - - {/* {advancedDate && ( + ])}> + + + + +
+ + {/* {advancedDate && (
@@ -443,59 +451,90 @@ const AnimalDashboard : React.FC = () => {
)} */} - + + + + - - - - - One item - {!loading && data - ?.animals + + {!loading && search + ?.animals ?.slice(0, numCard) - .reverse() - .map((animal : any) => ( -
- - {type.length === 0 && ( - - animalOnMap(animal.location.lat, animal.location.lon)}> - {animal.files !== undefined && animal.files.length !== 0 && ( - // eslint-disable-next-line jsx-a11y/alt-text - ( + +
+ + {type.length === 0 && ( + + + {animal.files !== undefined && animal.files.length !== 0 && ( + // eslint-disable-next-line jsx-a11y/alt-text + - )} - - Animal Information -
Type: {animal.type}
-
Breed: {animal.breed}
-
Color: {animal.color}
-
Location: {animal.neighborhood}
-
- Date:{" "} {new Date(animal.createdAt) - .toString() - .substr(0, new Date(animal.createdAt).toString().indexOf("GMT")) + "(CDT)"}{" "} -
-
-
-
- )} -
- ))} + src={"https://nsf-scc1.isis.vanderbilt.edu/file/animal/" + animal._id + "/" + animal.files[0] + } > + )} + + +
Animal: {animal.color} {" "} {animal.breed}`
+ +
Location: {animal.neighborhood} + { + setOpenMap(true); + animalOnMap(animal.location.lat, animal.location.lon)}} + + > + +
+ +
+ Time Reported:{" "} {moment(new Date(animal.createdAt) + .toString() + .substr(0, new Date(animal.createdAt).toString().indexOf("GMT"))).format("ddd MMM YYYY h:mm:ss a") + " (CDT)"}{" "} + +
+
+
+
+ )} + +
+ ))}
+ + setOpenMap(false)} > +{/*
+Hello +
*/} + {animalLat !== 0 && animalLon !== 0 && ( + + + + Animal Location: + + + )} + +
- { ); - - + + }; export default AnimalDashboard diff --git a/src/theme/variables.css b/src/theme/variables.css index 3e64827..6bff0d0 100644 --- a/src/theme/variables.css +++ b/src/theme/variables.css @@ -278,4 +278,15 @@ ion-toast::part(button) { --padding-start: 0; --padding-end: 0; --min-height: 56px; -} \ No newline at end of file +} + +.popover-content { + --width: 800px; +} + +/* @media screen and (max-width: 768px) { + .popover-content { + --width: 100%; + } +} */ + \ No newline at end of file diff --git a/{ b/{ deleted file mode 100644 index e69de29..0000000