HistoryGraph.js 4.18 KB
import React, { PureComponent } from 'react'
import { View, Text, StyleSheet } from 'react-native';
import { Svg, G, Line, Rect } from 'react-native-svg'
import { Text as SvgText } from 'react-native-svg'
import * as d3 from 'd3'
// import Showkg from './ShowKg'

const GRAPH_MARGIN = 20
const GRAPH_BAR_WIDTH = 10
const colors = {
  axis: '#E4E4E4',
  bars: '#0066cc',
  bardefult: '#CED4DA'
}

export default class HistoryGraph extends PureComponent {

    constructor(props){
        super(props);
        this.handleClick = this.handleClick.bind(this);
        this.state = {
            kg: this.props.data[this.props.data.length - 1].label,
            index: this.props.data.length-1
        }
    }

    handleClick = inkg => {
        this.setState({kg: inkg});
    }

    componentDidUpdate(prevProps, prevState){
      if (this.props.data !== prevProps.data) {
        this.setState({
              ...this.state,
              kg : this.props.data[this.props.data.length - 1].label,
              index: this.props.data.length-1
            })
  }    }

    render() {
      // Dimensions
      const SVGHeight = 300
      const SVGWidth = 450
      const graphHeight = SVGHeight - 2 * GRAPH_MARGIN
      const graphWidth = SVGWidth - 2 * GRAPH_MARGIN
      const data = this.props.data

      // X scale point
      const xDomain = data.map(item => item.label)
      const xRange = [0, graphWidth]
      const x = d3.scalePoint()
        .domain(xDomain)
        .range(xRange)
        .padding(1)

      // Y scale linear
      const maxValue = d3.max(data, d => d.value)
      const topValue = Math.ceil(maxValue / this.props.round) * this.props.round
      const yDomain = [0, topValue]
      const yRange = [0, graphHeight]
      const y = d3.scaleLinear()
        .domain(yDomain)
        .range(yRange)

      // top axis and middle axis
      const middleValue = topValue / 2

      return (
      <View>
        <Svg width={SVGWidth} height={SVGHeight}>
          <G y={graphHeight + GRAPH_MARGIN}>
            {/* Top value label */}
            <SvgText
                x={graphWidth}
                textAnchor="end"
                y={y(topValue) * -1 - 5}
                fontSize={15}
                fill="black"
                fillOpacity={0.4}>
                {topValue + ' ' + this.props.unit}
              </SvgText>

            {/* top axis */}
            <Line
              x1="0"
              y1={y(topValue) * -1}
              x2={graphWidth}
              y2={y(topValue) * -1}
              stroke={colors.axis}
              strokeDasharray={[3, 3]}
              strokeWidth="0.5"
            />

            {/* middle axis */}
            <Line
              x1="0"
              y1={y(middleValue) * -1}
              x2={graphWidth}
              y2={y(middleValue) * -1}
              stroke={colors.axis}
              strokeDasharray={[3, 3]}
              strokeWidth="0.5"
            />

            {/* bottom axis */}
            <Line
              x1="0"
              y1="2"
              x2={graphWidth}
              y2="2"
              stroke={colors.axis}
              strokeWidth="0.5"
            />

              {/* bars */}
              {data.map(item => (
              <Rect
                key={'bar' + item.label}
                x={x(item.label) - (GRAPH_BAR_WIDTH / 2)}
                y={y(item.value) * -1}
                rx={2.5}
                width={GRAPH_BAR_WIDTH}
                height={y(item.value)}
                fill = {this.state.kg == item.label ? colors.bars : colors.bardefult}
                onPress={()=>this.handleClick(item.label)}
              />
            ))}

            {/* labels */}
            {data.map(item => (
              <SvgText
              key={'label' + item.label}
              fontSize="12"
              x={x(item.label)}
              y="10"
              textAnchor="middle">{item.label}</SvgText>
            ))}
          </G>
          </Svg>
          <View style={style.container}>
            <Text>{this.state.kg}</Text>
          </View>
        </View>
      )
    }
}

const style = StyleSheet.create({
  container: {
    flex : 8.8,
    backgroundColor:"rgba(230,230,230,0.5)",
    justifyContent : 'center',
    padding : 25,
  }
});