Skip to content

Commit

Permalink
[#2PlaysAMonth]: Travel app (reactplay#1007)
Browse files Browse the repository at this point in the history
* start

* functions done

* addiation

* cleanup

* fixes

* fix

* video 1

* cover

* marker fix

* video link

* fix

* lint fix

* styles update

* api fix

* lint fix

---------

Co-authored-by: Tapas Adhikary <[email protected]>
Co-authored-by: Sachin Chaurasiya <[email protected]>
  • Loading branch information
3 people authored Mar 7, 2023
1 parent 1564943 commit 528341a
Show file tree
Hide file tree
Showing 11 changed files with 364 additions and 0 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"html2canvas": "^1.4.1",
"json-graphql-parser": "^0.1.8",
"jspdf": "^2.5.1",
"leaflet": "^1.9.3",
"lodash": "^4.17.21",
"mathjs": "^11.5.1",
"node-sass": "^8.0.0",
Expand All @@ -49,6 +50,7 @@
"react-helmet": "^6.1.0",
"react-hot-toast": "^2.3.0",
"react-icons": "^4.3.1",
"react-leaflet": "^4.2.0",
"react-loader-spinner": "~5.1.5",
"react-organizational-chart": "^2.1.1",
"react-p5": "^1.3.33",
Expand Down
27 changes: 27 additions & 0 deletions src/plays/travel-advisor/Readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Travel Advisor

A travel advisor app where we can checkout locations on map by fetching restaurants and hotels

## Play Demographic

- Language: js
- Level: Intermediate

## Creator Information

- User: yung-coder
- Gihub Link: https://github.com/yung-coder
- Blog:
- Video: https://www.stack-stream.com/v/react-play-twoplaysamonth

## Implementation Details

Update your implementation idea and details here

## Consideration

Update all considerations(if any)

## Resources

Update external resources(if any)
71 changes: 71 additions & 0 deletions src/plays/travel-advisor/TravelAdvisor.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import PlayHeader from 'common/playlists/PlayHeader';
import { useEffect, useState } from 'react';
import { getCoordinates, getPlacesData } from './api/travel_api';
import DropDown from './components/DropDown';
import Map from './components/Map';
import Search from './components/Search';
import './styles.css';

// WARNING: Do not change the entry componenet name
function TravelAdvisor(props) {
// Your Code Start below.
const [latitude, setlatitude] = useState('');
const [longitude, setlongitude] = useState('');
const [resdata, setresdata] = useState();
const [inputval, setinputval] = useState('');
const [type, setype] = useState('restaurants');
const [sumbit, setsumbit] = useState(false);

useEffect(() => {
navigator.geolocation.getCurrentPosition(({ coords: { latitude, longitude } }) => {
setlatitude(latitude);
setlongitude(longitude);
});
}, []);

useEffect(() => {
getPlacesData(latitude, longitude, type).then((data) => {
setresdata(data);
});
}, [latitude, longitude, type]);

useEffect(() => {
getCoordinates(inputval).then((data) => {
if (data) {
setlatitude(data[0]?.latitude.toString());
setlongitude(data[0]?.longitude.toString());
}
});
}, [sumbit]);

return (
<>
<div className="play-details">
<PlayHeader play={props} />
<div className="play-details-body">
{/* Your Code Starts Here */}
<div className="travel-advisor-main-Contanier">
<div className="travel-advisor-input-select-cont">
<Search inputval={inputval} setinputval={setinputval} setsumbit={setsumbit} />
<DropDown setype={setype} type={type} />
</div>
<div className="travel-advisor-map-cont">
{resdata && (
<Map
latitude={latitude}
longitude={longitude}
resdata={resdata}
setlatitude={setlatitude}
setlongitude={setlongitude}
/>
)}
</div>
</div>
{/* Your Code Ends Here */}
</div>
</div>
</>
);
}

export default TravelAdvisor;
40 changes: 40 additions & 0 deletions src/plays/travel-advisor/api/travel_api.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import axios from 'axios';

export const getPlacesData = async (latitude, longitude, type) => {
try {
const { data } = await axios.get(
`https://travel-advisor.p.rapidapi.com/${type}/list-by-latlng`,
{
params: {
longitude: longitude,
latitude: latitude
},
headers: {
'X-RapidAPI-Key': '66e17f9775msh52ab94609039378p183539jsned52ecf69948',
'X-RapidAPI-Host': 'travel-advisor.p.rapidapi.com'
}
}
);

return data;
} catch (error) {
return error;
}
};

export const getCoordinates = async (city) => {
try {
const { data } = await axios.get(
`https://api.api-ninjas.com/v1/geocoding?city=${city}&country=india`,
{
headers: {
'X-Api-Key': 'Nqq/eOevhCmgOSmniHar7g==qtlAPLC2d3oWOiY3'
}
}
);

return data;
} catch (error) {
return error;
}
};
18 changes: 18 additions & 0 deletions src/plays/travel-advisor/components/DropDown.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import React from 'react';
import '../styles/dropdown.css';
const DropDown = ({ setype, type }) => {
return (
<div className="travel-advisor-select-cont">
<select
className="travel-advisor-select"
value={type}
onChange={(e) => setype(e.target.value)}
>
<option value="restaurants">Restaurants</option>
<option value="hotels">Hotels</option>
</select>
</div>
);
};

export default DropDown;
67 changes: 67 additions & 0 deletions src/plays/travel-advisor/components/Map.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import React, { useEffect } from 'react';
import { MapContainer, Popup, TileLayer, useMap, Marker } from 'react-leaflet';
import 'leaflet/dist/leaflet.css';
import '../styles.css';

import L from 'leaflet';

const customMarker = new L.icon({
iconUrl: 'https://unpkg.com/[email protected]/dist/images/marker-icon.png',
iconSize: [25, 41],
iconAnchor: [10, 41],
popupAnchor: [2, -40]
});

const Map = ({ latitude, longitude, resdata, setlatitude, setlongitude }) => {
const GetCoordinates = () => {
const map = useMap();

useEffect(() => {
if (!map) return;

map.on('click', (e) => {
setlatitude(e.latlng.lat);
setlongitude(e.latlng.lng);
});
}, [map]);

return null;
};

return (
<div className="travel-advisor-leaflet-cont">
<MapContainer
center={[latitude, longitude]}
scrollWheelZoom={false}
style={{ height: '100%', width: '100%' }}
zoom={13}
>
<TileLayer
attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>

{resdata &&
resdata.data.map((item, i) => {
const position = [
Number(item.latitude ? item.latitude : ''),
Number(item.longitude ? item.longitude : '')
];

return (
<Marker icon={customMarker} key={i} position={position}>
<Popup>
{item.name}
<img src={item.photo ? item.photo.images.medium.url : ''} />
</Popup>
</Marker>
);
})}

<GetCoordinates />
</MapContainer>
</div>
);
};

export default Map;
31 changes: 31 additions & 0 deletions src/plays/travel-advisor/components/Search.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import React from 'react';
import '../styles/search.css';
import { FcSearch } from 'react-icons/fc';

const Search = ({ inputval, setinputval, setsumbit }) => {
const onSumbit = (e) => {
e.preventDefault();
setsumbit(true);
};

return (
<div className="travel-advisor-form__group">
<form action="" className="travel-advisor-form" onSubmit={onSumbit}>
<input
className="travel-advisor-form__input"
id="name"
placeholder="Enter City name"
required=""
type="text"
value={inputval}
onChange={(e) => setinputval(e.target.value)}
/>
<button className="travel-advisor-btn" type="submit">
<FcSearch size={27} />
</button>
</form>
</div>
);
};

export default Search;
Binary file added src/plays/travel-advisor/cover.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
33 changes: 33 additions & 0 deletions src/plays/travel-advisor/styles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/* enter stlyes here */

.travel-advisor-main-Contanier {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
padding: 25px 25px;
background-image: linear-gradient(to left bottom, #051937, #00293c, #023537, #293f34, #44483a);
height: 100%;
}

.travel-advisor-map-cont {
width: 100%;
height: 100%;
border-radius: 12px;
margin-top: 20px;
}

.travel-advisor-input-select-cont {
display: flex;
padding: 40px 40px;
width: 100%;
justify-content: center;
align-items: center;
}

.travel-advisor-leaflet-cont {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
}
41 changes: 41 additions & 0 deletions src/plays/travel-advisor/styles/dropdown.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
.travel-advisor-select {
appearance: none;
outline: 0;
border: 0;
box-shadow: none;
flex: 1;
padding: 0 1em;
color: black;
background-color: white;
background-image: none;
cursor: pointer;
}

.travel-advisor-select::-ms-expand {
display: none;
}

.travel-advisor-select-cont {
position: relative;
display: flex;
width: 20em;
height: 3em;
border-radius: 0.25em;
margin: 12px;
overflow: hidden;
}

.travel-advisor-select-cont::after {
content: '\25BC';
position: absolute;
top: 0;
right: 0;
padding: 1em;
background-color: #34495e;
transition: 0.25s all ease;
pointer-events: none;
}

.travel-advisor-select-cont:hover::after {
color: #f39c12;
}
34 changes: 34 additions & 0 deletions src/plays/travel-advisor/styles/search.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
.travel-advisor-form__label {
font-family: 'Roboto', sans-serif;
font-size: 1.2rem;
margin-left: 2rem;
margin-top: 0.7rem;
display: block;
transition: all 0.3s;
transform: translateY(0rem);
}

.travel-advisor-form__input {
font-family: 'Roboto', sans-serif;
color: #333;
font-size: 1.2rem;
/* margin: 0 auto; */
padding: 1.5rem 2rem;
border-radius: 0.2rem;
background-color: rgb(255, 255, 255);
border: none;
width: 90%;
display: block;
border-bottom: 0.3rem solid transparent;
transition: all 0.3s;
}

.travel-advisor-form{
display: flex;
padding: 15px;
}

.travel-advisor-form button {
padding: 6px;
border-left: 10px;
}

0 comments on commit 528341a

Please sign in to comment.