railbird-gql/component/charts/bar-graph/bar-graph.tsx
loewy ec6d36b44c ChartLabel -- graph helper component to render title + labels for a chart/graph (#30)
-- question: helper functions can be used directly in chartLabel OR I could have them be part of useGraphData hook since this component will be called on a graph.

image: shows the Chart Label up top with capital cased keys/labels and color boxes

FIXES #29

Co-authored-by: Loewy <loewy@chainstarters.com>
Reviewed-on: billnerds/rn-playground#30
Reviewed-by: Kat Huang <kkathuang@gmail.com>
Co-authored-by: loewy <loewymalkov@gmail.com>
Co-committed-by: loewy <loewymalkov@gmail.com>
2024-01-17 14:29:28 -07:00

117 lines
3.9 KiB
TypeScript

import React from 'react';
import * as scale from 'd3-scale';
import { View } from 'react-native';
import { BarChart, XAxis, YAxis } from 'react-native-svg-charts';
import { useGraphData } from '../use-graph-data';
import { GraphData, YAxisProps } from '../graph-types';
import { CustomBars } from '../custom-bars';
import { CustomGrid } from '../custom-grid';
import { graphStyles } from '../chart-styles';
import ChartView from '../chart-view';
import ChartLabel from '../chart-label/chart-label';
interface Props {
data: GraphData;
height?: number;
spacingInner?: number;
spacingOuter?: number;
contentInset?: { top: number; bottom: number };
min?: number;
numberOfTicks?: number;
barColors?: Array<string>;
useCommonScale?: boolean;
yAxisProps?: YAxisProps;
testID?: string;
}
// 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,
yAxisRightLabels,
yAxisLeftLabels,
defaultProps: {
height,
spacingInner,
spacingOuter,
contentInset,
min,
numberOfTicks,
barColors,
yAxisProps: {
maxLeftYAxisValue,
maxRightYAxisValue,
formatRightYAxisLabel,
formatLeftYAxisLabel
}
}
// Proper error/loading handling from useQueryHandler can work with this rule
// eslint-disable-next-line react-hooks/rules-of-hooks
} = useGraphData(data, props);
// TODO: Will come from BE & destructured / color assigned in useGraphData
const yLabels = [{ displayName: 'Shots Taken', axis: 'LEFT' as 'LEFT', color: barColors[0] }, { displayName:'Make Percentage', axis: 'RIGHT' as 'RIGHT', color: barColors[1] }]
const title = 'Shots Taken / Make Percentage by Cut Angle'
return (
<ChartView>
<ChartLabel title={title} yLabels={yLabels} />
<View style={[graphStyles.rowContainer, { height: height }]} testID={`bar-graph-${testID}`}>
<YAxis
data={yAxisLeftLabels.values}
contentInset={contentInset}
svg={graphStyles.yAxisFontStyle}
style={graphStyles.yAxisLeftPadding}
min={min}
max={maxLeftYAxisValue}
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 - 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}
spacingOuter={spacingOuter}
>
<CustomGrid />
<CustomBars barData={yData} xValues={xValues} barColors={barColors} />
</BarChart>
<XAxis
data={xValues.map((_, index) => index)}
formatLabel={(_, index) => xValues[index]}
style={graphStyles.xAxisMarginTop}
svg={graphStyles.xAxisFontStyle}
scale={scale.scaleBand}
/>
</View>
<YAxis
data={yAxisRightLabels?.values ?? yAxisLeftLabels.values}
contentInset={contentInset}
svg={graphStyles.yAxisFontStyle}
style={graphStyles.yAxisRightPadding}
min={min}
max={maxRightYAxisValue}
numberOfTicks={numberOfTicks}
formatLabel={formatRightYAxisLabel}
/>
</View>
</ChartView>
);
};
export default BarGraph;