diff --git a/src/components/ConsumptionVisualizer/DataloadConsumptionVisualizer.tsx b/src/components/ConsumptionVisualizer/DataloadConsumptionVisualizer.tsx index 0753bc7759deb400c3d29bc16aa61594cca33f1b..67396474a5194554177995bc14f113335b477a64 100644 --- a/src/components/ConsumptionVisualizer/DataloadConsumptionVisualizer.tsx +++ b/src/components/ConsumptionVisualizer/DataloadConsumptionVisualizer.tsx @@ -1,266 +1,296 @@ -import React, { useCallback, useState } 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 { Dataload } from 'models' -import { FluidType } from 'enum/fluid.enum' -import ConverterService from 'services/converter.service' -import DateChartService from 'services/dateChart.service' -import { getNavPicto } from 'utils/picto' - -import Icon from 'cozy-ui/transpiled/react/Icon' -import { useClient } from 'cozy-client' -import { UsageEventType } from 'enum/usageEvent.enum' -import UsageEventService from 'services/usageEvent.service' -import EstimatedConsumptionModal from './EstimatedConsumptionModal' - -interface DataloadConsumptionVisualizerProps { - fluidType: FluidType - dataload: Dataload - compareDataload: Dataload | null - showCompare: boolean - lastDataDate: DateTime | null - setActive: React.Dispatch<React.SetStateAction<boolean>> -} -const DataloadConsumptionVisualizer = ({ - fluidType, - dataload, - compareDataload, - showCompare, - lastDataDate, - setActive, -}: DataloadConsumptionVisualizerProps) => { - const { t } = useI18n() - const { loading } = useSelector((state: AppStore) => state.ecolyo.chart) - const client = useClient() - const [openEstimationModal, setOpenEstimationModal] = useState<boolean>(false) - const converterService = new ConverterService() - const dateChartService = new DateChartService() - - const emitNavEvent = useCallback( - async (targetPage: string) => { - await UsageEventService.addEvent(client, { - type: UsageEventType.NAVIGATION_EVENT, - target: targetPage, - }) - }, - [client] - ) - const handleToggleKonnectionCard = useCallback(() => { - setActive(true) - const app = document.querySelector('.app-content') - - const content = document.querySelector('.content-view') - if (content && app) { - setTimeout(() => { - //Desktop devices - app.scrollTo({ - top: content.scrollHeight + 300, - behavior: 'smooth', - }) - //Mobiles devices - app.scrollIntoView({ - behavior: 'smooth', - block: 'end', - inline: 'end', - }) - }, 300) - } - }, [setActive]) - const toggleEstimationModal = useCallback(() => { - setOpenEstimationModal(prev => !prev) - }, []) - return ( - <div className="dataloadvisualizer-root"> - {!loading && dataload && dataload.value > -1 ? ( - <div className="dataloadvisualizer-content"> - {showCompare && compareDataload && ( - <> - {compareDataload.value === -1 ? ( - <div className="dataloadvisualizer-section dataloadvisualizer-section-left-novalue"> - <div - className={`dataloadvisualizer-novalue ${FluidType[ - fluidType - ].toLowerCase()}-compare text-20-normal`} - > - {t('consumption_visualizer.no_data')} - </div> - </div> - ) : ( - <div className="dataloadvisualizer-section dataloadvisualizer-section-left"> - <div - className={`dataloadvisualizer-value ${FluidType[ - fluidType - ].toLowerCase()}-compare text-36-bold`} - > - {formatNumberValues(compareDataload.value)} - <span className="text-18-normal">{`${t( - 'FLUID.' + FluidType[fluidType] + '.UNIT' - )}`}</span> - </div> - <div - className={`dataloadvisualizer-euro ${FluidType[ - fluidType - ].toLowerCase()}-compare text-16-normal`} - > - {`${formatNumberValues( - converterService.LoadToEuro( - compareDataload.value, - fluidType - ) - )} €`} - </div> - </div> - )} - </> - )} - <div - className={ - showCompare - ? 'dataloadvisualizer-section dataloadvisualizer-section-right' - : 'dataloadvisualizer-section' - } - > - <div - className={`dataloadvisualizer-value ${FluidType[ - fluidType - ].toLowerCase()} text-36-bold`} - > - {formatNumberValues(dataload.value, FluidType[fluidType], true) >= - 1000 ? ( - <> - {formatNumberValues(dataload.value, FluidType[fluidType])} - <span className="text-18-normal"> - {`${t('FLUID.' + FluidType[fluidType] + '.MEGAUNIT')}`} - </span> - </> - ) : ( - <> - {formatNumberValues(dataload.value)} - <sup className="text-18-normal euroUnit"> - {`${t('FLUID.' + FluidType[fluidType] + '.UNIT')}`} - </sup> - {fluidType === FluidType.MULTIFLUID && ( - <sup - className="text-14-normal estimated" - onClick={toggleEstimationModal} - > - {t('consumption_visualizer.estimated')} - </sup> - )} - </> - )} - </div> - {fluidType !== FluidType.MULTIFLUID ? ( - <div - className={`dataloadvisualizer-euro ${FluidType[ - fluidType - ].toLowerCase()} text-16-normal`} - > - {`${formatNumberValues( - converterService.LoadToEuro(dataload.value, fluidType) - )} €`} - </div> - ) : ( - <div className="dataloadvisualizer-euro text-16-normal"> - {dataload.valueDetail ? ( - dataload.valueDetail.map((load, index) => { - return ( - <NavLink - key={index} - to={`/consumption/${FluidType[index].toLowerCase()}`} - className="dataloadvisualizer-euro-link" - > - <div - className={ - load === -1 && - !dateChartService.isDataToCome(dataload, index) - ? 'dataloadvisualizer-euro-fluid error' - : `dataloadvisualizer-euro-fluid ${FluidType[ - index - ].toLowerCase()}` - } - onClick={() => - emitNavEvent(FluidType[index].toLowerCase()) - } - > - <Icon - className="dataloadvisualizer-euro-fluid-icon" - icon={getNavPicto(index, true, true)} - size={22} - /> - <div> - {!dateChartService.isDataToCome(dataload, index) && - load !== -1 - ? `${formatNumberValues(load)} €` - : dateChartService.isDataToCome(dataload, index) - ? t('consumption_visualizer.data_to_come') - : '---- €'} - </div> - </div> - </NavLink> - ) - }) - ) : ( - <NavLink - to={`/consumption/${FluidType[fluidType].toLowerCase()}`} - className="dataloadvisualizer-euro-link" - > - <div - className={`dataloadvisualizer-euro-fluid ${FluidType[ - fluidType - ].toLowerCase()}`} - > - <Icon - className="dataloadvisualizer-euro-fluid-icon" - icon={getNavPicto(fluidType, true, true)} - size={22} - /> - <div>{`${formatNumberValues( - converterService.LoadToEuro(dataload.value, fluidType) - )} €`}</div> - </div> - </NavLink> - )} - </div> - )} - </div> - </div> - ) : ( - <> - {!dataload ? null : dataload && - lastDataDate && - dataload.date > lastDataDate ? ( - <div - className={`dataloadvisualizer-content ${FluidType[ - fluidType - ].toLowerCase()} text-22-normal`} - > - {`${t( - 'consumption_visualizer.last_data' - )} : ${lastDataDate.toFormat("dd'/'MM'/'yy")}`} - </div> - ) : ( - <div - onClick={handleToggleKonnectionCard} - className={`dataloadvisualizer-content text-22-normal error`} - > - {`${t('consumption_visualizer.no_data')}`} - </div> - )} - </> - )} - <EstimatedConsumptionModal - open={openEstimationModal} - handleCloseClick={toggleEstimationModal} - /> - </div> - ) -} - -export default DataloadConsumptionVisualizer +import React, { useCallback, useState } 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 { Dataload } from 'models' +import { FluidType } from 'enum/fluid.enum' +import ConverterService from 'services/converter.service' +import DateChartService from 'services/dateChart.service' +import { getNavPicto } from 'utils/picto' + +import Icon from 'cozy-ui/transpiled/react/Icon' +import { useClient } from 'cozy-client' +import { UsageEventType } from 'enum/usageEvent.enum' +import UsageEventService from 'services/usageEvent.service' +import EstimatedConsumptionModal from './EstimatedConsumptionModal' + +interface DataloadConsumptionVisualizerProps { + fluidType: FluidType + dataload: Dataload + compareDataload: Dataload | null + showCompare: boolean + lastDataDate: DateTime | null + setActive: React.Dispatch<React.SetStateAction<boolean>> +} +const DataloadConsumptionVisualizer = ({ + fluidType, + dataload, + compareDataload, + showCompare, + lastDataDate, + setActive, +}: DataloadConsumptionVisualizerProps) => { + const { t } = useI18n() + const { loading } = useSelector((state: AppStore) => state.ecolyo.chart) + const client = useClient() + const [openEstimationModal, setOpenEstimationModal] = useState<boolean>(false) + const converterService = new ConverterService() + const dateChartService = new DateChartService() + + const emitNavEvent = useCallback( + async (targetPage: string) => { + await UsageEventService.addEvent(client, { + type: UsageEventType.NAVIGATION_EVENT, + target: targetPage, + }) + }, + [client] + ) + const handleToggleKonnectionCard = useCallback(() => { + setActive(true) + const app = document.querySelector('.app-content') + + const content = document.querySelector('.content-view') + if (content && app) { + setTimeout(() => { + //Desktop devices + app.scrollTo({ + top: content.scrollHeight + 300, + behavior: 'smooth', + }) + //Mobiles devices + app.scrollIntoView({ + behavior: 'smooth', + block: 'end', + inline: 'end', + }) + }, 300) + } + }, [setActive]) + const toggleEstimationModal = useCallback(() => { + setOpenEstimationModal(prev => !prev) + }, []) + return ( + <div className="dataloadvisualizer-root"> + {!loading && dataload && dataload.value > -1 ? ( + <div className="dataloadvisualizer-content"> + {showCompare && compareDataload && ( + <> + {compareDataload.value === -1 ? ( + <div className="dataloadvisualizer-section dataloadvisualizer-section-left-novalue"> + <div + className={`dataloadvisualizer-novalue ${FluidType[ + fluidType + ].toLowerCase()}-compare text-20-normal`} + > + {t('consumption_visualizer.no_data')} + </div> + </div> + ) : ( + <div className="dataloadvisualizer-section dataloadvisualizer-section-left"> + <div + className={`dataloadvisualizer-value ${FluidType[ + fluidType + ].toLowerCase()}-compare text-36-bold`} + > + {formatNumberValues(compareDataload.value)} + <span className="text-18-normal">{`${t( + 'FLUID.' + FluidType[fluidType] + '.UNIT' + )}`}</span> + </div> + <> + {fluidType === FluidType.MULTIFLUID ? ( + <></> + ) : ( + <div + className={`dataloadvisualizer-euro ${FluidType[ + fluidType + ].toLowerCase()}-compare text-16-normal`} + > + {`${formatNumberValues( + converterService.LoadToEuro( + compareDataload.value, + fluidType + ) + )} €`} + </div> + )} + </> + </div> + )} + </> + )} + <div + className={ + showCompare + ? 'dataloadvisualizer-section dataloadvisualizer-section-right' + : 'dataloadvisualizer-section' + } + > + <div + className={`dataloadvisualizer-value ${FluidType[ + fluidType + ].toLowerCase()} text-36-bold`} + > + {formatNumberValues(dataload.value, FluidType[fluidType], true) >= + 1000 ? ( + <> + {formatNumberValues(dataload.value, FluidType[fluidType])} + <span className="text-18-normal"> + {`${t('FLUID.' + FluidType[fluidType] + '.MEGAUNIT')}`} + </span> + </> + ) : ( + <> + {formatNumberValues(dataload.value)} + <span + className={`text-18-normal ${ + fluidType === FluidType.MULTIFLUID && !showCompare + ? 'euroUnit' + : '' + }`} + > + {`${t('FLUID.' + FluidType[fluidType] + '.UNIT')}`} + </span> + {fluidType === FluidType.MULTIFLUID && !showCompare && ( + <span + className="text-14-normal estimated" + onClick={toggleEstimationModal} + > + {t('consumption_visualizer.estimated')} + </span> + )} + </> + )} + </div> + {fluidType !== FluidType.MULTIFLUID ? ( + <div + className={`dataloadvisualizer-euro ${FluidType[ + fluidType + ].toLowerCase()} text-16-normal`} + > + {`${formatNumberValues( + converterService.LoadToEuro(dataload.value, fluidType) + )} €`} + </div> + ) : ( + <> + {showCompare ? ( + <></> + ) : ( + <div className="dataloadvisualizer-euro text-16-normal"> + {dataload.valueDetail ? ( + dataload.valueDetail.map((load, index) => { + return ( + <NavLink + key={index} + to={`/consumption/${FluidType[ + index + ].toLowerCase()}`} + className="dataloadvisualizer-euro-link" + > + <div + className={ + load === -1 && + !dateChartService.isDataToCome(dataload, index) + ? 'dataloadvisualizer-euro-fluid error' + : `dataloadvisualizer-euro-fluid ${FluidType[ + index + ].toLowerCase()}` + } + onClick={() => + emitNavEvent(FluidType[index].toLowerCase()) + } + > + <Icon + className="dataloadvisualizer-euro-fluid-icon" + icon={getNavPicto(index, true, true)} + size={22} + /> + <div> + {!dateChartService.isDataToCome( + dataload, + index + ) && load !== -1 + ? `${formatNumberValues(load)} €` + : dateChartService.isDataToCome( + dataload, + index + ) + ? t('consumption_visualizer.data_to_come') + : '---- €'} + </div> + </div> + </NavLink> + ) + }) + ) : ( + <NavLink + to={`/consumption/${FluidType[ + fluidType + ].toLowerCase()}`} + className="dataloadvisualizer-euro-link" + > + <div + className={`dataloadvisualizer-euro-fluid ${FluidType[ + fluidType + ].toLowerCase()}`} + > + <Icon + className="dataloadvisualizer-euro-fluid-icon" + icon={getNavPicto(fluidType, true, true)} + size={22} + /> + <div>{`${formatNumberValues( + converterService.LoadToEuro( + dataload.value, + fluidType + ) + )} €`}</div> + </div> + </NavLink> + )} + </div> + )} + </> + )} + </div> + </div> + ) : ( + <> + {!dataload ? null : dataload && + lastDataDate && + dataload.date > lastDataDate ? ( + <div + className={`dataloadvisualizer-content ${FluidType[ + fluidType + ].toLowerCase()} text-22-normal`} + > + {`${t( + 'consumption_visualizer.last_data' + )} : ${lastDataDate.toFormat("dd'/'MM'/'yy")}`} + </div> + ) : ( + <div + onClick={handleToggleKonnectionCard} + className={`dataloadvisualizer-content text-22-normal error`} + > + {`${t('consumption_visualizer.no_data')}`} + </div> + )} + </> + )} + <EstimatedConsumptionModal + open={openEstimationModal} + handleCloseClick={toggleEstimationModal} + /> + </div> + ) +} + +export default DataloadConsumptionVisualizer diff --git a/src/components/FluidChart/FluidChart.tsx b/src/components/FluidChart/FluidChart.tsx index e4b91392967676d57c6948474e85e86835b9660a..3375fad3a67112755f17baf17126f2f84cceecfb 100644 --- a/src/components/FluidChart/FluidChart.tsx +++ b/src/components/FluidChart/FluidChart.tsx @@ -142,8 +142,7 @@ const FluidChart: React.FC<FluidChartProps> = ({ </div> )} <TimeStepSelector fluidType={fluidType} /> - {fluidType !== FluidType.MULTIFLUID && - currentTimeStep !== TimeStep.YEAR ? ( + {currentTimeStep !== TimeStep.YEAR ? ( <div className="fluidchart-footer" onClick={handleChangeSwitch}> <div className="fluidchart-footer-compare text-15-normal"> <StyledSwitch diff --git a/src/services/consumption.service.ts b/src/services/consumption.service.ts index 18138db7609cc9ce68c63bd6b8466a3e70263d83..dbb0664ad28d5f79f0ed2424c8706ec22af18309 100644 --- a/src/services/consumption.service.ts +++ b/src/services/consumption.service.ts @@ -34,6 +34,15 @@ export default class ConsumptionDataManager { this._consumptionValidatorService = new ConsumptionValidatorService() } + /** + * Get graph data according on timeStep and fluidType + * @param timePeriod TimePeriod + * @param timeStep TimeStep + * @param fluidTypes FluidType[] + * @param compareTimePeriod - Optional TimePeriod + * @param isHome - Optional boolean + * @returns DataChart | null + */ public async getGraphData( timePeriod: TimePeriod, timeStep: TimeStep, diff --git a/src/services/converter.service.spec.ts b/src/services/converter.service.spec.ts index 94f6b29ed382e2561ccb1d0a9512476f7754fc19..e9dde6f239a23698933417e039243e64cd13ef5e 100644 --- a/src/services/converter.service.spec.ts +++ b/src/services/converter.service.spec.ts @@ -27,6 +27,12 @@ describe('Converter service', () => { expect(result).toEqual(expectedConversion) }) + it('shoud return the load to euro for Multifluid, no coeff apply', () => { + const expectedConversion = 20 + const result = converterService.LoadToEuro(20, FluidType.MULTIFLUID) + expect(result).toEqual(expectedConversion) + }) + it('shoud return 0.01 if the load is below 0.01 euro', () => { const expectedConversion = 0.01 const result = converterService.LoadToEuro(0.002, FluidType.WATER) diff --git a/src/services/converter.service.ts b/src/services/converter.service.ts index 253351fa368f2dbbef6821b82887bbaeeefa9eb3..29519cbbaab475f96b5541b47d1404146f5057ee 100644 --- a/src/services/converter.service.ts +++ b/src/services/converter.service.ts @@ -10,8 +10,15 @@ export default class ConverterService { } public LoadToEuro(load: number, fluidType: FluidType): number { - let convertedLoad: number = load * this._fluidConfig[fluidType].coefficient + let convertedLoad: number + // If Multifluid do not apply coeff because it doesn't exist + if (fluidType === FluidType.MULTIFLUID) { + convertedLoad = load + } else { + convertedLoad = load * this._fluidConfig[fluidType].coefficient + } + // Prevent round 0 case when the actual value is not 0 if (convertedLoad > 0 && convertedLoad < 0.01) { convertedLoad = 0.01 }