import React, { useState, useEffect } from 'react'; import { fetchRoads, fetchCities, getShortestPath } from './requests'; import { Layout, 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 { Header, Footer, Content } = Layout; 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}

}
{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 }} /> )}
{shortestPath && (

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

{shortestPath.path.map((city) => ( {city.name} ))}
)}
); } export default HomeView; // STYLED COMPONENTS const InlineP = styled.p` display: inline; `; const InlineH1 = styled.h1` display: inline; `; const Main = styled.main` padding-top: 20px; max-width: 1200px; margin: 0 auto; height: calc(100vh - 147px); `; 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; } } `;