diff --git a/package-lock.json b/package-lock.json index 81e76a5a..08d76d2f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6813,6 +6813,11 @@ "@types/jest": "*" } }, + "@types/tinycolor2": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/@types/tinycolor2/-/tinycolor2-1.4.3.tgz", + "integrity": "sha512-Kf1w9NE5HEgGxCRyIcRXR/ZYtDv0V8FVPtYHwLxl0O+maGX0erE77pQlD0gpP+/KByMZ87mOA79SjifhSB3PjQ==" + }, "@types/uglify-js": { "version": "3.11.1", "resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.11.1.tgz", @@ -23191,6 +23196,11 @@ "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" }, + "tinycolor2": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.4.2.tgz", + "integrity": "sha512-vJhccZPs965sV/L2sU4oRQVAos0pQXwsvTLkWYdqJ+a8Q5kPFzJTuOFwy7UniPli44NKQGAglksjvOcpo95aZA==" + }, "tmpl": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz", diff --git a/package.json b/package.json index ab09b9b4..651d5877 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "@types/classnames": "^2.3.1", "@types/leaflet.heat": "^0.2.0", "@types/query-string": "^6.3.0", + "@types/tinycolor2": "^1.4.3", "axios": "^0.21.2", "classnames": "^2.3.1", "env-cmd": "^10.1.0", @@ -33,6 +34,7 @@ "react-scripts": "4.0.3", "react-share": "^4.4.0", "recharts": "^2.0.9", + "tinycolor2": "^1.4.2", "typescript": "^4.3.5" }, "scripts": { diff --git a/src/components/molecules/GenericBarChart.tsx b/src/components/molecules/GenericBarChart.tsx new file mode 100644 index 00000000..264616b0 --- /dev/null +++ b/src/components/molecules/GenericBarChart.tsx @@ -0,0 +1,119 @@ +import React, { FC } from 'react'; +import { ResponsiveContainer, BarChart, LabelList, XAxis, Bar, Tooltip, Legend } from 'recharts'; +import { roseColor, honeyColor, yellowColor, blackColor, whiteColor } from 'style'; +import { Typography } from 'components/atoms'; +import tinycolor from 'tinycolor2'; + +const colors = [yellowColor, honeyColor, roseColor]; +const Y_AXIS_OFFSET = 20; +const MIN_BAR_HEIGHT = 20; + +type BarDataMap = { + [key: string]: number | string; +}; + +type CustomizedLabelProps = { + x?: number; + y?: number; + value?: number; + height?: number; + width?: number; + isPercentage?: boolean; + isStacked?: boolean; +}; + +interface IBarChartBaseProps { + data: Array; + isPercentage: boolean; + textLabel?: string; +} + +interface ISingleBarChartProps extends IBarChartBaseProps {} + +interface IMultiBarChartProps extends IBarChartBaseProps { + isStacked: boolean; +} + +const CustomizedLabel = (props: CustomizedLabelProps) => { + const { x = 0, y = 0, value = 0, height = 0, width = 0, isPercentage, isStacked } = props; + const calculatedValue = isPercentage ? value + '%' : value; + return ( + + + {height < MIN_BAR_HEIGHT ? null : calculatedValue} + + + ); +}; + +const BarChartContainer: FC = ({ data, textLabel, children }) => { + return ( + <> + {textLabel && {textLabel}} + + + + + + {children} + + + + ); +}; + +const SingleBarChart: FC = ({ data, isPercentage, textLabel }) => { + const yLabels = data ? Object.keys(data[0]) : []; + yLabels.splice(0, 1); + + const barStyle = { + filter: `drop-shadow(0.2em 0.2em 0 ${tinycolor(roseColor).darken().toString()})`, + }; + return ( + + + } dataKey={yLabels[0]} /> + + + ); +}; + +const MultiBarChart: FC = ({ data, isPercentage, isStacked, textLabel }) => { + const yLabels = data ? Object.keys(data[0]) : []; + yLabels.splice(0, 1); + const maxBarsNum = yLabels.length; + + return ( + + {Array.from({ length: maxBarsNum }, (_, i) => { + const barStyle = { + filter: `drop-shadow(0.2em ${isStacked ? '0' : '0.2em'} 0 ${tinycolor(colors[i]).darken().toString()})`, + }; + + return ( + + } + dataKey={yLabels[i]} + /> + + ); + })} + + ); +}; + +export { SingleBarChart, MultiBarChart };