Updated structure and added Vegetables page

This commit is contained in:
dbroqua 2018-11-18 19:53:29 +01:00
parent 773ef7e859
commit 9f29edb00e
12 changed files with 371 additions and 224 deletions

View file

@ -4,9 +4,9 @@ import {
BrowserRouter as Router, Route, BrowserRouter as Router, Route,
Switch, Switch,
} from 'react-router-dom'; } from 'react-router-dom';
import Map from './Map'; import Map from '../Routes/Map';
import Home from './Home'; import Home from '../Routes/Home';
import Vegetables from './Vegetables'; import Vegetables from '../Routes/Vegetables';
class App extends Component { class App extends Component {
constructor(props) { constructor(props) {
@ -43,8 +43,7 @@ class App extends Component {
<Switch> <Switch>
<Route exact path="/" component={Home} /> <Route exact path="/" component={Home} />
<Route exact path="/carte" component={Map} /> <Route exact path="/carte" component={Map} />
<Route exact path="/vegetaux" component={Vegetables} /> <Route exact path="/vegetaux/:typeId-:typeSlug" component={Vegetables} />
<Route exact path="/vegetaux/:id-:slug" component={Vegetables} />
</Switch> </Switch>
</Router> </Router>
</div> </div>

120
src/Components/Map.js Normal file
View file

@ -0,0 +1,120 @@
import React from 'react';
import {
Row,
Col,
Tooltip
} from 'reactstrap';
import {
FaMapMarkerAlt
} from 'react-icons/fa';
import {
Link
} from 'react-router-dom';
import strToSlug from '../StrToSlug'
import '../css/Map.css'
const MapDimensions = {
width: 734,
height: 530,
};
export default class Map extends React.Component {
constructor(props) {
super(props);
this.state = {
selectedType: this.props.selectedType,
selectedVegetable: this.props.selectedVegetable,
Map: {
width: '20px',
height: '20px',
},
tooltipOpen: false
}
this.selectVegetable = this.selectVegetable.bind(this);
this.setMap = this.setMap.bind(this);
this.toggle = this.toggle.bind(this);
}
componentWillReceiveProps(newProps) {
this.setState(prevState => ({
...prevState,
selectedType: newProps.selectedType,
selectedVegetable: newProps.selectedVegetable
}));
}
componentDidMount() {
window.addEventListener('resize', this.setMap);
this.setMap();
}
componentWillUnmount() {
window.removeEventListener('resize', this.setMap);
}
setMap() {
const width = document.getElementById('MapContainer').clientWidth;
let MapWidth = MapDimensions.width;
let MapHeight = MapDimensions.height;
if (width < MapDimensions.width) {
MapWidth = width;
MapHeight = Math.round(MapDimensions.height * MapWidth / MapDimensions.width);
}
this.setState({
Map: {
width: MapWidth,
height: MapHeight,
},
});
}
selectVegetable(vegetable) {
this.setState({
selectedVegetable: vegetable
})
this.props.selectVegetable(vegetable)
}
toggle(id) {
this.setState(prevState => ({
tooltipOpen: prevState.tooltipOpen === id ? false : id
}));
}
render() {
return (
<Row className="with-margin">
<Col className="with-border with-background">
<div id="MapContainer">
<div className="map" style={{ width: this.state.Map.width, height: this.state.Map.height }}>
{
this.state.selectedType &&
this.state.selectedType.Vegetables &&
this.state.selectedType.Vegetables.map((vegetable, key) =>
(
<Link to={`/vegetaux/${this.state.selectedType.id}-${strToSlug(this.state.selectedType.name)}/${vegetable.id}-${strToSlug(vegetable.name)}`}
key={key}
className={`mapMarker ${this.state.selectedVegetable && this.state.selectedVegetable.id === vegetable.id ? 'selected' : ''}`}
style={{ left: `calc(${vegetable.lat}% - 16px)`, top: `calc(${vegetable.lng}% - 16px)` }}
onMouseOver={(e) => this.selectVegetable(vegetable)}
>
<Tooltip placement='top' isOpen={this.state.tooltipOpen === vegetable.id} target={'Tooltip-' + vegetable.id} toggle={() => this.toggle(vegetable.id)}>
{vegetable.name}
</Tooltip>
<FaMapMarkerAlt id={'Tooltip-' + vegetable.id} />
</Link>
)
)
}
</div>
</div>
</Col>
</Row>
);
}
}

View file

@ -0,0 +1,56 @@
import React from 'react';
import {
ListGroup,
ListGroupItem
} from 'reactstrap';
import {
Link
} from 'react-router-dom';
import strToSlug from '../StrToSlug'
import '../css/Vegetables.css'
export default class Map extends React.Component {
constructor(props) {
super(props);
this.state = {
selectedType: this.props.selectedType,
selectedVegetable: this.props.selectVegetable
}
}
componentWillReceiveProps(newProps) {
this.setState(newProps);
}
render() {
return (
<div className="with-margin">
<div className=" with-border with-background">
<ListGroup className='vegetables--types--group'>
{
this.state.selectedType &&
this.state.selectedType.Vegetables &&
this.state.selectedType.Vegetables.map((vegetable, key) =>
(
<ListGroupItem
key={key}
className={this.state.selectedVegetable.id === vegetable.id ? "selected" : "null"}
onMouseOver={(e) => this.props.selectVegetable(vegetable)}
>
<Link to={`/vegetaux/${this.state.selectedType.id}-${strToSlug(this.state.selectedType.name)}/${vegetable.id}-${strToSlug(vegetable.name)}`}>
{vegetable.name}
</Link>
</ListGroupItem>
)
)
}
</ListGroup>
</div>
</div>
);
}
}

View file

@ -7,7 +7,7 @@ import {
import '../css/Home.css'; import '../css/Home.css';
export default class Home extends React.Component { export default class RouterHome extends React.Component {
render() { render() {
return ( return (

108
src/Routes/Map.js Normal file
View file

@ -0,0 +1,108 @@
import React from 'react';
import {
Container,
Row,
Col,
ListGroup,
ListGroupItem,
Badge
} from 'reactstrap';
import Api from '../Components/Api';
import {
NotificationContainer,
NotificationManager
} from 'react-notifications';
import MapItem from '../Components/Map'
import Vegetables from '../Components/Vegetables'
export default class RouterMap extends React.Component {
constructor(props) {
super(props);
this.state = {
types: [],
vegetables: [],
selectedType: {},
selectedVegetable: {}
}
this.getVegetablesTypes = this.getVegetablesTypes.bind(this);
this.selectType = this.selectType.bind(this);
this.selectVegetable = this.selectVegetable.bind(this);
this.getVegetablesTypes();
}
getVegetablesTypes() {
Api.get('types')
.then(res => {
this.setState({
types: res.data.rows
});
})
.catch(() => {
NotificationManager.error('Erreur lors de la récupération des catégories');
})
}
selectType(type) {
this.setState({
selectedType: type
});
}
selectVegetable(vegetable) {
this.setState({
selectedVegetable: vegetable
})
}
render() {
return (
<Container>
<NotificationContainer />
<Row>
<Col xs="12" sm="8">
<MapItem
selectedType={this.state.selectedType}
selectedVegetable={this.state.selectedVegetable}
selectVegetable={this.selectVegetable}
/>
</Col>
<Col xs="12" sm="4">
<Row>
<Col xs="6" sm="12">
<div className="with-margin">
<div className=" with-border with-background">
<ListGroup className='vegetables--types--group'>
{
this.state.types.map((type, key) =>
(
<ListGroupItem
key={key}
className={this.state.selectedType.id === type.id ? "selected" : "null"} onClick={(e) => this.selectType(type)}>
{type.name}
<Badge pill>{type.Vegetables.length}</Badge>
</ListGroupItem>
)
)
}
</ListGroup>
</div>
</div>
</Col>
<Col xs="6" sm="12">
<Vegetables
selectedType={this.state.selectedType}
selectedVegetable={this.state.selectedVegetable}
selectVegetable={this.selectVegetable}
/>
</Col>
</Row>
</Col>
</Row >
</Container >
);
}
}

78
src/Routes/Vegetables.js Normal file
View file

@ -0,0 +1,78 @@
import React from 'react';
import {
Container,
Row,
Col
} from 'reactstrap';
import Api from '../Components/Api';
import {
NotificationContainer,
NotificationManager
} from 'react-notifications';
import MapItem from '../Components/Map'
import VegetablesList from '../Components/Vegetables'
export default class RouterVegetables extends React.Component {
constructor(props) {
super(props);
this.state = {
typeId: props.match.params.typeId,
selectedType: {},
selectedVegetable: {}
}
this.getItem = this.getItem.bind(this);
this.selectVegetable = this.selectVegetable.bind(this);
this.getItem();
}
selectVegetable(vegetable) {
this.setState({
selectedVegetable: vegetable
})
}
getItem() {
Api.get(`/types/${this.state.typeId}`)
.then(res => {
this.setState({
selectedType: res.data
});
})
.catch(() => {
NotificationManager.error('Erreur lors de la récupération des végétaux');
})
}
render() {
return (
<Container>
<NotificationContainer />
<Row>
<Col xs="12" sm="8">
<MapItem
selectedType={this.state.selectedType}
selectedVegetable={this.state.selectedVegetable}
selectVegetable={this.selectVegetable}
/>
</Col>
<Col xs="12" sm="4">
<Row>
<Col xs="6" sm="12">
<VegetablesList
selectedType={this.state.selectedType}
selectedVegetable={this.state.selectedVegetable}
selectVegetable={this.selectVegetable}
/>
</Col>
</Row>
</Col>
</Row >
</Container >
);
}
}

View file

@ -1,206 +0,0 @@
import React from 'react';
import {
Container,
Row,
Col,
ListGroup,
ListGroupItem,
Badge,
Tooltip
} from 'reactstrap';
import Api from './Api';
import {
FaMapMarkerAlt
} from 'react-icons/fa';
import {
NotificationContainer,
NotificationManager
} from 'react-notifications';
import {
Link
} from 'react-router-dom';
import strToSlug from '../StrToSlug'
import '../css/Map.css'
const MapDimensions = {
width: 734,
height: 530,
};
export default class Map extends React.Component {
constructor(props) {
super(props);
this.state = {
types: [],
vegetables: [],
selectedType: {},
selectedVegetable: {},
Map: {
width: '20px',
height: '20px',
},
tooltipOpen: false
}
this.getVegetablesTypes = this.getVegetablesTypes.bind(this);
this.selectType = this.selectType.bind(this);
this.selectVegetable = this.selectVegetable.bind(this);
this.setMap = this.setMap.bind(this);
this.toggle = this.toggle.bind(this);
this.getVegetablesTypes();
}
componentDidMount() {
window.addEventListener('resize', this.setMap);
this.setMap();
}
componentWillUnmount() {
window.removeEventListener('resize', this.setMap);
}
setMap() {
const width = document.getElementById('MapContainer').clientWidth;
let MapWidth = MapDimensions.width;
let MapHeight = MapDimensions.height;
if (width < MapDimensions.width) {
MapWidth = width;
MapHeight = Math.round(MapDimensions.height * MapWidth / MapDimensions.width);
}
this.setState({
Map: {
width: MapWidth,
height: MapHeight,
},
});
}
getVegetablesTypes() {
Api.get('types')
.then(res => {
this.setState({
types: res.data.rows
});
})
.catch(() => {
NotificationManager.error('Erreur lors de la récupération des catégories');
})
}
getVegetable(id) {
Api.get(`types/${id}`)
.then(res => {
this.setState({
vegetables: res.data
});
})
.catch(() => {
NotificationManager.error('Erreur lors de la récupération des végétaux');
})
}
selectType(type) {
this.setState({
selectedType: type
});
}
selectVegetable(vegetable) {
this.setState({
selectedVegetable: vegetable
})
}
toggle(id) {
this.setState(prevState => ({
tooltipOpen: prevState.tooltipOpen === id ? false : id
}));
}
render() {
return (
<Container>
<NotificationContainer />
<Row>
<Col xs="12" sm="8">
<Row className="with-margin">
<Col className="with-border with-background">
<div id="MapContainer">
<div className="map" style={{ width: this.state.Map.width, height: this.state.Map.height }}>
{
this.state.selectedType &&
this.state.selectedType.Vegetables &&
this.state.selectedType.Vegetables.map((vegetable, key) =>
(
<Link to={`/vegetaux/${this.state.selectedType.id}-${strToSlug(this.state.selectedType.name)}/${vegetable.id}-${strToSlug(vegetable.name)}`}
key={key}
className={`mapMarker ${this.state.selectedVegetable && this.state.selectedVegetable.id === vegetable.id ? 'selected' : ''}`}
style={{ left: `calc(${vegetable.lat}% - 16px)`, top: `calc(${vegetable.lng}% - 16px)` }}
onMouseOver={(e) => this.selectVegetable(vegetable)}
>
<Tooltip placement='top' isOpen={this.state.tooltipOpen === vegetable.id} target={'Tooltip-' + vegetable.id} toggle={() => this.toggle(vegetable.id)}>
{vegetable.name}
</Tooltip>
<FaMapMarkerAlt id={'Tooltip-' + vegetable.id} />
</Link>
)
)
}
</div>
</div>
</Col>
</Row>
</Col>
<Col xs="12" sm="4">
<Row>
<Col xs="6" sm="12">
<div className="with-margin">
<div className=" with-border with-background">
<ListGroup className='vegetables--types--group'>
{
this.state.types.map((type, key) =>
(
<ListGroupItem
key={key}
className={this.state.selectedType.id === type.id ? "selected" : "null"} onClick={(e) => this.selectType(type)}>
{type.name}
<Badge pill>{type.Vegetables.length}</Badge>
</ListGroupItem>
)
)
}
</ListGroup>
</div>
</div>
</Col>
<Col xs="6" sm="12">
<div className="with-margin">
<div className=" with-border with-background">
<ListGroup className='vegetables--types--group'>
{
this.state.selectedType &&
this.state.selectedType.Vegetables &&
this.state.selectedType.Vegetables.map((vegetable, key) =>
(
<ListGroupItem key={key} className={this.state.selectedVegetable.id === vegetable.id ? "selected" : "null"} onMouseOver={(e) => this.selectVegetable(vegetable)}>
{vegetable.name}
</ListGroupItem>
)
)
}
</ListGroup>
</div>
</div>
</Col>
</Row>
</Col>
</Row>
</Container>
);
}
}

View file

@ -1,11 +0,0 @@
import React from 'react';
export default class Vegetables extends React.Component {
render() {
return (
<div>
</div>
);
}
}

3
src/css/Vegetables.css Normal file
View file

@ -0,0 +1,3 @@
.vegetables--types--group.list-group a {
color: #212529;
}

View file

@ -1,6 +1,6 @@
import React from 'react'; import React from 'react';
import ReactDOM from 'react-dom'; import ReactDOM from 'react-dom';
import App from './components/App'; import App from './Components/App';
import * as serviceWorker from './serviceWorker'; import * as serviceWorker from './serviceWorker';
import 'react-notifications/lib/notifications.css'; import 'react-notifications/lib/notifications.css';