Skip to content
Snippets Groups Projects
Bar.tsx 6.97 KiB
Newer Older
  • Learn to ignore specific revisions
  • Hugo NOUTS's avatar
    Hugo NOUTS committed
    import React, { useState, useEffect } from 'react'
    
    import { useDispatch, useSelector } from 'react-redux'
    import { AppStore } from 'store'
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
    import { ScaleBand, ScaleLinear } from 'd3-scale'
    import { DateTime } from 'luxon'
    
    Romain CREY's avatar
    Romain CREY committed
    import { detect } from 'detect-browser'
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
    
    
    Yoan VALLET's avatar
    Yoan VALLET committed
    import { FluidType } from 'enum/fluid.enum'
    
    import { TimeStep } from 'enum/timeStep.enum'
    
    Yoan VALLET's avatar
    Yoan VALLET committed
    import { Dataload } from 'models'
    import DateChartService from 'services/dateChart.service'
    
    import {
      setCurrentDatachartIndex,
      setSelectedDate,
    } from 'store/chart/chart.actions'
    
    Guilhem CARRON's avatar
    Guilhem CARRON committed
    import { Client } from 'cozy-client'
    import { UsageEventType } from 'enum/usageEvent.enum'
    import UsageEventService from 'services/usageEvent.service'
    
    Yoan VALLET's avatar
    Yoan VALLET committed
    
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
    interface BarProps {
      index: number
    
    Yoan VALLET's avatar
    Yoan VALLET committed
      dataload: Dataload
      compareDataload: Dataload | null
    
      fluidType: FluidType
    
      timeStep: TimeStep
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
      showCompare: boolean
      xScale: ScaleBand<string>
      yScale: ScaleLinear<number, number>
      height: number
    
      isSwitching: boolean
    
    Rémi PAPIN's avatar
    Rémi PAPIN committed
      isDuel?: boolean
    
    Guilhem CARRON's avatar
    Guilhem CARRON committed
      client: Client
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
    }
    
    
    const Bar = ({
      index,
      dataload,
      compareDataload,
    
      fluidType,
    
      timeStep,
    
      showCompare,
      xScale,
      yScale,
      height,
      isSwitching,
    
    Rémi PAPIN's avatar
    Rémi PAPIN committed
      isDuel,
    
    Guilhem CARRON's avatar
    Guilhem CARRON committed
      client,
    
    }: BarProps) => {
    
      const dispatch = useDispatch()
    
      const { selectedDate } = useSelector((state: AppStore) => state.ecolyo.chart)
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
      const [clicked, setClicked] = useState(false)
      const [animationEnded, setAnimationEnded] = useState(false)
      const [compareAnimationEnded, setCompareAnimationEnded] = useState(false)
    
    Romain CREY's avatar
    Romain CREY committed
      const browser = detect()
    
    
      const fluidStyle =
        fluidType === FluidType.MULTIFLUID ? 'MULTIFLUID' : FluidType[fluidType]
    
    Guilhem CARRON's avatar
    Guilhem CARRON committed
      const handleClick = async () => {
        await UsageEventService.addEvent(client, {
          type: UsageEventType.CONSUMPTION_INTERACT_EVENT,
          context: FluidType[fluidType] + ' / ' + TimeStep[timeStep],
        })
    
    Yoan VALLET's avatar
    Yoan VALLET committed
        if (!isSwitching && !isDuel) {
    
          setClicked(true)
    
          dispatch(setSelectedDate(dataload.date))
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
      }
    
      const onAnimationEnd = () => {
        setClicked(false)
        setAnimationEnded(true)
      }
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
      const onCompareAnimationEnd = () => {
        setClicked(false)
        setCompareAnimationEnded(true)
      }
    
    
      const tempYScale: number | undefined = yScale(dataload.value)
      const yScaleValue: number = tempYScale ? tempYScale : 0
    
      const tempCompareYScale: number | undefined = yScale(
        compareDataload ? compareDataload.value : 0
      )
      const yScaleCompareValue: number = tempCompareYScale ? tempCompareYScale : 0
    
      const tempXScale: number | undefined = xScale(
        dataload.date.toLocaleString(DateTime.DATETIME_SHORT)
      )
      const xScaleValue: number = tempXScale ? tempXScale : 0
    
    
    Yoan VALLET's avatar
    Yoan VALLET committed
      const isSelectedDate = isDuel
        ? false
        : new DateChartService().compareStepDate(
            timeStep,
            selectedDate,
            dataload.date
          )
    
    Romain CREY's avatar
    Romain CREY committed
    
    
    Romain CREY's avatar
    Romain CREY committed
      const barClass = clicked
        ? `bar-${fluidStyle} selected bounce-${
            browser && browser.name !== 'edge' ? '2' : '3'
          } delay`
        : isSelectedDate
        ? animationEnded
          ? `bar-${fluidStyle} selected`
          : `bar-${fluidStyle} selected bounce-${
              browser && browser.name !== 'edge' ? '1' : '3'
            } delay--${index % 13}`
        : animationEnded
        ? `bar-${fluidStyle} `
        : `bar-${fluidStyle} bounce-${
            browser && browser.name !== 'edge' ? '1' : '3'
          } delay--${index % 13}`
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
    
    
    Romain CREY's avatar
    Romain CREY committed
      const barBackgroundClass = isSelectedDate
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
    
    
    Romain CREY's avatar
    Romain CREY committed
      const compareBarClass = clicked
        ? `bar-compare-${fluidStyle} selected bounce-${
            browser && browser.name !== 'edge' ? '2' : '3'
          } delay--0`
        : isSelectedDate
        ? compareAnimationEnded
          ? `bar-compare-${fluidStyle} selected`
          : `bar-compare-${fluidStyle} selected bounce-${
              browser && browser.name !== 'edge' ? '1' : '3'
            } delay--${index % 13}`
        : compareAnimationEnded
        ? `bar-compare-${fluidStyle} `
        : `bar-compare-${fluidStyle} bounce-${
            browser && browser.name !== 'edge' ? '1' : '3'
          } delay--${index % 13}`
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
    
      const getBandWidth = (): number => {
        return showCompare ? xScale.bandwidth() / 2 : xScale.bandwidth()
      }
    
      const topRoundedRect = (
    
        _x: number,
        _y: number,
        _width: number,
        _height: number
      ): string => {
        const radius = _height > 4 ? 4 : _height / 4
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
        return (
          'M' +
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
          ',' +
    
          (_y + radius) +
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
          ' a' +
          radius +
          ',' +
          radius +
          ' 0 0 1 ' +
          radius +
          ',' +
          -radius +
          'h' +
    
          (_width - 2 * radius) +
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
          'a' +
          radius +
          ',' +
          radius +
          ' 0 0 1 ' +
          radius +
          ',' +
          radius +
          'v' +
    
          (_height - radius) +
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
          'h' +
    
          -_width +
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
          'z'
        )
      }
    
      useEffect(() => {
    
    Yoan VALLET's avatar
    Yoan VALLET committed
        if (isSelectedDate && !isDuel) {
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
          setClicked(true)
    
          dispatch(setCurrentDatachartIndex(index))
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
        }
    
    Yoan VALLET's avatar
    Yoan VALLET committed
      }, [dispatch, isSelectedDate, isDuel, index])
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
    
      return (
        <g>
          {height > 0 ? (
    
            <g transform={`translate(${xScaleValue}, -40)`}>
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
              <rect
    
                onClick={handleClick}
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
                x="0"
                y="0"
                width={showCompare ? getBandWidth() * 2 : getBandWidth()}
                height={height + 40}
                className={`background-${barBackgroundClass}`}
    
    Romain CREY's avatar
    Romain CREY committed
                fill="#E0E0E0"
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
              />
            </g>
          ) : null}
          {height > 0 && dataload.value && dataload.value >= 0 ? (
    
            <g transform={`translate(${xScaleValue}, ${yScaleValue})`}>
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
              <defs>
                <linearGradient
                  id="gradient"
                  className={barClass}
                  x1="0"
                  x2="0"
                  y1="0"
                  y2="1"
                >
                  <stop id="stop-color-1" offset="0%" />
                  <stop id="stop-color-2" offset="100%" />
                </linearGradient>
              </defs>
              <path
                d={topRoundedRect(
                  showCompare ? getBandWidth() : 0,
                  0,
                  getBandWidth(),
    
                  height - yScaleValue
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
                )}
                fill="url(#gradient)"
    
    Rémi PAPIN's avatar
    Rémi PAPIN committed
                className={isDuel ? 'bar-duel' : barClass}
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
                onClick={handleClick}
                onAnimationEnd={onAnimationEnd}
              />
            </g>
          ) : null}
    
          {showCompare &&
          compareDataload &&
          compareDataload.value &&
          dataload.value >= 0 &&
          compareDataload.value >= 0 ? (
    
            <g transform={`translate(${xScaleValue}, ${yScaleCompareValue})`}>
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
              <defs>
                <linearGradient
                  id="gradient-compare"
                  className={compareBarClass}
                  x1="0"
                  x2="0"
                  y1="0"
                  y2="1"
                >
                  <stop id="stop-compare-color-1" offset="0%" />
                  <stop id="stop-compare-color-2" offset="100%" />
                </linearGradient>
              </defs>
              <path
    
                d={topRoundedRect(
                  0,
                  0,
                  getBandWidth(),
                  height - yScaleCompareValue
                )}
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
                fill="url(#gradient-compare)"
                className={compareBarClass}
                onClick={handleClick}
                onAnimationEnd={onCompareAnimationEnd}
              />
            </g>
          ) : null}
        </g>
      )
    }
    
    export default Bar