diff --git a/src/components/Charts/AxisBottom.tsx b/src/components/Charts/AxisBottom.tsx index 9bc1c15404e620a10e2b6988172d057444616921..769207c28ac3a1de7eba8fa4cc8801917e901f7a 100644 --- a/src/components/Charts/AxisBottom.tsx +++ b/src/components/Charts/AxisBottom.tsx @@ -1,4 +1,6 @@ import React from 'react' +import { useSelector } from 'react-redux' +import { AppStore } from 'store' import { DateTime } from 'luxon' import { ScaleBand } from 'd3-scale' @@ -104,26 +106,24 @@ function TextAxis(props: TextTypeProps) { interface AxisBottomProps { data: Dataload[] - timeStep: TimeStep xScale: ScaleBand<string> height: number marginLeft: number marginBottom: number - selectedDate: DateTime isDuel?: boolean } -const AxisBottom = (props: AxisBottomProps) => { - const { - data, - timeStep, - xScale, - height, - marginLeft, - marginBottom, - selectedDate, - isDuel, - } = props +const AxisBottom: React.FC<AxisBottomProps> = ({ + data, + xScale, + height, + marginLeft, + marginBottom, + isDuel, +}: AxisBottomProps) => { + const { currentTimeStep, selectedDate } = useSelector( + (state: AppStore) => state.ecolyo.chart + ) const dashArray = `${height / 30} ${height / 30}` const dateChartService = new DateChartService() return ( @@ -143,13 +143,13 @@ const AxisBottom = (props: AxisBottomProps) => { <TextAxis index={index} dataload={d} - timeStep={timeStep} + timeStep={currentTimeStep} width={xScale.bandwidth() / 2} selectedDate={selectedDate} isDuel={isDuel} /> {dateChartService.compareStepDate( - timeStep, + currentTimeStep, DateTime.local().setZone('utc', { keepLocalTime: true, }), diff --git a/src/components/Charts/Bar.tsx b/src/components/Charts/Bar.tsx index 4118586ad2368769dea1a0c72bfec483911f5e0f..fe550e882c9b74ec39279d2a7ad3f83062463128 100644 --- a/src/components/Charts/Bar.tsx +++ b/src/components/Charts/Bar.tsx @@ -1,26 +1,25 @@ import React, { useState, useEffect } from 'react' +import { useDispatch, useSelector } from 'react-redux' +import { AppStore } from 'store' import { ScaleBand, ScaleLinear } from 'd3-scale' import { DateTime } from 'luxon' import { detect } from 'detect-browser' import { FluidType } from 'enum/fluid.enum' -import { TimeStep } from 'enum/timeStep.enum' import { Dataload } from 'models' import DateChartService from 'services/dateChart.service' +import { + setCurrentDatachartIndex, + setSelectedDate, +} from 'store/chart/chart.actions' interface BarProps { index: number dataload: Dataload compareDataload: Dataload | null fluidTypes: FluidType[] - timeStep: TimeStep multiFluid: boolean - selectedDate: DateTime showCompare: boolean - handleClickData: ( - dataload: Dataload, - compareDataload: Dataload | null - ) => void xScale: ScaleBand<string> yScale: ScaleLinear<number, number> height: number @@ -33,17 +32,18 @@ const Bar = ({ dataload, compareDataload, fluidTypes, - timeStep, multiFluid, - selectedDate, showCompare, - handleClickData, xScale, yScale, height, isSwitching, isDuel, }: BarProps) => { + const dispatch = useDispatch() + const { currentTimeStep, selectedDate } = useSelector( + (state: AppStore) => state.ecolyo.chart + ) const [clicked, setClicked] = useState(false) const [animationEnded, setAnimationEnded] = useState(false) const [compareAnimationEnded, setCompareAnimationEnded] = useState(false) @@ -60,7 +60,8 @@ const Bar = ({ const handleClick = () => { if (!isSwitching) { setClicked(true) - handleClickData(dataload, compareDataload) + dispatch(setSelectedDate(dataload.date)) + dispatch(setCurrentDatachartIndex(index)) } } @@ -74,8 +75,15 @@ const Bar = ({ setCompareAnimationEnded(true) } + const tempYScale: number | undefined = yScale(dataload.value) + const yScaleValue: number = tempYScale ? tempYScale : 0 + const tempXScale: number | undefined = xScale( + dataload.date.toLocaleString(DateTime.DATETIME_SHORT) + ) + const xScaleValue: number = tempXScale ? tempXScale : 0 + const isSelectedDate = new DateChartService().compareStepDate( - timeStep, + currentTimeStep, selectedDate, dataload.date ) @@ -159,18 +167,14 @@ const Bar = ({ useEffect(() => { if (isSelectedDate) { setClicked(true) - handleClickData(dataload, compareDataload) + // handleClickData(dataload, compareDataload) } - }, [compareDataload, dataload, handleClickData, isSelectedDate]) + }, [compareDataload, dataload, isSelectedDate]) return ( <g> {height > 0 ? ( - <g - transform={`translate(${xScale( - dataload.date.toLocaleString(DateTime.DATETIME_SHORT) - )}, -40)`} - > + <g transform={`translate(${xScaleValue}, -40)`}> <rect onClick={handleClick} x="0" @@ -183,11 +187,7 @@ const Bar = ({ </g> ) : null} {height > 0 && dataload.value && dataload.value >= 0 ? ( - <g - transform={`translate(${xScale( - dataload.date.toLocaleString(DateTime.DATETIME_SHORT) - )}, ${yScale(dataload.value)})`} - > + <g transform={`translate(${xScaleValue}, ${yScaleValue})`}> <defs> <linearGradient id="gradient" @@ -206,7 +206,7 @@ const Bar = ({ showCompare ? getBandWidth() : 0, 0, getBandWidth(), - height - yScale(dataload.value) + height - yScaleValue )} fill="url(#gradient)" className={isDuel ? 'bar-duel' : barClass} @@ -221,11 +221,7 @@ const Bar = ({ compareDataload.value && dataload.value >= 0 && compareDataload.value >= 0 ? ( - <g - transform={`translate(${xScale( - dataload.date.toLocaleString(DateTime.DATETIME_SHORT) - )}, ${yScale(compareDataload.value)})`} - > + <g transform={`translate(${xScaleValue}, ${yScaleValue})`}> <defs> <linearGradient id="gradient-compare" @@ -240,12 +236,7 @@ const Bar = ({ </linearGradient> </defs> <path - d={topRoundedRect( - 0, - 0, - getBandWidth(), - height - yScale(compareDataload.value) - )} + d={topRoundedRect(0, 0, getBandWidth(), height - yScaleValue)} fill="url(#gradient-compare)" className={compareBarClass} onClick={handleClick} diff --git a/src/components/Charts/BarChart.tsx b/src/components/Charts/BarChart.tsx index 29efe7109bb068e3484e7e773405baa2ede00f9e..33f397cf42a8c601fd1fa0dca9d4957926284ce2 100644 --- a/src/components/Charts/BarChart.tsx +++ b/src/components/Charts/BarChart.tsx @@ -3,8 +3,7 @@ import { scaleBand, ScaleBand, scaleLinear, ScaleLinear } from 'd3-scale' import { DateTime } from 'luxon' import { FluidType } from 'enum/fluid.enum' -import { TimeStep } from 'enum/timeStep.enum' -import { Datachart, Dataload } from 'models' +import { Datachart } from 'models' import Bar from 'components/Charts/Bar' import AxisBottom from 'components/Charts/AxisBottom' @@ -13,14 +12,8 @@ import AxisRight from 'components/Charts/AxisRight' export interface BarChartProps { chartData: Datachart fluidTypes: FluidType[] - timeStep: TimeStep multiFluid: boolean - selectedDate: DateTime showCompare: boolean - handleClickData: ( - dataload: Dataload, - compareDataload: Dataload | null - ) => void width?: number height?: number marginLeft?: number @@ -31,36 +24,20 @@ export interface BarChartProps { isHome: boolean } -interface DefaultProps { - width: number - height: number - marginLeft: number - marginRight: number - marginTop: number - marginBottom: number -} - -type PropsWithDefaults = BarChartProps & DefaultProps - -const BarChart: React.FC<BarChartProps> = (props: BarChartProps) => { - const { - chartData, - fluidTypes, - timeStep, - multiFluid, - selectedDate, - showCompare, - handleClickData, - width, - height, - marginLeft, - marginRight, - marginTop, - marginBottom, - isSwitching, - isHome, - } = props as PropsWithDefaults - +const BarChart: React.FC<BarChartProps> = ({ + chartData, + fluidTypes, + multiFluid, + showCompare, + width = 600, + height = 400, + marginLeft = 10, + marginRight = 50, + marginTop = 20, + marginBottom = 50, + isSwitching, + isHome, +}: BarChartProps) => { const getContentWidth = () => { return width - marginLeft - marginRight } @@ -116,11 +93,8 @@ const BarChart: React.FC<BarChartProps> = (props: BarChartProps) => { : null } fluidTypes={fluidTypes} - timeStep={timeStep} multiFluid={multiFluid} - selectedDate={selectedDate} showCompare={showCompare} - handleClickData={handleClickData} xScale={xScale} yScale={yScale} height={getContentHeight()} @@ -130,24 +104,13 @@ const BarChart: React.FC<BarChartProps> = (props: BarChartProps) => { </g> <AxisBottom data={chartData.actualData} - timeStep={timeStep} xScale={xScale} height={height} marginLeft={marginLeft} marginBottom={marginBottom} - selectedDate={selectedDate} /> </svg> ) } -BarChart.defaultProps = { - width: 600, - height: 400, - marginLeft: 10, - marginRight: 50, - marginTop: 20, - marginBottom: 50, -} - export default BarChart diff --git a/src/components/ConsumptionNavigator/ConsumptionNavigator.spec.tsx b/src/components/ConsumptionNavigator/ConsumptionNavigator.spec.tsx deleted file mode 100644 index f5c62fbfa3366eeb602ee4647882c681a86c0bc9..0000000000000000000000000000000000000000 --- a/src/components/ConsumptionNavigator/ConsumptionNavigator.spec.tsx +++ /dev/null @@ -1,90 +0,0 @@ -import React from 'react' -import { mount } from 'enzyme' -import ConsumptionNavigator from './ConsumptionNavigator' -import { FluidType } from 'enum/fluid.enum' -import { TimeStep } from 'enum/timeStep.enum' -import configureStore from 'redux-mock-store' -import { globalStateData } from '../../../test/__mocks__/globalStateData.mock' -import { Provider } from 'react-redux' -import * as reactRedux from 'react-redux' -import { userChallengeExplo1OnGoing } from '../../../test/__mocks__/userChallengeData.mock' - -jest.mock('cozy-ui/transpiled/react/I18n', () => { - return { - useI18n: jest.fn(() => { - return { - t: (str: string) => str, - } - }), - } -}) - -const mockUseSelector = jest.spyOn(reactRedux, 'useSelector') - -const mockHandleClickTimeStep = jest.fn() - -const mockConfigureStore = configureStore([]) -const mockStore = mockConfigureStore({ - ecolyo: { - gloabl: globalStateData, - }, -}) - -const mockProps = { - multiFluid: false, - timeStep: TimeStep.DAY, - handleClickTimeStep: mockHandleClickTimeStep, -} - -describe('ConsumptionNavigator component test', () => { - it('should render correctly Electricty ConsumptionNavigator', () => { - mockUseSelector.mockReturnValue(userChallengeExplo1OnGoing) - - const wrapper = mount( - <Provider store={mockStore}> - <ConsumptionNavigator - {...mockProps} - fluidTypes={[FluidType.ELECTRICITY]} - /> - </Provider> - ) - expect(wrapper.getElement()).toMatchSnapshot() - }) - - it('should render correctly Water ConsumptionNavigator', () => { - mockUseSelector.mockReturnValue(userChallengeExplo1OnGoing) - - const wrapper = mount( - <Provider store={mockStore}> - <ConsumptionNavigator {...mockProps} fluidTypes={[FluidType.WATER]} /> - </Provider> - ) - expect(wrapper.getElement()).toMatchSnapshot() - }) - - it('should render correclty Gas ConsumptionNavigator', () => { - mockUseSelector.mockReturnValue(userChallengeExplo1OnGoing) - - const wrapper = mount( - <Provider store={mockStore}> - <ConsumptionNavigator {...mockProps} fluidTypes={[FluidType.GAS]} /> - </Provider> - ) - expect(wrapper.getElement()).toMatchSnapshot() - }) - - it('should render correctly ConsumptionNavigator with multifluid option', () => { - mockUseSelector.mockReturnValue(userChallengeExplo1OnGoing) - - const mockMultiFluidProps = { ...mockProps, multiFluid: true } - const wrapper = mount( - <Provider store={mockStore}> - <ConsumptionNavigator - {...mockMultiFluidProps} - fluidTypes={[FluidType.MULTIFLUID]} - /> - </Provider> - ) - expect(wrapper.getElement()).toMatchSnapshot() - }) -}) diff --git a/src/components/ConsumptionNavigator/ConsumptionNavigator.tsx b/src/components/ConsumptionNavigator/ConsumptionNavigator.tsx deleted file mode 100644 index 60c455ddaea30e0dddd353e60244ec2ce2097c96..0000000000000000000000000000000000000000 --- a/src/components/ConsumptionNavigator/ConsumptionNavigator.tsx +++ /dev/null @@ -1,103 +0,0 @@ -import React from 'react' -import { IuseI18n, useI18n } from 'cozy-ui/transpiled/react/I18n' - -import { FluidType } from 'enum/fluid.enum' -import { TimeStep } from 'enum/timeStep.enum' - -import Tabs from 'components/CommonKit/Tabs/StyledTabs' -import Tab from 'components/CommonKit/Tabs/StyledTab' -import './consumptionNavigator.scss' -import useExploration from 'components/Hooks/useExploration' -import { UserExplorationID } from 'enum/userExploration.enum' -interface ConsumptionNavigatorProps { - fluidTypes: FluidType[] - multiFluid: boolean - timeStep: TimeStep - handleClickTimeStep(timeStep: TimeStep): void -} - -const ConsumptionNavigator: React.FC<ConsumptionNavigatorProps> = ({ - fluidTypes, - multiFluid, - timeStep, - handleClickTimeStep, -}: ConsumptionNavigatorProps) => { - const { t }: IuseI18n = useI18n() - const fluidStyle = multiFluid - ? 'MULTIFLUID' - : fluidTypes.length === 0 - ? 'MULTIFLUID' - : fluidTypes.length > 1 - ? 'MULTIFLUID' - : FluidType[fluidTypes[0]] - - const [, setValidExploration] = useExploration() - - const handleClick = (timeStep: TimeStep) => { - handleClickTimeStep(timeStep) - if (timeStep === TimeStep.YEAR) { - setValidExploration(UserExplorationID.EXPLORATION002) - } - } - - const defineNavTab = (fluidTypes: FluidType[]) => { - if (multiFluid) { - return [TimeStep.DAY, TimeStep.MONTH, TimeStep.YEAR] - } else if (fluidTypes.length === 1) { - switch (fluidTypes[0]) { - case FluidType.ELECTRICITY: - return [ - TimeStep.HALF_AN_HOUR, - TimeStep.DAY, - TimeStep.MONTH, - TimeStep.YEAR, - ] - case FluidType.WATER: - return [TimeStep.DAY, TimeStep.MONTH, TimeStep.YEAR] - case FluidType.GAS: - return [TimeStep.DAY, TimeStep.MONTH, TimeStep.YEAR] - } - } - return [TimeStep.DAY, TimeStep.MONTH, TimeStep.YEAR] - } - - const defineLabel = (dataTimeStep: TimeStep) => { - const classes = - dataTimeStep === timeStep - ? `${fluidStyle.toLowerCase()} tab-text-on` - : `${fluidStyle.toLowerCase()} tab-text-off` - return ( - <span className={classes}> - {t(`TIMESTEP.${TimeStep[dataTimeStep]}.STEP`)} - </span> - ) - } - - return ( - <div className="cn"> - <Tabs - className="cn-tabs" - value={timeStep} - variant="fullWidth" - fluidTypes={fluidTypes} - multiFluid={multiFluid} - > - {defineNavTab(fluidTypes).map((dataTimeStep, index) => { - return ( - <Tab - className="cn-tab" - key={index} - value={dataTimeStep} - fluidTypes={fluidTypes} - multiFluid={multiFluid} - label={defineLabel(dataTimeStep)} - onClick={() => handleClick(dataTimeStep)} - /> - ) - })} - </Tabs> - </div> - ) -} - -export default ConsumptionNavigator diff --git a/src/components/ConsumptionNavigator/__snapshots__/ConsumptionNavigator.spec.tsx.snap b/src/components/ConsumptionNavigator/__snapshots__/ConsumptionNavigator.spec.tsx.snap deleted file mode 100644 index 36ba61b88766e40b3a4102cdd528d1e787970543..0000000000000000000000000000000000000000 --- a/src/components/ConsumptionNavigator/__snapshots__/ConsumptionNavigator.spec.tsx.snap +++ /dev/null @@ -1,105 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`ConsumptionNavigator component test should render correclty Gas ConsumptionNavigator 1`] = ` -<Provider - store={ - Object { - "clearActions": [Function], - "dispatch": [Function], - "getActions": [Function], - "getState": [Function], - "replaceReducer": [Function], - "subscribe": [Function], - } - } -> - <ConsumptionNavigator - fluidTypes={ - Array [ - 2, - ] - } - handleClickTimeStep={[MockFunction]} - multiFluid={false} - timeStep={20} - /> -</Provider> -`; - -exports[`ConsumptionNavigator component test should render correctly ConsumptionNavigator with multifluid option 1`] = ` -<Provider - store={ - Object { - "clearActions": [Function], - "dispatch": [Function], - "getActions": [Function], - "getState": [Function], - "replaceReducer": [Function], - "subscribe": [Function], - } - } -> - <ConsumptionNavigator - fluidTypes={ - Array [ - 3, - ] - } - handleClickTimeStep={[MockFunction]} - multiFluid={true} - timeStep={20} - /> -</Provider> -`; - -exports[`ConsumptionNavigator component test should render correctly Electricty ConsumptionNavigator 1`] = ` -<Provider - store={ - Object { - "clearActions": [Function], - "dispatch": [Function], - "getActions": [Function], - "getState": [Function], - "replaceReducer": [Function], - "subscribe": [Function], - } - } -> - <ConsumptionNavigator - fluidTypes={ - Array [ - 0, - ] - } - handleClickTimeStep={[MockFunction]} - multiFluid={false} - timeStep={20} - /> -</Provider> -`; - -exports[`ConsumptionNavigator component test should render correctly Water ConsumptionNavigator 1`] = ` -<Provider - store={ - Object { - "clearActions": [Function], - "dispatch": [Function], - "getActions": [Function], - "getState": [Function], - "replaceReducer": [Function], - "subscribe": [Function], - } - } -> - <ConsumptionNavigator - fluidTypes={ - Array [ - 1, - ] - } - handleClickTimeStep={[MockFunction]} - multiFluid={false} - timeStep={20} - /> -</Provider> -`; diff --git a/src/components/ConsumptionNavigator/consumptionNavigator.scss b/src/components/ConsumptionNavigator/consumptionNavigator.scss deleted file mode 100644 index c934f5412bcc504fa2141c53e963ccc7f1a9ae12..0000000000000000000000000000000000000000 --- a/src/components/ConsumptionNavigator/consumptionNavigator.scss +++ /dev/null @@ -1,16 +0,0 @@ -@import 'src/styles/base/breakpoint'; - -.cn { - display: flex; - justify-content: center; - .cn-tabs { - width: 50.625rem; - @media #{$large-phone} { - width: 100%; - margin: 0 1.25rem; - } - .cn-tab { - outline: none !important; - } - } -} diff --git a/src/components/ConsumptionVisualizer/ConsumptionVisualizer.tsx b/src/components/ConsumptionVisualizer/ConsumptionVisualizer.tsx index 320f90802bc2c9b2c5a5a72792c19f43beb408f4..59decd6b7bc0514ed8a300a71f28589658a71998 100644 --- a/src/components/ConsumptionVisualizer/ConsumptionVisualizer.tsx +++ b/src/components/ConsumptionVisualizer/ConsumptionVisualizer.tsx @@ -1,60 +1,55 @@ import React from 'react' +import './consumptionVisualizer.scss' +import { useSelector } from 'react-redux' +import { AppStore } from 'store' import { FluidType } from 'enum/fluid.enum' import { DateTime } from 'luxon' -import { TimeStep } from 'enum/timeStep.enum' import { Dataload } from 'models' import DateChartService from 'services/dateChart.service' -import DateNavigator from 'components/DateNavigator/DateNavigator' import DataloadConsumptionVisualizer from 'components/ConsumptionVisualizer/DataloadConsumptionVisualizer' import LastDataConsumptionVisualizer from 'components/ConsumptionVisualizer/LastDataConsumptionVisualizer' import ErrorDataConsumptionVisualizer from 'components/ConsumptionVisualizer/ErrorDataConsumptionVisualizer' -import './consumptionVisualizer.scss' + interface ConsumptionVisualizerProps { fluidTypes: FluidType[] - timeStep: TimeStep - date: DateTime - dataload: Dataload - compareDataload: Dataload showCompare: boolean multiFluid: boolean - lastDataDate: DateTime - lastDateWithAllData: DateTime - isLoaded: boolean - indexDisplayed: number - setSelectedDate: Function - setIndexDisplayed: Function - handleClickMove: (increment: number) => void - handleChangeIndex: (index: number) => void } -const ConsumptionVisualizer = ({ +const ConsumptionVisualizer: React.FC<ConsumptionVisualizerProps> = ({ fluidTypes, - timeStep, - date, - dataload, - compareDataload, showCompare, multiFluid, - lastDataDate, - lastDateWithAllData, - isLoaded, - indexDisplayed, - setSelectedDate, - setIndexDisplayed, - handleClickMove, - handleChangeIndex, }: ConsumptionVisualizerProps) => { + const { fluidStatus } = useSelector((state: AppStore) => state.ecolyo.global) + const { currentDatachart, currentDatachartIndex } = useSelector( + (state: AppStore) => state.ecolyo.chart + ) + const dataload: Dataload = currentDatachart.actualData[currentDatachartIndex] + const compareDataload: Dataload | null = currentDatachart.comparisonData + ? currentDatachart.comparisonData[currentDatachartIndex] + : null const dateChartService = new DateChartService() + + const getLastDataDate = (): DateTime | null => { + let lastDay: DateTime | null = null + const lastDays: DateTime[] = [] + for (const fluidType of fluidTypes) { + const date: DateTime | null = fluidStatus[fluidType].lastDataDate + if (date) { + lastDays.push(date) + } + } + lastDay = lastDays.reduce(function(a, b) { + return a < b ? a : b + }) + return lastDay + } + const lastDataDate: DateTime | null = getLastDataDate() + return ( - <div className="cv"> - <DateNavigator - timeStep={timeStep} - date={date} - handleClickMove={handleClickMove} - indexDisplayed={indexDisplayed} - handleChangeIndex={handleChangeIndex} - /> + <div className="consumptionvisualizer-root"> <DataloadConsumptionVisualizer fluidTypes={fluidTypes} dataload={dataload} @@ -62,9 +57,8 @@ const ConsumptionVisualizer = ({ showCompare={showCompare} multiFluid={multiFluid} lastDataDate={lastDataDate} - isLoaded={isLoaded} /> - <div className="cv-info"> + <div className="consumptionvisualizer-info"> {dataload && dataload.valueDetail && ((dataload.valueDetail[0] === -1 && @@ -73,24 +67,14 @@ const ConsumptionVisualizer = ({ !dateChartService.isDataToCome(dataload, fluidTypes[1])) || (dataload.valueDetail[2] === -1 && !dateChartService.isDataToCome(dataload, fluidTypes[2]))) && ( - <ErrorDataConsumptionVisualizer - date={date} - indexDisplayed={indexDisplayed} - setIndexDisplayed={setIndexDisplayed} - lastDateWithAllData={lastDateWithAllData} - setSelectedDate={setSelectedDate} - /> + <ErrorDataConsumptionVisualizer fluidTypes={fluidTypes} /> )} {!dataload || (dataload && dataload.value === -1 && + lastDataDate && dataload.date > lastDataDate && ( - <LastDataConsumptionVisualizer - fluidTypes={fluidTypes} - timeStep={timeStep} - multiFluid={multiFluid} - handleChangeIndex={handleChangeIndex} - /> + <LastDataConsumptionVisualizer lastDataDate={lastDataDate} /> ))} </div> </div> diff --git a/src/components/ConsumptionVisualizer/DataloadConsumptionVisualizer.tsx b/src/components/ConsumptionVisualizer/DataloadConsumptionVisualizer.tsx index a23660e250ba8bb845885f10d6adc096385c0b72..ca5275f13fe0546bc7a2d09289f1ea432b085d7d 100644 --- a/src/components/ConsumptionVisualizer/DataloadConsumptionVisualizer.tsx +++ b/src/components/ConsumptionVisualizer/DataloadConsumptionVisualizer.tsx @@ -1,25 +1,27 @@ -import React, { useState, useEffect } from 'react' +import React from 'react' +import './dataloadConsumptionVisualizer.scss' import { useI18n } from 'cozy-ui/transpiled/react/I18n' +import { useSelector } from 'react-redux' +import { AppStore } from 'store' import { NavLink } from 'react-router-dom' import { DateTime } from 'luxon' +import { formatNumberValues } from 'utils/utils' -import { FluidType } from 'enum/fluid.enum' import { Dataload } from 'models' +import { FluidType } from 'enum/fluid.enum' import ConverterService from 'services/converter.service' import DateChartService from 'services/dateChart.service' import { getPicto } from 'utils/picto' -import { formatNumberValues } from 'utils/utils' import StyledIcon from 'components/CommonKit/Icon/StyledIcon' -import './dataloadConsumptionVisualizer.scss' + interface DataloadConsumptionVisualizerProps { fluidTypes: FluidType[] dataload: Dataload - compareDataload: Dataload + compareDataload: Dataload | null showCompare: boolean multiFluid: boolean - lastDataDate: DateTime - isLoaded: boolean + lastDataDate: DateTime | null } const DataloadConsumptionVisualizer = ({ fluidTypes, @@ -28,12 +30,10 @@ const DataloadConsumptionVisualizer = ({ showCompare, multiFluid, lastDataDate, - isLoaded, }: DataloadConsumptionVisualizerProps) => { const { t } = useI18n() + const { loading } = useSelector((state: AppStore) => state.ecolyo.chart) const converterService = new ConverterService() - const [hasData, setHasData] = useState(false) - const [hasCompareData, setHasCompareData] = useState(false) const fluidStyle = multiFluid ? 'MULTIFLUID' : fluidTypes.length > 1 @@ -41,65 +41,44 @@ const DataloadConsumptionVisualizer = ({ : FluidType[fluidTypes[0]] const dateChartService = new DateChartService() - useEffect(() => { - if ((dataload && dataload.value) || (dataload && dataload.value === 0)) { - if (dataload.value === -1) { - setHasData(false) - } else { - setHasData(true) - } - } else { - setHasData(false) - } - if ( - compareDataload && - compareDataload.value && - compareDataload.value === -1 - ) { - setHasCompareData(false) - } else { - if (showCompare && !multiFluid) { - setHasCompareData(true) - } else { - setHasCompareData(false) - } - } - }, [dataload, showCompare, compareDataload, multiFluid]) return ( - <div className="cv-load"> - {isLoaded && hasData ? ( - <div className="cv-load-content"> - {hasCompareData && ( - <div className="cv-load-section cv-load-section-left"> - <div - className={`cv-load-value ${fluidStyle.toLowerCase()}-compare chart-result`} - > - {formatNumberValues(compareDataload.value)} - <span className="text-18-normal">{`${t( - 'FLUID.' + fluidStyle + '.UNIT' - )}`}</span> - </div> - <div - className={`cv-euro ${fluidStyle.toLowerCase()}-compare chart-fluid`} - > - {`${formatNumberValues( - converterService.LoadToEuro( - compareDataload.value, - fluidTypes[0] - ) - )} €`} + <div className="dataloadvisualizer-root"> + {!loading && dataload.value > -1 ? ( + <div className="dataloadvisualizer-content"> + {showCompare && + !multiFluid && + compareDataload && + compareDataload.value > -1 && ( + <div className="dataloadvisualizer-section dataloadvisualizer-section-left"> + <div + className={`dataloadvisualizer-value ${fluidStyle.toLowerCase()}-compare chart-result`} + > + {formatNumberValues(compareDataload.value)} + <span className="text-18-normal">{`${t( + 'FLUID.' + fluidStyle + '.UNIT' + )}`}</span> + </div> + <div + className={`dataloadvisualizer-euro ${fluidStyle.toLowerCase()}-compare chart-fluid`} + > + {`${formatNumberValues( + converterService.LoadToEuro( + compareDataload.value, + fluidTypes[0] + ) + )} €`} + </div> </div> - </div> - )} + )} <div className={ showCompare - ? 'cv-load-section cv-load-section-right' - : 'cv-load-section' + ? 'dataloadvisualizer-section dataloadvisualizer-section-right' + : 'dataloadvisualizer-section' } > <div - className={`cv-load-value ${fluidStyle.toLowerCase()} chart-result`} + className={`dataloadvisualizer-value ${fluidStyle.toLowerCase()} chart-result`} > {fluidStyle && formatNumberValues(dataload.value, fluidStyle, true) >= 1000 ? ( @@ -120,14 +99,14 @@ const DataloadConsumptionVisualizer = ({ </div> {!multiFluid ? ( <div - className={`cv-euro ${fluidStyle.toLowerCase()} chart-fluid`} + className={`dataloadvisualizer-euro ${fluidStyle.toLowerCase()} chart-fluid`} > {`${formatNumberValues( converterService.LoadToEuro(dataload.value, fluidTypes[0]) )} €`} </div> ) : ( - <div className="cv-euro chart-fluid"> + <div className="dataloadvisualizer-euro chart-fluid"> {dataload.valueDetail ? ( dataload.valueDetail.map((load, index) => { return ( @@ -136,20 +115,20 @@ const DataloadConsumptionVisualizer = ({ to={`/consumption/${t( 'FLUID.' + FluidType[index] + '.NAME' ).toLowerCase()}`} - className="cv-euro-link" + className="dataloadvisualizer-euro-link" > <div className={ load === -1 && !dateChartService.isDataToCome(dataload, index) - ? 'cv-euro-fluid error' - : `cv-euro-fluid ${FluidType[ + ? 'dataloadvisualizer-euro-fluid error' + : `dataloadvisualizer-euro-fluid ${FluidType[ index ].toLowerCase()}` } > <StyledIcon - className="cv-euro-fluid-icon" + className="dataloadvisualizer-euro-fluid-icon" icon={getPicto(index)} size={22} /> @@ -170,15 +149,15 @@ const DataloadConsumptionVisualizer = ({ to={`/consumption/${t( 'FLUID.' + FluidType[fluidTypes[0]] + '.NAME' ).toLowerCase()}`} - className="cv-euro-link" + className="dataloadvisualizer-euro-link" > <div - className={`cv-euro-fluid ${FluidType[ + className={`dataloadvisualizer-euro-fluid ${FluidType[ fluidTypes[0] ].toLowerCase()}`} > <StyledIcon - className="cv-euro-fluid-icon" + className="dataloadvisualizer-euro-fluid-icon" icon={getPicto(fluidTypes[0])} size={22} /> @@ -197,9 +176,9 @@ const DataloadConsumptionVisualizer = ({ </div> ) : ( <> - {dataload && dataload.date > lastDataDate ? ( + {dataload && lastDataDate && dataload.date > lastDataDate ? ( <div - className={`cv-load-content ${fluidStyle.toLowerCase()} text-22-normal`} + className={`dataloadvisualizer-content ${fluidStyle.toLowerCase()} text-22-normal`} > {`${t('COMMON.LASTDATA')} : ${lastDataDate.toFormat( "dd'/'MM'/'yy" @@ -207,7 +186,7 @@ const DataloadConsumptionVisualizer = ({ </div> ) : ( <div - className={`cv-load-content ${fluidStyle.toLowerCase()} text-22-normal`} + className={`dataloadvisualizer-content ${fluidStyle.toLowerCase()} text-22-normal`} > {`${t('COMMON.NODATA')}`} </div> diff --git a/src/components/ConsumptionVisualizer/ErrorDataConsumptionVisualizer.tsx b/src/components/ConsumptionVisualizer/ErrorDataConsumptionVisualizer.tsx index 8cbc2cb34c97fe309efbac7dd16e02a3bba86191..a8494572cfa12c008109e49973698353335fd6f8 100644 --- a/src/components/ConsumptionVisualizer/ErrorDataConsumptionVisualizer.tsx +++ b/src/components/ConsumptionVisualizer/ErrorDataConsumptionVisualizer.tsx @@ -1,48 +1,65 @@ import React from 'react' +import './errorDataConsumptionVisualizer.scss' import { useI18n } from 'cozy-ui/transpiled/react/I18n' -import { DateTime, Interval } from 'luxon' +import { useDispatch, useSelector } from 'react-redux' +import { AppStore } from 'store' +import { setCurrentIndex, setSelectedDate } from 'store/chart/chart.actions' +import { DateTime } from 'luxon' +import DateChartService from 'services/dateChart.service' import warning from 'assets/icons/ico/warning.svg' import StyledIcon from 'components/CommonKit/Icon/StyledIcon' -import './errorDataConsumptionVisualizer.scss' +import { FluidType } from 'enum/fluid.enum' interface ErrorDataConsumptionVisualizerProps { - lastDateWithAllData: DateTime - indexDisplayed: number - setSelectedDate: Function - setIndexDisplayed: Function - date: DateTime + fluidTypes: FluidType[] } -const ErrorDataConsumptionVisualizer = ({ - lastDateWithAllData, - date, - indexDisplayed, - setIndexDisplayed, - setSelectedDate, +const ErrorDataConsumptionVisualizer: React.FC<ErrorDataConsumptionVisualizerProps> = ({ + fluidTypes, }: ErrorDataConsumptionVisualizerProps) => { const { t } = useI18n() + const dispatch = useDispatch() + const { currentTimeStep } = useSelector( + (state: AppStore) => state.ecolyo.chart + ) + const { fluidStatus } = useSelector((state: AppStore) => state.ecolyo.global) + + const getLastDateWithAllData = (): DateTime | null => { + let lastDay: DateTime | null = null + const lastDays: DateTime[] = [] + for (const fluidType of fluidTypes) { + const date: DateTime | null = fluidStatus[fluidType].lastDataDate + if (date) { + lastDays.push(date) + } + } + lastDay = lastDays.reduce(function(a, b) { + return a < b ? a : b + }) + return lastDay + } + const lastDateWithAllData: DateTime | null = getLastDateWithAllData() + const setDateAndMoveToindex = () => { - let indexToMove = 0 - if (date < lastDateWithAllData) { - indexToMove = -( - Interval.fromDateTimes(date, lastDateWithAllData).count('weeks') - 1 + if (lastDateWithAllData) { + const dateChartService = new DateChartService() + const updatedIndex: number = dateChartService.defineDateIndex( + currentTimeStep, + lastDateWithAllData ) - } else { - indexToMove = - Interval.fromDateTimes(lastDateWithAllData, date).count('weeks') - 1 - } - if (indexToMove !== 0) { - setIndexDisplayed(indexDisplayed + indexToMove) + dispatch(setSelectedDate(lastDateWithAllData)) + dispatch(setCurrentIndex(updatedIndex)) } - setSelectedDate(lastDateWithAllData) } return ( <div onClick={() => setDateAndMoveToindex()} className="error-line"> <StyledIcon icon={warning} size={22} className="warning-icon" /> <span className={`text-16-normal underlined-error`}> - {`${t('COMMON.LASTVALIDDATA')} : ${lastDateWithAllData.toFormat( - "dd'/'MM'/'yy" - )}`} + {`${t('COMMON.LASTVALIDDATA')} : ${ + lastDateWithAllData + ? lastDateWithAllData.toFormat("dd'/'MM'/'yy") + : '-' + }`} </span> </div> ) diff --git a/src/components/ConsumptionVisualizer/LastDataConsumptionVisualizer.tsx b/src/components/ConsumptionVisualizer/LastDataConsumptionVisualizer.tsx index 3f8ae042cdcec97a76fba33a133745eda5bedd01..6165c3fa9c652005461d76439175a8352f910661 100644 --- a/src/components/ConsumptionVisualizer/LastDataConsumptionVisualizer.tsx +++ b/src/components/ConsumptionVisualizer/LastDataConsumptionVisualizer.tsx @@ -1,22 +1,40 @@ import React from 'react' -import { useI18n } from 'cozy-ui/transpiled/react/I18n' -import { FluidType } from 'enum/fluid.enum' -import { TimeStep } from 'enum/timeStep.enum' import './lastDataConsumptionVisualizer.scss' +import { useI18n } from 'cozy-ui/transpiled/react/I18n' +import { useDispatch, useSelector } from 'react-redux' +import { AppStore } from 'store' +import { setCurrentIndex, setSelectedDate } from 'store/chart/chart.actions' +import { DateTime } from 'luxon' +import DateChartService from 'services/dateChart.service' interface LastDataConsumptionVisualizerProps { - fluidTypes: FluidType[] - timeStep: TimeStep - multiFluid: boolean - handleChangeIndex: (index: number) => void + lastDataDate: DateTime | null } -const LastDataConsumptionVisualizer = ({ - handleChangeIndex, + +const LastDataConsumptionVisualizer: React.FC<LastDataConsumptionVisualizerProps> = ({ + lastDataDate, }: LastDataConsumptionVisualizerProps) => { const { t } = useI18n() + const dispatch = useDispatch() + const { currentTimeStep } = useSelector( + (state: AppStore) => state.ecolyo.chart + ) + + const moveToDate = () => { + if (lastDataDate) { + const dateChartService = new DateChartService() + const updatedIndex: number = dateChartService.defineDateIndex( + currentTimeStep, + lastDataDate + ) + dispatch(setSelectedDate(lastDataDate)) + dispatch(setCurrentIndex(updatedIndex)) + } + } + return ( <div> - <button className="cv-button" onClick={() => handleChangeIndex(0)}> + <button className="lastdatavisualizer-button" onClick={moveToDate}> {t('CONSUMPTION.DISPLAY_LAST_DATA')} </button> </div> diff --git a/src/components/ConsumptionVisualizer/consumptionVisualizer.scss b/src/components/ConsumptionVisualizer/consumptionVisualizer.scss index 59e717757e20fce669c3ba5d6961327c7b09da93..5d614ea0f000e8c197e74b0d8a104cf5da315d5e 100644 --- a/src/components/ConsumptionVisualizer/consumptionVisualizer.scss +++ b/src/components/ConsumptionVisualizer/consumptionVisualizer.scss @@ -1,7 +1,7 @@ @import 'src/styles/base/color'; @import 'src/styles/base/breakpoint'; -.cv { +.consumptionvisualizer-root { display: flex; flex-direction: column; align-items: center; @@ -9,7 +9,7 @@ @media #{$large-phone} { width: 100%; } - .cv-info { + .consumptionvisualizer-info { min-height: 1.5rem; display: flex; align-items: center; diff --git a/src/components/ConsumptionVisualizer/dataloadConsumptionVisualizer.scss b/src/components/ConsumptionVisualizer/dataloadConsumptionVisualizer.scss index e31803e817fcaa9ff87d2713f1974ca587cb36d6..6c51f7f3536e9eb8f8ba9bc5b8e1e4899ea1f4c8 100644 --- a/src/components/ConsumptionVisualizer/dataloadConsumptionVisualizer.scss +++ b/src/components/ConsumptionVisualizer/dataloadConsumptionVisualizer.scss @@ -1,75 +1,75 @@ @import 'src/styles/base/color'; @import 'src/styles/base/breakpoint'; -.cv-load { +.dataloadvisualizer-root { min-height: 5.25rem; display: flex; align-items: center; - .cv-load-content { +} +.dataloadvisualizer-content { + display: flex; + flex-direction: row; + align-items: center; + color: $grey-bright; + .dataloadvisualizer-section { display: flex; - flex-direction: row; + flex-direction: column; align-items: center; - color: $grey-bright; - .cv-load-section { - display: flex; - flex-direction: column; - align-items: center; - padding: 0.5rem 0.5rem; - &.cv-load-section-left { - align-items: flex-end; - } - &.cv-load-section-right { - align-items: flex-start; - } - .cv-load-value { - flex-direction: row; - & span { - align-self: flex-end; - margin-left: 0.5em; - } - } - .electricity { - color: $elec-color; - } - .electricity-compare { - color: $elec-compare-color; - } - .water { - color: $water-color; - } - .water-compare { - color: $water-compare-color; - } - .gas { - color: $gas-color; - } - .gas-compare { - color: $gas-compare-color; - } - .multifluid { - color: $white; - } - .multifluid-compare { - color: $multi-compare-color; - } - .error { - color: $red-primary; + padding: 0.5rem 0.5rem; + &.dataloadvisualizer-section-left { + align-items: flex-end; + } + &.dataloadvisualizer-section-right { + align-items: flex-start; + } + .dataloadvisualizer-value { + flex-direction: row; + & span { + align-self: flex-end; + margin-left: 0.5em; } } + .electricity { + color: $elec-color; + } + .electricity-compare { + color: $elec-compare-color; + } + .water { + color: $water-color; + } + .water-compare { + color: $water-compare-color; + } + .gas { + color: $gas-color; + } + .gas-compare { + color: $gas-compare-color; + } + .multifluid { + color: $white; + } + .multifluid-compare { + color: $multi-compare-color; + } + .error { + color: $red-primary; + } } } -.cv-euro { +.dataloadvisualizer-euro { display: flex; flex-direction: row; - .cv-euro-link { + .dataloadvisualizer-euro-link { text-decoration: none; color: transparent; } - .cv-euro-fluid { + .dataloadvisualizer-euro-fluid { padding: 0 0.5rem; display: flex; align-items: center; - .cv-euro-fluid-icon { + .dataloadvisualizer-euro-fluid-icon { margin-right: 0.5rem; } & div { diff --git a/src/components/ConsumptionVisualizer/lastDataConsumptionVisualizer.scss b/src/components/ConsumptionVisualizer/lastDataConsumptionVisualizer.scss index 444c235496d97dca00f027b5648a9d22392b8108..5a85afc6488c765c77a13c652af4c52569a51884 100644 --- a/src/components/ConsumptionVisualizer/lastDataConsumptionVisualizer.scss +++ b/src/components/ConsumptionVisualizer/lastDataConsumptionVisualizer.scss @@ -1,6 +1,6 @@ @import 'src/styles/base/color'; -.cv-button { +.lastdatavisualizer-button { border: none; background: none; color: $soft-grey; diff --git a/src/components/DateNavigator/DateNavigator.tsx b/src/components/DateNavigator/DateNavigator.tsx index f1e20928efe8ae03d01aedc5f8b83382822dba48..1f312ce80d3847fe3791dc332e97f821d0b1fe21 100644 --- a/src/components/DateNavigator/DateNavigator.tsx +++ b/src/components/DateNavigator/DateNavigator.tsx @@ -39,12 +39,12 @@ const DateNavigator: React.FC = () => { selectedDate, increment ) - const UpdatedIndex: number = dateChartService.defineDateIndex( + const updatedIndex: number = dateChartService.defineDateIndex( currentTimeStep, updatedDate ) dispatch(setSelectedDate(updatedDate)) - dispatch(setCurrentIndex(UpdatedIndex)) + dispatch(setCurrentIndex(updatedIndex)) } const handleChangePrevIndex = () => { diff --git a/src/components/FluidChart/FluidChart.tsx b/src/components/FluidChart/FluidChart.tsx index 2293d3e8633c70ca7ad9bdf1686e1945f3686fb1..5c6387562ebafb99cf600f97e79ee0efd538aed1 100644 --- a/src/components/FluidChart/FluidChart.tsx +++ b/src/components/FluidChart/FluidChart.tsx @@ -1,50 +1,44 @@ import React, { useState, useEffect } from 'react' +import './fluidChart.scss' +import { useI18n } from 'cozy-ui/transpiled/react/I18n' import { useClient } from 'cozy-client' -import { DateTime } from 'luxon' +import { useSelector } from 'react-redux' +import { AppStore } from 'store' +import useExploration from 'components/Hooks/useExploration' import { FluidType } from 'enum/fluid.enum' import { TimeStep } from 'enum/timeStep.enum' +import { UserExplorationID } from 'enum/userExploration.enum' import ConsumptionService from 'services/consumption.service' -import FluidChartContent from 'components/FluidChart/FluidChartContent' +import Switch from 'components/CommonKit/Switch/StyledSwitch' +import TimeStepSelector from 'components/TimeStepSelector/TimeStepSelector' import ActivateHalfHourLoad from 'components/ConsumptionNavigator/ActivateHalfHourLoad' -import './fluidChart.scss' -import useExploration from 'components/Hooks/useExploration' -import { UserExplorationID } from 'enum/userExploration.enum' +import FluidChartSwipe from './FluidChartSwipe' +import ConsumptionVisualizer from 'components/ConsumptionVisualizer/ConsumptionVisualizer' + interface FluidChartProps { - timeStep: TimeStep fluidTypes: FluidType[] - resetReferenceDate: boolean multiFluid: boolean - setChartLoaded(): void } const FluidChart: React.FC<FluidChartProps> = ({ - timeStep, fluidTypes, - resetReferenceDate, multiFluid, - setChartLoaded, }: FluidChartProps) => { + const { t } = useI18n() const client = useClient() - const [, setValidExploration] = useExploration() - const [lastDataDate, setLastDataDate] = useState<DateTime>( - DateTime.local().setZone('utc', { - keepLocalTime: true, - }) - ) - const [lastDateWithAllData, setLastDateWithAllData] = useState<DateTime>( - DateTime.local().setZone('utc', { - keepLocalTime: true, - }) + const { currentTimeStep } = useSelector( + (state: AppStore) => state.ecolyo.chart ) + const [, setValidExploration] = useExploration() const [isMinuteBlocked, setMinuteBlocked] = useState<boolean>(false) - const [referenceDate, setReferenceDate] = useState<DateTime>( - DateTime.local().setZone('utc', { - keepLocalTime: true, - }) - ) const [isLoaded, setIsLoaded] = useState<boolean>(false) + const [showCompare, setShowCompare] = useState<boolean>(false) + + const handleChangeSwitch = () => { + setShowCompare(!showCompare) + } useEffect(() => { let subscribed = true @@ -54,72 +48,61 @@ const FluidChart: React.FC<FluidChartProps> = ({ FluidType.ELECTRICITY, TimeStep.HALF_AN_HOUR )) - - const data = await consumptionService.fetchLastDateData(fluidTypes) - const dataWithAllFluids = await consumptionService.fetchLastDateData( - fluidTypes, - true - ) - if (subscribed && data) { - setLastDataDate(data) - setReferenceDate(data) - } - if (subscribed && dataWithAllFluids) { - setLastDateWithAllData(dataWithAllFluids) - } if (subscribed && activateHalfHourLoad) { setMinuteBlocked(true) + setIsLoaded(true) } - if ( - subscribed && - !activateHalfHourLoad && - timeStep === TimeStep.HALF_AN_HOUR - ) { - setValidExploration(UserExplorationID.EXPLORATION006) - } - setChartLoaded() - setIsLoaded(true) } loadData() return () => { subscribed = false } - }, [client, fluidTypes, setChartLoaded, setValidExploration, timeStep]) + }, [client]) useEffect(() => { - let subscribed = true - async function reset() { - if (subscribed && resetReferenceDate) { - setReferenceDate(lastDataDate) - setChartLoaded() - setIsLoaded(true) - } - } - reset() - return () => { - subscribed = false + if (!isMinuteBlocked && currentTimeStep === TimeStep.HALF_AN_HOUR) { + setValidExploration(UserExplorationID.EXPLORATION006) } - }, [resetReferenceDate, lastDataDate, setChartLoaded]) + }, [isMinuteBlocked, currentTimeStep, setValidExploration]) return ( <> {isLoaded && ( <> - {isMinuteBlocked && timeStep === TimeStep.HALF_AN_HOUR && ( - <ActivateHalfHourLoad /> - )} - <div className="fc-root"> - <div className="fc-content"> - <FluidChartContent - referenceDate={referenceDate} - lastDataDate={lastDataDate} - lastDateWithAllData={lastDateWithAllData} - fluidTypes={fluidTypes} - timeStep={timeStep} - multiFluid={multiFluid} - isDataLoaded={isLoaded} - ></FluidChartContent> - </div> + <div className="fluidchart-root"> + {isMinuteBlocked && currentTimeStep === TimeStep.HALF_AN_HOUR ? ( + <ActivateHalfHourLoad /> + ) : ( + <div className="fluidchart-content"> + <ConsumptionVisualizer + fluidTypes={fluidTypes} + showCompare={showCompare} + multiFluid={multiFluid} + /> + <FluidChartSwipe + fluidTypes={fluidTypes} + multiFluid={multiFluid} + showCompare={showCompare} + /> + </div> + )} + <TimeStepSelector fluidType={FluidType.MULTIFLUID} /> + {!multiFluid && currentTimeStep !== TimeStep.YEAR ? ( + <div className="fluidchart-footer" onClick={handleChangeSwitch}> + <div className="fluidchart-footer-compare text-15-normal"> + <Switch fluidTypes={fluidTypes} checked={showCompare} /> + <span + className={ + showCompare + ? `fluidchart-footer-label graph-switch-text selected` + : `fluidchart-footer-label graph-switch-text` + } + > + {t(`TIMESTEP.${TimeStep[currentTimeStep]}.COMPARELABEL`)} + </span> + </div> + </div> + ) : null} </div> </> )} diff --git a/src/components/FluidChart/FluidChartContent.tsx b/src/components/FluidChart/FluidChartContent.tsx deleted file mode 100644 index ac67364f537e41f56dd48357b899c1d70e02e532..0000000000000000000000000000000000000000 --- a/src/components/FluidChart/FluidChartContent.tsx +++ /dev/null @@ -1,168 +0,0 @@ -import React, { useState, useEffect, useCallback } from 'react' -import { useI18n } from 'cozy-ui/transpiled/react/I18n' -import { DateTime } from 'luxon' - -import { FluidType } from 'enum/fluid.enum' -import { TimeStep } from 'enum/timeStep.enum' -import { Dataload } from 'models' -import DateChartService from 'services/dateChart.service' - -import Switch from 'components/CommonKit/Switch/StyledSwitch' -import FluidChartSwipe from 'components/FluidChart/FluidChartSwipe' -import ConsumptionVisualizer from 'components/ConsumptionVisualizer/ConsumptionVisualizer' -import './fluidChartContent.scss' - -interface FluidChartContentProps { - fluidTypes: FluidType[] - timeStep: TimeStep - referenceDate: DateTime - lastDataDate: DateTime - lastDateWithAllData: DateTime - multiFluid: boolean - isDataLoaded: boolean -} - -const FluidChartContent: React.FC<FluidChartContentProps> = ({ - fluidTypes, - timeStep, - referenceDate, - lastDataDate, - lastDateWithAllData, - multiFluid, - isDataLoaded, -}: FluidChartContentProps) => { - const { t } = useI18n() - const [indexDisplayed, setIndexDisplayed] = useState<number>(0) - const [selectedDate, setSelectedDate] = useState<DateTime>(referenceDate) - const [selectedDataload, setSelectedDataload] = useState<Dataload>({ - date: DateTime.local().setZone('utc', { - keepLocalTime: true, - }), - value: 0, - valueDetail: null, - }) - const [selectedCompareDataload, setSelectedComparedataload] = useState< - Dataload - >({ - date: DateTime.local().setZone('utc', { - keepLocalTime: true, - }), - value: 0, - valueDetail: null, - }) - const [showCompare, setShowCompare] = useState<boolean>(false) - const [isLoaded, setIsLoaded] = useState<boolean>(true) - - const handleChangeIndex = useCallback( - (index: number) => { - const dateChartService = new DateChartService() - const date = - index === 0 - ? referenceDate - : dateChartService.defineLastStepDate(referenceDate, timeStep, index) - setSelectedDate(date) - setIndexDisplayed(index) - setIsLoaded(false) - }, - [referenceDate, timeStep] - ) - - const handleClickData = useCallback( - (dataload: Dataload, compareDataload: Dataload | null) => { - setSelectedDate(dataload.date) - setSelectedDataload(dataload) - if (compareDataload) { - setSelectedComparedataload(compareDataload) - } - setIsLoaded(true) - }, - [] - ) - - const handleClickMove = useCallback( - (increment: number) => { - const dateChartService = new DateChartService() - const { - incrementIndex, - incrementedDate, - } = dateChartService.incrementDate( - increment, - selectedDate, - timeStep, - lastDataDate - ) - setSelectedDate(incrementedDate) - if (incrementIndex != 0) { - setIndexDisplayed(indexDisplayed + incrementIndex) - setIsLoaded(false) - } - }, - [indexDisplayed, lastDataDate, selectedDate, timeStep] - ) - - const handleChangeSwitch = () => { - setShowCompare(!showCompare) - } - - useEffect(() => { - setSelectedDate(referenceDate) - setIndexDisplayed(0) - setIsLoaded(false) - }, [referenceDate, timeStep, fluidTypes]) - - return ( - <div className="fv-root"> - <div className="fv-header"> - <ConsumptionVisualizer - fluidTypes={fluidTypes} - timeStep={timeStep} - date={selectedDate} - dataload={selectedDataload} - compareDataload={selectedCompareDataload} - showCompare={showCompare} - multiFluid={multiFluid} - lastDataDate={lastDataDate} - lastDateWithAllData={lastDateWithAllData} - isLoaded={isLoaded} - indexDisplayed={indexDisplayed} - setSelectedDate={setSelectedDate} - setIndexDisplayed={setIndexDisplayed} - handleClickMove={handleClickMove} - handleChangeIndex={handleChangeIndex} - /> - </div> - - {isDataLoaded && ( - <FluidChartSwipe - fluidTypes={fluidTypes} - timeStep={timeStep} - multiFluid={multiFluid} - referenceDate={referenceDate} - selectedDate={selectedDate} - indexDisplayed={indexDisplayed} - showCompare={showCompare} - handleChangeIndex={handleChangeIndex} - handleClickData={handleClickData} - /> - )} - {!multiFluid && timeStep !== TimeStep.YEAR ? ( - <div className="fv-footer" onClick={handleChangeSwitch}> - <div className="fv-footer-compare text-15-normal"> - <Switch fluidTypes={fluidTypes} checked={showCompare} /> - <span - className={ - showCompare - ? `fv-footer-label graph-switch-text selected` - : `fv-footer-label graph-switch-text` - } - > - {t(`TIMESTEP.${TimeStep[timeStep]}.COMPARELABEL`)} - </span> - </div> - </div> - ) : null} - </div> - ) -} - -export default FluidChartContent diff --git a/src/components/FluidChart/FluidChartSlide.tsx b/src/components/FluidChart/FluidChartSlide.tsx index e0524a87f149362686ea76c1a20fbba0fba589e6..55713b48e39c18d5be107ac38dbfed614f04bd4e 100644 --- a/src/components/FluidChart/FluidChartSlide.tsx +++ b/src/components/FluidChart/FluidChartSlide.tsx @@ -1,148 +1,112 @@ import React, { useState, useEffect } from 'react' +import './fluidChartSlide.scss' import { useClient } from 'cozy-client' -import { useDispatch } from 'react-redux' -import { addMaxLoad } from 'store/chart/chart.actions' - +import { useDispatch, useSelector } from 'react-redux' +import { AppStore } from 'store' +import { setCurrentDatachart, setLoading } from 'store/chart/chart.actions' import { DateTime } from 'luxon' import { FluidType } from 'enum/fluid.enum' -import { TimeStep } from 'enum/timeStep.enum' -import { Datachart, Dataload } from 'models' +import { Datachart } from 'models' import ConsumptionService from 'services/consumption.service' import DateChartService from 'services/dateChart.service' import BarChart from 'components/Charts/BarChart' import StyledSpinner from 'components/CommonKit/Spinner/StyledSpinner' -import './fluidChartSlide.scss' interface FluidChartSlideProps { index: number fluidTypes: FluidType[] - timeStep: TimeStep multiFluid: boolean - referenceDate: DateTime - selectedDate: DateTime showCompare: boolean width: number height: number - handleClickData: ( - dataload: Dataload, - compareDataload: Dataload | null - ) => void isSwitching: boolean } const FluidChartSlide: React.FC<FluidChartSlideProps> = ({ index, fluidTypes, - timeStep, multiFluid, - referenceDate, - selectedDate, showCompare, width, height, - handleClickData, isSwitching, }: FluidChartSlideProps) => { const client = useClient() const dispatch = useDispatch() + const { currentTimeStep, currentIndex } = useSelector( + (state: AppStore) => state.ecolyo.chart + ) const [chartData, setChartData] = useState<Datachart>({ actualData: [], comparisonData: null, }) const [isLoaded, setIsLoaded] = useState<boolean>(false) - const isHome: boolean = !window.location.hash.split('/')[2] ? true : false - useEffect(() => { let subscribed = true async function loadData() { const dateChartService = new DateChartService() + const referenceDate = DateTime.local().setZone('utc', { + keepLocalTime: true, + }) const [timePeriod, compareTimePeriod] = await Promise.all([ - dateChartService.defineTimePeriod(referenceDate, timeStep, index), - dateChartService.defineTimePeriod(referenceDate, timeStep, index + 1), + dateChartService.defineTimePeriod( + referenceDate, + currentTimeStep, + index + ), + dateChartService.defineTimePeriod( + referenceDate, + currentTimeStep, + index + 1 + ), ]) const consumptionService = new ConsumptionService(client) const graphData = await consumptionService.getGraphData( timePeriod, - timeStep, + currentTimeStep, fluidTypes, compareTimePeriod, - isHome + multiFluid ) - - if ( - graphData && - graphData.actualData.length > 0 && - (timeStep === TimeStep.DAY || timeStep === TimeStep.HALF_AN_HOUR) - ) { - const lastSlideDate = - graphData.actualData[graphData.actualData.length - 1].date - const actualMonth = lastSlideDate.startOf('week').month - const actualYear = lastSlideDate.startOf('week').year - - // From the first monday of the month to the first monday of the next month for for TimeStep.DAY - // Full month + last day of the previous month for TimeStep.HALF_AN_HOUR - - const maxTimePeriod = { - startDate: lastSlideDate.startOf('month'), - endDate: lastSlideDate.endOf('month'), - } - - const compareMaxTimePeriod = maxTimePeriod - - const key = `${actualMonth}/${actualYear}-${isHome}-${fluidTypes.join( - '-' - )}-${timeStep}` - - const graphMaxLoad = await consumptionService.getMaxLoad( - maxTimePeriod, - timeStep, - fluidTypes, - compareMaxTimePeriod, - isHome - ) - dispatch(addMaxLoad(new Map().set(key, graphMaxLoad))) - } - if (subscribed && graphData && graphData.actualData.length > 0) { setChartData(graphData) setIsLoaded(true) + dispatch(setLoading(false)) } } setIsLoaded(false) - loadData() return () => { subscribed = false } - }, [timeStep, fluidTypes, client, dispatch, index, isHome, referenceDate]) + }, [currentTimeStep, fluidTypes, client, dispatch, index, multiFluid]) + + useEffect(() => { + if (index === currentIndex) { + dispatch(setCurrentDatachart(chartData)) + } + }, [dispatch, index, currentIndex, chartData]) return ( - <> - <div className="fs-slide"> - {!isLoaded ? ( - <div className="chart-loading"> - <StyledSpinner size="5em" fluidTypes={fluidTypes} isHome={isHome} /> - </div> - ) : ( - <BarChart - chartData={chartData} - fluidTypes={fluidTypes} - timeStep={timeStep} - multiFluid={multiFluid} - selectedDate={selectedDate} - showCompare={showCompare} - handleClickData={handleClickData} - height={height} - width={width} - isSwitching={isSwitching} - isHome={isHome} - /> - )} - </div> - </> + <div className={'fluidchartslide-root'}> + {!isLoaded ? ( + <StyledSpinner size="5em" fluidTypes={fluidTypes} isHome={multiFluid} /> + ) : ( + <BarChart + chartData={chartData} + fluidTypes={fluidTypes} + multiFluid={multiFluid} + showCompare={showCompare} + height={height} + width={width} + isSwitching={isSwitching} + isHome={multiFluid} + /> + )} + </div> ) } diff --git a/src/components/FluidChart/FluidChartSwipe.tsx b/src/components/FluidChart/FluidChartSwipe.tsx index be91b745c35444650f69e3465704ab4b0fb7fe7b..8259ce84302d96927277fc77d0024f697489495a 100644 --- a/src/components/FluidChart/FluidChartSwipe.tsx +++ b/src/components/FluidChart/FluidChartSwipe.tsx @@ -1,48 +1,67 @@ import React, { useState, useEffect, useRef } from 'react' +import './fluidChartSwipe.scss' +import { useDispatch, useSelector } from 'react-redux' +import { AppStore } from 'store' +import { setCurrentIndex, setSelectedDate } from 'store/chart/chart.actions' import SwipeableViews from 'react-swipeable-views' import { virtualize } from 'react-swipeable-views-utils' import { DateTime } from 'luxon' -import { TimeStep } from 'enum/timeStep.enum' import { FluidType } from 'enum/fluid.enum' -import { Dataload } from 'models' - import FluidChartSlide from 'components/FluidChart/FluidChartSlide' -import './fluidChartSwipe.scss' +import DateChartService from 'services/dateChart.service' const VirtualizeSwipeableViews = virtualize(SwipeableViews) interface FluidChartSwipeProps { fluidTypes: FluidType[] - timeStep: TimeStep multiFluid: boolean - referenceDate: DateTime - selectedDate: DateTime - indexDisplayed: number showCompare: boolean - handleChangeIndex: (index: number) => void - handleClickData: ( - dataload: Dataload, - compareDataload: Dataload | null - ) => void } const FluidChartSwipe: React.FC<FluidChartSwipeProps> = ({ fluidTypes, - timeStep, multiFluid, - referenceDate, - selectedDate, - indexDisplayed, showCompare, - handleChangeIndex, - handleClickData, }: FluidChartSwipeProps) => { + const dispatch = useDispatch() + const { currentIndex, currentTimeStep, selectedDate } = useSelector( + (state: AppStore) => state.ecolyo.chart + ) const swipe = useRef<HTMLDivElement>(null) const [width, setWidth] = useState(0) const [height, setHeight] = useState(0) const [isSwitching, setIsSwitching] = useState(false) + const handleChangeIndex = (index: number) => { + const dateChartService = new DateChartService() + let increment = 0 + if (currentIndex < index) { + increment = dateChartService.defineIncrementForPreviousIndex( + currentTimeStep, + selectedDate, + currentIndex + ) + } else { + increment = dateChartService.defineIncrementForNextIndex( + currentTimeStep, + selectedDate, + currentIndex + ) + } + const updatedDate: DateTime = dateChartService.incrementeDate( + currentTimeStep, + selectedDate, + increment + ) + const updatedIndex: number = dateChartService.defineDateIndex( + currentTimeStep, + updatedDate + ) + dispatch(setSelectedDate(updatedDate)) + dispatch(setCurrentIndex(updatedIndex)) + } + useEffect(() => { function handleResize() { const maxWidth = 940 @@ -59,16 +78,30 @@ const FluidChartSwipe: React.FC<FluidChartSwipeProps> = ({ : swipe.current.offsetHeight : 300 setHeight(_height) + console.log(_width) + console.log(_height) } handleResize() window.addEventListener('resize', handleResize) return () => window.removeEventListener('resize', handleResize) }, []) + useEffect(() => { + function initIndex() { + const dateChartService = new DateChartService() + const updatedIndex: number = dateChartService.defineDateIndex( + currentTimeStep, + selectedDate + ) + dispatch(setCurrentIndex(updatedIndex)) + } + initIndex() + }, [dispatch, currentTimeStep, selectedDate]) + return ( - <div className="fs-root" ref={swipe}> + <div className={'fluidchartswipe-root'} ref={swipe}> <VirtualizeSwipeableViews - index={indexDisplayed} + index={currentIndex} overscanSlideAfter={1} overscanSlideBefore={1} onChangeIndex={handleChangeIndex} @@ -77,14 +110,10 @@ const FluidChartSwipe: React.FC<FluidChartSwipeProps> = ({ key={key} index={index} fluidTypes={fluidTypes} - timeStep={timeStep} multiFluid={multiFluid} - referenceDate={referenceDate} - selectedDate={selectedDate} showCompare={showCompare} width={width} height={height} - handleClickData={handleClickData} isSwitching={isSwitching} /> )} diff --git a/src/components/FluidChart/fluidChart.scss b/src/components/FluidChart/fluidChart.scss index 9dacb38810f738d2b8861e88a9b66c02a991428f..44ffe48e173b6ce2164e74a093427aa4aff9fc58 100644 --- a/src/components/FluidChart/fluidChart.scss +++ b/src/components/FluidChart/fluidChart.scss @@ -1,7 +1,8 @@ @import 'src/styles/base/color'; @import 'src/styles/base/breakpoint'; -.fc-root { +.fluidchart-root { + width: 100%; background-color: $dark-light-2; padding: 2rem 2rem 1rem 2rem; margin-bottom: 1rem; @@ -9,19 +10,14 @@ padding: 1.5rem 1rem 1rem 1rem; margin-bottom: 0.5rem; } - .fc-content { - min-height: 31.875rem; - @media #{$large-phone} { - min-height: 23.875rem; - } - .fc-loader { - min-height: 31.875rem; - @media #{$large-phone} { - min-height: 23.875rem; - } - display: flex; - justify-content: center; - align-items: center; - } - } } +.fluidchart-content { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + min-height: 29.5rem; + @media #{$large-phone} { + min-height: 21.5rem; + } +} \ No newline at end of file diff --git a/src/components/FluidChart/fluidChartContent.scss b/src/components/FluidChart/fluidChartContent.scss deleted file mode 100644 index 21ac4548f28e21f774941186b1534dccc1ed62d0..0000000000000000000000000000000000000000 --- a/src/components/FluidChart/fluidChartContent.scss +++ /dev/null @@ -1,64 +0,0 @@ -@import 'src/styles/base/color'; -@import 'src/styles/base/breakpoint'; - -//FluidView -.fv-root { - direction: 'rtl'; - .fv-nav-period { - display: flex; - flex-direction: row; - & .nav-button { - flex: 1; - font-size: large; - } - } - .fv-header { - display: flex; - flex-direction: column; - align-items: center; - min-height: 8.375rem; - margin-bottom: 0.25rem; - } - .fv-footer { - display: flex; - justify-content: center; - .fv-footer-compare { - width: 100%; - max-width: 58.75rem; - display: flex; - flex-direction: row; - align-items: center; - & :hover { - cursor: pointer; - } - & .fv-footer-label { - flex: 1; - display: flex; - justify-content: flex-start; - color: $soft-grey; - &.selected { - color: $white; - } - } - } - - .fv-footer-challenge { - width: 100%; - max-width: 58.75rem; - display: flex; - flex-direction: row; - align-items: center; - .fv-link { - text-decoration: none; - color: $soft-grey; - } - & .fv-footer-label-padding { - flex: 1; - display: flex; - justify-content: flex-start; - padding-left: 0.75rem; - color: $soft-grey; - } - } - } -} diff --git a/src/components/FluidChart/fluidChartSlide.scss b/src/components/FluidChart/fluidChartSlide.scss index 0a247a3238cbcaea32d389a34989555973063e18..e3dfd501719afc8f8af171f048f42e3074106c03 100644 --- a/src/components/FluidChart/fluidChartSlide.scss +++ b/src/components/FluidChart/fluidChartSlide.scss @@ -1,6 +1,6 @@ @import 'src/styles/base/breakpoint'; -.fs-slide { +.fluidchartslide-root { min-height: 22rem; overflow-x: hidden; display: flex; @@ -9,11 +9,4 @@ @media #{$large-phone} { min-height: 14rem; } - .chart-none { - visibility: hidden; - width: 0; - } - .chart-block { - visibility: visible; - } } diff --git a/src/components/FluidChart/fluidChartSwipe.scss b/src/components/FluidChart/fluidChartSwipe.scss index df38cdc35b13e30ad0988e539276d615072f4fe2..601f2e9a2d3a0797ee28f542b4e7fd1e39b328f3 100644 --- a/src/components/FluidChart/fluidChartSwipe.scss +++ b/src/components/FluidChart/fluidChartSwipe.scss @@ -1,15 +1,9 @@ @import 'src/styles/base/breakpoint'; -//FluidSwipe -.fs-root { +.fluidchartswipe-root { flex: 1; height: 22rem; @media #{$large-phone} { height: 14rem; } - .chart-loading { - width: 100%; - justify-content: center; - display: flex; - } } diff --git a/src/components/Home/HomeIndicators.tsx b/src/components/Home/HomeIndicators.tsx index e2687dcff2103d0a0ecabadf9b0c1dc305464e39..02409abc22f620cbfbf461b34bac242aba615bef 100644 --- a/src/components/Home/HomeIndicators.tsx +++ b/src/components/Home/HomeIndicators.tsx @@ -19,12 +19,10 @@ import KonnectorViewerCard from 'components/Konnector/KonnectorViewerCard' interface HomeIndicatorsProps { timeStep: TimeStep - setIndicatorsLoaded(): void } const HomeIndicators: React.FC<HomeIndicatorsProps> = ({ timeStep, - setIndicatorsLoaded, }: HomeIndicatorsProps) => { const { t } = useI18n() const client = useClient() @@ -77,14 +75,13 @@ const HomeIndicators: React.FC<HomeIndicatorsProps> = ({ setCurrentTimePeriod(periods.timePeriod) } } - setIndicatorsLoaded() setIsLoaded(true) } populatePerformanceIndicators() return () => { subscribed = false } - }, [timeStep, fluidTypes, client, setIndicatorsLoaded]) + }, [timeStep, fluidTypes, client]) return ( <> diff --git a/src/components/Home/HomeView.tsx b/src/components/Home/HomeView.tsx index 76a9df467da2438a59e2bba9c2737e1c8c65af52..4abdf99035b3207b1604efa586f658dcc5c4b1f6 100644 --- a/src/components/Home/HomeView.tsx +++ b/src/components/Home/HomeView.tsx @@ -1,41 +1,37 @@ import React, { useState, useEffect, useCallback } from 'react' +import './homeView.scss' +import classNames from 'classnames' import { useSelector, useDispatch } from 'react-redux' import { AppStore } from 'store' import { updateProfile } from 'store/profile/profile.actions' -import { setPreviousTimeStep } from 'store/chart/chart.actions' - -import { TimeStep } from 'enum/timeStep.enum' - import StyledSpinner from 'components/CommonKit/Spinner/StyledSpinner' import CozyBar from 'components/Header/CozyBar' import Header from 'components/Header/Header' import Content from 'components/Content/Content' import FluidChart from 'components/FluidChart/FluidChart' -import ConsumptionNavigator from 'components/ConsumptionNavigator/ConsumptionNavigator' + import HomeIndicators from 'components/Home/HomeIndicators' import KonnectorViewerList from 'components/Konnector/KonnectorViewerList' import OldFluidDataModal from 'components/Home/OldFluidDataModal' import { FluidState, FluidType } from 'enum/fluid.enum' import { DateTime } from 'luxon' +import DateNavigator from 'components/DateNavigator/DateNavigator' +import { Profile } from 'models' +import { setLoading, setSelectedDate } from 'store/chart/chart.actions' const HomeView: React.FC = () => { const dispatch = useDispatch() const { fluidStatus, fluidTypes } = useSelector( (state: AppStore) => state.ecolyo.global ) - const profile = useSelector((state: AppStore) => state.ecolyo.profile) - const { previousTimeStep } = useSelector( - (state: AppStore) => state.ecolyo.chart + const profile: Profile = useSelector( + (state: AppStore) => state.ecolyo.profile ) - - const [timeStep, setTimeStep] = useState<TimeStep>( - previousTimeStep !== TimeStep.HALF_AN_HOUR ? previousTimeStep : TimeStep.DAY + const { currentTimeStep, loading } = useSelector( + (state: AppStore) => state.ecolyo.chart ) - const [resetRefenceDate, setResetReferenceDate] = useState<boolean>(false) const [headerHeight, setHeaderHeight] = useState<number>(0) - const [isChartLoading, setChartLoading] = useState<boolean>(true) - const [isIndicatorsLoading, setIndicatorsLoading] = useState<boolean>(true) const [openOldFluidDataModal, setopenOldFluidDataModal] = useState(false) const [fluidOldData] = useState<FluidType[]>([]) @@ -49,23 +45,6 @@ const HomeView: React.FC = () => { ) }, [dispatch]) - const setChartLoaded = useCallback(() => { - setChartLoading(false) - }, []) - - const setIndicatorsLoaded = useCallback(() => { - setIndicatorsLoading(false) - }, []) - - const handleClickTimeStepForNavigation = useCallback( - (_timeStep: TimeStep) => { - setResetReferenceDate(true) - setTimeStep(_timeStep) - dispatch(setPreviousTimeStep(_timeStep)) - }, - [dispatch] - ) - const defineHeaderHeight = (height: number) => { setHeaderHeight(height) } @@ -119,49 +98,47 @@ const HomeView: React.FC = () => { async function checkData() { await checkFluidDataPeriod() } + dispatch(setLoading(true)) checkData() - }, [checkFluidDataPeriod]) + }, [dispatch, checkFluidDataPeriod]) + + useEffect(() => { + async function defineLastDataDate() { + const refDate: DateTime = DateTime.fromISO('0001-01-01') + let lastDataDate: DateTime | null = DateTime.fromISO('0001-01-01') + for (const fluid of fluidStatus) { + if (fluid.lastDataDate && fluid.lastDataDate > lastDataDate) { + lastDataDate = fluid.lastDataDate + } + } + if (lastDataDate > refDate) { + dispatch(setSelectedDate(lastDataDate)) + } + } + defineLastDataDate() + }, [dispatch, fluidStatus]) return ( <React.Fragment> <CozyBar /> {fluidTypes && fluidTypes.length > 0 ? ( <> - <Header - setHeaderHeight={defineHeaderHeight} - textKey={'COMMON.APP_PRESENTATION'} - > - <ConsumptionNavigator - fluidTypes={fluidTypes} - multiFluid={true} - timeStep={timeStep} - handleClickTimeStep={handleClickTimeStepForNavigation} - /> + <Header setHeaderHeight={defineHeaderHeight}> + <DateNavigator /> </Header> <Content height={headerHeight}> - {(isChartLoading || isIndicatorsLoading) && ( - <div className="content-view-loading"> + {loading && ( + <div className={'homeview-loading'}> <StyledSpinner size="5em" /> </div> )} <div - className={`${ - isChartLoading || isIndicatorsLoading - ? 'chart-indicator-none' - : 'chart-indicator-block' - }`} + className={classNames('homeview-content', { + ['--hidden']: loading, + })} > - <FluidChart - timeStep={timeStep} - fluidTypes={fluidTypes} - resetReferenceDate={resetRefenceDate} - multiFluid={true} - setChartLoaded={setChartLoaded} - /> - <HomeIndicators - timeStep={timeStep} - setIndicatorsLoaded={setIndicatorsLoaded} - /> + <FluidChart fluidTypes={fluidTypes} multiFluid={true} /> + <HomeIndicators timeStep={currentTimeStep} /> </div> </Content> {fluidStatus.length > 0 && openOldFluidDataModal && ( diff --git a/src/components/Home/homeView.scss b/src/components/Home/homeView.scss new file mode 100644 index 0000000000000000000000000000000000000000..e335b31f710473862ee4ad0beccd32ea5cfaf920 --- /dev/null +++ b/src/components/Home/homeView.scss @@ -0,0 +1,19 @@ +@import 'src/styles/base/color'; +@import 'src/styles/base/breakpoint'; + +.homeview-loading { + height: 80vh; + width: 100%; + display: flex; + justify-content: center; + align-items: center; +} +.homeview-content { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + &.--hidden{ + display: none; + } +} \ No newline at end of file diff --git a/src/components/PerformanceIndicator/PerformanceIndicatorContent.tsx b/src/components/PerformanceIndicator/PerformanceIndicatorContent.tsx index d22b9781d0a7f724c278b91382cccbb4ef72df16..baa8d516bedeaf225be1b00d246439f1ace7f6cc 100644 --- a/src/components/PerformanceIndicator/PerformanceIndicatorContent.tsx +++ b/src/components/PerformanceIndicator/PerformanceIndicatorContent.tsx @@ -64,23 +64,18 @@ const PerformanceIndicatorContent: React.FC<PerformanceIndicatorContentProps> = case TimeStep.HALF_AN_HOUR: frequency += 'DAILY_FRENQUENCY' break - - case TimeStep.HOUR: - frequency += 'DAILY_FRENQUENCY' + case TimeStep.WEEK: + frequency += 'WEEKLY_FRENQUENCY' break - case TimeStep.DAY: frequency += 'MONTHLY_FRENQUENCY' break - case TimeStep.MONTH: frequency += 'MONTHLY_FRENQUENCY' break - case TimeStep.YEAR: frequency += 'YEARLY_FRENQUENCY' break - default: return '' } diff --git a/src/components/SingleFluid/SingleFluidIndicators.tsx b/src/components/SingleFluid/SingleFluidIndicators.tsx index 6b0a5d73cfb88f4295b0cab6d7f8516053492edc..1c426f0e37ec4952f8cb9b39ec2481f65654cfef 100644 --- a/src/components/SingleFluid/SingleFluidIndicators.tsx +++ b/src/components/SingleFluid/SingleFluidIndicators.tsx @@ -1,4 +1,5 @@ import React, { useEffect, useState } from 'react' +import './singleFluidIndicators.scss' import { useI18n } from 'cozy-ui/transpiled/react/I18n' import { useClient } from 'cozy-client' import { useSelector } from 'react-redux' @@ -14,16 +15,14 @@ import PerformanceIndicatorService from 'services/performanceIndicator.service' import PerformanceIndicatorContent from 'components/PerformanceIndicator/PerformanceIndicatorContent' import SingleFluidRedirect from 'components/SingleFluid/SingleFluidRedirect' -import './singleFluidIndicators.scss' + interface SingleFluidIndicatorsProps { timeStep: TimeStep - setIndicatorsLoaded(): void fluidTypes: FluidType[] } const SingleFluidIndicators: React.FC<SingleFluidIndicatorsProps> = ({ timeStep, - setIndicatorsLoaded, fluidTypes, }: SingleFluidIndicatorsProps) => { const { t } = useI18n() @@ -72,14 +71,13 @@ const SingleFluidIndicators: React.FC<SingleFluidIndicatorsProps> = ({ setPerformanceIndicators(fetchedPerformanceIndicators) setCurrentTimePeriod(periods.timePeriod) setComparisonTimePeriod(periods.comparisonTimePeriod) - setIndicatorsLoaded() setIsLoaded(true) } } } populatePerformanceIndicators() - }, [timeStep, client, fluidTypes, setIndicatorsLoaded]) + }, [timeStep, client, fluidTypes]) return ( <> diff --git a/src/components/SingleFluid/SingleFluidView.spec.tsx b/src/components/SingleFluid/SingleFluidView.spec.tsx index de765fb70a23413e79b8771ff6944a50bfbc0cf1..aef9300c80e8539b32cb9c61e52488483f7d36f7 100644 --- a/src/components/SingleFluid/SingleFluidView.spec.tsx +++ b/src/components/SingleFluid/SingleFluidView.spec.tsx @@ -1,8 +1,8 @@ import React from 'react' import { shallow } from 'enzyme' import SingleFluidView from 'components/SingleFluid/SingleFluidView' -import { chartStateData } from '../../../test/__mocks__/chartStateData.mock' import { FluidType } from 'enum/fluid.enum' +import { mockInitialChartState } from '../../../test/__mocks__/store' jest.mock('cozy-ui/transpiled/react/I18n', () => ({ useI18n: jest.fn().mockResolvedValue({ @@ -10,7 +10,7 @@ jest.mock('cozy-ui/transpiled/react/I18n', () => ({ }), })) -const mockUseSelector = chartStateData +const mockUseSelector = mockInitialChartState jest.mock('react-redux', () => ({ useSelector: jest.fn().mockResolvedValue(mockUseSelector), useDispatch: () => jest.fn(), diff --git a/src/components/SingleFluid/SingleFluidView.tsx b/src/components/SingleFluid/SingleFluidView.tsx index e883cb98e1ff5c1ca39f57d67d0b94510f81b242..b9eacbed7becff16259686504ee8c3df0b624720 100644 --- a/src/components/SingleFluid/SingleFluidView.tsx +++ b/src/components/SingleFluid/SingleFluidView.tsx @@ -1,7 +1,8 @@ -import React, { useCallback, useState } from 'react' +import React, { useCallback, useEffect, useState } from 'react' +import './singleFluidView.scss' import { useSelector, useDispatch } from 'react-redux' import { AppStore } from 'store' -import { setPreviousTimeStep } from 'store/chart/chart.actions' +import classNames from 'classnames' import { FluidType } from 'enum/fluid.enum' import { TimeStep } from 'enum/timeStep.enum' @@ -11,9 +12,10 @@ import CozyBar from 'components/Header/CozyBar' import Header from 'components/Header/Header' import Content from 'components/Content/Content' import FluidChart from 'components/FluidChart/FluidChart' -import ConsumptionNavigator from 'components/ConsumptionNavigator/ConsumptionNavigator' +import DateNavigator from 'components/DateNavigator/DateNavigator' import SingleFluidIndicators from 'components/SingleFluid/SingleFluidIndicators' -import './singleFluidView.scss' +import { setCurrentTimeStep, setLoading } from 'store/chart/chart.actions' + interface SingleFluidViewProps { fluidTypes: FluidType[] } @@ -21,40 +23,26 @@ const SingleFluidView: React.FC<SingleFluidViewProps> = ({ fluidTypes, }: SingleFluidViewProps) => { const dispatch = useDispatch() - const { previousTimeStep } = useSelector( + const { currentTimeStep, loading } = useSelector( (state: AppStore) => state.ecolyo.chart ) - const [timeStep, setTimeStep] = useState<TimeStep>( - previousTimeStep !== TimeStep.HALF_AN_HOUR ? previousTimeStep : TimeStep.DAY - ) - const [resetRefenceDate, setResetReferenceDate] = useState<boolean>(false) const [headerHeight, setHeaderHeight] = useState<number>(0) - const [isChartLoading, setChartLoading] = useState<boolean>(true) - const [isIndicatorsLoading, setIndicatorsLoading] = useState<boolean>(true) - - const setChartLoaded = useCallback(() => { - setChartLoading(false) - }, []) - - const setIndicatorsLoaded = useCallback(() => { - setIndicatorsLoading(false) - }, []) - - const handleClickTimeStepForNavigation = useCallback( - (_timeStep: TimeStep) => { - setResetReferenceDate(true) - setTimeStep(_timeStep) - dispatch(setPreviousTimeStep(_timeStep)) - }, - [dispatch] - ) - const defineHeaderHeight = useCallback((height: number) => { setHeaderHeight(height) }, []) + useEffect(() => { + if ( + fluidTypes[0] !== FluidType.ELECTRICITY && + currentTimeStep == TimeStep.HALF_AN_HOUR + ) { + dispatch(setCurrentTimeStep(TimeStep.WEEK)) + } + dispatch(setLoading(true)) + }, [dispatch, fluidTypes, currentTimeStep]) + return ( <> <CozyBar @@ -66,36 +54,22 @@ const SingleFluidView: React.FC<SingleFluidViewProps> = ({ desktopTitleKey={`FLUID.${FluidType[fluidTypes[0]]}.NAME`} displayBackArrow={true} > - <ConsumptionNavigator - fluidTypes={fluidTypes} - multiFluid={false} - timeStep={timeStep} - handleClickTimeStep={handleClickTimeStepForNavigation} - /> + <DateNavigator /> </Header> <Content height={headerHeight}> - {(isChartLoading || isIndicatorsLoading) && ( - <div className="content-view-loading"> + {loading && ( + <div className={'singlefluidview-loading'}> <StyledSpinner size="5em" fluidTypes={fluidTypes} /> </div> )} <div - className={`${ - isChartLoading || isIndicatorsLoading - ? 'chart-indicator-none' - : 'chart-indicator-block' - }`} + className={classNames('singlefluidview-content', { + ['--hidden']: loading, + })} > - <FluidChart - timeStep={timeStep} - fluidTypes={fluidTypes} - resetReferenceDate={resetRefenceDate} - multiFluid={false} - setChartLoaded={setChartLoaded} - /> + <FluidChart fluidTypes={fluidTypes} multiFluid={false} /> <SingleFluidIndicators - timeStep={timeStep} - setIndicatorsLoaded={setIndicatorsLoaded} + timeStep={currentTimeStep} fluidTypes={fluidTypes} /> </div> diff --git a/src/components/SingleFluid/singleFluidView.scss b/src/components/SingleFluid/singleFluidView.scss index bf7115a90b235139a5eba3b36aad13e5329a5517..ea0710d56c1529f35382033666ba0c13c8a52921 100644 --- a/src/components/SingleFluid/singleFluidView.scss +++ b/src/components/SingleFluid/singleFluidView.scss @@ -1,8 +1,16 @@ -.chart-indicator-none { - visibility: hidden; - height: 0; -} -.chart-indicator-block { - visibility: visible; - height: auto; +.singlefluidview-loading { + height: 80vh; + width: 100%; + display: flex; + justify-content: center; + align-items: center; } +.singlefluidview-content { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + &.--hidden{ + display: none; + } +} \ No newline at end of file diff --git a/src/components/TimeStepSelector/timeStepSelector.scss b/src/components/TimeStepSelector/timeStepSelector.scss index 899aa0d4fd13ea5c833c4572553906a0370b9616..30acd69233c963a4abcd8f2bb0e8bc24236504c8 100644 --- a/src/components/TimeStepSelector/timeStepSelector.scss +++ b/src/components/TimeStepSelector/timeStepSelector.scss @@ -6,7 +6,7 @@ flex-direction: row; justify-content: space-evenly; align-items: center; - width: 100%; + margin: auto 1rem; button { width: 3rem; min-width: 3rem;