Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle Same Day Data in Sleep Charts #508

Merged
merged 1 commit into from
Jan 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 90 additions & 1 deletion src/components/MyData/SleepChart/useSleepChartData.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ describe('useSleepChartData', () => {
expect(result.current.isFetching).toBe(false);
});

it('should fetch the trace data', () => {
it('should fetch the sleep data', () => {
const observation: fhir3.Observation = {
resourceType: 'Observation',
status: 'final',
Expand Down Expand Up @@ -106,6 +106,95 @@ describe('useSleepChartData', () => {
expect(result.current.xDomain.domain()[1]).toEqual(new Date(10));
});

it('should only use the datum with the most detail per day', () => {
const observation1: fhir3.Observation = {
resourceType: 'Observation',
status: 'final',
code: {},
effectiveDateTime: new Date(10).toISOString(),
valuePeriod: {
start: new Date(0).toISOString(),
end: new Date(10).toISOString(),
},
};
const observation2: fhir3.Observation = {
resourceType: 'Observation',
status: 'final',
code: {},
effectiveDateTime: new Date(10).toISOString(),
valuePeriod: {
start: new Date(0).toISOString(),
end: new Date(10).toISOString(),
},
component: [
// two data points, so this observation has the most detail
{
code: {},
valuePeriod: {
start: new Date(0).toISOString(),
end: new Date(5).toISOString(),
},
},
{
code: {},
valuePeriod: {
start: new Date(5).toISOString(),
end: new Date(10).toISOString(),
},
},
],
};
const observation3: fhir3.Observation = {
resourceType: 'Observation',
status: 'final',
code: {},
effectiveDateTime: addDays(new Date(10), 1).toISOString(),
valuePeriod: {
start: addDays(new Date(0), 1).toISOString(),
end: addDays(new Date(10), 1).toISOString(),
},
};
useSearchResourcesQuery.mockReturnValue({
isFetching: false,
isFetched: true,
data: {
entry: [
{
resource: observation1,
},
{
resource: observation2,
},
{
resource: observation1,
},
{
resource: observation3, // No data but different day
},
],
},
});

const { result } = renderHook(useSleepChartData, {
initialProps: {
dateRange: [new Date(0), new Date(0)],
},
});

expect(useSearchResourcesQuery).toHaveBeenNthCalledWith(1, {
resourceType: 'Observation',
coding: [{ code: '258158006', system: 'http://snomed.info/sct' }],
dateRange: [startOfDay(new Date(0)), endOfDay(new Date(0))],
pageSize: 50,
});

expect(result.current.sleepData).toEqual([observation2, observation3]);
expect(result.current.xDomain.domain()[0]).toEqual(new Date(0));
expect(result.current.xDomain.domain()[1]).toEqual(
addDays(new Date(10), 1),
);
});

it('should fetch the data with a pageSize based on the dateRange', () => {
useSearchResourcesQuery.mockReturnValue({
isFetching: false,
Expand Down
17 changes: 16 additions & 1 deletion src/components/MyData/SleepChart/useSleepChartData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { differenceInDays, min, max, startOfDay, endOfDay } from 'date-fns';
import { useCommonChartProps } from '../useCommonChartProps';
import { Observation } from 'fhir/r3';
import compact from 'lodash/compact';
import groupBy from 'lodash/groupBy';

type Props = {
dateRange: [Date, Date];
Expand Down Expand Up @@ -39,11 +40,25 @@ export const useSleepChartData = (props: Props) => {

useEffect(() => {
if (!isFetching && isFetched) {
const newSleepData =
const sleepObservations =
data?.entry
?.map((e) => e.resource)
.filter((v): v is Observation => !!v) ?? [];

const groupedData = groupBy(sleepObservations, (d) =>
startOfDay(new Date(d.effectiveDateTime!)),
);

// Use only one observation per day, selecting the observation with the most
// components since it should have the most detail
const newSleepData = Object.values(groupedData).flatMap((entries) =>
entries
.sort(
(a, b) => (b.component?.length || 0) - (a.component?.length || 0),
)
.slice(0, 1),
);

const { start, end } = newSleepData.reduce(
(domain, observation) => ({
start: min(
Expand Down
Loading