import { Popup } from "semantic-ui-react"; import * as React from "react"; interface Props { /** Lista a ser renderizada na barra de percentual */ readings: Readings[]; /** Tamanho minimo da barra */ minWidth: number; /** NĂºmero de casas decimais do percentual total */ decimals?: number; /** Popup do percentual total */ mainPopup?: any; } interface State { filteredReadings: Readings[]; offsetRows: Readings[]; totalReadings: number; } interface Readings { value: number; color: string; width?: number; popup?: any; } export default class MagaMultiProgressBar extends React.Component< Props, State > { static defaultProps = { decimals: 2, minWidth: 2 }; constructor(props: Props) { super(props); this.state = { filteredReadings: [], offsetRows: [], totalReadings: 0, }; } componentDidMount() { this.setComponentState(this.props); } setComponentState = (props: Props) => { const { minWidth, readings } = props; const filteredReadings = readings.filter(({ value }) => value > 0); const totalReadings = filteredReadings.length; const offsetRows = filteredReadings.filter(({ value }) => value < minWidth); this.setState({ filteredReadings, offsetRows, totalReadings }); }; UNSAFE_componentWillReceiveProps(nextProps: Props) { this.setComponentState(nextProps); } getWidth = (value: number) => { const { minWidth } = this.props; const { offsetRows, totalReadings } = this.state; const totalWithoutMinWidth = offsetRows.reduce( (total, reading) => total + (minWidth - reading.value), 0 ); const offsetDiff = totalReadings - offsetRows.length; if (offsetDiff === 0) { return minWidth; } const result = Math.round(value - totalWithoutMinWidth / offsetDiff); return result > minWidth ? result : minWidth; }; getWidthTotal = (readings: Readings[]) => { return readings.reduce((total, reading) => total + reading.width!, 0); }; getPercentageTotal = () => { return this.state.filteredReadings.reduce( (total, { value }) => total + value, 0 ); }; getReadingsWithWidth = () => { return this.state.filteredReadings.map((reading) => ({ ...reading, width: this.getWidth(reading.value), })); }; render() { const { decimals, mainPopup, minWidth } = this.props; const { filteredReadings } = this.state; let { readings } = this.props; let percentageTotal = 0; let widthGraduation = 100; if (filteredReadings.length) { readings = this.getReadingsWithWidth(); percentageTotal = this.getPercentageTotal(); const totalWidth = this.getWidthTotal(readings); const percentageDiff = percentageTotal - totalWidth; widthGraduation = totalWidth; if (percentageDiff !== 0) { const maxValue = readings.reduce( (max, p) => (p.width! > max ? p.width! : max), readings[0].width! ); if (maxValue > minWidth) { const indexReading = readings.findIndex( (reading) => reading.width! === maxValue ); const width = Math.round( readings[indexReading].width! + percentageDiff ); readings[indexReading] = { ...readings[indexReading], width }; widthGraduation = this.getWidthTotal(readings); } } if (percentageTotal > 100) { readings.forEach((x) => { x.width = Math.floor((x.width! * 100) / Math.floor(percentageTotal)); }); } } const bar = (color: string, width: number) => (
); const percentBar = (percentage: number) => (