From ca476632653ae422557d6e143bb1b707efbef822 Mon Sep 17 00:00:00 2001 From: KOUTO Dosseh Date: Mon, 6 Jan 2020 21:49:41 +0100 Subject: [PATCH] creation de front end pour la visualiser des graphiques montrant la repartition des ventes par region --- api/src/DataFixtures/AppFixtures.php | 2 +- client/package-lock.json | 65 +++++++++ client/package.json | 1 + client/src/Cascading_Style_Sheets/index.css | 23 ++- client/src/Cascading_Style_Sheets/pichart.css | 23 +++ client/src/Helpers/PieSVG.js | 138 ++++++++++++------ .../ Repartitiondesventesparregion.js | 92 ------------ .../valeursfonciere/Nombredeventeparjma.js | 2 - .../Repartitiondesventesparregion.js | 96 ++++++++++++ .../src/components/valeursfonciere/index.js | 4 +- client/src/routes/valeursfonciere.js | 8 +- 11 files changed, 305 insertions(+), 149 deletions(-) create mode 100644 client/package-lock.json create mode 100644 client/src/Cascading_Style_Sheets/pichart.css delete mode 100644 client/src/components/valeursfonciere/ Repartitiondesventesparregion.js create mode 100644 client/src/components/valeursfonciere/Repartitiondesventesparregion.js diff --git a/api/src/DataFixtures/AppFixtures.php b/api/src/DataFixtures/AppFixtures.php index 93efe8e..8139e33 100644 --- a/api/src/DataFixtures/AppFixtures.php +++ b/api/src/DataFixtures/AppFixtures.php @@ -134,7 +134,7 @@ function region($cp) for($annee= 5; $annee<10; $annee++){ var_dump("Chargement des donnees de 201".$annee); $reader = Reader::createFromPath('%kernel.root_dir%/../src/Data/valeursfoncieres-201'.$annee.'.txt'); - $reader->setDelimiter("|"); + $reader->setDelimiter("|");return $reader->setHeaderOffset(0); $manager->getConnection()->getConfiguration()->setSQLLogger(null); $stmt = (new Statement())->offset(0); diff --git a/client/package-lock.json b/client/package-lock.json new file mode 100644 index 0000000..5cf3384 --- /dev/null +++ b/client/package-lock.json @@ -0,0 +1,65 @@ +{ + "name": "client", + "version": "0.1.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@babel/runtime": { + "version": "7.7.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.7.7.tgz", + "integrity": "sha512-uCnC2JEVAu8AKB5do1WRIsvrdJ0flYx/A/9f/6chdacnEZ7LmavjdsDXr5ksYBegxtuTPR5Va9/+13QF/kFkCA==", + "requires": { + "regenerator-runtime": "^0.13.2" + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "react-is": { + "version": "16.12.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.12.0.tgz", + "integrity": "sha512-rPCkf/mWBtKc97aLL9/txD8DZdemK0vkA3JMLShjlJB3Pj3s+lpf1KaBzMfQrAmhMQB0n1cU/SUGgKKBCe837Q==" + }, + "react-spring": { + "version": "8.0.27", + "resolved": "https://registry.npmjs.org/react-spring/-/react-spring-8.0.27.tgz", + "integrity": "sha512-nDpWBe3ZVezukNRandTeLSPcwwTMjNVu1IDq9qA/AMiUqHuRN4BeSWvKr3eIxxg1vtiYiOLy4FqdfCP5IoP77g==", + "requires": { + "@babel/runtime": "^7.3.1", + "prop-types": "^15.5.8" + }, + "dependencies": { + "prop-types": { + "version": "15.7.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", + "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", + "requires": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.8.1" + } + } + } + }, + "regenerator-runtime": { + "version": "0.13.3", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz", + "integrity": "sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw==" + } + } +} diff --git a/client/package.json b/client/package.json index 034d7be..970a11d 100644 --- a/client/package.json +++ b/client/package.json @@ -17,6 +17,7 @@ "react-redux": "^5.1.0", "react-router-dom": "^4.3.1", "react-scripts": "^3.1.2", + "react-spring": "^8.0.27", "redux": "^4.0.1", "redux-form": "^7.4.2", "redux-thunk": "^2.3.0" diff --git a/client/src/Cascading_Style_Sheets/index.css b/client/src/Cascading_Style_Sheets/index.css index 803dec5..f62a93e 100644 --- a/client/src/Cascading_Style_Sheets/index.css +++ b/client/src/Cascading_Style_Sheets/index.css @@ -2,12 +2,12 @@ padding: 20px; font-family: robot, arial } -svg { +.svg { fill: #000; fill-opacity: 0.3; } -path { +.path { stroke: steelblue; stroke-width: 2px; fill: none; @@ -32,3 +32,22 @@ path { opacity: 0.2; } + + +span { + margin: 20px; +} + +.label { + display: inline-block; + width: 120px; +} + +.container { + border-radius: .5em; + padding: 100px; + display: flex; + width: 1200px; + height :950px; +} + diff --git a/client/src/Cascading_Style_Sheets/pichart.css b/client/src/Cascading_Style_Sheets/pichart.css new file mode 100644 index 0000000..fc09b4c --- /dev/null +++ b/client/src/Cascading_Style_Sheets/pichart.css @@ -0,0 +1,23 @@ +div#app { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + width: 960px; + height: 500px; + position: relative; + } + + svg { + width: 100%; + height: 100%; + } + + path.slice{ + stroke-width:2px; + } + + polyline{ + opacity: .3; + stroke: black; + stroke-width: 2px; + fill: none; + } + \ No newline at end of file diff --git a/client/src/Helpers/PieSVG.js b/client/src/Helpers/PieSVG.js index 50089f3..8eb4480 100644 --- a/client/src/Helpers/PieSVG.js +++ b/client/src/Helpers/PieSVG.js @@ -1,50 +1,92 @@ -import React from "react"; +import React, { createRef, Component } from "react"; import * as d3 from "d3"; -const Arc = ({ data, index, createArc, colors, format }) => ( - - - - {format(data.value)} - - -); - -const Pie = props => { - const createPie = d3 - .pie() - .value(d => d.value) - .sort(null); - const createArc = d3 - .arc() - .innerRadius(props.innerRadius) - .outerRadius(props.outerRadius); - const colors = d3.scaleOrdinal(d3.schemeCategory10); - const format = d3.format(".2f"); - const data = createPie(props.data); - - return ( - - - {data.map((d, i) => ( - - ))} - - - ); -}; - -export default Pie; +class PieClass extends Component { + constructor(props) { + super(props); + this.ref = createRef(); + this.createPie = d3 + .pie() + .value(d => d.value) + .sort(null); + this.createArc = d3 + .arc() + .innerRadius(props.innerRadius) + .outerRadius(props.outerRadius); + this.colors = d3.scaleOrdinal(d3.schemeCategory10); + this.format = d3.format(".2f"); + } + componentDidMount() { + const svg = d3.select(this.ref.current); + const data = this.createPie(this.props.data); + const { width, height, innerRadius, outerRadius } = this.props; + + svg + .attr("class", "chart") + .attr("width", width) + .attr("height", height) + const group = svg + .append("g") + .attr("transform", `translate(${outerRadius} ${outerRadius})`); + + const groupWithEnter = group + .selectAll("g.arc") + .data(data) + .enter(); + + const path = groupWithEnter.append("g").attr("class", "arc"); + + path + .append("path") + .attr("class", "arc") + .attr("d", this.createArc) + .attr("fill", (d, i) => this.colors(d.index)) + + path + .append("text") + .attr("text-anchor", "middle") + .attr("alignment-baseline", "middle") + .attr("transform", d => `translate(${this.createArc.centroid(d)})`) + .style("font-size", 10) + .text(d =>"d"); + } + + componentWillUpdate(nextProps, nextState) { + const svg = d3.select(this.ref.current); + const data = this.createPie(nextProps.data); + + const group = svg + .select("g") + .selectAll("g.arc") + .data(data); + + group.exit().remove(); + + const groupWithUpdate = group + .enter() + .append("g") + .attr("class", "arc"); + + const path = groupWithUpdate.append("path").merge(group.select("path.arc")); + + path + .attr("class", "arc") + .attr("d", this.createArc) + .attr("fill", (d, i) => this.colors(i)); + + const text = groupWithUpdate.append("text").merge(group.select("text")); + + text + .attr("text-anchor", "middle") + .attr("alignment-baseline", "middle") + .attr("transform", d => `translate(${this.createArc.centroid(d)})`) + .style("fill", "white") + .style("font-size", 14) + .text(d => this.format(d.value/100) +" %" +"----> "+ d.data.region); + } + render() { + return ; + } +} + +export default PieClass; diff --git a/client/src/components/valeursfonciere/ Repartitiondesventesparregion.js b/client/src/components/valeursfonciere/ Repartitiondesventesparregion.js deleted file mode 100644 index fb81824..0000000 --- a/client/src/components/valeursfonciere/ Repartitiondesventesparregion.js +++ /dev/null @@ -1,92 +0,0 @@ -import React from "react"; -import ReactDOM from "react-dom"; -import * as d3 from "d3"; -import PieSVG from "../../Helpers/PieSVG"; - -class Repartitiondesventesparregion extends React.Component { - constructor(props) { - super(props); - - this.state = {annee: '2018',data: []}; - - }; - - componentWillMount(){ - console.log('Je suis appeler en premier!'); - } - - getData(){ - fetch(`https://${document.domain}:8443/repartitionDesVentesParRegion?anneeFiltre=${this.state.annee}`) - .then(response => { - if (response.ok) { - const data = response.json() - return data; - } else { - throw new Error('Something went wrong ...'); - } - }) - .then(data => { - this.setState({data: data }); - }) - .catch(error => console.log("error")); - } - - componentDidMount(){ - this.timerID = setInterval( - () => this.getData(), - 1000 - ); - - } - - handleChange(event) { - this.setState({ annee: event.target.value}); - }; - - render() { - - function parseData(data) { - var arr = []; - data.map(function (thisList){ - arr.push({ - nombre_de_vente: thisList.nombre_de_vente | 0, - dat : thisList.dat - }); - }) - return arr; - } - - const c =parseData(this.state.data) - - const generateData = () => - c.map((item, index) => ({ - index: index, - date: new Date(item.dat).toLocaleDateString('fr-FR', {day: 'numeric', year: 'numeric', month: 'long' }), - value: item.nombre_de_vente - })); - - const data = generateData(); - console.log(data) - - return ( -
-
- - - - SVG Elements - -
- -
- ); - } - } - - export default Repartitiondesventesparregion; \ No newline at end of file diff --git a/client/src/components/valeursfonciere/Nombredeventeparjma.js b/client/src/components/valeursfonciere/Nombredeventeparjma.js index 665ccfd..64e1941 100644 --- a/client/src/components/valeursfonciere/Nombredeventeparjma.js +++ b/client/src/components/valeursfonciere/Nombredeventeparjma.js @@ -1,6 +1,4 @@ import React from "react"; -import ReactDOM from "react-dom"; -import * as d3 from "d3"; import Bar from "../../Helpers/Bar"; class Nombredeventeparjma extends React.Component { diff --git a/client/src/components/valeursfonciere/Repartitiondesventesparregion.js b/client/src/components/valeursfonciere/Repartitiondesventesparregion.js new file mode 100644 index 0000000..ded5d3b --- /dev/null +++ b/client/src/components/valeursfonciere/Repartitiondesventesparregion.js @@ -0,0 +1,96 @@ +import React from "react"; +import PieSVG from "../../Helpers/PieSVG"; +import '../../Cascading_Style_Sheets/index.css'; + +class Repartitiondesventesparregion extends React.Component { + constructor(props) { + super(props); + + this.state = {annee: '2016',data: []}; + + }; + + componentWillMount(){ + console.log('Je suis appeler en premier!'); + } + + + getData(){ + fetch(`https://${document.domain}:8443/repartition_des_ventes_par_region?anneeFiltre=${this.state.annee}`) + .then(response => { + if (response.ok) { + const data = response.json() + return data; + } else { + throw new Error('Something went wrong ...'); + } + }) + .then(data => { + this.setState({data: data }); + }) + .catch(error => console.log("error")); + } + + componentDidMount(){ + this.timerID = setInterval( + () => this.getData(), + 1000 + ); + } + + handleChange(event) { + this.setState({ annee: event.target.value}); + }; + + + + render() { + + function parseData(data) { + var arr = []; + data.map(function (thisList){ + arr.push({ + nombre_de_vente: thisList.nombre_de_vente, + region : thisList.region + }); + }) + return arr; + } + + const c =parseData(this.state.data) + + const generateData = () => + c.map((item, index) => ({ + index: index, + value: item.nombre_de_vente, + region: item.region + + })); + + const data = generateData(); + console.log(data) + + return ( +
+
+
+ +
+ + +
+
+ +
+ ); +} +} + + + export default Repartitiondesventesparregion; \ No newline at end of file diff --git a/client/src/components/valeursfonciere/index.js b/client/src/components/valeursfonciere/index.js index 8442570..ef5d333 100644 --- a/client/src/components/valeursfonciere/index.js +++ b/client/src/components/valeursfonciere/index.js @@ -4,5 +4,7 @@ import Update from './Update'; import Show from './Show'; import Prixmoyenparannee from './Prixmoyenparannee'; import Nombredeventeparjma from './Nombredeventeparjma'; +import Repartitiondesventesparregion from './Repartitiondesventesparregion'; -export { Create, List, Update, Show, Prixmoyenparannee, Nombredeventeparjma}; + +export { Create, List, Update, Show, Prixmoyenparannee, Nombredeventeparjma, Repartitiondesventesparregion}; diff --git a/client/src/routes/valeursfonciere.js b/client/src/routes/valeursfonciere.js index b9c3a64..72ab66b 100644 --- a/client/src/routes/valeursfonciere.js +++ b/client/src/routes/valeursfonciere.js @@ -1,6 +1,6 @@ import React from 'react'; import { Route } from 'react-router-dom'; -import { List, Create, Update, Show,Prixmoyenparannee, Nombredeventeparjma} from '../components/valeursfonciere/'; +import { List, Create, Update, Show,Prixmoyenparannee, Nombredeventeparjma, Repartitiondesventesparregion} from '../components/valeursfonciere/'; export default [ , @@ -8,7 +8,9 @@ export default [ , , , - , - + , + , + + ]; -- GitLab