Skip to content
Snippets Groups Projects
BarChart.tsx 4.18 KiB
Newer Older
  • Learn to ignore specific revisions
  • Hugo NOUTS's avatar
    Hugo NOUTS committed
    import React from 'react'
    import { scaleBand, ScaleBand, scaleLinear, ScaleLinear } from 'd3-scale'
    import {
      IDataload,
      IChartData,
      TimeStep,
      ITimePeriod,
    } from 'services/dataConsumptionContracts'
    import { FluidType } from 'enum/fluid.enum'
    import Bar from 'components/ContentComponents/Charts/Bar'
    import Hash from 'components/ContentComponents/Charts/Hash'
    import AxisBottom from 'components/ContentComponents/Charts/AxisBottom'
    import AxisRight from 'components/ContentComponents/Charts/AxisRight'
    import { DateTime } from 'luxon'
    
    export interface BarChartProps {
      chartData: IChartData
      fluidTypes: FluidType[]
      timeStep: TimeStep
      multiFluid: boolean
      selectedDate: DateTime
      showCompare: boolean
      challengePeriod: ITimePeriod | null
      handleClickData: (
        dataload: IDataload,
        compareDataload: IDataload | null
      ) => void
      width?: number
      height?: number
      marginLeft?: number
      marginRight?: number
      marginTop?: number
      marginBottom?: number
    }
    
    interface DefaultProps {
      width: number
      height: number
      marginLeft: number
      marginRight: number
      marginTop: number
      marginBottom: number
    }
    
    type PropsWithDefaults = BarChartProps & DefaultProps
    
    const BarChart: React.FC<BarChartProps> = (props: BarChartProps) => {
      const {
        chartData,
        fluidTypes,
        timeStep,
        multiFluid,
        selectedDate,
        showCompare,
        challengePeriod,
        handleClickData,
        width,
        height,
        marginLeft,
        marginRight,
        marginTop,
        marginBottom,
      } = props as PropsWithDefaults
      const getContentWidth = () => {
        return width - marginLeft - marginRight
      }
    
      const getContentHeight = () => {
        return height - marginTop - marginBottom
      }
    
      const getMaxLoad = () => {
        let max = chartData.actualData
          ? Math.max(...chartData.actualData.map(d => d.value))
          : 0
        const maxCompare = chartData.comparisonData
          ? Math.max(...chartData.comparisonData.map(d => d.value))
          : 0
        max = max === -1 ? 15 : max
        return showCompare ? Math.max(max, maxCompare) : max
      }
    
      const xScale: ScaleBand<string> = scaleBand()
        .domain(
          chartData.actualData.map(d =>
            d.date.toLocaleString(DateTime.DATETIME_SHORT)
          )
        )
        .range([0, getContentWidth()])
        .padding(0.2)
    
      const xScaleWithoutPadding: ScaleBand<string> = scaleBand()
        .domain(
          chartData.actualData.map(d =>
            d.date.toLocaleString(DateTime.DATETIME_SHORT)
          )
        )
        .range([0, getContentWidth()])
    
      const yScale: ScaleLinear<number, number> = scaleLinear()
        .domain([0, getMaxLoad()])
        .range([getContentHeight(), 0])
    
      return (
        <svg width={width} height={height}>
          <g transform={`translate(${marginLeft},${marginTop})`}>
            <Hash
              challengePeriod={challengePeriod}
              multiFluid={multiFluid}
              xScale={xScale}
              padding={(xScaleWithoutPadding.bandwidth() - xScale.bandwidth()) / 2}
              width={getContentWidth()}
              height={getContentHeight()}
            />
          </g>
          <AxisRight
            fluidTypes={fluidTypes}
            yScale={yScale}
            width={width}
            marginRight={marginRight}
            marginTop={marginTop}
          />
          <g transform={`translate(${marginLeft},${marginTop})`}>
            {chartData.actualData.map((d, index) => (
              <Bar
                key={index}
                index={index}
                dataload={d}
                compareDataload={
                  chartData.comparisonData ? chartData.comparisonData[index] : null
                }
                fluidTypes={fluidTypes}
                timeStep={timeStep}
                multiFluid={multiFluid}
                selectedDate={selectedDate}
                showCompare={showCompare}
                handleClickData={handleClickData}
                xScale={xScale}
                yScale={yScale}
                height={getContentHeight()}
              />
            ))}
          </g>
          <AxisBottom
            data={chartData.actualData}
            timeStep={timeStep}
            xScale={xScale}
            height={height}
            marginLeft={marginLeft}
            marginBottom={marginBottom}
            selectedDate={selectedDate}
          />
        </svg>
      )
    }
    
    BarChart.defaultProps = {
      width: 600,
      height: 400,
      marginLeft: 10,
      marginRight: 60,
      marginTop: 20,
      marginBottom: 50,
    }
    
    export default BarChart