import React, { useState, useEffect } from 'react'; import { Layout, Select, Button } from 'antd'; import styled from 'styled-components'; import { fetchRoads, fetchCities, getShortestPath } from '../utils/requests'; import Map from './Map'; import 'antd/dist/antd.css'; import arrow from '../assets/arrow-right.png'; const { Header, Content } = Layout; const { Option } = Select; let highlightInitial = { bruges: '#00856E', ghent: '#00856E', antwerp: '#00856E', mechelen: '#00856E', tournai: '#00856E', brussels: '#00856E', mons: '#00856E', namur: '#00856E', liege: '#00856E', arlon: '#00856E', }; 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([]); const [highlighted, setHighlighted] = useState(highlightInitial); 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; } // Reset the error message and shown path setHighlighted(highlightInitial); 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; } // Reset the error message and shown path setHighlighted(highlightInitial); setShortestPath(); setError({ flag: false }); } function handleSubmit() { if (startingPoint === destination) { setError({ message: 'Please select a start and a destination', flag: true, }); } else if (startingPoint && destination) { getShortestPath(startingPoint.id, destination.id) .then((data) => { setShortestPath(data); // Add cities to highlight let updatedgHighlighted = {}; data.path.forEach((city) => { updatedgHighlighted[city.name] = '#E63318'; }); setHighlighted(updatedgHighlighted); }) .catch((error) => console.log(error)); setError({ flag: false }); } else { setError({ message: 'Please select a start and a destination', flag: true, }); } } return ( <>
Dijkstra | Find the shortest path between different cities | GIT{' '} backend {' '} &{' '} frontend {' '}

Starting Point

Destination

{errorSelect.flag &&

{errorSelect.message}

}
{graph.nodes.length > 0 && (
)} {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: 1000px; 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; } } `;