import React, { useState ,useEffect } from 'react'; import { fetchRoads, fetchCities, getShortestPath } from './requests'; import { Select, Button, Icon } from 'antd'; import Graph from 'react-graph-vis'; import styled from 'styled-components'; import 'antd/dist/antd.css'; import arrow from '../assets/arrow-right.png'; const { Option } = Select; function HomeView() { const [startingPoint, setStartingPoint] = useState(1); const [destination, setDestination] = useState(9); const [errorSelect, setError] = useState({ message: '', flag: false }); const [shortestPath, setShortestPath] = useState(); const [cities, setCities] = useState([]); useEffect(() => { fetchCities() .then(data => setCities(data)) .catch(error => console.log(error)) }, []); const [roads, setRoads] = useState([]); useEffect(() => { fetchRoads() .then(data => setRoads(data)) .catch(error => console.log(error)); }, []); const [graph, setGraph] = useState({nodes: [], edges: []}); useEffect(() => { let nodes = cities.map(node => ( { id: node.id, label: node.name, title: node.name} )); let edges = roads.map(edge => ( { from: edge.start_city_id, to: edge.end_city_id, length: edge.distance * 2 } )) setGraph({nodes, edges}) }, [cities, roads, shortestPath]) function handleStart(city_id) { // eslint-disable-next-line let [ startingPoint ] = cities.filter(city => city.id == city_id); setStartingPoint(startingPoint); // Check if start and destination are the same if (startingPoint === destination) { setError({ message: 'The start and destination must be different.', flag: true }); return } // Will reset the error message and shown path setShortestPath(); setError({ flag: false }); } function handleDestination(city_id) { // eslint-disable-next-line let [ destination ] = cities.filter(city => city.id == city_id); setDestination(destination); // Check if start and destination are the same if (startingPoint === destination) { setError({ message: 'The start and destination must be different.', flag: true }); return } // Will reset the error message and shown path setShortestPath(); setError({ flag: false }); } function handleSubmit() { if (startingPoint === destination) { setError({ message: 'Please select a start and a destination', flag: true}); return } else if (startingPoint && destination) { getShortestPath(startingPoint.id, destination.id) .then(data => setShortestPath(data)) .catch(error => console.log(error)); setError({ flag: false }); } else { setError({ message: 'Please select a start and a destination', flag: true}); } } // Graph visualization settings const options = { layout: { hierarchical: false }, edges: { color: "#000000" }, height: "500px" }; const events = { select: function(event) { let { nodes, edges } = event; } } // // TODO Find a solution to trigger a re-render of the map // // Add dashes to shortest path edges // let path = test.path; // let pairs = []; // for (let i = 0; path.length - 1 > i; i++) { // let obj = { from: path[i], to: path[i+1]} // pairs.push(obj); // } // let updatedEdges = graph.edges.map(edge => { // if (pairs.includes(edge)){ // edge['dashes'] = true; // } // return edge // }) // console.log(updatedEdges) // setGraph({...graph, edges: updatedEdges}); return(

Dijkstra

Find the shortest path between different cities in Belgium with Dijkstra algorithm.

Starting Point

Destination

{errorSelect.flag &&

{errorSelect.message}

}
{ shortestPath &&

Shortest path from {startingPoint.name} to {destination.name} ({shortestPath.distance}km)

{shortestPath.path.map(city => ( {city.name} ))}
} { graph.nodes.length > 0 && { // if you want access to vis.js network api you can set the state in a parent component using this property }} /> }

On github: backend & frontend

); } export default HomeView const Main = styled.main` padding-top: 20px; max-width: 800px; margin: 0 auto; ` const Section = styled.section` margin: 20px 0; ` const StyledSelect = styled(Select)` margin-right:10px; ` const StyledSpan = styled.span` ::after { content: ""; background-image: url(${arrow}); background-size: 13px 17px; display: inline-block; width: 13px; height: 17px; margin-right: 10px; margin-left: 10px; padding-top: 10px; bottom: -10px; } font-size:1.5rem; color: #40a9ff; ` const StyledP = styled.p` span:last-child { ::after { background-image: none; } } `