diff --git a/src/components/Analysis/AnalysisView.tsx b/src/components/Analysis/AnalysisView.tsx index 34b135007e51ff05bfaa8f78eb6ce1b268f5ba4a..9bef8722c57729b28fca4bc63556607b35dc6229 100644 --- a/src/components/Analysis/AnalysisView.tsx +++ b/src/components/Analysis/AnalysisView.tsx @@ -102,6 +102,7 @@ const AnalysisView: React.FC = () => { <DateNavigator currentAnalysisDate={currentAnalysisDate} setCurrentAnalysisDate={setCurrentAnalysisDate} + inlineDateDisplay={true} /> </Header> <Content height={headerHeight}> diff --git a/src/components/Analysis/MonthlyAnalysis.tsx b/src/components/Analysis/MonthlyAnalysis.tsx index 77131983da7c84662e6bfdd796b39e8ef0bc6165..b70cc4f5de0fe36a92c82806e07e3b012d4610dc 100644 --- a/src/components/Analysis/MonthlyAnalysis.tsx +++ b/src/components/Analysis/MonthlyAnalysis.tsx @@ -11,7 +11,6 @@ import { PerformanceIndicator } from 'models' import ConsumptionService from 'services/consumption.service' import PerformanceIndicatorService from 'services/performanceIndicator.service' import ConfigService from 'services/fluidConfig.service' -import { convertDateToMonthString } from 'utils/date' import PerformanceIndicatorContent from 'components/PerformanceIndicator/PerformanceIndicatorContent' import FluidPerformanceIndicator from 'components/PerformanceIndicator/FluidPerformanceIndicator' @@ -23,6 +22,7 @@ import { useHistory } from 'react-router-dom' import StyledSpinner from 'components/CommonKit/Spinner/StyledSpinner' import AnalysisErrorModal from './AnalysisErrorModal' import { DateTime } from 'luxon' +import StyledCard from 'components/CommonKit/Card/StyledCard' interface MonthlyAnalysisProps { analysisDate: DateTime @@ -108,53 +108,9 @@ const MonthlyAnalysis: React.FC<MonthlyAnalysisProps> = ({ <> {isLoaded ? ( <div> - <div className="analysis-root black"> - <div className="analysis-content"> - <div className="status-header"> - <div className="text-16-normal-uppercase"> - {t('analysis.status')} - </div> - <Button - aria-label={t('analysis.accessibility.button_go_to_profil')} - onClick={goToForm} - classes={{ - root: 'btn-secondary-negative', - label: 'text-16-normal', - }} - > - <StyledIcon icon={ProfileEditIcon} size={40} /> - </Button> - </div> - {fluidTypes.length >= 1 ? ( - <AnalysisConsumption - aggregatedPerformanceIndicator={ - aggregatedPerformanceIndicators - } - performanceIndicators={performanceIndicators} - analysisDate={analysisDate} - /> - ) : ( - <AnalysisErrorModal /> - )} - </div> - </div> <div className="analysis-root"> <div className="analysis-content"> - <div className="analysis-header text-16-normal-uppercase"> - {t('analysis.analysis_date')}{' '} - {convertDateToMonthString(analysisDate.plus({ month: -1 }))} - </div> - <PerformanceIndicatorContent - performanceIndicator={aggregatedPerformanceIndicators} - timeStep={timeStep} - fluidLackOfData={fluidLackOfData} - analysisDate={analysisDate} - /> <div> - <div className="analysis-header text-16-normal-uppercase"> - {t('analysis.detail')} - {convertDateToMonthString(analysisDate.plus({ month: -1 }))} - </div> {fluidConfig.map((fluid, index) => { return fluidTypes.includes(fluid.fluidTypeId) ? ( <FluidPerformanceIndicator @@ -169,6 +125,48 @@ const MonthlyAnalysis: React.FC<MonthlyAnalysisProps> = ({ })} </div> </div> + <div className="analysis-content"> + <StyledCard> + <span className="analysis-header text-16-normal-uppercase"> + {t('analysis.analysis_date')} + </span> + <div> + <PerformanceIndicatorContent + performanceIndicator={aggregatedPerformanceIndicators} + timeStep={timeStep} + fluidLackOfData={fluidLackOfData} + analysisDate={analysisDate} + /> + </div> + </StyledCard> + </div> + <div className="analysis-content"> + <StyledCard> + <div className="status-header"> + <Button + aria-label={t('analysis.accessibility.button_go_to_profil')} + onClick={goToForm} + classes={{ + root: 'btn-secondary-negative', + label: 'text-16-normal', + }} + > + <StyledIcon icon={ProfileEditIcon} size={40} /> + </Button> + </div> + {fluidTypes.length >= 1 ? ( + <AnalysisConsumption + aggregatedPerformanceIndicator={ + aggregatedPerformanceIndicators + } + performanceIndicators={performanceIndicators} + analysisDate={analysisDate} + /> + ) : ( + <AnalysisErrorModal /> + )} + </StyledCard> + </div> </div> </div> ) : ( diff --git a/src/components/Analysis/monthlyanalysis.scss b/src/components/Analysis/monthlyanalysis.scss index 00ab31ae150c37b451bf5e3001a82faf17b05ce1..2ce582839b8cbbd2dbfc9191f449082324956ee7 100644 --- a/src/components/Analysis/monthlyanalysis.scss +++ b/src/components/Analysis/monthlyanalysis.scss @@ -14,7 +14,6 @@ margin-bottom: 0; } .analysis-content { - min-height: 23.875rem; width: 45.75rem; @media #{$large-phone} { diff --git a/src/components/DateNavigator/DateNavigator.tsx b/src/components/DateNavigator/DateNavigator.tsx index 509d47c4dbe16f1864b88b7ee0d8710078af556f..6ab0e3bdd0851dc9d436848b507626bcbefd9d12 100644 --- a/src/components/DateNavigator/DateNavigator.tsx +++ b/src/components/DateNavigator/DateNavigator.tsx @@ -1,138 +1,141 @@ -import React from 'react' -import './datenavigator.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 classNames from 'classnames' - -import DateChartService from 'services/dateChart.service' -import { isLastDateReached } from 'utils/date' - -import DateNavigatorFormat from 'components/DateNavigator/DateNavigatorFormat' -import LeftArrowIcon from 'assets/icons/ico/left-arrow.svg' -import RigthArrowIcon from 'assets/icons/ico/right-arrow.svg' -import IconButton from '@material-ui/core/IconButton' -import Icon from 'cozy-ui/transpiled/react/Icon' -import { TimeStep } from 'enum/timeStep.enum' -import { isKonnectorActive } from 'utils/utils' -import { FluidType } from 'enum/fluid.enum' - -interface DateNavigatorProps { - currentAnalysisDate?: DateTime - setCurrentAnalysisDate?: React.Dispatch<React.SetStateAction<DateTime>> -} - -const DateNavigator: React.FC<DateNavigatorProps> = ({ - currentAnalysisDate, - setCurrentAnalysisDate, -}: DateNavigatorProps) => { - const { t } = useI18n() - const dispatch = useDispatch() - const { currentTimeStep, selectedDate, currentIndex } = useSelector( - (state: AppStore) => state.ecolyo.chart - ) - const { fluidStatus } = useSelector((state: AppStore) => state.ecolyo.global) - - const disablePrev = - selectedDate < - DateTime.local(0, 1, 1).setZone('utc', { - keepLocalTime: true, - }) - const disableNext: boolean = currentAnalysisDate - ? isLastDateReached(currentAnalysisDate, TimeStep.MONTH) - : isLastDateReached(selectedDate, currentTimeStep) - - const dateChartService = new DateChartService() - - const handleClickMove = (increment: number) => { - if (!currentAnalysisDate) { - const updatedDate: DateTime = dateChartService.incrementeDate( - currentTimeStep, - selectedDate, - increment - ) - const updatedIndex: number = dateChartService.defineDateIndex( - currentTimeStep, - updatedDate - ) - dispatch(setSelectedDate(updatedDate)) - dispatch(setCurrentIndex(updatedIndex)) - } else { - const updatedDate: DateTime = dateChartService.incrementeDate( - TimeStep.MONTH, - currentAnalysisDate, - increment - ) - setCurrentAnalysisDate && setCurrentAnalysisDate(updatedDate) - } - } - - const handleChangePrevIndex = () => { - if (!disablePrev && isKonnectorActive(fluidStatus, FluidType.MULTIFLUID)) { - const increment: number = dateChartService.defineIncrementForPreviousIndex( - currentTimeStep, - selectedDate, - currentIndex - ) - if (currentAnalysisDate) { - handleClickMove(-1) - } else handleClickMove(increment) - } - } - const handleChangeNextIndex = () => { - if (!disableNext && isKonnectorActive(fluidStatus, FluidType.MULTIFLUID)) { - const increment: number = dateChartService.defineIncrementForNextIndex( - currentTimeStep, - selectedDate, - currentIndex - ) - if (currentAnalysisDate) { - handleClickMove(1) - } else handleClickMove(increment) - } - } - - return ( - <div className="date-navigator"> - <div> - <IconButton - aria-label={t('consumption.accessibility.button_previous_value')} - className={classNames('date-navigator-button', { - ['disable']: - disablePrev || - !isKonnectorActive(fluidStatus, FluidType.MULTIFLUID), - })} - onClick={() => handleChangePrevIndex()} - > - <Icon icon={LeftArrowIcon} size={16} /> - </IconButton> - </div> - <DateNavigatorFormat - timeStep={currentAnalysisDate ? TimeStep.MONTH : currentTimeStep} - date={ - currentAnalysisDate - ? currentAnalysisDate.minus({ month: 1 }) - : selectedDate - } - /> - - <div> - <IconButton - aria-label={t('consumption.accessibility.button_next_value')} - className={classNames('date-navigator-button', { - ['disable']: - disableNext || - !isKonnectorActive(fluidStatus, FluidType.MULTIFLUID), - })} - onClick={() => handleChangeNextIndex()} - > - <Icon icon={RigthArrowIcon} size={16} /> - </IconButton> - </div> - </div> - ) -} - -export default DateNavigator +import React from 'react' +import './datenavigator.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 classNames from 'classnames' + +import DateChartService from 'services/dateChart.service' +import { isLastDateReached } from 'utils/date' + +import DateNavigatorFormat from 'components/DateNavigator/DateNavigatorFormat' +import LeftArrowIcon from 'assets/icons/ico/left-arrow.svg' +import RigthArrowIcon from 'assets/icons/ico/right-arrow.svg' +import IconButton from '@material-ui/core/IconButton' +import Icon from 'cozy-ui/transpiled/react/Icon' +import { TimeStep } from 'enum/timeStep.enum' +import { isKonnectorActive } from 'utils/utils' +import { FluidType } from 'enum/fluid.enum' + +interface DateNavigatorProps { + currentAnalysisDate?: DateTime + setCurrentAnalysisDate?: React.Dispatch<React.SetStateAction<DateTime>> + inlineDateDisplay?: boolean +} + +const DateNavigator: React.FC<DateNavigatorProps> = ({ + currentAnalysisDate, + setCurrentAnalysisDate, + inlineDateDisplay = false, +}: DateNavigatorProps) => { + const { t } = useI18n() + const dispatch = useDispatch() + const { currentTimeStep, selectedDate, currentIndex } = useSelector( + (state: AppStore) => state.ecolyo.chart + ) + const { fluidStatus } = useSelector((state: AppStore) => state.ecolyo.global) + + const disablePrev = + selectedDate < + DateTime.local(0, 1, 1).setZone('utc', { + keepLocalTime: true, + }) + const disableNext: boolean = currentAnalysisDate + ? isLastDateReached(currentAnalysisDate, TimeStep.MONTH) + : isLastDateReached(selectedDate, currentTimeStep) + + const dateChartService = new DateChartService() + + const handleClickMove = (increment: number) => { + if (!currentAnalysisDate) { + const updatedDate: DateTime = dateChartService.incrementeDate( + currentTimeStep, + selectedDate, + increment + ) + const updatedIndex: number = dateChartService.defineDateIndex( + currentTimeStep, + updatedDate + ) + dispatch(setSelectedDate(updatedDate)) + dispatch(setCurrentIndex(updatedIndex)) + } else { + const updatedDate: DateTime = dateChartService.incrementeDate( + TimeStep.MONTH, + currentAnalysisDate, + increment + ) + setCurrentAnalysisDate && setCurrentAnalysisDate(updatedDate) + } + } + + const handleChangePrevIndex = () => { + if (!disablePrev && isKonnectorActive(fluidStatus, FluidType.MULTIFLUID)) { + const increment: number = dateChartService.defineIncrementForPreviousIndex( + currentTimeStep, + selectedDate, + currentIndex + ) + if (currentAnalysisDate) { + handleClickMove(-1) + } else handleClickMove(increment) + } + } + const handleChangeNextIndex = () => { + if (!disableNext && isKonnectorActive(fluidStatus, FluidType.MULTIFLUID)) { + const increment: number = dateChartService.defineIncrementForNextIndex( + currentTimeStep, + selectedDate, + currentIndex + ) + if (currentAnalysisDate) { + handleClickMove(1) + } else handleClickMove(increment) + } + } + + return ( + <div className="date-navigator"> + <div> + <IconButton + aria-label={t('consumption.accessibility.button_previous_value')} + className={classNames('date-navigator-button', { + ['disable']: + disablePrev || + !isKonnectorActive(fluidStatus, FluidType.MULTIFLUID), + })} + onClick={() => handleChangePrevIndex()} + > + <Icon icon={LeftArrowIcon} size={16} /> + </IconButton> + </div> + <DateNavigatorFormat + timeStep={currentAnalysisDate ? TimeStep.MONTH : currentTimeStep} + date={ + currentAnalysisDate + ? currentAnalysisDate.minus({ month: 1 }) + : selectedDate + } + inline={inlineDateDisplay} + /> + + <div> + <IconButton + aria-label={t('consumption.accessibility.button_next_value')} + className={classNames('date-navigator-button', { + ['disable']: + disableNext || + !isKonnectorActive(fluidStatus, FluidType.MULTIFLUID), + })} + onClick={() => handleChangeNextIndex()} + > + <Icon icon={RigthArrowIcon} size={16} /> + </IconButton> + </div> + </div> + ) +} + +export default DateNavigator diff --git a/src/components/DateNavigator/DateNavigatorFormat.tsx b/src/components/DateNavigator/DateNavigatorFormat.tsx index 0a112e4391576e25cc88d171d2b939563792ecc1..d13361f6e38964276732aa2fa5b079bfea3e04c2 100644 --- a/src/components/DateNavigator/DateNavigatorFormat.tsx +++ b/src/components/DateNavigator/DateNavigatorFormat.tsx @@ -6,11 +6,13 @@ import './datenavigatorformat.scss' interface DateNavigatorFormatProps { timeStep: TimeStep date: DateTime + inline: boolean } const DateNavigatorFormat: React.FC<DateNavigatorFormatProps> = ({ timeStep, date, + inline, }: DateNavigatorFormatProps) => { const formatDate = (_timeStep: TimeStep) => { switch (_timeStep) { @@ -61,15 +63,27 @@ const DateNavigatorFormat: React.FC<DateNavigatorFormatProps> = ({ return ( <div className="date-navigator-format"> - {formatedDate[0] && ( - <div className="date-navigator-format-date text-16-bold"> - {formatedDate[0]} - </div> - )} - {formatedDate[1] && ( - <div className="date-navigator-format-date text-15-normal"> - {formatedDate[1]} - </div> + {inline ? ( + <> + {formatedDate[0] && formatedDate[1] && ( + <div className="date-navigator-format-date text-16-bold"> + {formatedDate[0]} {formatedDate[1]} + </div> + )} + </> + ) : ( + <> + {formatedDate[0] && ( + <div className="date-navigator-format-date text-16-bold"> + {formatedDate[0]} + </div> + )} + {formatedDate[1] && ( + <div className="date-navigator-format-date text-15-normal"> + {formatedDate[1]} + </div> + )} + </> )} </div> ) diff --git a/src/components/PerformanceIndicator/FluidPerformanceIndicator.tsx b/src/components/PerformanceIndicator/FluidPerformanceIndicator.tsx index 0de905de98b67f8b75acf3101c6d0a1929b89fa6..42a9043b0d6c1b39a2eb5df693db53232369e5c7 100644 --- a/src/components/PerformanceIndicator/FluidPerformanceIndicator.tsx +++ b/src/components/PerformanceIndicator/FluidPerformanceIndicator.tsx @@ -1,24 +1,15 @@ -import React, { useCallback } from 'react' +import React from 'react' import './fluidPerformanceIndicator.scss' -import { useHistory } from 'react-router-dom' import { useI18n } from 'cozy-ui/transpiled/react/I18n' -import { useDispatch } from 'react-redux' import { DateTime } from 'luxon' import { FluidType } from 'enum/fluid.enum' import { PerformanceIndicator } from 'models' import { getPicto } from 'utils/picto' -import { formatNumberValues } from 'utils/utils' +import { formatNumberValues, getPreviousMonthName } from 'utils/utils' import StyledCard from 'components/CommonKit/Card/StyledCard' import StyledIcon from 'components/CommonKit/Icon/StyledIcon' -import BlackArrowIcon from 'assets/icons/ico/black-arrow.svg' -import ConverterService from 'services/converter.service' -import { setCurrentTimeStep, setSelectedDate } from 'store/chart/chart.actions' -import { TimeStep } from 'enum/timeStep.enum' -import { useClient } from 'cozy-client' -import { UsageEventType } from 'enum/usageEvent.enum' -import UsageEventService from 'services/usageEvent.service' interface FluidPerformanceIndicatorProps { performanceIndicator: PerformanceIndicator @@ -32,33 +23,16 @@ const FluidPerformanceIndicator: React.FC<FluidPerformanceIndicatorProps> = ({ date, }: FluidPerformanceIndicatorProps) => { const { t } = useI18n() - const history = useHistory() - const dispatch = useDispatch() const iconType = getPicto(fluidType) - const converterService = new ConverterService() - const client = useClient() let displayedValue: string if (performanceIndicator && performanceIndicator.value) displayedValue = formatNumberValues(performanceIndicator.value).toString() else displayedValue = '-----' - const handleClick = useCallback(async () => { - await UsageEventService.addEvent(client, { - type: UsageEventType.NAVIGATION_EVENT, - target: FluidType[fluidType].toLowerCase(), - }) - dispatch(setCurrentTimeStep(TimeStep.DAY)) - dispatch(setSelectedDate(date)) - history.push(`/consumption/${FluidType[fluidType].toLowerCase()}`) - }, [dispatch, history, date, fluidType, client]) - return ( - <StyledCard onClick={handleClick} fluidType={fluidType}> + <StyledCard> <div className="fpi"> <div className="fpi-left"> - <div className="fpi-title card-title-on"> - {t('FLUID.' + FluidType[fluidType] + '.LABEL')} - </div> <div className="fpi-content"> <StyledIcon className="fpi-content-icon" @@ -71,25 +45,37 @@ const FluidPerformanceIndicator: React.FC<FluidPerformanceIndicatorProps> = ({ <span className="card-indicator"> {t('FLUID.' + FluidType[fluidType] + '.UNIT')} </span> - <span - className={`${FluidType[fluidType] + '-color euro-value'}`} - > - {performanceIndicator && - performanceIndicator.value && - `${formatNumberValues( - converterService.LoadToEuro( - performanceIndicator.value, - fluidType + <span className={`euro-value month`}> + <span + className={`${ + performanceIndicator && + performanceIndicator.percentageVariation && + performanceIndicator.percentageVariation > 0 + ? 'positive' + : 'negative' + }`} + > + {performanceIndicator && + performanceIndicator.percentageVariation ? ( + performanceIndicator.percentageVariation > 0 ? ( + `+${formatNumberValues( + performanceIndicator.percentageVariation * 100 + )} %` + ) : ( + `${formatNumberValues( + performanceIndicator.percentageVariation * 100 + )} %` ) - )} €`} + ) : ( + <></> + )} + </span> + {`/ ${getPreviousMonthName(date.minus({ month: 1 }))}`} </span> </div> </div> </div> </div> - <div className="fpi-right"> - <StyledIcon icon={BlackArrowIcon} size={18} /> - </div> </div> </StyledCard> ) diff --git a/src/components/PerformanceIndicator/PerformanceIndicatorContent.tsx b/src/components/PerformanceIndicator/PerformanceIndicatorContent.tsx index 286cdd842de0f806a9922218e0d1d80675222e21..44380016085d123a1729f10fb9755bee2f04ebe9 100644 --- a/src/components/PerformanceIndicator/PerformanceIndicatorContent.tsx +++ b/src/components/PerformanceIndicator/PerformanceIndicatorContent.tsx @@ -1,158 +1,157 @@ -import React from 'react' -import { useI18n } from 'cozy-ui/transpiled/react/I18n' - -import { TimeStep } from 'enum/timeStep.enum' -import { PerformanceIndicator } from 'models' -import { formatNumberValues } from 'utils/utils' - -import StyledIcon from 'components/CommonKit/Icon/StyledIcon' -import PileIcon from 'assets/icons/ico/coins.svg' - -import GreenIndicatorIcon from 'assets/icons/visu/indicator/green.svg' -import RedIndicatorIcon from 'assets/icons/visu/indicator/red.svg' -import GreyIndicatorIcon from 'assets/icons/visu/indicator/grey.svg' -import ErrorIndicatorIcon from 'assets/icons/visu/indicator/error.svg' -import { FluidType } from 'enum/fluid.enum' -import './fluidPerformanceIndicator.scss' -import { convertDateToMonthString } from 'utils/date' -import { DateTime } from 'luxon' - -interface PerformanceIndicatorContentProps { - performanceIndicator: PerformanceIndicator - timeStep: TimeStep - fluidLackOfData?: Array<FluidType> - analysisDate?: DateTime -} - -const PerformanceIndicatorContent: React.FC<PerformanceIndicatorContentProps> = ({ - performanceIndicator, - fluidLackOfData = [], - analysisDate, -}: PerformanceIndicatorContentProps) => { - const { t } = useI18n() - let displayedValue: string - if (performanceIndicator && performanceIndicator.value) - displayedValue = formatNumberValues(performanceIndicator.value).toString() - else displayedValue = '-----' - - let errorInPerf = false - if (performanceIndicator && !performanceIndicator.value) { - errorInPerf = true - } - - let perf: number | null = null - let diffInEuro: number | null = null - if ( - performanceIndicator && - performanceIndicator.value && - performanceIndicator.compareValue - ) { - perf = - 100 * (performanceIndicator.value / performanceIndicator.compareValue - 1) - diffInEuro = performanceIndicator.value - performanceIndicator.compareValue - } - const perfString = perf ? formatNumberValues(perf) : '' - const diffString = diffInEuro ? formatNumberValues(diffInEuro) : '' - let perfStatus = ['error', ErrorIndicatorIcon] - if (perf === null && !errorInPerf) perfStatus = ['nodata', ErrorIndicatorIcon] - else if (perf === null && errorInPerf) - perfStatus = ['error', ErrorIndicatorIcon] - else if (perf && perf === 0) perfStatus = ['zero', GreyIndicatorIcon] - else if (perf && perf > 0) perfStatus = ['positive', RedIndicatorIcon] - else if (perf && perf < 0) perfStatus = ['negative', GreenIndicatorIcon] - return ( - <div className="fpi"> - <div className="fpi-left"> - <div className="fpi-content"> - <div className="fpi-content-perf"> - <div className="fpi-content-perf-result card-result"> - <div className="icon-line"> - <StyledIcon - className="fpi-content-icon perf-icon" - icon={PileIcon} - size={35} - /> - <div> - <span className="euro-value">{displayedValue}</span> - <span className="card-indicator"> €</span> - </div> - </div> - </div> - {perfStatus[0] === 'positive' || - perfStatus[0] === 'negative' || - perfStatus[0] === 'zero' ? ( - <div className="fpi-content-perf-indicator bilan-card card-text"> - <div className="icon-line"> - <StyledIcon - className="fpi-content-icon perf-icon" - icon={perfStatus[1]} - size={35} - /> - <div className="evolution-text"> - {t('performance_indicator.bilan.text1')} - {analysisDate && - convertDateToMonthString( - analysisDate.plus({ month: -2 }) - ).substring(3)}{' '} - : - <span - className={`fpi-content-perf-indicator-kpi ${perfStatus[0]} card-text-bold`} - > - {perfStatus[0] === 'positive' ? ' + ' : ' '} - {perfString}% - </span> - <br /> - <span> - {t('performance_indicator.bilan.text2')} - <span className="diff-value">{diffString} €</span> - </span> - </div> - </div> - </div> - ) : ( - <div className="fpi-content-perf-indicator card-text error"> - <StyledIcon - className="fpi-content-icon perf-icon" - icon={perfStatus[1]} - size={35} - /> - - {fluidLackOfData.length !== 0 ? ( - <div> - <div> - {' '} - {t('performance_indicator.error_no_compare_no_data')}{' '} - </div> - <div> - {fluidLackOfData.map(fluidType => { - return ( - <div key={fluidType} className="fluid-enum"> - {' '} - - {t( - 'FLUID.' + FluidType[fluidType] + '.NAME' - )}{' '} - </div> - ) - })} - </div> - </div> - ) : ( - <div> - <div> {t('performance_indicator.error_no_compare')} </div> - <div> - {' '} - {t('performance_indicator.error_no_compare_reason')}{' '} - </div> - </div> - )} - </div> - )} - </div> - </div> - </div> - <div className="fpi-right"></div> - </div> - ) -} - -export default PerformanceIndicatorContent +import React from 'react' +import { useI18n } from 'cozy-ui/transpiled/react/I18n' + +import { TimeStep } from 'enum/timeStep.enum' +import { PerformanceIndicator } from 'models' +import { formatNumberValues } from 'utils/utils' + +import StyledIcon from 'components/CommonKit/Icon/StyledIcon' +import PileIcon from 'assets/icons/ico/coins.svg' + +import GreenIndicatorIcon from 'assets/icons/visu/indicator/green.svg' +import RedIndicatorIcon from 'assets/icons/visu/indicator/red.svg' +import GreyIndicatorIcon from 'assets/icons/visu/indicator/grey.svg' +import ErrorIndicatorIcon from 'assets/icons/visu/indicator/error.svg' +import { FluidType } from 'enum/fluid.enum' +import './fluidPerformanceIndicator.scss' +import { convertDateToMonthString } from 'utils/date' +import { DateTime } from 'luxon' + +interface PerformanceIndicatorContentProps { + performanceIndicator: PerformanceIndicator + timeStep: TimeStep + fluidLackOfData?: Array<FluidType> + analysisDate?: DateTime +} + +const PerformanceIndicatorContent: React.FC<PerformanceIndicatorContentProps> = ({ + performanceIndicator, + fluidLackOfData = [], + analysisDate, +}: PerformanceIndicatorContentProps) => { + const { t } = useI18n() + let displayedValue: string + if (performanceIndicator && performanceIndicator.value) + displayedValue = formatNumberValues(performanceIndicator.value).toString() + else displayedValue = '-----' + + let errorInPerf = false + if (performanceIndicator && !performanceIndicator.value) { + errorInPerf = true + } + + let perf: number | null = null + let diffInEuro: number | null = null + if ( + performanceIndicator && + performanceIndicator.value && + performanceIndicator.compareValue + ) { + perf = + 100 * (performanceIndicator.value / performanceIndicator.compareValue - 1) + diffInEuro = performanceIndicator.value - performanceIndicator.compareValue + } + const perfString = perf ? formatNumberValues(perf) : '' + const diffString = diffInEuro ? formatNumberValues(diffInEuro) : '' + let perfStatus = ['error', ErrorIndicatorIcon] + if (perf === null && !errorInPerf) perfStatus = ['nodata', ErrorIndicatorIcon] + else if (perf === null && errorInPerf) + perfStatus = ['error', ErrorIndicatorIcon] + else if (perf && perf === 0) perfStatus = ['zero', GreyIndicatorIcon] + else if (perf && perf > 0) perfStatus = ['positive', RedIndicatorIcon] + else if (perf && perf < 0) perfStatus = ['negative', GreenIndicatorIcon] + return ( + <div className="fpi"> + <div className="fpi-left"> + <div className="fpi-content"> + <div className="fpi-content-perf"> + <div className="fpi-content-perf-result card-result"> + <div className="icon-line"> + <StyledIcon + className="fpi-content-icon perf-icon" + icon={PileIcon} + size={35} + /> + <div> + <span className="euro-value">{displayedValue}</span> + <span className="card-indicator"> €</span> + </div> + </div> + </div> + {perfStatus[0] === 'positive' || + perfStatus[0] === 'negative' || + perfStatus[0] === 'zero' ? ( + <div className="fpi-content-perf-indicator bilan-card card-text"> + <div className="icon-line"> + <StyledIcon + className="fpi-content-icon perf-icon" + icon={perfStatus[1]} + size={35} + /> + <div className="evolution-text"> + {t('performance_indicator.bilan.text1')} + {analysisDate && + convertDateToMonthString( + analysisDate.plus({ month: -2 }) + ).substring(3)}{' '} + : + <span + className={`fpi-content-perf-indicator-kpi ${perfStatus[0]} card-text-bold`} + > + {perfStatus[0] === 'positive' ? ' + ' : ' '} + {perfString}% + </span> + <br /> + <span> + {t('performance_indicator.bilan.text2')} + <span className="diff-value">{diffString} €</span> + </span> + </div> + </div> + </div> + ) : ( + <div className="fpi-content-perf-indicator card-text error"> + <StyledIcon + className="fpi-content-icon perf-icon" + icon={perfStatus[1]} + size={35} + /> + + {fluidLackOfData.length !== 0 ? ( + <div> + <div> + {' '} + {t('performance_indicator.error_no_compare_no_data')}{' '} + </div> + <div> + {fluidLackOfData.map(fluidType => { + return ( + <div key={fluidType} className="fluid-enum"> + {' '} + - {t( + 'FLUID.' + FluidType[fluidType] + '.NAME' + )}{' '} + </div> + ) + })} + </div> + </div> + ) : ( + <div> + <div> {t('performance_indicator.error_no_compare')} </div> + <div> + {' '} + {t('performance_indicator.error_no_compare_reason')}{' '} + </div> + </div> + )} + </div> + )} + </div> + </div> + </div> + </div> + ) +} + +export default PerformanceIndicatorContent diff --git a/src/components/PerformanceIndicator/fluidPerformanceIndicator.scss b/src/components/PerformanceIndicator/fluidPerformanceIndicator.scss index 248f2bbaa53b28ce0bcefda5d21fd54347347488..69f2f9029a9b9ddce005a15f86ba4c97d475d7a8 100644 --- a/src/components/PerformanceIndicator/fluidPerformanceIndicator.scss +++ b/src/components/PerformanceIndicator/fluidPerformanceIndicator.scss @@ -113,6 +113,15 @@ display: inline-block; padding-right: 0.25rem; } + .positive { + color: $red-primary !important; + } + .negative { + color: $green !important; + } + .month { + color: $soft-grey !important; + } .euro-value { font-size: 1.125rem; display: block; @@ -135,9 +144,6 @@ color: $soft-grey; } } - .fpi-right { - align-self: center; - } } .flex-center { display: flex; diff --git a/src/locales/fr.json b/src/locales/fr.json index 376608435e240d0f2def9fbe45fb2c7ae73ee71d..c5597da739a13dcf3597c1f093a1df67f20ddca8 100644 --- a/src/locales/fr.json +++ b/src/locales/fr.json @@ -72,10 +72,8 @@ }, "analysis": { "viewTitle": "Analyse", - "status": "Votre situation", "comparison": "Comparatif", - "analysis_date": "Conso du mois", - "detail": "Détail du mois", + "analysis_date": "Conso totale", "challenge": "Défis terminés en", "user_consumption": "Votre conso", "average_home": "Conso moyenne d'un profil similaire",