import React, { useState, useEffect } from "react"; import { useParams } from "react-router-dom"; import gql from "graphql-tag"; import { useLazyQuery, useQuery } from "@apollo/react-hooks"; import styled from "styled-components"; import ZipSearchBar from "../molecules/ZipSearchBar"; import walkingImage from "../images/walking_graphic.svg"; import LocationCard from "../molecules/LocationCard"; import Spinner from "../atoms/Spinner"; import { withTheme } from "styled-components"; export const GET_LOCATIONS = gql` query getLocations($material_id: Int, $latitude: Float!, $longitude: Float!) { locations( latitude: $latitude longitude: $longitude material_id: $material_id ) { description address full_address hours phone url } } `; export const GET_POSTAL = gql` query getPostal($postal_code: String!) { postal_code(postal_code: $postal_code, country: "US") { postal_code longitude latitude } } `; export const GET_ZIP = gql` query getZip($latitude: String!, $longitude: String!) { getZip(latitude: $latitude, longitude: $longitude) { postal_code } } `; export const GET_GPS = gql` query coordinates { GPS { latitude longitude } } `; const Container = styled.div` display: flex; flex-direction: column; justify-content: center; align-items: center; `; const Blurb = styled.h2` font-family: Muli; font-style: normal; font-weight: bold; font-size: 26px; text-align: center; margin: 0; margin-top: 10vh; pading: 0; color: ${({ theme }) => theme.text}; `; const CardsContainer = styled.div` margin: 0; margin-bottom: 70px; `; const Img = styled.img` // margin-top: 108px; margin-bottom: 150px; margin-top: ${props => props.marginBottom}px; `; const NoResults = styled.h3` font-family: Muli; font-style: normal; font-weight: bold; font-size: 18px; line-height: 23px; text-align: center; margin: 0; color: ${({ theme }) => theme.resultsText}; `; const NoResultsP = styled.p` font-family: Muli; font-style: normal; font-size: 18px; line-height: 23px; text-align: center; margin: 0; margin-bottom: 51px; color: ${({ theme }) => theme.resultsText}; `; function validateZip(zip) { return /^\d{5}$/.test(zip); } function renderLocations(locations, loaded, theme) { return locations.length > 0 ? ( <CardsContainer> {locations.map((loc, key) => ( <LocationCard title={loc.description} address={loc.full_address} hours={loc.hours} phone={loc.phone} key={key} /> ))} </CardsContainer> ) : ( <div> {loaded ? ( <div> <NoResults>Sorry</NoResults> <NoResultsP>There are no results in your area</NoResultsP> </div> ) : ( "" )} <Img src={loaded ? theme.sadManImg : walkingImage} marginTop={loaded ? "51" : "108"} /> </div> ); } const LocationsPage = ({ theme }) => { const { materialId } = useParams(); const [zip, setZip] = useState(""); const [loading, setLoading] = useState(false); const [locations, setLocations] = useState([]); const gps = JSON.parse(localStorage.getItem("gps")); const [getLocations, locationInfo] = useLazyQuery(GET_LOCATIONS); const [getPostal, postalInfo] = useLazyQuery(GET_POSTAL); const [getZip, zipInfo] = useLazyQuery(GET_ZIP); useEffect(() => { if (gps) { const { latitude, longitude } = gps; //Set zip code field to contain current users zip code location getZip({ variables: { latitude: latitude.toString(), longitude: longitude.toString() } }); //Search for nearby centers automatically setLoading(true); getLocations({ variables: { latitude, longitude, material_id: parseInt(materialId) } }); } }, [location]); useEffect(() => { if (zipInfo.called && zipInfo.data) { setZip(zipInfo.data.getZip.postal_code.slice(0, 5)); } }, [zipInfo]); useEffect(() => { if (postalInfo.called && postalInfo.data) { const { longitude, latitude } = postalInfo.data.postal_code; getLocations({ variables: { latitude, longitude, material_id: parseInt(materialId) } }); } //invalid postal_codes still return objects but nothing that is resolved by our backend if ( !postalInfo.loading && postalInfo.postal_code !== 0 && !locationInfo.loading && locationInfo.called ) { setLoading(false); } }, [postalInfo]); useEffect(() => { if (locationInfo.called && locationInfo.data && !locationInfo.loading) { setLocations(locationInfo.data.locations); setLoading(false); } }, [locationInfo.loading, locationInfo.called, locationInfo.data]); const handleClick = () => { if ( postalInfo.variables && postalInfo.variables.postal_code && postalInfo.variables.postal_code === zip ) { return; } if (validateZip(zip)) { setLoading(true); console.log("Searching for ", zip); getPostal({ variables: { postal_code: zip } }); } else alert("Please enter a valid 5-digit US zip code"); }; const handleKeyDown = e => { if (e.key === "Enter") if (zip.length >= 5) handleClick(); }; return ( <Container> <Blurb>Where can I bring this?</Blurb> <ZipSearchBar handleClick={handleClick} value={zip} onChange={e => setZip(e.target.value)} btnDisabled={zip.length < 5 || loading} onKeyDown={handleKeyDown} /> {loading ? ( <Spinner /> ) : ( renderLocations(locations, locationInfo.called, theme) )} </Container> ); }; export default withTheme(LocationsPage);