Skip to content
Snippets Groups Projects
Bar.tsx 5.81 KiB
Newer Older
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
            onClick={handleClick}
Hugo NOUTS's avatar
Hugo NOUTS committed
            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