Improve styling

This commit is contained in:
rui hildt 2020-08-16 20:45:15 +02:00
parent 121f5c6e92
commit c62106f2c1
1 changed files with 281 additions and 204 deletions

View File

@ -1,239 +1,316 @@
import React, { useState ,useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { fetchRoads, fetchCities, getShortestPath } from './requests'; import { fetchRoads, fetchCities, getShortestPath } from './requests';
import { Select, Button, Icon } from 'antd'; import { Layout, Select, Button, Icon } from 'antd';
import Graph from 'react-graph-vis'; import Graph from 'react-graph-vis';
import styled from 'styled-components'; import styled from 'styled-components';
import 'antd/dist/antd.css'; import 'antd/dist/antd.css';
import arrow from '../assets/arrow-right.png'; import arrow from '../assets/arrow-right.png';
const { Header, Footer, Content } = Layout;
const { Option } = Select; const { Option } = Select;
function HomeView() { function HomeView() {
const [startingPoint, setStartingPoint] = useState(1); const [startingPoint, setStartingPoint] = useState(1);
const [destination, setDestination] = useState(9); const [destination, setDestination] = useState(9);
const [errorSelect, setError] = useState({ message: '', flag: false }); const [errorSelect, setError] = useState({ message: '', flag: false });
const [shortestPath, setShortestPath] = useState(); 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: []}); const [cities, setCities] = useState([]);
useEffect(() => {
fetchCities()
.then((data) => setCities(data))
.catch((error) => console.log(error));
}, []);
useEffect(() => { const [roads, setRoads] = useState([]);
let nodes = cities.map(node => ( useEffect(() => {
{ id: node.id, label: node.name, title: node.name} fetchRoads()
)); .then((data) => setRoads(data))
.catch((error) => console.log(error));
}, []);
let edges = roads.map(edge => ( const [graph, setGraph] = useState({ nodes: [], edges: [] });
{ from: edge.start_city_id, to: edge.end_city_id, length: edge.distance * 2 }
))
setGraph({nodes, edges}) useEffect(() => {
}, [cities, roads, shortestPath]) let nodes = cities.map((node) => ({
id: node.id,
label: node.name,
title: node.name,
}));
function handleStart(city_id) { let edges = roads.map((edge) => ({
// eslint-disable-next-line from: edge.start_city_id,
let [ startingPoint ] = cities.filter(city => city.id == city_id); to: edge.end_city_id,
setStartingPoint(startingPoint); length: edge.distance * 2,
// 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) { setGraph({ nodes, edges });
// eslint-disable-next-line }, [cities, roads, shortestPath]);
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() { function handleStart(city_id) {
if (startingPoint === destination) { // eslint-disable-next-line
setError({ message: 'Please select a start and a destination', flag: true}); let [startingPoint] = cities.filter((city) => city.id == city_id);
return setStartingPoint(startingPoint);
} else // Check if start and destination are the same
if (startingPoint && destination) { if (startingPoint === destination) {
getShortestPath(startingPoint.id, destination.id) setError({
.then(data => setShortestPath(data)) message: 'The start and destination must be different.',
.catch(error => console.log(error)); flag: true,
setError({ flag: false }); });
} else { return;
setError({ message: 'Please select a start and a destination', flag: true}); }
} // Will reset the error message and shown path
} setShortestPath();
setError({ flag: false });
}
// Graph visualization settings function handleDestination(city_id) {
const options = { // eslint-disable-next-line
layout: { let [destination] = cities.filter((city) => city.id == city_id);
hierarchical: false setDestination(destination);
}, // Check if start and destination are the same
edges: { if (startingPoint === destination) {
color: "#000000" setError({
}, message: 'The start and destination must be different.',
height: "500px" flag: true,
}; });
const events = { return;
select: function(event) { }
let { nodes, edges } = event; // Will reset the error message and shown path
} setShortestPath();
} setError({ flag: false });
}
// TODO Find a solution to trigger a re-render of the map function handleSubmit() {
// Add dashes to shortest path edges if (startingPoint === destination) {
// let path = test.path; setError({
// let pairs = []; 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,
});
}
}
// for (let i = 0; path.length - 1 > i; i++) { // Graph visualization settings
// let obj = { from: path[i], to: path[i+1]} const options = {
// pairs.push(obj); layout: {
// } hierarchical: false,
},
edges: {
color: '#000000',
},
height: '500px',
};
const events = {
select: function (event) {
let { nodes, edges } = event;
},
};
// let updatedEdges = graph.edges.map(edge => { // // TODO Find a solution to trigger a re-render of the map
// if (pairs.includes(edge)){ // // Add dashes to shortest path edges
// edge['dashes'] = true; // let path = test.path;
// } // let pairs = [];
// return edge
// })
// console.log(updatedEdges)
// setGraph({...graph, edges: updatedEdges});
return( // for (let i = 0; path.length - 1 > i; i++) {
<Main> // let obj = { from: path[i], to: path[i+1]}
<h1>Dijkstra</h1> // pairs.push(obj);
<p>Find the shortest path between different cities in Belgium with Dijkstra algorithm.</p> // }
<Section>
<h2>Starting Point</h2>
<div>
<StyledSelect defaultValue="Belgium" disabled>
</StyledSelect>
<Select
defaultValue="Select a city"
onChange={handleStart}
style={{ width: 139 }}
>
{cities.map(city => (
<Option key={city.id}>{city.name}</Option>
))}
</Select>
</div>
</Section>
<Section>
<h2>Destination</h2>
<div>
<StyledSelect defaultValue="Belgium" disabled>
</StyledSelect>
<Select
defaultValue="Select a city"
onChange={handleDestination}
style={{ width: 139 }}
>
{cities.map(city => (
<Option key={city.id}>{city.name}</Option>
))}
</Select>
</div>
</Section>
<Section>
<Button
type="primary"
onClick={handleSubmit}
>
Get shortest path between the cities
<Icon type="right" />
</Button>
{errorSelect.flag &&
<p>{errorSelect.message}</p>
}
</Section>
{
shortestPath &&
<Section>
<h2>Shortest path from {startingPoint.name} to {destination.name} ({shortestPath.distance}km)</h2>
<StyledP>{shortestPath.path.map(city => (
<StyledSpan key={city.id} class="cityPath">{city.name}</StyledSpan>
))}
</StyledP>
</Section> // let updatedEdges = graph.edges.map(edge => {
} // if (pairs.includes(edge)){
{ graph.nodes.length > 0 && // edge['dashes'] = true;
// }
// return edge
// })
// console.log(updatedEdges)
// setGraph({...graph, edges: updatedEdges});
<Graph return (
graph={graph} <>
options={options} <Header style={{ backgroundColor: '#ededed' }}>
events={events} <div style={{ margin: '0 auto', maxWidth: '800px' }}>
getNetwork={network => { <InlineH1>Dijkstra | </InlineH1>
// if you want access to vis.js network api you can set the state in a parent component using this property <InlineP>
}} Find the shortest path between different cities in
/> Belgium with Dijkstra algorithm
} </InlineP>
<Section> </div>
<p>Git: <a href="https://git.armada.digital/rui/dijkstra-backend">backend</a> & <a href="https://git.armada.digital/rui/dijkstra-frontend">frontend</a> </p> </Header>
</Section>
</Main> <Content>
); <Main
style={{
display: 'flex',
flexFlow: 'row wrap',
justifyContent: 'space-between',
alignItems: 'center'
}}
>
<div style={{margin: '0 20px'}}>
<Section>
<h2>Starting Point</h2>
<div>
<StyledSelect
defaultValue='Belgium'
disabled
></StyledSelect>
<Select
defaultValue='Select a city'
onChange={handleStart}
style={{ width: 139 }}
>
{cities.map((city) => (
<Option key={city.id}>
{city.name}
</Option>
))}
</Select>
</div>
</Section>
<Section>
<h2>Destination</h2>
<div>
<StyledSelect
defaultValue='Belgium'
disabled
></StyledSelect>
<Select
defaultValue='Select a city'
onChange={handleDestination}
style={{ width: 139 }}
>
{cities.map((city) => (
<Option key={city.id}>
{city.name}
</Option>
))}
</Select>
</div>
</Section>
<Section>
<Button type='primary' onClick={handleSubmit}>
Get shortest path between the cities
<Icon type='right' />
</Button>
{errorSelect.flag && <p>{errorSelect.message}</p>}
</Section>
</div>
<div style={{ maxWidth: '660px', minWidth: '400px' }}>
{graph.nodes.length > 0 && (
<Graph
graph={graph}
options={options}
events={events}
getNetwork={(network) => {
// if you want access to vis.js network api you can set the state in a parent component using this property
}}
/>
)}
</div>
<div>
{shortestPath && (
<Section>
<h2>
Shortest path from {startingPoint.name} to{' '}
{destination.name} ({shortestPath.distance}
km)
</h2>
<StyledP>
{shortestPath.path.map((city) => (
<StyledSpan
key={city.id}
class='cityPath'
>
{city.name}
</StyledSpan>
))}
</StyledP>
</Section>
)}
</div>
</Main>
</Content>
<Footer>
<div style={{ margin: '0 auto', maxWidth: '800px' }}>
<p>
Git |{' '}
<a href='https://git.armada.digital/rui/dijkstra-backend'>
backend
</a>{' '}
&{' '}
<a href='https://git.armada.digital/rui/dijkstra-frontend'>
frontend
</a>{' '}
</p>
</div>
</Footer>
</>
);
} }
export default HomeView export default HomeView;
// STYLED COMPONENTS
const InlineP = styled.p`
display: inline;
`;
const InlineH1 = styled.h1`
display: inline;
`;
const Main = styled.main` const Main = styled.main`
padding-top: 20px; padding-top: 20px;
max-width: 800px; max-width: 1200px;
margin: 0 auto; margin: 0 auto;
` height: calc(100vh - 147px);
`;
const Section = styled.section` const Section = styled.section`
margin: 20px 0; margin: 20px 0;
` `;
const StyledSelect = styled(Select)` const StyledSelect = styled(Select)`
margin-right:10px; margin-right: 10px;
` `;
const StyledSpan = styled.span` const StyledSpan = styled.span`
::after { ::after {
content: ""; content: '';
background-image: url(${arrow}); background-image: url(${arrow});
background-size: 13px 17px; background-size: 13px 17px;
display: inline-block; display: inline-block;
width: 13px; width: 13px;
height: 17px; height: 17px;
margin-right: 10px; margin-right: 10px;
margin-left: 10px; margin-left: 10px;
padding-top: 10px; padding-top: 10px;
bottom: -10px; bottom: -10px;
} }
font-size:1.5rem; font-size: 1.5rem;
color: #40a9ff; color: #40a9ff;
` `;
const StyledP = styled.p` const StyledP = styled.p`
span:last-child { span:last-child {
::after { ::after {
background-image: none; background-image: none;
} }
} }
` `;