Skip to content
Snippets Groups Projects
AnalysisConsumption.tsx 9.44 KiB
Newer Older
  • Learn to ignore specific revisions
  • import {
      Accordion,
      AccordionDetails,
      AccordionSummary,
    } from '@material-ui/core'
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
    import Button from '@material-ui/core/Button'
    import chevronDown from 'assets/icons/ico/chevron-down.svg'
    
    import ProfileEditIcon from 'assets/icons/ico/profile-edit.svg'
    import AnalysisIcon from 'assets/icons/visu/analysis/analysis.svg'
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
    import PlaceHolderIcon from 'assets/icons/visu/analysis/no-profile-placeholder.svg'
    import StyledIcon from 'components/CommonKit/Icon/StyledIcon'
    import Loader from 'components/Loader/Loader'
    import { Client, useClient } from 'cozy-client'
    import { useI18n } from 'cozy-ui/transpiled/react/I18n'
    import Icon from 'cozy-ui/transpiled/react/Icon'
    import { FluidType } from 'enum/fluid.enum'
    import { DateTime } from 'luxon'
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
    import { PerformanceIndicator } from 'models'
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
    import { MonthlyForecast, ProfileType } from 'models/profileType.model'
    import React, { useCallback, useEffect, useState } from 'react'
    import { useSelector } from 'react-redux'
    
    import { useNavigate } from 'react-router-dom'
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
    import ProfileTypeService from 'services/profileType.service'
    import ProfileTypeEntityService from 'services/profileTypeEntity.service'
    import { AppStore } from 'store'
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
    import AnalysisConsumptionRow from './AnalysisConsumptionRow'
    
    import './analysisConsumption.scss'
    
    interface AnalysisConsumptionProps {
      aggregatedPerformanceIndicator: PerformanceIndicator
    
      performanceIndicators: PerformanceIndicator[]
    
    }
    
    const AnalysisConsumption: React.FC<AnalysisConsumptionProps> = ({
      aggregatedPerformanceIndicator,
    
      performanceIndicators,
    
    }: AnalysisConsumptionProps) => {
      const { t } = useI18n()
    
      const navigate = useNavigate()
    
      const userPriceConsumption: number = aggregatedPerformanceIndicator.value || 0
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
      const {
        global: { fluidTypes },
        profile,
      } = useSelector((state: AppStore) => state.ecolyo)
    
      const [homePriceConsumption, setHomePriceConsumption] = useState<number>(0)
    
      const [forecast, setForecast] = useState<MonthlyForecast | null>(null)
    
      const [isLoading, setIsLoading] = useState<boolean>(true)
    
      const [activeAverageHome, setActiveAverageHome] = useState<boolean>(false)
      const toggleAccordion = () => {
        setActiveAverageHome(prev => !prev)
        if (!activeAverageHome) {
          setTimeout(() => {
            const content = document.querySelector('.consumption-electricity')
            if (content) {
              content.scrollIntoView({
                behavior: 'smooth',
                block: 'start',
              })
            }
          }, 300)
        }
      }
    
    
      // Disconnected + empty fluids to show in AnalysisConsumptionRow
    
      const disconnectedFluidTypes: FluidType[] = [
        FluidType.ELECTRICITY,
        FluidType.WATER,
        FluidType.GAS,
      ].filter(fluidType => !fluidTypes.includes(fluidType))
    
      const emptyFluidTypes: FluidType[] = []
    
      for (let i = 0; i < performanceIndicators.length; i++) {
    
        if (!performanceIndicators[i]?.value && fluidTypes[i]) {
    
          emptyFluidTypes.push(fluidTypes[i])
        }
      }
    
      const getTotalValueWithConnectedFluids = useCallback(
        (monthlyForecast: MonthlyForecast) => {
          if (fluidTypes.length === 3) {
    
            setHomePriceConsumption(monthlyForecast.totalValue)
    
          } else {
            let totalPrice = 0
            fluidTypes.forEach(fluid => {
    
              if (monthlyForecast.fluidForecast[fluid].value)
                totalPrice += monthlyForecast.fluidForecast[fluid].value
    
            setHomePriceConsumption(totalPrice)
    
      const goToForm = () => {
    
        navigate('/profileType')
    
      useEffect(() => {
        let subscribed = true
    
        async function loadAverageConsumption() {
    
          const profileTypeEntityService = new ProfileTypeEntityService(client)
    
          const profileType: ProfileType | null =
            await profileTypeEntityService.getProfileType(
              analysisDate.minus({ month: 1 }).startOf('month')
            )
    
          if (profileType !== null) {
            const profileTypeService: ProfileTypeService = new ProfileTypeService(
              profileType,
              client,
              analysisDate.year
            )
    
            const monthlyForecast: MonthlyForecast =
              await profileTypeService.getMonthlyForecast(
                analysisDate.minus({ month: 1 }).startOf('month').month
              )
    
            if (subscribed) {
              setForecast(monthlyForecast)
              if (monthlyForecast) {
                getTotalValueWithConnectedFluids(monthlyForecast)
              }
    
              setIsLoading(false)
    
        loadAverageConsumption()
    
        return () => {
          subscribed = false
        }
    
      }, [
        profile.monthlyAnalysisDate.month,
        getTotalValueWithConnectedFluids,
    
      const profileNotCompleted = (
    
        <div className="no-profile">
          <div className="text-16-normal">
            {t('analysis.approximative_description')}
          </div>
          <Button
            aria-label={t('analysis.accessibility.button_go_to_profil')}
            onClick={goToForm}
            classes={{
              root: 'btn-highlight',
              label: 'text-18-bold',
            }}
          >
            {t('analysis.accessibility.button_go_to_profil')}
          </Button>
          <Icon
            icon={PlaceHolderIcon}
            width="100%"
            height="60%"
            alt="pas de profil remplis"
          />
        </div>
      )
    
    
      const Consumption = (
    
        <div className="analysis-graph">
          {isLoading ? (
            <div className="loader-container">
              <Loader color="elec" />
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
            </div>
    
          ) : (
            <>
              <div className="consumption-title text-20-bold">
                <div className="user-title">{t('analysis.user_consumption')}</div>
                <div className={`average-title`}>{t(`analysis.comparison`)}</div>
              </div>
              <div className="consumption-price">
                <AnalysisConsumptionRow
                  fluid={FluidType.MULTIFLUID}
                  userPriceConsumption={userPriceConsumption}
                  homePriceConsumption={homePriceConsumption}
                  performanceValue={null}
                  forecast={forecast}
                  connected={fluidTypes.length > 0}
                  noData={false}
                />
              </div>
              {fluidTypes.map(
                fluid =>
                  Boolean(performanceIndicators[fluid]?.value) && (
                    <AnalysisConsumptionRow
                      key={fluid}
                      fluid={fluid}
                      userPriceConsumption={userPriceConsumption}
                      homePriceConsumption={homePriceConsumption}
                      performanceValue={performanceIndicators[fluid].value}
                      forecast={forecast}
                      connected={true}
                      noData={false}
                    />
                  )
              )}
              {fluidTypes.length < 3 && <hr className="consumption-sep" />}
              {disconnectedFluidTypes.map(fluid => (
                <AnalysisConsumptionRow
                  key={fluid}
                  fluid={fluid}
                  userPriceConsumption={userPriceConsumption}
                  homePriceConsumption={homePriceConsumption}
                  performanceValue={null}
                  forecast={forecast}
                  connected={false}
                  noData={false}
                />
              ))}
              {emptyFluidTypes.map(fluid => (
                <AnalysisConsumptionRow
                  key={fluid}
                  fluid={fluid}
                  userPriceConsumption={userPriceConsumption}
                  homePriceConsumption={homePriceConsumption}
                  performanceValue={null}
                  forecast={forecast}
                  connected={false}
                  noData={true}
                />
              ))}
    
              <Accordion
                expanded={activeAverageHome}
                onChange={toggleAccordion}
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
                classes={{
    
                  root: 'expansion-panel-root',
    
                <AccordionSummary
                  aria-label={t(
                    'profile_type.accessibility.button_toggle_average_home'
                  )}
                  expandIcon={
                    <Icon icon={chevronDown} size={16} className="accordion-icon" />
                  }
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
                  classes={{
    
                    root: 'expansion-panel-summary',
                    content: 'expansion-panel-content',
    
                  <div className="accordion-title accordion-title">
                    {t('analysis.average_home')}
                  </div>
                </AccordionSummary>
                <AccordionDetails
                  classes={{
                    root: 'expansion-panel-details',
                  }}
                >
                  <span className="accordion-desc text-16-normal">
                    {t('analysis.average_home_description')}
                  </span>
                </AccordionDetails>
              </Accordion>
            </>
          )}
        </div>
    
        <>
          <div className="status-header">
            <div>
              <StyledIcon icon={AnalysisIcon} size={44} />
              <p className="text-16-normal">{t('analysis.compare.title')}</p>
            </div>
            {profile.isProfileTypeCompleted && (
    
              <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>
    
          <div className="analysis-graph">
    
            {!profile.isProfileTypeCompleted && profileNotCompleted}
            {profile.isProfileTypeCompleted && Consumption}
    
      )
    }
    
    export default AnalysisConsumption