Skip to content

Commit

Permalink
fix: Make Daily Tick Memoizable
Browse files Browse the repository at this point in the history
  • Loading branch information
sternetj committed Jan 3, 2024
1 parent d457505 commit 706d5d2
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 82 deletions.
36 changes: 20 additions & 16 deletions src/components/MyData/SleepChart/DailyChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -154,18 +154,25 @@ export const DailyChart = (props: Props) => {
</G>

<VictoryAxis
tickValues={ticks}
tickFormat={(v, i, a) =>
i === 0 || i + 1 === a.length ? format(v, 'hh:mm aa') : '*'
}
tickLabelComponent={<Tick enabled={!!data.length} />}
tickValues={data.length ? ticks : []}
tickFormat={(v, i, a) => {
const isFirstOrLast = i === 0 || i === a.length - 1;
if (!data.length) {
return ''; // hide tick labels
} else if (isFirstOrLast) {
return format(v, 'hh:mm aa');
} else {
return '*';
}
}}
tickLabelComponent={<Tick />}
style={theme.independentAxis}
/>
</VictoryChart>
</ViewShot>

<View style={styles.loadingContainer}>
{<ActivityIndicatorView animating={isFetching} />}
<ActivityIndicatorView animating={isFetching} />
</View>

<DataSelector
Expand Down Expand Up @@ -236,27 +243,24 @@ const valToName = (value: number) =>
type TickProps = {
text?: string;
index?: number;
enabled: boolean;
} & VictoryLabelProps;

const Tick = ({ text, index, enabled, ...props }: TickProps) => {
const Tick = ({ text, index, ...props }: TickProps) => {
const { Moon, Sunrise } = useIcons();
const { styles } = useStyles(defaultStyles);
const Icon = index === 0 ? Moon : Sunrise;

if (!enabled) {
if (!text) {
return null;
}

if (text === '*') {
return (
null && (
<Circle
{...(props as any)}
style={{ ...props.style, ...styles.tickDot }}
r={2}
/>
)
<Circle
{...(props as any)}
style={{ ...props.style, ...styles.tickDot }}
r={2}
/>
);
}

Expand Down
79 changes: 46 additions & 33 deletions src/components/MyData/SleepChart/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
addMonths,
startOfYear,
endOfYear,
addHours,
} from 'date-fns';
import { scaleTime } from 'd3-scale';

Expand Down Expand Up @@ -60,8 +61,12 @@ const Deep = {
code: '93831-6',
};

describe('LineChart', () => {
describe('SleepChart', () => {
it('should render daily chart', async () => {
const dateRange = {
start: startOfDay(new Date(0)),
end: startOfDay(new Date(0)),
};
mockUseSleepChartData.mockReturnValue({
isFetching: false,
sleepData: [
Expand Down Expand Up @@ -103,7 +108,7 @@ describe('LineChart', () => {
},
valuePeriod: {
start: addMinutes(new Date(0), 4).toISOString(),
end: addMinutes(new Date(0), 5).toISOString(),
end: addHours(new Date(0), 3).toISOString(),
},
},
// malformed components - not rendered:
Expand All @@ -126,13 +131,13 @@ describe('LineChart', () => {
],
},
],
xDomain: scaleTime().domain([new Date(0), addMinutes(new Date(0), 5)]),
dateRange: [new Date(0), new Date(0)],
xDomain: scaleTime().domain([new Date(0), addHours(new Date(0), 3)]),
dateRange: [dateRange.start, dateRange.end],
});

const { findByText, findByLabelText } = render(
<SleepChart
dateRange={{ start: new Date(0), end: new Date(0) }}
dateRange={dateRange}
title="Single Day Test Title"
onBlockScrollChange={jest.fn()}
/>,
Expand All @@ -141,7 +146,7 @@ describe('LineChart', () => {
expect(await findByText('Single Day Test Title')).toBeDefined();
expect(await findByText(format(new Date(0), 'hh:mm aa'))).toBeDefined();
expect(
await findByText(format(addMinutes(new Date(0), 5), 'hh:mm aa')),
await findByText(format(addHours(new Date(0), 3), 'hh:mm aa')),
).toBeDefined();
expect(await findByText('Awake')).toBeDefined();
expect(await findByText('REM')).toBeDefined();
Expand Down Expand Up @@ -172,7 +177,7 @@ describe('LineChart', () => {
).toBeDefined();
expect(
await findByLabelText(
`1 minutes of Deep sleep starting at ${addMinutes(
`176 minutes of Deep sleep starting at ${addMinutes(
new Date(0),
4,
).toLocaleTimeString()}`,
Expand All @@ -181,6 +186,10 @@ describe('LineChart', () => {
});

it('should select data on daily chart', async () => {
const dateRange = {
start: startOfDay(new Date(0)),
end: startOfDay(new Date(0)),
};
const xDomain = scaleTime().domain([
new Date(0),
addMinutes(new Date(0), 2),
Expand All @@ -206,14 +215,14 @@ describe('LineChart', () => {
},
],
xDomain,
dateRange: [new Date(0), new Date(0)],
dateRange: [dateRange.start, dateRange.end],
});

const onBlockScrollChange = jest.fn();

const { findByText, findAllByText, getByTestId } = render(
<SleepChart
dateRange={{ start: new Date(0), end: new Date(0) }}
dateRange={dateRange}
title="Single Day Test Title"
onBlockScrollChange={onBlockScrollChange}
/>,
Expand Down Expand Up @@ -269,6 +278,10 @@ describe('LineChart', () => {
});

it('should render multi day chart', async () => {
const dateRange = {
start: startOfDay(new Date(0)),
end: startOfDay(addDays(new Date(0), 7)),
};
mockUseSleepChartData.mockReturnValue({
isFetching: false,
sleepData: [
Expand Down Expand Up @@ -296,13 +309,13 @@ describe('LineChart', () => {
},
},
],
xDomain: scaleTime().domain([new Date(0), addDays(new Date(0), 7)]),
dateRange: [new Date(0), addDays(new Date(0), 7)],
xDomain: scaleTime().domain([dateRange.start, dateRange.end]),
dateRange: [dateRange.start, dateRange.end],
});

const { findByText, findByLabelText } = render(
<SleepChart
dateRange={{ start: new Date(0), end: addDays(new Date(0), 7) }}
dateRange={dateRange}
title="Multi Day Test Title"
onBlockScrollChange={jest.fn()}
/>,
Expand Down Expand Up @@ -332,7 +345,11 @@ describe('LineChart', () => {
});

it('should select data on multi-day chart', async () => {
const xDomain = scaleTime().domain([new Date(0), addDays(new Date(0), 7)]);
const dateRange = {
start: startOfDay(new Date(0)),
end: startOfDay(addDays(new Date(0), 7)),
};
const xDomain = scaleTime().domain([dateRange.start, dateRange.end]);
mockUseSleepChartData.mockReturnValue({
isFetching: false,
sleepData: [
Expand Down Expand Up @@ -361,14 +378,14 @@ describe('LineChart', () => {
},
],
xDomain,
dateRange: [new Date(0), addDays(new Date(0), 7)],
dateRange: [dateRange.start, dateRange.end],
});

const onBlockScrollChange = jest.fn();

const { findByText, getByTestId } = render(
<SleepChart
dateRange={{ start: new Date(0), end: addDays(new Date(0), 7) }}
dateRange={dateRange}
title="Multi Day Test Title"
onBlockScrollChange={onBlockScrollChange}
/>,
Expand Down Expand Up @@ -403,6 +420,10 @@ describe('LineChart', () => {
});

it('should render year chart', async () => {
const dateRange = {
start: startOfDay(startOfYear(new Date(0))),
end: startOfDay(endOfYear(new Date(0))),
};
mockUseSleepChartData.mockReturnValue({
isFetching: false,
sleepData: [
Expand Down Expand Up @@ -430,19 +451,13 @@ describe('LineChart', () => {
},
},
],
xDomain: scaleTime().domain([
startOfYear(new Date(0)),
endOfYear(new Date(0)),
]),
dateRange: [startOfYear(new Date(0)), endOfYear(new Date(0))],
xDomain: scaleTime().domain([dateRange.start, dateRange.end]),
dateRange: [dateRange.start, dateRange.end],
});

const { findByText, findByLabelText } = render(
<SleepChart
dateRange={{
start: startOfYear(new Date(0)),
end: endOfYear(new Date(0)),
}}
dateRange={dateRange}
title="Year Test Title"
onBlockScrollChange={jest.fn()}
/>,
Expand Down Expand Up @@ -474,10 +489,11 @@ describe('LineChart', () => {
});

it('should select data on year chart', async () => {
const xDomain = scaleTime().domain([
startOfYear(new Date(0)),
endOfYear(new Date(0)),
]);
const dateRange = {
start: startOfDay(startOfYear(new Date(0))),
end: startOfDay(endOfYear(new Date(0))),
};
const xDomain = scaleTime().domain([dateRange.start, dateRange.end]);
mockUseSleepChartData.mockReturnValue({
isFetching: false,
sleepData: [
Expand Down Expand Up @@ -522,16 +538,13 @@ describe('LineChart', () => {
},
],
xDomain,
dateRange: [startOfYear(new Date(0)), endOfYear(new Date(0))],
dateRange: [dateRange.start, dateRange.end],
});

const onBlockScrollChange = jest.fn();
const { findByText, getByTestId } = render(
<SleepChart
dateRange={{
start: startOfYear(new Date(0)),
end: endOfYear(new Date(0)),
}}
dateRange={dateRange}
title="Year Test Title"
onBlockScrollChange={onBlockScrollChange}
/>,
Expand Down
25 changes: 7 additions & 18 deletions src/components/MyData/SleepChart/index.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,4 @@
import React, {
useCallback,
useEffect,
useMemo,
useRef,
useState,
} from 'react';
import React, { useCallback, useMemo, useRef } from 'react';
import { startOfDay, differenceInDays } from 'date-fns';
import ViewShot from 'react-native-view-shot';
import { useVictoryTheme } from '../useVictoryTheme';
Expand Down Expand Up @@ -37,8 +31,6 @@ const SleepChart = (props: Props) => {
const { title, dateRange: incomingDateRange, onShare } = props;
const { onBlockScrollChange } = props;
const viewShotRef = useRef<ViewShot>(null);
const [_showSelection, setShowSelection] = useState(false);
const [isSwitchingChartType, setIsSwitchingChartType] = useState(false);
const dateRange = useMemo<[Date, Date]>(
() => [
startOfDay(incomingDateRange.start),
Expand All @@ -50,29 +42,26 @@ const SleepChart = (props: Props) => {
const chartData = useSleepChartData({ dateRange });

const handleExport = useCallback(async () => {
setShowSelection(true);
const dataUri = await viewShotRef.current?.capture?.();
onShare?.({
selectedPoints: [],
title,
dataUri,
dateRange,
});
setShowSelection(false);
}, [title, dateRange, onShare]);

const ChartType = useMemo(
() => (differenceInDays(...dateRange) === 0 ? DailyChart : MultiDayChart),
[dateRange],
);

useEffect(() => setIsSwitchingChartType(true), [ChartType]);
useEffect(() => {
// end existing switch once isFetching is false
setIsSwitchingChartType(
(chartTypeChanged) => chartTypeChanged && chartData.isFetching,
);
}, [chartData.isFetching]);
const isSwitchingChartType = useMemo(
() =>
differenceInDays(...dateRange) !==
differenceInDays(...chartData.dateRange),
[dateRange, chartData.dateRange],
);

return (
<View style={styles.container}>
Expand Down
Loading

0 comments on commit 706d5d2

Please sign in to comment.