diff --git a/client/src/App.js b/client/src/App.js index 54c93e2..afca576 100644 --- a/client/src/App.js +++ b/client/src/App.js @@ -1,11 +1,19 @@ -import {useState} from "react" +import {useRef, useState} from "react" import {Icon} from 'leaflet' import {Polyline, MapContainer, Marker, TileLayer} from 'react-leaflet' import './App.css'; -function Map({dep, arr}) { + +function distance(apt1, apt2) { + const [lat1, lng1] = [Math.PI * apt1.lat / 180, Math.PI * apt1.lng / 180] + const [lat2, lng2] = [Math.PI * apt2.lat / 180, Math.PI * apt2.lng / 180] + const a = Math.sin((lat2 - lat1) / 2) ** 2 + Math.cos(lat1) * Math.cos(lat2) * Math.sin((lng2 - lng1) / 2) ** 2 + return (6371 * 2 * Math.atan(Math.sqrt(a) / Math.sqrt(1 - a))).toFixed(0) +} + +function Map({mapRef, dep, arr}) { const redIcon = new Icon({ iconUrl: "https://raw.githubusercontent.com/pointhi/leaflet-color-markers/master/img/marker-icon-red.png", iconSize: [25, 41], @@ -20,50 +28,84 @@ function Map({dep, arr}) { popupAnchor: [1, -34], shadowSize: [41, 41] }) + + let depCoords = [dep.lat, dep.lng] + let arrCoords = [arr.lat, arr.lng] + return ( - + - - - + + + ) } -function AirportSearch({name, updateFun}) { +function AirportSearch({name, type, updateFun, dep, arr, updateFlights, mapRef}) { const [airports, setAirports] = useState([]) function autocomplete(event) { const target = event.target const value = target.value - fetch(`/api/airports?search=${value}`).then(resp => resp.json()).then(setAirports) + fetch(`/api/airports?search=${value}&limit=10`).then(resp => resp.json()).then(airports => { + setAirports(airports) + if (airports.length === 1) + selectAirport(airports[0]) + }) + } + + function selectAirport(airport) { + updateFun(airport) + if (type === 'dep') + dep = airport + else + arr = airport + + if (dep.icao_code && arr.icao_code) + fetch(`/api/flights/${dep.icao_code}/${arr.icao_code}`).then(resp => resp.json()).then(updateFlights) + mapRef.current.flyToBounds([[dep.lat, dep.lng], [arr.lat, arr.lng]]) } return <> {airports.map(airport => <> - + data-lng={airport.lng}>{airport.name} )} - + } +function FlightsTable({dep, arr, flights}) { + return
+

{dep.name} --> {arr.name} ({distance(dep, arr)} km)

+ +
+} + function App() { - const [dep, setDep] = useState([0, 0]) - const [arr, setArr] = useState([0, 0]) + const [dep, setDep] = useState({lat: 0, lng: 0}) + const [arr, setArr] = useState({lat: 0, lng: 0}) + const [flights, setFlights] = useState([]) + const mapRef = useRef(null) return <> - - - + + + + } diff --git a/server/index.js b/server/index.js index b4a53c9..2efa50d 100644 --- a/server/index.js +++ b/server/index.js @@ -20,15 +20,30 @@ app.get("/api", (req, res) => { app.get("/api/airports", (req, res) => { const search = req.query.search.toLowerCase() - let where = {} + let options = {} + if (search) { let or_array = [] for (let col_name of ['name', 'icao_code', 'iata_code']) or_array.push(db.sequelize.where(db.sequelize.fn('lower', db.sequelize.col(col_name)), {[db.Sequelize.Op.like]: `%${search}%`})) - where = {[db.Sequelize.Op.or]: or_array} + options.where = {[db.Sequelize.Op.or]: or_array} } - Airport.findAll({where: where}).then(airports => res.json(airports)) + + options.limit = 10 + if (req.query.limit) { + const limit = parseInt(req.query.limit) + if (limit >= 1) + options.limit = limit + } + + if (req.query.page) { + const page = parseInt(req.query.page) + if (page > 1) + options.offset = (page - 1) * options.limit + } + + Airport.findAll(options).then(airports => res.json(airports)) }) app.get("/api/airport/:icao_code", (req, res) => { @@ -43,7 +58,7 @@ app.get("/api/airport/:icao_code", (req, res) => { app.get("/api/flights/:dep_icao", (req, res) => { const dep_icao = req.params.dep_icao - Flight.findAll({where: {dep_icao: dep_icao}}).then(data => { + Flight.findAll({order: [['dep_time_utc']], where: {dep_icao: dep_icao}}).then(data => { if (data) res.json(data) else @@ -54,7 +69,7 @@ app.get("/api/flights/:dep_icao", (req, res) => { app.get("/api/flights/:dep_icao/:arr_icao", (req, res) => { const dep_icao = req.params.dep_icao const arr_icao = req.params.arr_icao - Flight.findAll({where: {dep_icao: dep_icao, arr_icao: arr_icao}}).then(data => { + Flight.findAll({order: [['dep_time_utc']], where: {dep_icao: dep_icao, arr_icao: arr_icao}}).then(data => { if (data) res.json(data) else