Skip to content
Snippets Groups Projects
Bar.tsx 5.78 KiB
Newer Older
  • Learn to ignore specific revisions
  • Hugo NOUTS's avatar
    Hugo NOUTS committed
    import React, { useState, useEffect } from 'react'
    import { ScaleBand, ScaleLinear } from 'd3-scale'
    import {
      IDataload,
      TimeStep,
      ITimePeriod,
    } from 'services/dataConsumptionContracts'
    import { compareStepDate } from 'services/dateChartService'
    import { FluidType } from 'enum/fluid.enum'
    import { DateTime } from 'luxon'
    
    interface BarProps {
      index: number
      dataload: IDataload
      compareDataload: IDataload | null
      fluidTypes: FluidType[]
      timeStep: TimeStep
      multiFluid: boolean
      selectedDate: DateTime
      showCompare: boolean
      handleClickData: (
        dataload: IDataload,
        compareDataload: IDataload | null
      ) => void
      xScale: ScaleBand<string>
      yScale: ScaleLinear<number, number>
      height: number
    }
    
    const Bar = (props: BarProps) => {
      const {
        index,
        dataload,
        compareDataload,
        fluidTypes,
        timeStep,
        multiFluid,
        selectedDate,
        showCompare,
        handleClickData,
        xScale,
        yScale,
        height,
      } = props
    
      const [clicked, setClicked] = useState(false)
      const [animationEnded, setAnimationEnded] = useState(false)
      const [compareAnimationEnded, setCompareAnimationEnded] = useState(false)
    
      const fluidStyle = multiFluid
        ? 'MULTIFLUID'
        : fluidTypes.length === 0
        ? 'MULTIFLUID'
        : fluidTypes.length > 1
        ? 'MULTIFLUID'
        : FluidType[fluidTypes[0]]
      const handleClick = () => {
        setClicked(true)
        handleClickData(dataload, compareDataload)
      }
    
      const onAnimationEnd = () => {
        setClicked(false)
        setAnimationEnded(true)
      }
      const onCompareAnimationEnd = () => {
        setClicked(false)
        setCompareAnimationEnded(true)
      }
    
      const isSelectedDate = compareStepDate(timeStep, selectedDate, dataload.date)
    
      const barClass = clicked
        ? `bar-${fluidStyle} selected bounce-2 delay`
        : isSelectedDate
        ? animationEnded
          ? `bar-${fluidStyle} selected`
          : `bar-${fluidStyle} selected bounce-1 delay--${index % 13}`
        : animationEnded
        ? `bar-${fluidStyle} `
        : `bar-${fluidStyle} bounce-1 delay--${index % 13}`
    
      const barBackgroundClass = isSelectedDate
    
      const compareBarClass = clicked
        ? `bar-compare-${fluidStyle} selected bounce-2 delay--0`
        : isSelectedDate
        ? compareAnimationEnded
          ? `bar-compare-${fluidStyle} selected`
          : `bar-compare-${fluidStyle} selected bounce-1 delay--${index % 13}`
        : compareAnimationEnded
        ? `bar-compare-${fluidStyle} `
        : `bar-compare-${fluidStyle} bounce-1 delay--${index % 13}`
    
      const getBandWidth = (): number => {
        return showCompare ? xScale.bandwidth() / 2 : xScale.bandwidth()
      }
    
      const topRoundedRect = (
        x: number,
        y: number,
        width: number,
        height: number
      ) => {
        const radius = height > 4 ? 4 : height / 4
        return (
          'M' +
          x +
          ',' +
          (y + radius) +
          ' a' +
          radius +
          ',' +
          radius +
          ' 0 0 1 ' +
          radius +
          ',' +
          -radius +
          'h' +
          (width - 2 * radius) +
          'a' +
          radius +
          ',' +
          radius +
          ' 0 0 1 ' +
          radius +
          ',' +
          radius +
          'v' +
          (height - radius) +
          'h' +
          -width +
          'z'
        )
      }
    
      useEffect(() => {
        if (isSelectedDate) {
          setClicked(true)
          handleClickData(dataload, compareDataload)
        }
      }, [selectedDate.toString()])
    
      return (
        <g>
          {height > 0 ? (
            <g
              transform={`translate(${xScale(
                dataload.date.toLocaleString(DateTime.DATETIME_SHORT)
              )}, -40)`}
            >
              <rect
                x="0"
                y="0"
                width={showCompare ? getBandWidth() * 2 : getBandWidth()}
                height={height + 40}
                className={`background-${barBackgroundClass}`}
                fill="#E0E0E010"
              />
            </g>
          ) : null}
          {height > 0 && dataload.value && dataload.value >= 0 ? (
            <g
              transform={`translate(${xScale(
                dataload.date.toLocaleString(DateTime.DATETIME_SHORT)
              )}, ${yScale(dataload.value)})`}
            >
              <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 - yScale(dataload.value)
                )}
                fill="url(#gradient)"
                className={barClass}
                onClick={handleClick}
                onAnimationEnd={onAnimationEnd}
              />
            </g>
          ) : null}
    
          {showCompare &&
          compareDataload &&
          compareDataload.value &&
          dataload.value >= 0 &&
          compareDataload.value >= 0 ? (
            <g
              transform={`translate(${xScale(
                dataload.date.toLocaleString(DateTime.DATETIME_SHORT)
              )}, ${yScale(compareDataload.value)})`}
            >
              <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 - yScale(compareDataload.value)
                )}
                fill="url(#gradient-compare)"
                className={compareBarClass}
                onClick={handleClick}
                onAnimationEnd={onCompareAnimationEnd}
              />
            </g>
          ) : null}
        </g>
      )
    }
    
    export default Bar