From 8c3b745d4dbbf5a57308e74eefffd23d2bf99920 Mon Sep 17 00:00:00 2001 From: Loewy Date: Tue, 13 Feb 2024 11:50:06 -0800 Subject: [PATCH 1/4] wip: minor changes --- .../charts/container/chart-container.tsx | 91 ++++++++++++++ src/component/charts/graph-types.ts | 9 ++ .../charts/line-graph/line-graph.tsx | 114 ++++-------------- src/screens/session.tsx | 7 +- 4 files changed, 129 insertions(+), 92 deletions(-) create mode 100644 src/component/charts/container/chart-container.tsx diff --git a/src/component/charts/container/chart-container.tsx b/src/component/charts/container/chart-container.tsx new file mode 100644 index 0000000..58f5c09 --- /dev/null +++ b/src/component/charts/container/chart-container.tsx @@ -0,0 +1,91 @@ +import React from "react"; +import { View } from "react-native"; +import { YAxis } from "react-native-svg-charts"; + +import { graphStyles } from "../chart-styles"; +import ChartView from "../chart-view"; +import { ChartContainerProps } from "../graph-types"; +import { useGraphData } from "../use-graph-data"; + +// TODO: separate PR will update useGraphData to take into account useCommonScale +// eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars +const ChartContainer: React.FC = ({ + ChartComponent, + data, + useCommonScale = false, + testID, + ...props +}) => { + if (!data || typeof data !== "object") { + return null; + } // TODO:#38 + const { + xValues, + yData, + yAxisLeftLabels, + yAxisRightLabels, + defaultProps: { + height, + contentInset, + min, + numberOfTicks, + lineStrokeWidth, + yAxisProps: { + maxLeftYAxisValue, + maxRightYAxisValue, + formatLeftYAxisLabel, + formatRightYAxisLabel, + }, + }, + // Proper error/loading handling from useQueryHandler can work with this rule #38 + // eslint-disable-next-line react-hooks/rules-of-hooks + } = useGraphData(data, props); + + // TODO: This could be done by the hook since it already handles spreading props. + // Depending on if we want a context provider for Charts, that could be another way to handle it + const chartComponentProps = { + yData, + xValues, + lineStrokeWidth, + min, + contentInset, + numberOfTicks, + }; + return ( + + + + + + + + + + ); +}; + +export default ChartContainer; diff --git a/src/component/charts/graph-types.ts b/src/component/charts/graph-types.ts index e498466..bc36201 100644 --- a/src/component/charts/graph-types.ts +++ b/src/component/charts/graph-types.ts @@ -76,3 +76,12 @@ export interface CommonProps { yAxisProps?: YAxisProps; testID?: string; } +/** + * Common properties for graph render components. + * + * @interface ChartContainerProps + * @property {React.FC} ChartComponent - The graph component to render + */ +export interface ChartContainerProps extends CommonProps { + ChartComponent?: React.FC; +} diff --git a/src/component/charts/line-graph/line-graph.tsx b/src/component/charts/line-graph/line-graph.tsx index 3b7af11..066f88d 100644 --- a/src/component/charts/line-graph/line-graph.tsx +++ b/src/component/charts/line-graph/line-graph.tsx @@ -1,102 +1,38 @@ import * as shape from "d3-shape"; import React from "react"; -import { View } from "react-native"; -import { LineChart, XAxis, YAxis } from "react-native-svg-charts"; - +import { LineChart, XAxis } from "react-native-svg-charts"; import { graphStyles } from "../chart-styles"; -import ChartView from "../chart-view"; import { CustomGrid } from "../custom-grid"; import { CommonProps } from "../graph-types"; -import { useGraphData } from "../use-graph-data"; // TODO: separate PR will update useGraphData to take into account useCommonScale // eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars -const LineGraph: React.FC = ({ - data, - useCommonScale = false, - testID, - ...props -}) => { - if (!data || typeof data !== "object") { - return null; - } // TODO:#38 - const { - xValues, - yData, - yAxisLeftLabels, - yAxisRightLabels, - defaultProps: { - height, - contentInset, - min, - numberOfTicks, - lineStrokeWidth, - yAxisProps: { - maxLeftYAxisValue, - maxRightYAxisValue, - formatLeftYAxisLabel, - formatRightYAxisLabel, - }, - }, - // Proper error/loading handling from useQueryHandler can work with this rule #38 - // eslint-disable-next-line react-hooks/rules-of-hooks - } = useGraphData(data, props); - +const LineGraph: React.FC = ({ ...chartComponentProps }) => { + const { yData, xValues, lineStrokeWidth, min, contentInset, numberOfTicks } = + chartComponentProps; return ( - - + (item as unknown as { value: number }).value} + xAccessor={({ index }) => xValues[index] as number} + gridMin={min} + contentInset={contentInset} + numberOfTicks={numberOfTicks} > - - - - (item as unknown as { value: number }).value - } - xAccessor={({ index }) => xValues[index] as number} - gridMin={min} - contentInset={contentInset} - numberOfTicks={numberOfTicks} - > - - - index)} // TODO: update when useGraphHook returns explicit display values - style={[graphStyles.xAxisMarginTop]} - svg={graphStyles.xAxisFontStyle} - numberOfTicks={numberOfTicks} - contentInset={graphStyles.horizontalInset} - /> - - - - + + + index)} // TODO: update when useGraphHook returns explicit display values + style={[graphStyles.xAxisMarginTop]} + svg={graphStyles.xAxisFontStyle} + numberOfTicks={numberOfTicks} + contentInset={graphStyles.horizontalInset} + /> + ); }; diff --git a/src/screens/session.tsx b/src/screens/session.tsx index e44b554..ef1d982 100644 --- a/src/screens/session.tsx +++ b/src/screens/session.tsx @@ -1,14 +1,15 @@ import React from "react"; import { StyleSheet, View } from "react-native"; -import { graph_data_two_measures } from "../../test/mock/charts/mock-data"; -import BarGraph from "../component/charts/bar-graph/bar-graph"; +import { line_chart_two_y_data } from "../../test/mock/charts/mock-data"; +import ChartContainer from "../component/charts/container/chart-container"; +import LineGraph from "../component/charts/line-graph/line-graph"; // Session Mock - can be used for session summary screen using a query handler component // BarGraph component using mocked data currently export default function SessionScreen() { return ( - + ); } From 3eab510f5a54fe6fa6bc51f83ee1210662481918 Mon Sep 17 00:00:00 2001 From: Loewy Date: Tue, 13 Feb 2024 13:38:47 -0800 Subject: [PATCH 2/4] wip: types updated, works with x axis wrapped in container --- src/component/charts/container/chart-container.tsx | 12 ++++++++++-- src/component/charts/graph-types.ts | 8 +++++--- src/component/charts/line-graph/line-graph.tsx | 9 +-------- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/src/component/charts/container/chart-container.tsx b/src/component/charts/container/chart-container.tsx index 58f5c09..096405f 100644 --- a/src/component/charts/container/chart-container.tsx +++ b/src/component/charts/container/chart-container.tsx @@ -1,7 +1,6 @@ import React from "react"; import { View } from "react-native"; -import { YAxis } from "react-native-svg-charts"; - +import { XAxis, YAxis } from "react-native-svg-charts"; import { graphStyles } from "../chart-styles"; import ChartView from "../chart-view"; import { ChartContainerProps } from "../graph-types"; @@ -69,6 +68,15 @@ const ChartContainer: React.FC = ({ /> + index)} // TODO: update when useGraphHook returns explicit display values + formatLabel={(_, index) => xValues[index]} + style={[graphStyles.xAxisMarginTop]} + svg={graphStyles.xAxisFontStyle} + numberOfTicks={numberOfTicks} // need a dynamic way of setting number of ticks + contentInset={graphStyles.horizontalInset} + // scale={scale.scaleBand} // Need to know the type of ChartComponent + /> } ChartComponent - The graph component to render */ export interface ChartContainerProps extends CommonProps { - ChartComponent?: React.FC; + ChartComponent: React.ComponentType; + data: GraphData; } diff --git a/src/component/charts/line-graph/line-graph.tsx b/src/component/charts/line-graph/line-graph.tsx index 066f88d..cbb0893 100644 --- a/src/component/charts/line-graph/line-graph.tsx +++ b/src/component/charts/line-graph/line-graph.tsx @@ -1,6 +1,6 @@ import * as shape from "d3-shape"; import React from "react"; -import { LineChart, XAxis } from "react-native-svg-charts"; +import { LineChart } from "react-native-svg-charts"; import { graphStyles } from "../chart-styles"; import { CustomGrid } from "../custom-grid"; import { CommonProps } from "../graph-types"; @@ -25,13 +25,6 @@ const LineGraph: React.FC = ({ ...chartComponentProps }) => { > - index)} // TODO: update when useGraphHook returns explicit display values - style={[graphStyles.xAxisMarginTop]} - svg={graphStyles.xAxisFontStyle} - numberOfTicks={numberOfTicks} - contentInset={graphStyles.horizontalInset} - /> ); }; From 4e7046bd28290938e4ead200b149d4f2b9a85867 Mon Sep 17 00:00:00 2001 From: Loewy Date: Tue, 13 Feb 2024 14:10:05 -0800 Subject: [PATCH 3/4] update test to be for the container rather than component --- .../charts/container/chart-container.tsx | 2 +- test/component/chart-container.test.tsx | 24 +++++++++++++ test/component/line-graph.test.tsx | 20 ----------- test/mock/charts/mock-data.ts | 35 +++++++++++++++++++ 4 files changed, 60 insertions(+), 21 deletions(-) create mode 100644 test/component/chart-container.test.tsx delete mode 100644 test/component/line-graph.test.tsx diff --git a/src/component/charts/container/chart-container.tsx b/src/component/charts/container/chart-container.tsx index 096405f..3b62f53 100644 --- a/src/component/charts/container/chart-container.tsx +++ b/src/component/charts/container/chart-container.tsx @@ -54,7 +54,7 @@ const ChartContainer: React.FC = ({ { + it("renders correctly with data -- line graph", () => { + const { getByTestId } = render( + , + ); + expect(getByTestId(`chart-container-1`)).toBeTruthy(); + }); + + it("does not render without data props", () => { + // Have to ts-ignore to test null data conditions + // @ts-ignore + const { queryByTestId } = render(); + expect(queryByTestId(`chart-container-2`)).toBeNull(); + }); +}); diff --git a/test/component/line-graph.test.tsx b/test/component/line-graph.test.tsx deleted file mode 100644 index 5c1e745..0000000 --- a/test/component/line-graph.test.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import { render } from "@testing-library/react-native"; -import React from "react"; -import LineGraph from "../../src/component/charts/line-graph/line-graph"; -import { line_chart_two_y_data } from "../mock/charts/mock-data"; - -describe("LineGraph Component Tests", () => { - it("renders correctly with data", () => { - const { getByTestId } = render( - , - ); - expect(getByTestId(`line-graph-1`)).toBeTruthy(); - }); - - it("does not render without data", () => { - // Have to ts-ignore to test null data conditions - // @ts-ignore - const { queryByTestId } = render(); - expect(queryByTestId(`line-graph-2`)).toBeNull(); - }); -}); diff --git a/test/mock/charts/mock-data.ts b/test/mock/charts/mock-data.ts index 94800a3..3a7e472 100644 --- a/test/mock/charts/mock-data.ts +++ b/test/mock/charts/mock-data.ts @@ -62,3 +62,38 @@ export const line_chart_two_y_data = { }, ], }; + +export const mockYData = [ + { + data: [ + { value: 71.42857142857143 }, + { value: 100 }, + { value: 64.28571428571429 }, + { value: 57.14285714285714 }, + { value: 28.57142857142857 }, + { value: 14.285714285714285 }, + { value: 50 }, + { value: 14.285714285714285 }, + { value: 21.428571428571427 }, + { value: 21.428571428571427 }, + ], + svg: { fill: "transparent", stroke: "#598EBB" }, + }, + { + data: [ + { value: 27.77777777777778 }, + { value: 37.22222222222222 }, + { value: 68.33333333333333 }, + { value: 77.77777777777779 }, + { value: 86.66666666666667 }, + { value: 81.66666666666667 }, + { value: 70 }, + { value: 100 }, + { value: 68.33333333333333 }, + { value: 48.333333333333336 }, + ], + svg: { fill: "transparent", stroke: "#F2D4BC" }, + }, +]; + +export const mockXValues = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; From 2e49bc47096fd933c52e8b2a9ba1647d06c07a3a Mon Sep 17 00:00:00 2001 From: Loewy Date: Tue, 13 Feb 2024 14:57:19 -0800 Subject: [PATCH 4/4] link issues to todo comments --- src/component/charts/bar-graph/bar-graph.tsx | 2 +- src/component/charts/container/chart-container.tsx | 2 +- src/component/charts/line-graph/line-graph.tsx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/component/charts/bar-graph/bar-graph.tsx b/src/component/charts/bar-graph/bar-graph.tsx index 9c6593d..f0cd6ff 100644 --- a/src/component/charts/bar-graph/bar-graph.tsx +++ b/src/component/charts/bar-graph/bar-graph.tsx @@ -26,7 +26,7 @@ interface Props { testID?: string; } -// TODO: separate PR will update useGraphData to take into account useCommonScale +// TODO: #43 #31 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 = ({ data, diff --git a/src/component/charts/container/chart-container.tsx b/src/component/charts/container/chart-container.tsx index 3b62f53..59c393c 100644 --- a/src/component/charts/container/chart-container.tsx +++ b/src/component/charts/container/chart-container.tsx @@ -6,7 +6,7 @@ import ChartView from "../chart-view"; import { ChartContainerProps } from "../graph-types"; import { useGraphData } from "../use-graph-data"; -// TODO: separate PR will update useGraphData to take into account useCommonScale +// TODO: #43 #31 separate PR will update useGraphData to take into account useCommonScale // eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars const ChartContainer: React.FC = ({ ChartComponent, diff --git a/src/component/charts/line-graph/line-graph.tsx b/src/component/charts/line-graph/line-graph.tsx index cbb0893..011a970 100644 --- a/src/component/charts/line-graph/line-graph.tsx +++ b/src/component/charts/line-graph/line-graph.tsx @@ -5,7 +5,7 @@ import { graphStyles } from "../chart-styles"; import { CustomGrid } from "../custom-grid"; import { CommonProps } from "../graph-types"; -// TODO: separate PR will update useGraphData to take into account useCommonScale +// TODO: #43 #31 separate PR will update useGraphData to take into account useCommonScale // eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars const LineGraph: React.FC = ({ ...chartComponentProps }) => { const { yData, xValues, lineStrokeWidth, min, contentInset, numberOfTicks } =