import * as React from 'react'; import classNames from 'classnames'; interface IProps { value: number; error: boolean; counter: boolean; } interface IState { width: number; strokeWidth: number; addCSSTransition: boolean; } export class GridItemProgressCircle extends React.Component { svgNode: React.RefObject; constructor(props: IProps) { super(props); this.state = { width: 0, strokeWidth: 0, addCSSTransition: false, }; this.svgNode = React.createRef(); this.updateStateFromRefNode = this.updateStateFromRefNode.bind(this); } componentDidMount() { this.updateStateFromRefNode(); setTimeout(() => { this.setState({addCSSTransition: true}); }, 500); } updateStateFromRefNode() { if (this.svgNode.current != null) { const boundingBox = this.svgNode.current.getBoundingClientRect(); const circleNode = this.svgNode.current.querySelector('circle'); if (circleNode != null) { this.setState({ width: boundingBox.width, strokeWidth: parseInt( window.getComputedStyle(circleNode).strokeWidth, 10, ), }); } } else { setTimeout(this.updateStateFromRefNode, 50); } } computeSVGAttributes() { let attributes = { radius: 0, circumference: 0, dashOffset: 0, }; if (this.state.width > 0 && this.state.strokeWidth > 0) { attributes.radius = (this.state.width / 2) - (this.state.strokeWidth / 2); attributes.circumference = 2 * Math.PI * attributes.radius; attributes.dashOffset = attributes.circumference * (1 - (this.props.value / 100)); } return attributes; } render() { const {radius, circumference, dashOffset} = this.computeSVGAttributes(); let status = ''; if (this.props.error === true) { status = 'error'; } else if (this.props.value >= 100) { status = 'completed'; } const progressDoneClasses = classNames( 'progress-done', { 'progress-done--completed': status === 'completed', 'progress-done--error': status === 'error', }, ); const svgClasses = classNames( 'progress-svg', { 'error': this.props.error, 'completed': status === 'completed', }, ); const circleTransitionStyle = this.state.addCSSTransition === false ? {} : {transition: 'stroke-dashoffset ease-in-out .3s'}; return (
{status === 'error' ? null : ( )} {status === 'completed' ? null : ( )}
{this.props.counter !== true ? null : ( {this.props.value}% )}
); } }