add func logic for bar graph
This commit is contained in:
10
component/charts/graph-config.ts
Normal file
10
component/charts/graph-config.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
// if values in chartDefaults should not be accessible as props & are a style, move to graphStyles
|
||||
export const chartDefaults = {
|
||||
height: 300,
|
||||
spacingInner: 0.3,
|
||||
spacingOuter: 0.2,
|
||||
contentInset: { top: 30, bottom: 30 },
|
||||
numberOfTicks: 6,
|
||||
min: 0,
|
||||
barColors: ['#598EBB', '#F2D4BC', '#DB7878']
|
||||
};
|
@@ -1,3 +1,42 @@
|
||||
import { ScaleLinear } from 'd3-scale'
|
||||
|
||||
export type ScaleFunction = ScaleLinear<number, number>;
|
||||
export type ScaleFunction = ScaleLinear<number, number>;
|
||||
|
||||
export interface YAxisData {
|
||||
key: string; // string value for ChartLabel component
|
||||
values: number[];
|
||||
// including this code only for review --
|
||||
// do we prefer the idea of passing label formatting from the data or in the component?
|
||||
// generic function type, specific usage of value varies
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
formatLabel?: (value: number) => string;
|
||||
}
|
||||
|
||||
export interface GraphData {
|
||||
xValues: string[];
|
||||
yValues: YAxisData[];
|
||||
}
|
||||
|
||||
interface YAxisProps {
|
||||
maxLeftYAxisValue?: number;
|
||||
maxRightYAxisValue?: number;
|
||||
selectedLeftYAxisLabel?: string;
|
||||
selectedRightYAxisLabel?: string;
|
||||
// generic function type, specific usage of value varies
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
formatRightYAxisLabel?: (value: string) => string;
|
||||
// generic function type, specific usage of value varies
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
formatLeftYAxisLabel?: (value: string) => string;
|
||||
}
|
||||
export interface Props {
|
||||
data: GraphData;
|
||||
height?: number;
|
||||
spacingInner?: number;
|
||||
spacingOuter?: number;
|
||||
contentInset?: { top: number; bottom: number };
|
||||
min?: number;
|
||||
numberOfTicks?: number;
|
||||
barColors?: Array<string>;
|
||||
yAxisProps?: YAxisProps;
|
||||
}
|
40
component/charts/graph-utils.tsx
Normal file
40
component/charts/graph-utils.tsx
Normal file
@@ -0,0 +1,40 @@
|
||||
import { GraphData } from "./graph-types";
|
||||
|
||||
|
||||
export const convertToBarData = (
|
||||
graphData: GraphData,
|
||||
options: {
|
||||
selectedLeftYAxisLabel?: string;
|
||||
selectedRightYAxisLabel?: string;
|
||||
maxRightYAxisValue: number;
|
||||
maxLeftYAxisValue: number;
|
||||
}
|
||||
) => {
|
||||
const xValues = graphData.xValues;
|
||||
const leftAxisIndex = graphData.yValues.findIndex(
|
||||
(y) => y.key === options.selectedLeftYAxisLabel
|
||||
);
|
||||
const rightAxisIndex = graphData.yValues.findIndex(
|
||||
(y) => y.key === options.selectedRightYAxisLabel
|
||||
);
|
||||
|
||||
// scale data points according to max value
|
||||
const barData = graphData.yValues.map((yAxis, index) => {
|
||||
const maxValue =
|
||||
index === rightAxisIndex ? options.maxRightYAxisValue : options.maxLeftYAxisValue;
|
||||
|
||||
// scale values as a percentage of the max value
|
||||
const scaledValues = yAxis.values.map((value) => (value / maxValue) * 100);
|
||||
|
||||
const mappedData = scaledValues.map((scaledValue) => ({ value: scaledValue }));
|
||||
|
||||
return {
|
||||
data: mappedData,
|
||||
svg: { fill: 'transparent' } // fill handled in CustomBars
|
||||
};
|
||||
});
|
||||
const yAxisLeftLabels = leftAxisIndex !== -1 ? graphData.yValues[leftAxisIndex] : null;
|
||||
const yAxisRightLabels = rightAxisIndex !== -1 ? graphData.yValues[rightAxisIndex] : undefined;
|
||||
|
||||
return { barData, yAxisLeftLabels, yAxisRightLabels, xValues };
|
||||
};
|
57
component/charts/use-graph-data.ts
Normal file
57
component/charts/use-graph-data.ts
Normal file
@@ -0,0 +1,57 @@
|
||||
import { useMemo } from 'react';
|
||||
|
||||
import { convertToBarData } from './graph-utils';
|
||||
import { chartDefaults } from './graph-config';
|
||||
import { GraphData, Props, YAxisData } from './graph-types';
|
||||
|
||||
|
||||
|
||||
interface useGraphDataInterface {
|
||||
xValues: Array<string>;
|
||||
barData: {
|
||||
data: {
|
||||
value: number;
|
||||
}[];
|
||||
svg: {
|
||||
fill: string;
|
||||
};
|
||||
}[];
|
||||
yAxisLeftLabels: YAxisData;
|
||||
yAxisRightLabels: YAxisData;
|
||||
defaultProps: Partial<Props>;
|
||||
}
|
||||
|
||||
// this version assumes string values for X, this isn't necessarily the case
|
||||
// convertToBarData is specifically tailored to bar/group bar graphs
|
||||
// ultimately this component could be used by any x & y axis graph types (line/bar/scatter)
|
||||
export const useGraphData = (graphData: GraphData, props: Partial<Props>): useGraphDataInterface => {
|
||||
const { yAxisProps = {}, ...otherProps } = props;
|
||||
const defaultProps = {
|
||||
...chartDefaults,
|
||||
...otherProps,
|
||||
// assign default values for yAxisProps + spread to override with values coming from props
|
||||
yAxisProps: {
|
||||
maxLeftYAxisValue: Math.max(...(graphData.yValues[0]?.values ?? [0])),
|
||||
maxRightYAxisValue:
|
||||
graphData.yValues.length > 1 ? Math.max(...graphData.yValues[1]?.values) : undefined,
|
||||
formatRightYAxisLabel: yAxisProps.formatRightYAxisLabel,
|
||||
formatLeftYAxisLabel: yAxisProps.formatLeftYAxisLabel,
|
||||
selectedLeftYAxisLabel: graphData.yValues[0]?.key,
|
||||
selectedRightYAxisLabel: graphData.yValues[1]?.key,
|
||||
...yAxisProps
|
||||
}
|
||||
};
|
||||
|
||||
const { barData, yAxisLeftLabels, yAxisRightLabels, xValues } = useMemo(
|
||||
() => convertToBarData(graphData, defaultProps.yAxisProps),
|
||||
[graphData, defaultProps.yAxisProps]
|
||||
);
|
||||
|
||||
return {
|
||||
xValues,
|
||||
barData,
|
||||
yAxisLeftLabels,
|
||||
yAxisRightLabels,
|
||||
defaultProps
|
||||
};
|
||||
};
|
Reference in New Issue
Block a user