From ccb1c906872d247a5fb475e88e1e1d7b7ea138a9 Mon Sep 17 00:00:00 2001 From: firdaous elhalafi Date: Sat, 6 Jan 2024 12:02:25 +0100 Subject: [PATCH] Ameliorer le front de timeseries --- api/README.md | 12 ++++---- api/src/Service/SaleService.php | 9 ++++-- pwa/app/components/bar-chart/form.jsx | 7 +++-- .../timeseries.jsx} | 12 +++++--- pwa/app/help/fetch-service.js | 15 ++++++---- pwa/app/page.jsx | 29 ++++++++++++++----- pwa/config.js | 13 ++++++++- 7 files changed, 65 insertions(+), 32 deletions(-) rename pwa/app/components/{line_chart.jsx => timeseries/timeseries.jsx} (88%) diff --git a/api/README.md b/api/README.md index f7a5db9..8f90178 100755 --- a/api/README.md +++ b/api/README.md @@ -40,19 +40,17 @@ create index date_index on sale (date); ## Clear cache -```Shell -sudo docker exec -it php sh -```` -```sh -composer require --dev doctrine/doctrine-fixtures-bundle -``` - ```Shell sudo docker compose exec php bin/console cache:clear ``` ## Run tests +Install fixtures: +```shell +sudo docker compose exec php composer require --dev doctrine/doctrine-fixtures-bundle +``` + Create a test database: ```shell sudo docker compose exec php bin/console doctrine:database:create --env=test diff --git a/api/src/Service/SaleService.php b/api/src/Service/SaleService.php index cbd5d64..be0f120 100755 --- a/api/src/Service/SaleService.php +++ b/api/src/Service/SaleService.php @@ -55,6 +55,8 @@ class SaleService $result = $queryBuilder ->select('MONTH(s.date) as month', 'YEAR(s.date) as year', 'AVG(CASE WHEN s.surface <> 0 THEN s.amount / s.surface ELSE 0 END) as average_price') + #->select('MONTH(s.date) as month', 'YEAR(s.date) as year', 'SUM(s.amount) as total_price', 'SUM(s.surface) as total_surface') + #->select('MONTH(s.date) as month', 'YEAR(s.date) as year', 'AVG(s.amount) as total_price', 'AVG(s.surface) as total_surface') ->from(Sale::class, 's') ->groupBy('year, month') ->orderBy('year, month') @@ -63,6 +65,7 @@ class SaleService $monthlyAveragePriceEvolutions = []; foreach ($result as $row) { + #$row['average_price'] = $row['total_surface'] != 0 ? $row['total_price'] / $row['total_surface'] : 0; $monthlyAveragePriceEvolutions[] = new MonthlyAveragePriceEvolution( (int)$row['month'], (int)$row['year'], @@ -115,7 +118,7 @@ class SaleService ->groupBy('year', 'month') ->orderBy('year') ->getQuery() - ->getResult(); + ->getResult(Query::HYDRATE_ARRAY); } else { switch ($input->granularity) { case 'day': @@ -141,7 +144,7 @@ class SaleService ->groupBy("{$groupByAlias}") ->orderBy("{$groupByAlias}") ->getQuery() - ->getResult(); + ->getResult(Query::HYDRATE_ARRAY); } foreach ($result as $row) { @@ -181,7 +184,7 @@ class SaleService ->setParameter('year', $year) ->groupBy('s.region') ->getQuery() - ->getResult(); + ->getResult(Query::HYDRATE_ARRAY); $data = []; foreach ($result as $row) { diff --git a/pwa/app/components/bar-chart/form.jsx b/pwa/app/components/bar-chart/form.jsx index 7c5b78c..21601c4 100644 --- a/pwa/app/components/bar-chart/form.jsx +++ b/pwa/app/components/bar-chart/form.jsx @@ -1,10 +1,11 @@ import React, { useState } from 'react'; import '../../style/style.css'; +import constants from '../../../config.js'; const DataForm = ({ onSubmit }) => { - const [startDate, setStartDate] = useState(''); - const [endDate, setEndDate] = useState(''); - const [granularity, setGranularity] = useState('month'); + const [startDate, setStartDate] = useState(`${constants.initialBarChartFormData.startDate}`); + const [endDate, setEndDate] = useState(`${constants.initialBarChartFormData.endDate}`); + const [granularity, setGranularity] = useState(`${constants.initialBarChartFormData.granularity}`); const handleSubmit = (event) => { event.preventDefault(); diff --git a/pwa/app/components/line_chart.jsx b/pwa/app/components/timeseries/timeseries.jsx similarity index 88% rename from pwa/app/components/line_chart.jsx rename to pwa/app/components/timeseries/timeseries.jsx index c32bd66..8cd5e09 100644 --- a/pwa/app/components/line_chart.jsx +++ b/pwa/app/components/timeseries/timeseries.jsx @@ -3,7 +3,7 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faSpinner } from "@fortawesome/free-solid-svg-icons"; import * as d3 from "d3"; -function LineChart({ data }) { +function Timeseries({ data }) { const chartRef = useRef(null); const isLoading = data.length === 0; @@ -16,14 +16,18 @@ function LineChart({ data }) { useEffect(() => { + if (data.length === 0) { + return; + } const x = d3.scaleTime() .domain(d3.extent(data, d => new Date(d.year, d.month - 1))) .range([marginLeft, width - marginRight]); - const y = d3.scaleLinear() - .domain([0, d3.max(data, d => d.averagePrice)]) + const y = d3.scaleLog() + .domain([d3.min(data, d => d.averagePrice), d3.max(data, d => d.averagePrice)]) .range([height - marginBottom, marginTop]); + const svg = d3.select(chartRef.current) .attr("width", width) .attr("height", height); @@ -68,4 +72,4 @@ function LineChart({ data }) { ); } -export default LineChart; +export default Timeseries; diff --git a/pwa/app/help/fetch-service.js b/pwa/app/help/fetch-service.js index 5fa318d..e9b56d6 100644 --- a/pwa/app/help/fetch-service.js +++ b/pwa/app/help/fetch-service.js @@ -1,4 +1,4 @@ -import config from '../../config.js'; +import constants from '../../config.js'; /** * @param {number} year */ @@ -31,7 +31,7 @@ async function getDonutContent(year) { } const getTimesSeries = () => { - const url = `${config.apiUrl}/timeseries?page=1`; + const url = `${constants.config.apiUrl}/timeseries?page=1`; return fetch(url, { method: 'GET', headers: { @@ -41,10 +41,13 @@ const getTimesSeries = () => { } async function fetchBarChartData(formData) { - const url = `${config.apiUrl}/bar-chart/${formData.startDate}/${formData.endDate}/${formData.granularity}?page=1`; - const response = await fetch(url); - const data = await response.json(); - return data; + const url = `${constants.config.apiUrl}/bar-chart/${formData.startDate}/${formData.endDate}/${formData.granularity}?page=1`; + return fetch(url, { + method: 'GET', + headers: { + 'Content-Type': 'application/json' + } + }); } export default { diff --git a/pwa/app/page.jsx b/pwa/app/page.jsx index e61855e..1de97f9 100644 --- a/pwa/app/page.jsx +++ b/pwa/app/page.jsx @@ -1,14 +1,14 @@ "use client"; import React, {useEffect, useState} from "react"; -import config from '../config.js'; +import constants from '../config.js'; import FetchService from "./help/fetch-service"; import Donut from "./components/donut.jsx"; import DateInput from "./components/date-input"; import DataForm from "./components/bar-chart/form"; import BarChart from "./components/bar-chart/chart"; -import Line_Chart from "./components/line_chart.jsx"; +import Timeseries from "./components/timeseries/timeseries.jsx"; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faSpinner } from "@fortawesome/free-solid-svg-icons"; @@ -20,7 +20,11 @@ export default function Page() { const handleFormSubmit = async (formData) => { setIsLoading(true); - const data = await FetchService.fetchBarChartData(formData); + const response = await FetchService.fetchBarChartData(formData); + if (!response.ok) { + throw new Error(`HTTP error! Status: ${response.status}`); + } + const data = await response.json(); setChartData(data); setIsLoading(false); }; @@ -29,11 +33,15 @@ export default function Page() { setIsLoading(true); try { const formData = { - startDate: '2020-01-01', - endDate: '2022-01-01', - granularity: 'month' + startDate: `${constants.initialBarChartFormData.startDate}`, + endDate: `${constants.initialBarChartFormData.endDate}`, + granularity: `${constants.initialBarChartFormData.granularity}` }; - const data = await FetchService.fetchBarChartData(formData); + const response = await FetchService.fetchBarChartData(formData); + if (!response.ok) { + throw new Error(`HTTP error! Status: ${response.status}`); + } + const data = await response.json(); setChartData(data); } catch (error) { console.error('Error fetching bar chart data:', error); @@ -43,7 +51,10 @@ export default function Page() { useEffect(() => { (async () => { + // bar chart loadInitialBarChartData(); + + // time series try { const response = await FetchService.getTimesSeries(); if (!response.ok) { @@ -54,6 +65,8 @@ export default function Page() { } catch (error) { console.error('Error fetching time series data:', error); } + + // donut const data = await FetchService.getDonutContent(); const formattedData = data.map((x) => ({ id: x.region, @@ -68,7 +81,7 @@ export default function Page() {

L’évolution du prix de vente moyen du mètre carré

- +

Nombre des ventes par période

diff --git a/pwa/config.js b/pwa/config.js index 4650549..c1896d4 100644 --- a/pwa/config.js +++ b/pwa/config.js @@ -2,4 +2,15 @@ const config = { apiUrl: 'https://localhost/api', }; -export default config; +const initialBarChartFormData = { + startDate: '2020-01-01', + endDate: '2022-01-01', + granularity: 'month', +}; + +const constants = { + initialBarChartFormData, + config, +}; + +export default constants; -- GitLab