railbird-gql/component/charts/bar-graph/bar-graph.tsx

138 lines
3.6 KiB
TypeScript
Raw Normal View History

import * as scale from "d3-scale";
2024-02-03 20:30:00 -07:00
import React from "react";
import { View } from "react-native";
import { BarChart, XAxis, YAxis } from "react-native-svg-charts";
import { GraphData, YAxisProps } from "../graph-types";
2024-02-03 20:30:00 -07:00
import { useGraphData } from "../use-graph-data";
2024-02-03 20:30:00 -07:00
import ChartLabel from "../chart-label/chart-label";
import { graphStyles } from "../chart-styles";
import ChartView from "../chart-view";
2024-02-03 20:30:00 -07:00
import { CustomBars } from "../custom-bars";
import { CustomGrid } from "../custom-grid";
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;
} // TODO:#38
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 #38
// eslint-disable-next-line react-hooks/rules-of-hooks
} = useGraphData(data, { includeColors: false, ...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}
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;