Skip to content

Commit

Permalink
Merge branch 'dev'
Browse files Browse the repository at this point in the history
  • Loading branch information
ivozilkenat committed Apr 6, 2024
2 parents e6bc1ab + bfad472 commit 9117cf8
Show file tree
Hide file tree
Showing 18 changed files with 474 additions and 165 deletions.
6 changes: 4 additions & 2 deletions client/src/App.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import React from "react";
import "./App.css"
import MapComponent from './components/RealtimeMap';
import HeaderBanner from "./components/HeaderBanner";
import Banner from "./components/Banner";
import InputBox from "./components/inputBox";

function App() {

return (
<div className="App">
<main><HeaderBanner /></main>
<Banner />
<InputBox />
<MapComponent />
</div>
);
Expand Down
28 changes: 28 additions & 0 deletions client/src/components/ApiCall.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
export function fetchCurrentData(map, route) {
const bounds = map.getBounds();
const upperLeft = bounds.getNorthWest();
const lowerRight = bounds.getSouthEast();
const hostname = window.location.hostname;
const protocol = window.location.protocol;
const port = hostname === "localhost" ? "3001" : "443";

return fetch(`${protocol}//${hostname}:${port}/api/${route}/`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
"bounds": {
"upper-left": {
"lat": upperLeft.lat,
"lon": upperLeft.lng
},
"lower-right": {
"lat": lowerRight.lat,
"lon": lowerRight.lng
}
}
})
})
.then(response => response.json());
}
21 changes: 21 additions & 0 deletions client/src/components/Banner.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import React, { useEffect, useRef } from "react";
import "./css/Banner.css";

function Banner() {
return (
<div className="navbar">
<div className="brand">Wischen & Mischen</div>
<div className="spacer"></div> {/* This will take up the unused space */}
<div className="nav-items">
<div className="nav-item"><a href="https://www.youtube.com/watch?v=xvFZjo5PgG0" target="_blank">Home</a></div>
<div className="nav-item"><a href="https://www.youtube.com/watch?v=xvFZjo5PgG0" target="_blank">Data Solutions</a></div>
<div className="nav-item"><a href="https://www.youtube.com/watch?v=xvFZjo5PgG0" target="_blank">About</a></div>
<div className="nav-item"><a href="https://www.youtube.com/watch?v=xvFZjo5PgG0" target="_blank">Contact</a></div>
{/* Add more nav items as needed */}
</div>
</div>

);
}

export default Banner;
146 changes: 46 additions & 100 deletions client/src/components/RealtimeMap.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,149 +2,95 @@ import React, { useState, useEffect } from "react";
import L from 'leaflet';
import './../../node_modules/leaflet/dist/leaflet.css'
import './css/RealtimeMap.css';
import './css/Vehicle.css';
import 'leaflet-realtime';
import Vehicle from './Vehicle.js';
import { Marker } from 'react-leaflet';
import { Marker, Circle } from 'react-leaflet';
import { Popup } from 'react-leaflet';
import { MapContainer, TileLayer, useMap } from 'react-leaflet';
import busIconUrl from '../resources/bus_icon.png';
import trainIconUrl from '../resources/train_icon.png';
import tramIconUrl from '../resources/tram_icon.png';
import subwayIconUrl from '../resources/subway_icon.png';
import ferryIconUrl from '../resources/ferry_icon.png';
import expressIconUrl from '../resources/express_icon.png';
import suburbanIconUrl from '../resources/suburban_icon.png';
import VehicleIcons from './VehicleIcons';
import { fetchCurrentData } from './ApiCall';
import { getIcon, getColor } from './VehicleIcons';

const busIcon = L.icon({
iconUrl: busIconUrl,
iconSize: [40, 40],
});

const trainIcon = L.icon({
iconUrl: trainIconUrl,
iconSize: [25, 41],
});

const tramIcon = L.icon({
iconUrl: tramIconUrl,
iconSize: [25, 41],
});

const subwayIcon = L.icon({
iconUrl: subwayIconUrl,
iconSize: [25, 41],
});

const ferryIcon = L.icon({
iconUrl: suburbanIconUrl,
iconSize: [25, 41],
});

const expressIcon = L.icon({
iconUrl: expressIconUrl,
iconSize: [25, 41],
});

const suburbanIcon = L.icon({
iconUrl: ferryIconUrl,
iconSize: [25, 41],
});
function capitalizeFirstLetter(string) {
return string.charAt(0).toUpperCase() + string.slice(1);
}

function RealtimeMap() {
const map = useMap();
const [data, setData] = useState([]);
const [stations, setStations] = useState([]);

useEffect(() => {
const interval = setInterval(() => {
const bounds = map.getBounds();
const upperLeft = bounds.getNorthWest();
const lowerRight = bounds.getSouthEast();
const hostname = window.location.hostname;
const protocol = window.location.protocol;
const port = hostname === "localhost" ? "3001" : "443";
fetch(`${protocol}//${hostname}:${port}/api/trips/`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
"bounds": {
"upper-left": {
"lat": upperLeft.lat,
"lon": upperLeft.lng
},
"lower-right": {
"lat": lowerRight.lat,
"lon": lowerRight.lng
}
}
})
})
.then(response => response.json())
fetchCurrentData(map, 'trips')
.then(data => {
setData(data);
});
}, 1000);

return () => clearInterval(interval);
}, []);
return () => clearInterval(interval);
}, []);

return Object.values(data).map(item => {
useEffect(() => {
fetchCurrentData(map, 'stations')
.then(data => {
setStations(data);
});
}, []);

const tripMarkers = Object.values(data).map(item => {
let icon;
let colorClass;
if (item.utilization.rel < 0.3) {
if (item.utilization.rel == null) {
colorClass = 'gray-icon';
} else if (item.utilization.rel < 0.3) {
colorClass = 'green-icon';
} else if (item.utilization.rel >= 0.3 && item.utilization.rel <= 0.7) {
colorClass = 'yellow-icon';
} else {
colorClass = 'red-icon';
}

switch (item.subtype) {
case "suburban":
icon = suburbanIcon;
break;
case "subway":
icon = subwayIcon;
break;
case "tram":
icon = tramIcon;
break;
case "bus":
icon = busIcon;
break;
case "ferry":
icon = ferryIcon;
break;
case "express":
icon = expressIcon;
break;
case "regional":
icon = trainIcon;
break;
default:
icon = busIcon;
break;
}
icon = getIcon(item.subType);

icon.options.className = colorClass;
icon.options.className = `${colorClass} vehicle-icon`;

return (
<Marker position={[item.position.lat, item.position.lon]} icon={icon}>
<Popup>
<p>
Type: {capitalizeFirstLetter(item.type)} <br/>
Line: {item.line} | Direction: {item.direction} <br/>
<br/>
Absolute Utilization: {item.utilization.abs} <br/>
Relative Utilization: {item.utilization.rel}
</p>
</Popup>
</Marker>
);
});

const stationMarkers = Object.values(stations).map(item => {
let color = getColor(item.products);
return (
<Circle center={[item.position.lat, item.position.lon]} radius={25} color={color}>
<Popup>
<h1>{item.name}</h1>
<p>
Absolute Utilization: {item.utilization.abs} <br/>
Relative Utilization: {item.utilization.rel}
</p>
</Popup>
</Circle>
);
});

return [...tripMarkers, ...stationMarkers];
}

function MapComponent() {
return (
<MapContainer center={[52.3906, 13.0645]} zoom={13} className="map">
<MapContainer center={[52.3906, 13.0645]} zoom={13} zoomControl={false} className="map">
<TileLayer url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" />
<RealtimeMap />
</MapContainer>
Expand Down
15 changes: 0 additions & 15 deletions client/src/components/Vehicle.js

This file was deleted.

81 changes: 81 additions & 0 deletions client/src/components/VehicleIcons.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import L from 'leaflet';
import busIconUrl from '../resources/bus_icon.png';
import trainIconUrl from '../resources/train_icon.png';
import tramIconUrl from '../resources/tram_icon.png';
import subwayIconUrl from '../resources/subway_icon.png';
import ferryIconUrl from '../resources/ferry_icon.png';
import expressIconUrl from '../resources/express_icon.png';
import suburbanIconUrl from '../resources/suburban_icon.png';

const busIcon = L.icon({
iconUrl: busIconUrl,
iconSize: [40, 40],
});

const trainIcon = L.icon({
iconUrl: trainIconUrl,
iconSize: [25, 25],
});

const tramIcon = L.icon({
iconUrl: tramIconUrl,
iconSize: [40, 40],
});

const subwayIcon = L.icon({
iconUrl: subwayIconUrl,
iconSize: [40, 40],
});

const ferryIcon = L.icon({
iconUrl: ferryIconUrl,
iconSize: [40, 40],
});

const expressIcon = L.icon({
iconUrl: expressIconUrl,
iconSize: [40, 40],
});

const suburbanIcon = L.icon({
iconUrl: suburbanIconUrl,
iconSize: [32, 32],
});


export function getIcon(subtype) {
switch (subtype) {
case "suburban":
return suburbanIcon;
case "subway":
return subwayIcon;
case "tram":
return tramIcon;
case "bus":
return busIcon;
case "ferry":
return ferryIcon;
case "express":
return expressIcon;
case "regional":
return trainIcon;
default:
return busIcon;
}
}

export function getColor(products) {
if (products.suburban) {
return "green";
} else if (products.subway) {
return "red";
} else if (products.tram) {
return "blue";
} else if (products.bus) {
return "yellow";
} else if (products.ferry) {
return "purple";
} else {
return "black";
}
}
Loading

0 comments on commit 9117cf8

Please sign in to comment.