add bar graph, make changes to customgrid and custombars to match new structure

This commit is contained in:
Loewy
2024-01-15 17:40:24 -08:00
parent 981b5cebca
commit aed0faebf0
10 changed files with 840 additions and 68 deletions

View File

@@ -3,8 +3,7 @@ import * as scale from 'd3-scale';
import { View } from 'react-native';
import { BarChart, XAxis, YAxis } from 'react-native-svg-charts';
import { useGraphData } from '../../../hooks/charts/useGraphData';
import ChartView from '../ChartView';
import { useGraphData } from '../use-graph-data';
import { GraphData, YAxisProps } from '../graph-types';
import { CustomBars } from '../custom-bars';
@@ -22,10 +21,15 @@ interface Props {
barColors?: Array<string>;
useCommonScale?: boolean;
yAxisProps?: YAxisProps;
testID?: string;
}
export const BarGraph: React.FC<Props> = ({ data, useCommonScale = false, ...props }) => {
if (!data || typeof data !== 'object') return null; // TODO: replace when we have error/loading context from useQueryHandler
// TODO: separate PR will update useGraphData to take into account useCommonScale
// eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars
export const BarGraph: React.FC<Props> = ({ data, useCommonScale = false, testID, ...props }) => {
if (!data) {
return null
}
const {
xValues,
yData,
@@ -46,11 +50,14 @@ export const BarGraph: React.FC<Props> = ({ data, useCommonScale = false, ...pro
formatLeftYAxisLabel
}
}
} = useGraphData(data, props, useCommonScale);
// Proper error/loading handling from useQueryHandler can work with this rule
// eslint-disable-next-line react-hooks/rules-of-hooks
} = useGraphData(data, props);
return (
<ChartView>
<View style={[graphStyles.rowContainer, { height: height }]}>
<View style={[graphStyles.rowContainer, { height: height }]} testID={`bar-graph-${testID}`}>
<YAxis
data={yAxisLeftLabels.values}
contentInset={contentInset}
@@ -61,13 +68,14 @@ export const BarGraph: React.FC<Props> = ({ data, useCommonScale = false, ...pro
numberOfTicks={numberOfTicks}
formatLabel={formatLeftYAxisLabel}
/>
<View style={graphStyles.flex}>
<BarChart
style={graphStyles.flex}
data={yData}
gridMin={min}
svg={{ stroke: 'transparent' }} // might want to do the transparent from here?
numberOfTicks={numberOfTicks} // rethink numberOfTicks, it should be determined automatically if we do our y axis scaling proper
svg={{ stroke: 'transparent' }} // might want to do the transparent from here - if so may be best built as coming from defaultConfig
numberOfTicks={numberOfTicks} // rethink numberOfTicks, it should be determined automatically if we do our y axis scaling properly
yAccessor={({ item }) => (item as unknown as { value: number }).value}
contentInset={contentInset}
spacingInner={spacingInner}
@@ -84,6 +92,7 @@ export const BarGraph: React.FC<Props> = ({ data, useCommonScale = false, ...pro
scale={scale.scaleBand}
/>
</View>
<YAxis
data={yAxisRightLabels?.values ?? yAxisLeftLabels.values}
contentInset={contentInset}
@@ -92,10 +101,9 @@ export const BarGraph: React.FC<Props> = ({ data, useCommonScale = false, ...pro
min={min}
max={maxRightYAxisValue}
numberOfTicks={numberOfTicks}
formatLabel={formatRightYAxisLabel} // formatRightYAxisLabel formatting could come from yAxisRightLabels object
formatLabel={formatRightYAxisLabel}
/>
</View>
</ChartView>
);
};

View File

@@ -1,10 +1,10 @@
import { path as d3 } from 'd3-path';
import { ScaleFunction } from './graph-types';
import { ScaleLinearType, ScaleBandType } from './graph-types';
type BarCalculationProps = {
scaleX: ScaleFunction;
scaleY: ScaleFunction;
scaleX: ScaleBandType;
scaleY: ScaleLinearType;
data: { value: number };
barNumber: number;
index: number;

View File

@@ -2,7 +2,7 @@
import { Svg } from 'react-native-svg';
import { Bar } from './bar';
import { ScaleFunction } from './graph-types';
import { ScaleBandType, ScaleLinearType } from './graph-types';
import { calculateBarWidth } from './custom-bar-utils';
export interface CombinedData {
@@ -11,38 +11,38 @@ export interface CombinedData {
}
interface CustomBarsProps {
x: ScaleFunction;
y: ScaleFunction;
x: ScaleBandType;
y: ScaleLinearType;
bandwidth: number;
barColors: string[];
rawData: unknown[]; // TODO: update this value when this data type is defined
combinedData: CombinedData[];
xValues: unknown[]; // TODO: update this value when this data type is defined
barData: CombinedData[];
gap: number;
roundedRadius: number;
}
export const CustomBars: React.FC<CustomBarsProps> = ({
export const CustomBars: React.FC<Partial<CustomBarsProps>> = ({
x: scaleX,
y: scaleY,
bandwidth,
combinedData,
rawData,
barData,
xValues,
barColors,
gap = 2,
roundedRadius = 4
}) => {
const barWidth = calculateBarWidth(bandwidth, combinedData.length, gap);
const barWidth = calculateBarWidth(bandwidth, barData.length, gap);
return rawData.map((_, index) => (
return xValues.map((_, index) => (
<Svg key={`group-${index}`} testID={`svg-${index}`}>
{combinedData.map((item, i) => (
{barData.map((item, i) => (
<Bar
key={`bar-${i}-${index}`}
scaleX={scaleX}
scaleY={scaleY}
data={item.data[index]}
barNumber={i} // index of bar
index={index} // index of group
barNumber={i}
index={index}
fill={barColors[i]}
barWidth={barWidth}
gap={gap}

View File

@@ -1,14 +1,14 @@
import React from 'react';
import { G, Line } from 'react-native-svg';
import { colors } from '../../styles';
import { ScaleFunction } from './graph-types';
import { ScaleLinearType } from './graph-types';
interface CustomGridProps {
y: ScaleFunction;
y: ScaleLinearType;
ticks: Array<number>;
}
export const CustomGrid: React.FC<CustomGridProps> = ({ y, ticks }) => {
export const CustomGrid: React.FC<Partial<CustomGridProps>> = ({ y, ticks }) => {
const [firstTick, ...remainingTicks] = ticks;
const dashArray = [1, 3];
const strokeSolidWidth = 0.2;

View File

@@ -1,6 +1,7 @@
import { ScaleLinear } from 'd3-scale'
import { ScaleBand, ScaleLinear } from 'd3-scale'
export type ScaleFunction = ScaleLinear<number, number>;
export type ScaleLinearType = ScaleLinear<number, number>;
export type ScaleBandType = ScaleBand<number | string>;
export interface YAxisData {
key: string; // string value for ChartLabel and useGraphData
@@ -40,5 +41,6 @@ export interface GraphProps {
min?: number;
numberOfTicks?: number;
barColors?: Array<string>;
useCommonScale?: boolean;
yAxisProps?: YAxisProps;
}