Skip to content
Open
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
115 changes: 115 additions & 0 deletions app/pages/clinicworkspace/TideDashboardV2/PatientLastReviewed.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import React from 'react';
import { useSelector } from 'react-redux';
import { useTranslation } from 'react-i18next';
import { Text, Box, FlexProps } from 'theme-ui';
import moment from 'moment-timezone';
import CheckRoundedIcon from '@material-ui/icons/CheckRounded';
import { utils as vizUtils } from '@tidepool/viz';
import upperFirst from 'lodash/upperFirst';

import HoverButton from '../../../components/elements/HoverButton';
import Icon from '../../../components/elements/Icon';
import { useToasts } from '../../../providers/ToastProvider';
import { useSetClinicPatientLastReviewedMutation, useRevertClinicPatientLastReviewedMutation } from './tideDashboardApi';
import useTideDashboardPatients from './useTideDashboardPatients';

const {
formatTimeAgo,
getTimezoneFromTimePrefs,
} = vizUtils.datetime;

const trackMetric = () => {}; // TODO: FIX

const PatientLastReviewed = ({ patient }) => {
const { t } = useTranslation();
// const { set: setToast } = useToasts();
const selectedClinicId = useSelector((state) => state.blip.selectedClinicId);
const loggedInUserId = useSelector((state) => state.blip.loggedInUserId);
const timePrefs = useSelector((state) => state.blip.timePrefs);
const patientId = patient?.id;

const { isFetching } = useTideDashboardPatients();

const [setClinicPatientLastReviewed, { isLoading: isSetting }] = useSetClinicPatientLastReviewedMutation();
const [revertClinicPatientLastReviewed, { isLoading: isReverting }] = useRevertClinicPatientLastReviewedMutation();

const handleReview = () => {
// trackMetric('Clinic - Mark patient reviewed', { clinicId: selectedClinicId, source: metricSource });
setClinicPatientLastReviewed({ clinicId: selectedClinicId, patientId });
// onReview && onReview();
};

const handleUndo = () => {
// trackMetric('Clinic - Undo mark patient reviewed', { clinicId: selectedClinicId, source: metricSource });
revertClinicPatientLastReviewed({ clinicId: selectedClinicId, patientId });
};

const recentlyReviewedThresholdDate = moment().startOf('isoWeek').toISOString();

let clickHandler = handleReview;
let buttonText = t('Mark Reviewed');

let formattedLastReviewed = { daysText: '-' };
let lastReviewIsToday = false;
let reviewIsRecent = false;
let canReview = true;
let color = 'feedback.warning';

if (patient?.reviews?.[0]?.time) {
formattedLastReviewed = formatTimeAgo(patient.reviews[0].time, timePrefs);
lastReviewIsToday = moment.utc(patient.reviews[0].time).tz(getTimezoneFromTimePrefs(timePrefs)).isSame(moment(), 'day');

if (lastReviewIsToday) {
canReview = false;
clickHandler = null;
}

if (moment.utc(patient.reviews[0].time).isSameOrAfter(moment(recentlyReviewedThresholdDate))) {
reviewIsRecent = true;
}

if (lastReviewIsToday && patient.reviews[0].clinicianId === loggedInUserId) {
clickHandler = handleUndo;
buttonText = t('Undo');
};

if (reviewIsRecent) {
color = 'feedback.success';
}
}


return (
<Box sx={{ minWidth: '120px' }}>
<HoverButton
{...FlexProps}
buttonText={buttonText}
buttonProps={{
onClick: clickHandler,
variant: 'quickActionCondensed',
ml: canReview ? -2 : 0,
disabled: isSetting || isReverting || isFetching,
}}
hideChildrenOnHover={canReview}
>
<Box sx={{ whiteSpace: 'nowrap' }}>
<Text
sx={{
display: 'inline-flex',
alignItems: 'center',
gap: 1,
color: color,
fontWeight: 'medium',
whiteSpace: 'nowrap',
}}
>
{reviewIsRecent && <Icon variant="static" icon={CheckRoundedIcon} />}
{upperFirst(formattedLastReviewed.daysText)}
</Text>
</Box>
</HoverButton>
</Box>
);
};

export default PatientLastReviewed;
12 changes: 2 additions & 10 deletions app/pages/clinicworkspace/TideDashboardV2/TideDashboardV2.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import PaginationControls from '../components/PaginationControls';
import ActiveFilterCount from '../components/ActiveFilterCount';

import { resetTideDashboardState, setOffset } from './tideDashboardSlice';
import { useGetTideDashboardPatientsQuery } from './tideDashboardApi';
import useTideDashboardPatients, { LIMIT } from './useTideDashboardPatients';
import ResetFilters from '../components/ResetFilters';
import useActiveFiltersCount from './useActiveFiltersCount';
import useDerivedDataRecencyEndpoints from './useDerivedDataRecencyEndpoints';
Expand All @@ -27,8 +27,6 @@ import EmptyContentNode from './EmptyContentNode';
import FilterBySites from './FilterBySites';
import PatientCount from '../components/PatientCount';

const LIMIT = 12;

const Divider = () => <Box id='filter-divider' mx={2} sx={{ border: `1px solid ${vizColors.gray05}`, height: '24px' }}></Box>;

const Gap = () => <Box sx={{ marginLeft: 'auto' }}></Box>;
Expand All @@ -42,14 +40,8 @@ const TideDashboard = () => {
const selectedClinicId = useSelector(state => state.blip.selectedClinicId);
const category = useSelector(state => state.blip.tideDashboard.category);
const offset = useSelector(state => state.blip.tideDashboard.offset);
const { patientTags, clinicSites } = useSelector(state => state.blip.tideDashboardFilters);

const [lastDataFrom, lastDataTo] = useDerivedDataRecencyEndpoints();

const { data } = useGetTideDashboardPatientsQuery(
{ clinicId: selectedClinicId, offset, category, lastDataTo, lastDataFrom, tags: patientTags, sites: clinicSites, limit: LIMIT },
{ skip: !selectedClinicId }
);
const { data } = useTideDashboardPatients();

// Sync category to data fetching resolution; prevents visual glitch due to
// category updating view before the API call resolves and updates it again
Expand Down
26 changes: 25 additions & 1 deletion app/pages/clinicworkspace/TideDashboardV2/tideDashboardApi.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ export const buildGetTideDashboardPatientsParams = (offset, limit, category, las
};
};

const TAGS = {
TIDE_DASHBOARD_PATIENTS: 'TideDashboardPatients',
};

const { TIDE_DASHBOARD_PATIENTS } = TAGS;

const tideDashboardApi = RTKQueryApi.injectEndpoints({
endpoints: (builder) => ({
Expand All @@ -52,8 +57,27 @@ const tideDashboardApi = RTKQueryApi.injectEndpoints({
...response,
category: arg.category,
}),
providesTags: [TIDE_DASHBOARD_PATIENTS],
}),
setClinicPatientLastReviewed: builder.mutation({
query: ({ clinicId, patientId }) => ({
url: `/clinics/${clinicId}/patients/${patientId}/reviews`,
method: 'PUT',
}),
invalidatesTags: [TIDE_DASHBOARD_PATIENTS],
}),
revertClinicPatientLastReviewed: builder.mutation({
query: ({ clinicId, patientId }) => ({
url: `/clinics/${clinicId}/patients/${patientId}/reviews`,
method: 'DELETE',
}),
invalidatesTags: [TIDE_DASHBOARD_PATIENTS],
}),
}),
});

export const { useGetTideDashboardPatientsQuery } = tideDashboardApi;
export const {
useGetTideDashboardPatientsQuery,
useSetClinicPatientLastReviewedMutation,
useRevertClinicPatientLastReviewedMutation,
} = tideDashboardApi;
2 changes: 2 additions & 0 deletions app/pages/clinicworkspace/TideDashboardV2/useTableColumns.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import {
} from './Cells';

import TagListCell from '../components/TagListCell';
import PatientLastReviewed from './PatientLastReviewed';

const getColumnTypes = (t, category, thresholds) => ({
patientDetails: {
Expand Down Expand Up @@ -111,6 +112,7 @@ const getColumnTypes = (t, category, thresholds) => ({
title: t('Last Reviewed'),
field: 'lastReviewed',
align: 'center',
render: patient => <PatientLastReviewed patient={patient} />,
},
moreMenu: {
title: t(''),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { useSelector } from 'react-redux';
import { useGetTideDashboardPatientsQuery } from './tideDashboardApi';
import useDerivedDataRecencyEndpoints from './useDerivedDataRecencyEndpoints';

const LIMIT = 12;

const useTideDashboardPatients = () => {
const selectedClinicId = useSelector(state => state.blip.selectedClinicId);
const category = useSelector(state => state.blip.tideDashboard.category);
const offset = useSelector(state => state.blip.tideDashboard.offset);
const patientTags = useSelector(state => state.blip.tideDashboardFilters.patientTags);
const [lastDataFrom, lastDataTo] = useDerivedDataRecencyEndpoints();

return useGetTideDashboardPatientsQuery(
{ clinicId: selectedClinicId, offset, category, lastDataTo, lastDataFrom, tags: patientTags, limit: LIMIT },
{ skip: !selectedClinicId }
);
};

export { LIMIT };
export default useTideDashboardPatients;
2 changes: 1 addition & 1 deletion app/pages/clinicworkspace/components/TagListCell.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const TagListCell = ({ patient }) => {
const patientTags = clinic?.patientTags || [];

const tagIds = patient?.tags || [];
const tags = tagIds.map(tag => patientTags.find(ptTag => ptTag.id === tag)); // TODO: index
const tags = tagIds.map(tag => patientTags.find(ptTag => ptTag.id === tag)).filter(Boolean); // TODO: index

return <TagList tags={tags} maxTagsVisible={MAX_TAGS} />;
};
Expand Down
39 changes: 18 additions & 21 deletions app/pages/dashboard/PatientDrawer/MenuBar/MenuBar.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ const tabs = {
const MenuBar = ({ patientId, onClose, onSelectTab, selectedTab, trackMetric }) => {
const dispatch = useDispatch();
const { t } = useTranslation();
const { showTideDashboardLastReviewed } = useFlags();

const selectedClinicId = useSelector(state => state.blip.selectedClinicId);
const patient = useSelector(state => state.blip.clinics[state.blip.selectedClinicId]?.patients?.[patientId]);
Expand Down Expand Up @@ -87,26 +86,24 @@ const MenuBar = ({ patientId, onClose, onSelectTab, selectedTab, trackMetric })
</Flex>

<Flex sx={{ fontSize: 0, alignItems: 'center' }}>
{showTideDashboardLastReviewed && (
<Flex data-testid="last-reviewed-section" sx={{ alignItems: 'center', justifyContent: 'space-between', gap: 3 }}>
<Text sx={{
color: vizColors.purple90,
fontWeight: 'medium',
}}>
{t('Last Reviewed')}
</Text>

<PatientLastReviewed
sx={{ flexGrow: 1 }}
api={api}
trackMetric={trackMetric}
metricSource="TIDE dashboard"
patientId={patientId}
recentlyReviewedThresholdDate={recentlyReviewedThresholdDate}
onReview={handleReviewSuccess}
/>
</Flex>
)}
<Flex data-testid="last-reviewed-section" sx={{ alignItems: 'center', justifyContent: 'space-between', gap: 3 }}>
<Text sx={{
color: vizColors.purple90,
fontWeight: 'medium',
}}>
{t('Last Reviewed')}
</Text>

<PatientLastReviewed
sx={{ flexGrow: 1 }}
api={api}
trackMetric={trackMetric}
metricSource="TIDE dashboard"
patientId={patientId}
recentlyReviewedThresholdDate={recentlyReviewedThresholdDate}
onReview={handleReviewSuccess}
/>
</Flex>
</Flex>
</Flex>

Expand Down
1 change: 1 addition & 0 deletions app/redux/api/baseApi.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ export const RTKQueryApi = createApi({
baseQuery,
{ maxRetries: RETRY_COUNT },
),
tagTypes: ['TideDashboardPatients'],
refetchOnMountOrArgChange: true,
endpoints: () => ({}),
});