Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: Create the route detail page #83

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
3 changes: 2 additions & 1 deletion src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import about from './pages/about';
import favorite from './pages/favorite';
import history from './pages/history';
import { AuthProvider } from './providers/AuthProvider';
import route from './pages/route';

function App() {
return (
Expand All @@ -17,7 +18,6 @@ function App() {
<Switch>
{/* <Route path="/signin" component={Modal} />
<Route path="/signup" component={Modal} /> */}
<Route path="/route/:id" render={() => <div />} />
<Route path="/bus/:id" render={() => <div />} />
<Route
path="/form/:location/to/:location"
Expand All @@ -26,6 +26,7 @@ function App() {
<Route path="/about" component={about} />
<Route exact path="/me" render={() => <div />} />
<Route path="/me/history" component={history} />
<Route path="/route/:id" component={route} />
<Route path="/me/favorite" component={favorite} />
<Route path="/routes" component={routes} />
<Route exact path="/" component={home} />
Expand Down
29 changes: 15 additions & 14 deletions src/components/BusInfoContainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,22 @@ import BusInformations from './BusInformations';
import VerticalLineDivide from './VerticalLineDivide';
import PropTypes from 'prop-types';

export default function BusInfoContainer({ dontShowTakeIt, fillHeart }) {
const way = [
{ id: 0, isStart: true, name: '32 peak' },
{ id: 1, name: 'Italian Village' },
{ id: 2, name: 'Park View' },
{ id: 3, name: 'Naz Naz' },
{ id: 4, name: 'Empire' },
{ id: 5, name: 'Ankawa', isEnd: true },
];

export default function BusInfoContainer({
route = {},
dontShowTakeIt,
fillHeart,
}) {
const { way = [], bus = { working_hours: ' ', working_days: [] } } = route;
const time = bus.working_hours[0]
.split('-')
.map((time) => time.substr(0, 2) + ':' + time.substr(2))
.join(' - ');
return (
<div className="w-full">
<div className="mt-4 p-2 w-full bg-gray-300 rounded-md flex justify-between">
<div className="pl-12">
<strong className="text-xl text-primary">
Bus No. (473824 EBL - IRQ)
Bus No. ({bus.plate_number} EBL - IRQ)
</strong>
</div>
<div className="pr-10">
Expand Down Expand Up @@ -56,7 +56,7 @@ export default function BusInfoContainer({ dontShowTakeIt, fillHeart }) {
<div className="w-24">
<img alt="bus icon" src={BusIcon} />
</div>
<div className="text-gray-700 pl-2 pt-2">6:22 PM - 7:09 PM</div>
<div className="text-gray-700 pl-2 pt-2">{time}</div>
<div className="flex justify-center my-2">
<div className="w-6">
<img alt="Wifi available" src={WifiIcon} />
Expand All @@ -71,12 +71,12 @@ export default function BusInfoContainer({ dontShowTakeIt, fillHeart }) {
</div>
<VerticalLineDivide />
<div className="flex flex-col ml-2">
<BusInformations />
<BusInformations time={time} />
</div>
<VerticalLineDivide />
<div className="flex flex-col ml-2">
<div className="text-gray-700 pl-1 pt-6">
<h2>Work days: Saturday - Thusday</h2>
<h2>Work days: {bus.working_days.join(', ')}.</h2>
</div>
</div>
{!dontShowTakeIt && (
Expand All @@ -95,6 +95,7 @@ export default function BusInfoContainer({ dontShowTakeIt, fillHeart }) {
);
}
BusInfoContainer.propTypes = {
route: PropTypes.node,
dontShowTakeIt: PropTypes.bool.isRequired,
fillHeart: PropTypes.bool.isRequired,
};
9 changes: 7 additions & 2 deletions src/components/BusInformations.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';

export default function BusInformations() {
export default function BusInformations({ time }) {
return (
<div className="mr-8">
<div className="text-gray-700 pl-1">
Expand All @@ -10,8 +11,12 @@ export default function BusInformations() {
<h2>Date: 23/07/2020</h2>
</div>
<div className="text-gray-700 pl-1">
<h2>Work time: 9:00 Am - 9:00 PM</h2>
<h2>Work time: {time}</h2>
</div>
</div>
);
}

BusInformations.propTypes = {
time: PropTypes.string,
};
169 changes: 166 additions & 3 deletions src/pages/route.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,167 @@
import React from 'react';
export default function route() {
return <div>@todo return route details page</div>;
import React, { useState, useRef, useEffect } from 'react';
import ReactMapGL, { Source, Layer } from 'react-map-gl';
import BusInfoContainer from '../components/BusInfoContainer';
import { useParams } from 'react-router-dom';
import { routesRef, bussesRef } from '../api/firebase';
import pointMark from '../assets/point-marker.png';
import destMark from '../assets/destination-marker.png';

export default function Routedetails() {
const { id } = useParams();
const [viewport, setViewport] = useState({
latitude: 36.206291,
longitude: 44.008869,
width: '100%',
height: '250px',
zoom: 11,
});

const [route, setRoute] = useState();

useEffect(() => {
getRoute(id).then((route) => {
if (route) {
_mapRef.current
.getMap()
.fitBounds([
route.path.features[1].geometry.coordinates,
route.path.features[2].geometry.coordinates,
]);
setRoute(route);
}
});
}, [id]);

const _mapRef = useRef();

useEffect(() => {
// Load all markers and images
const map = _mapRef.current.getMap();
if (map) {
map.loadImage(pointMark, (error, image) => {
if (error) throw error;
if (!map.hasImage('pointMark')) map.addImage('pointMark', image);
});

map.loadImage(destMark, (error, image) => {
if (error) throw error;
if (!map.hasImage('destMark')) map.addImage('destMark', image);
});
}
}, [_mapRef]);

return (
<div className="h-full flex flex-col">
<ReactMapGL
className="flex-grow"
{...viewport}
ref={_mapRef}
mapboxApiAccessToken={process.env.REACT_APP_MAPBOX_TOKEN}
onViewportChange={(viewport) => {
setViewport({ ...viewport, width: '100%', height: '250px' });
}}
mapStyle="mapbox://styles/shna/ckd4x2xmy02kh1ir3hihcr36m"
>
{/* {route && (
<Source id="destinations" type="geojson" data={destinations}>
<Layer
type="symbol"
minzoom={10}
layout={{
'icon-image': 'pointMark',
'icon-size': 1 / 4,
'icon-offset': [5, 0],
}}
/>
</Source>
)} */}

{/* Show Route */}

{route && (
<Source id="polylineLayer" type="geojson" data={route.path}>
<Layer
minzoom={9.8}
id="lineLayer"
type="line"
source="my-data"
layout={{
'line-join': 'round',
'line-cap': 'round',
}}
paint={{
'line-color': '#36AF47',
'line-width': 8,
}}
filter={['==', '$type', 'LineString']}
/>
<Layer
type="symbol"
minzoom={10}
layout={{
'icon-image': 'pointMark',
'icon-size': 1 / 4,
'icon-offset': [5, 0],
}}
filter={['==', 'type', 'start']}
/>

<Layer
type="symbol"
minzoom={10}
layout={{
'icon-image': 'destMark',
'icon-size': 1 / 2,
'icon-offset': [-5, -30],
}}
filter={['==', 'type', 'end']}
/>
</Source>
)}
</ReactMapGL>
{route && (
<div className="flex-grow-0 mx-auto shadow-xl mb-2">
<BusInfoContainer route={route}></BusInfoContainer>
</div>
)}
</div>
);
}

async function getRoute(id) {
if (window.isJest) return null;
const document = await routesRef.doc(id).get();
const route = document.data();
const path = JSON.parse(route.path);
const coordinates = path.geometry.coordinates;
const start = {
type: 'Feature',
properties: { type: 'start' },
geometry: {
type: 'Point',
coordinates: coordinates[0],
},
};
const end = {
type: 'Feature',
properties: { type: 'end' },
geometry: {
type: 'Point',
coordinates: coordinates[coordinates.length - 1],
},
};
route.path = {
type: 'FeatureCollection',
features: [path, start, end],
};

route.buses = [];

const busesDocs = await bussesRef.where('route_id', '==', id).get();

busesDocs.forEach((doc) => {
route.buses.push({ id: doc.id, ...doc.data() });
});

return route;
}