From ab826d04280d637b6e34fbc2aae26be17a168197 Mon Sep 17 00:00:00 2001 From: henry-tp Date: Mon, 23 Feb 2026 16:49:29 -0800 Subject: [PATCH 01/31] add abstracted tags filter --- .../clinicworkspace/DeviceIssues/index.js | 24 +- .../clinicworkspace/Filters/TagsFilter.js | 220 ++++++++++++++++++ 2 files changed, 237 insertions(+), 7 deletions(-) create mode 100644 app/pages/clinicworkspace/Filters/TagsFilter.js diff --git a/app/pages/clinicworkspace/DeviceIssues/index.js b/app/pages/clinicworkspace/DeviceIssues/index.js index 2d76ba0297..81c366a47f 100644 --- a/app/pages/clinicworkspace/DeviceIssues/index.js +++ b/app/pages/clinicworkspace/DeviceIssues/index.js @@ -7,6 +7,7 @@ import { DIABETES_TYPES } from '../../../core/constants'; import { RTKQueryApi } from '../../../redux/api/baseApi'; import { TagList } from '../../../components/elements/Tag'; +import TagsFilter from '../Filters/TagsFilter'; const LIMIT = 50; @@ -19,10 +20,14 @@ const deviceIssuesApi = RTKQueryApi.injectEndpoints({ }), }), getDeviceIssuesPatients: builder.query({ - query: ({ clinicId, offset, limit }) => ({ - url: `/clinics/${clinicId}/patients`, - params: { offset, limit: LIMIT }, - }), + query: ({ clinicId, offset, tags = [] }) => { + const formattedTags = tags.length > 0 ? tags.join(',') : undefined; + + return { + url: `/clinics/${clinicId}/patients`, + params: { offset, tags: formattedTags, limit: LIMIT }, + }; + }, }), }), }); @@ -56,12 +61,13 @@ const DeviceIssues = () => { const selectedClinicId = useSelector(state => state.blip.selectedClinicId); const clinic = useSelector(state => state.blip.clinics?.[selectedClinicId]); - const [offset, setOffset] = useState(0); - const patientTags = clinic?.patientTags || []; + const [activeTags, setActiveTags] = useState([]); + const [offset, setOffset] = useState(0); + const { data } = useGetDeviceIssuesPatientsQuery( - { clinicId: selectedClinicId, offset, limit: LIMIT }, + { clinicId: selectedClinicId, offset, tags: activeTags, limit: LIMIT }, { skip: !selectedClinicId } ); @@ -71,6 +77,10 @@ const DeviceIssues = () => { return ( <> + + + + noop; +const prefixPopHealthMetric = () => noop; + +import { SPECIAL_FILTER_STATES } from '../ClinicPatients'; + +const TagsFilter = ({ + activeTags = [], + setActiveTags = noop, +}) => { + const { t } = useTranslation(); + const { showTideDashboard } = useFlags(); + + const patientTagsPopupFilterState = usePopupState({ + variant: 'popover', + popupId: 'patientTagFilters', + }); + + const selectedClinicId = useSelector((state) => state.blip.selectedClinicId); + const clinic = useSelector(state => state.blip.clinics?.[selectedClinicId]); + + const sortedTagFilterOptions = useMemo(() => { + return map(clinic?.patientTags, ({ id, name }) => ({ id, label: name })) + .toSorted((a, b) => utils.compareLabels(a.label, b.label)); + }, [clinic?.patientTags]); + + const [pendingTags, setPendingTags] = useState(activeTags); + + const isFilteringForZeroTags = isEqual(pendingTags, SPECIAL_FILTER_STATES.ZERO_TAGS); + + return ( + <> + { + if (!patientTagsPopupFilterState.isOpen) trackMetric(prefixPopHealthMetric('patient tags filter open'), { clinicId: selectedClinicId }); + }} + sx={{ flexShrink: 0 }} + > + + + + { + trackMetric(prefixPopHealthMetric('Patient tag filter close'), { clinicId: selectedClinicId }); + }} + onClose={() => { + patientTagsPopupFilterState.close(); + setPendingTags(activeTags); + }} + > + + + + + {t('Tags')} + + { sortedTagFilterOptions.length > 0 && + + {t('Only patients with ALL of the tags you select below will be shown.')} + + } + + + { // Render a list of checkboxes + sortedTagFilterOptions.map(({ id, label }) => { + const isChecked = pendingTags?.includes(id); + + return ( + + {label}} + checked={isChecked} + onChange={() => { + if (isFilteringForZeroTags) { + setPendingTags([id]); + } else if (isChecked) { + setPendingTags(pendingTags => without(pendingTags, id)); + } else { + setPendingTags(pendingTags => [...pendingTags, id]); + } + }} + /> + + ); + }) + } + + { // Display an option to filter for patients with zero tags + sortedTagFilterOptions.length > 0 && + + + {t('Patients without any tags')} + } + checked={isFilteringForZeroTags} + onChange={() => { + if (isFilteringForZeroTags) { + setPendingTags([]); + } else { + setPendingTags(SPECIAL_FILTER_STATES.ZERO_TAGS); + } + }} + /> + + } + + { // If no tags exist, display a message + sortedTagFilterOptions.length <= 0 && + + + {t('Tags help you segment your patient population based on criteria you define, such as clinician, type of diabetes, or care groups.')} + + + + } + + + + { sortedTagFilterOptions.length > 0 && + + + + + + } + + + + ); +}; + +export default TagsFilter; From d127721b4b5189070ccf206536b8dc70353efc5f Mon Sep 17 00:00:00 2001 From: henry-tp Date: Mon, 23 Feb 2026 17:20:49 -0800 Subject: [PATCH 02/31] move filter state to redux --- .../clinicworkspace/DeviceIssues/index.js | 4 +-- .../clinicworkspace/Filters/TagsFilter.js | 25 ++++++++++--------- .../clinicWorkspaceFiltersSlice.js | 16 ++++++++++++ app/redux/reducers/index.js | 2 ++ 4 files changed, 33 insertions(+), 14 deletions(-) create mode 100644 app/pages/clinicworkspace/clinicWorkspaceFiltersSlice.js diff --git a/app/pages/clinicworkspace/DeviceIssues/index.js b/app/pages/clinicworkspace/DeviceIssues/index.js index 4309a51355..c666553493 100644 --- a/app/pages/clinicworkspace/DeviceIssues/index.js +++ b/app/pages/clinicworkspace/DeviceIssues/index.js @@ -57,7 +57,7 @@ const DeviceIssues = () => { const clinic = useSelector(state => state.blip.clinics?.[selectedClinicId]); const patientTags = clinic?.patientTags || []; - const [activeTags, setActiveTags] = useState([]); + const activeTags = useSelector(state => state.blip.clinicWorkspaceFilters.patientTags); const [offset, setOffset] = useState(0); const { data } = useGetDeviceIssuesPatientsQuery( @@ -72,7 +72,7 @@ const DeviceIssues = () => { return ( <> - +
noop; const prefixPopHealthMetric = () => noop; import { SPECIAL_FILTER_STATES } from '../ClinicPatients'; +import { setPatientTagsFilter } from '../clinicWorkspaceFiltersSlice'; -const TagsFilter = ({ - activeTags = [], - setActiveTags = noop, -}) => { +const TagsFilter = () => { const { t } = useTranslation(); const { showTideDashboard } = useFlags(); + const dispatch = useDispatch(); + const patientTags = useSelector(state => state.blip.clinicWorkspaceFilters.patientTags); + const patientTagsPopupFilterState = usePopupState({ variant: 'popover', popupId: 'patientTagFilters', @@ -52,7 +53,7 @@ const TagsFilter = ({ .toSorted((a, b) => utils.compareLabels(a.label, b.label)); }, [clinic?.patientTags]); - const [pendingTags, setPendingTags] = useState(activeTags); + const [pendingTags, setPendingTags] = useState(patientTags); const isFilteringForZeroTags = isEqual(pendingTags, SPECIAL_FILTER_STATES.ZERO_TAGS); @@ -67,7 +68,7 @@ const TagsFilter = ({
{ + const { t } = useTranslation(); + const patientTags = useSelector(state => state.blip.clinicWorkspaceFilters.patientTags); + + const activeFiltersCount = without([ + patientTags?.length, + ], null, 0, undefined).length; + + return ( + + 0 ? 'purpleMedium' : 'grays.4', + alignItems: 'center', + gap: 1, + borderLeft: ['none', null, borders.divider], + flexShrink: 0, + }} + > + {activeFiltersCount > 0 ? ( + + ) : ( + + )} + {t('Filter By')} + + + ); +}; + +export default ActiveFilterCount; From 93eb37be7a592e22931d4868bc38dcbfe97887b9 Mon Sep 17 00:00:00 2001 From: henry-tp Date: Mon, 23 Feb 2026 21:41:07 -0800 Subject: [PATCH 04/31] fix bug with stale activeFilters --- app/pages/clinicworkspace/DeviceIssues/index.js | 17 +++++++++++++++-- app/pages/clinicworkspace/Filters/TagsFilter.js | 11 +++++++++-- app/pages/clinicworkspace/clinicworkspace.js | 2 +- 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/app/pages/clinicworkspace/DeviceIssues/index.js b/app/pages/clinicworkspace/DeviceIssues/index.js index 3767f3067d..7890ca6c6f 100644 --- a/app/pages/clinicworkspace/DeviceIssues/index.js +++ b/app/pages/clinicworkspace/DeviceIssues/index.js @@ -1,5 +1,5 @@ -import React, { useState } from 'react'; -import { useSelector } from 'react-redux'; +import React, { useState, useEffect } from 'react'; +import { useDispatch, useSelector } from 'react-redux'; import { useTranslation } from 'react-i18next'; import Table from '../../../components/elements/Table'; import { Box, Text, Flex } from 'theme-ui'; @@ -10,6 +10,8 @@ import { TagList } from '../../../components/elements/Tag'; import ActiveFilterCount from '../Filters/ActiveFilterCount'; import TagsFilter from '../Filters/TagsFilter'; import { CategorySelector, CategoryTab } from '../Filters/CategoryFilter'; +import useClinicPatientsFilters from '../useClinicPatientsFilters'; +import { setPatientTagsFilter } from '../clinicWorkspaceFiltersSlice'; const LIMIT = 50; @@ -58,6 +60,15 @@ const RenderPatient = ({ patient }) => { ; }; +const useInitialReduxSetup = () => { + const dispatch = useDispatch(); + + const [activeFiltersInLocalStorage] = useClinicPatientsFilters(); + useEffect(() => { + dispatch(setPatientTagsFilter(activeFiltersInLocalStorage.patientTags)); + }, []); +}; + const DeviceIssues = () => { const { t } = useTranslation(); @@ -65,6 +76,8 @@ const DeviceIssues = () => { const patientTags = useSelector(state => state.blip.clinicWorkspaceFilters.patientTags); const [offset, setOffset] = useState(0); + useInitialReduxSetup(); + const { data } = useGetDeviceIssuesPatientsQuery( { clinicId: selectedClinicId, offset, tags: patientTags, limit: LIMIT }, { skip: !selectedClinicId } diff --git a/app/pages/clinicworkspace/Filters/TagsFilter.js b/app/pages/clinicworkspace/Filters/TagsFilter.js index 997b49e1b4..176ccc5ba8 100644 --- a/app/pages/clinicworkspace/Filters/TagsFilter.js +++ b/app/pages/clinicworkspace/Filters/TagsFilter.js @@ -32,10 +32,12 @@ const prefixPopHealthMetric = () => noop; import { SPECIAL_FILTER_STATES } from '../ClinicPatients'; import { setPatientTagsFilter } from '../clinicWorkspaceFiltersSlice'; +import useClinicPatientsFilters from '../useClinicPatientsFilters'; const TagsFilter = () => { const { t } = useTranslation(); const { showTideDashboard } = useFlags(); + const [activeFilters, setActiveFilters] = useClinicPatientsFilters(); const dispatch = useDispatch(); const patientTags = useSelector(state => state.blip.clinicWorkspaceFilters.patientTags); @@ -57,6 +59,11 @@ const TagsFilter = () => { const isFilteringForZeroTags = isEqual(pendingTags, SPECIAL_FILTER_STATES.ZERO_TAGS); + const handleApplyTagFilter = (patientTags) => { + dispatch(setPatientTagsFilter(patientTags)); + setActiveFilters({ ...activeFilters, patientTags }); + }; + return ( <> { onClick={() => { trackMetric(prefixPopHealthMetric('Patient tag filter clear'), { clinicId: selectedClinicId }); setPendingTags([]); - dispatch(setPatientTagsFilter([])); + handleApplyTagFilter([]); patientTagsPopupFilterState.close(); }} > @@ -205,7 +212,7 @@ const TagsFilter = () => { + + + + } + + ); +}; + +const TagsFilter = () => { + const { t } = useTranslation(); + const { showTideDashboard } = useFlags(); + + const clinicWorkspaceFilters = useSelector(state => state.blip.clinicWorkspaceFilters); + const { patientTags } = clinicWorkspaceFilters; + + const patientTagsPopupFilterState = usePopupState({ + variant: 'popover', + popupId: 'patientTagFilters', + }); + + const selectedClinicId = useSelector((state) => state.blip.selectedClinicId); + const clinic = useSelector(state => state.blip.clinics?.[selectedClinicId]); return ( <> @@ -119,107 +225,11 @@ const TagsFilter = () => { }} onClose={() => { patientTagsPopupFilterState.close(); - setPendingTags(patientTags); }} > - - - - - {t('Tags')} - - { sortedTagFilterOptions.length > 0 && - - {t('Only patients with ALL of the tags you select below will be shown.')} - - } - - - { // Render a list of checkboxes - sortedTagFilterOptions.map(({ id, label }) => { - const isChecked = pendingTags?.includes(id); - - return ( - - {label}} - checked={isChecked} - onChange={() => { - if (isFilteringForZeroTags) { - setPendingTags([id]); - } else if (isChecked) { - setPendingTags(pendingTags => without(pendingTags, id)); - } else { - setPendingTags(pendingTags => [...pendingTags, id]); - } - }} - /> - - ); - }) - } - - { // Display an option to filter for patients with zero tags - sortedTagFilterOptions.length > 0 && - - - {t('Patients without any tags')} - } - checked={isFilteringForZeroTags} - onChange={() => { - if (isFilteringForZeroTags) { - setPendingTags([]); - } else { - setPendingTags(SPECIAL_FILTER_STATES.ZERO_TAGS); - } - }} - /> - - } - - { // If no tags exist, display a message - sortedTagFilterOptions.length <= 0 && - - - {t('Tags help you segment your patient population based on criteria you define, such as clinician, type of diabetes, or care groups.')} - - - - } - - - - { sortedTagFilterOptions.length > 0 && - - - - - + { patientTagsPopupFilterState.isOpen && + patientTagsPopupFilterState.close()} /> } - ); diff --git a/app/pages/clinicworkspace/clinicWorkspaceFiltersSlice.js b/app/pages/clinicworkspace/clinicWorkspaceFiltersSlice.js index 4a967da9b4..98c040d3ff 100644 --- a/app/pages/clinicworkspace/clinicWorkspaceFiltersSlice.js +++ b/app/pages/clinicworkspace/clinicWorkspaceFiltersSlice.js @@ -3,14 +3,23 @@ import { createSlice } from '@reduxjs/toolkit'; const clinicWorkspaceFiltersSlice = createSlice({ name: 'clinicWorkspaceFilters', initialState: { + timeCGMUsePercent: null, + lastData: null, + lastDataType: null, + timeInRange: [], + meetsGlycemicTargets: true, patientTags: [], + clinicSites: [], }, reducers: { + setClinicWorkspaceFilters: (state, action) => { + return { ...state, ...action.payload }; + }, setPatientTagsFilter: (state, action) => { state.patientTags = action.payload; }, }, }); -export const { setPatientTagsFilter } = clinicWorkspaceFiltersSlice.actions; +export const { setClinicWorkspaceFilters, setPatientTagsFilter } = clinicWorkspaceFiltersSlice.actions; export default clinicWorkspaceFiltersSlice.reducer; From 676f7299092bc9d9b7308fab2ae3bcb261077bec Mon Sep 17 00:00:00 2001 From: henry-tp Date: Tue, 24 Feb 2026 13:17:22 -0800 Subject: [PATCH 06/31] flip incorrect boolean check --- app/pages/clinicworkspace/DeviceIssues/DeviceIssues.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/pages/clinicworkspace/DeviceIssues/DeviceIssues.js b/app/pages/clinicworkspace/DeviceIssues/DeviceIssues.js index 217156ca9a..47cb590676 100644 --- a/app/pages/clinicworkspace/DeviceIssues/DeviceIssues.js +++ b/app/pages/clinicworkspace/DeviceIssues/DeviceIssues.js @@ -87,7 +87,7 @@ export const useRequireSummaryDashboardEntitlement = () => { const hasSummaryDashboard = clinic?.entitlements?.summaryDashboard || false; useEffect(() => { - if (isEntitlementsLoaded && hasSummaryDashboard) { + if (isEntitlementsLoaded && !hasSummaryDashboard) { history.push('/clinic-workspace/patients'); } }, [isEntitlementsLoaded, hasSummaryDashboard]); From 77485f9107b6cb38960e90c834adfab305812838 Mon Sep 17 00:00:00 2001 From: henry-tp Date: Tue, 24 Feb 2026 13:40:41 -0800 Subject: [PATCH 07/31] un-redux the filters --- .../DeviceIssues/DeviceIssues.js | 32 ++++++------------- .../Filters/ActiveFilterCount.js | 15 +++------ .../clinicworkspace/Filters/TagsFilter.js | 32 ++++++++++++------- .../clinicWorkspaceFiltersSlice.js | 25 --------------- .../useClinicPatientsFilters.js | 10 ++++++ app/redux/reducers/index.js | 2 -- 6 files changed, 44 insertions(+), 72 deletions(-) delete mode 100644 app/pages/clinicworkspace/clinicWorkspaceFiltersSlice.js diff --git a/app/pages/clinicworkspace/DeviceIssues/DeviceIssues.js b/app/pages/clinicworkspace/DeviceIssues/DeviceIssues.js index 47cb590676..84848e3925 100644 --- a/app/pages/clinicworkspace/DeviceIssues/DeviceIssues.js +++ b/app/pages/clinicworkspace/DeviceIssues/DeviceIssues.js @@ -12,7 +12,6 @@ import ActiveFilterCount from '../Filters/ActiveFilterCount'; import TagsFilter from '../Filters/TagsFilter'; import { CategorySelector, CategoryTab } from '../Filters/CategoryFilter'; import useClinicPatientsFilters from '../useClinicPatientsFilters'; -import { setClinicWorkspaceFilters } from '../clinicWorkspaceFiltersSlice'; const LIMIT = 50; @@ -39,7 +38,7 @@ const RenderTags = ({ 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(patientTag => patientTag.id === tag)); // TODO: index return ; }; @@ -61,23 +60,6 @@ const RenderPatient = ({ patient }) => { ; }; -const usePersistFiltersToLocalStorage = () => { - const dispatch = useDispatch(); - const clinicWorkspaceFilters = useSelector(state => state.blip.clinicWorkspaceFilters); - - const [activeFilters, setActiveFilters] = useClinicPatientsFilters(); - - // On load, initialize Redux state from localStorage - useEffect(() => { - dispatch(setClinicWorkspaceFilters(activeFilters)); - }, []); - - // Whenever the filters change, push to localStorage - useEffect(() => { - setActiveFilters(clinicWorkspaceFilters); - }, [clinicWorkspaceFilters]); -}; - export const useRequireSummaryDashboardEntitlement = () => { const history = useHistory(); const selectedClinicId = useSelector(state => state.blip.selectedClinicId); @@ -100,11 +82,11 @@ export const useRequireSummaryDashboardEntitlement = () => { const DeviceIssues = () => { const { t } = useTranslation(); - usePersistFiltersToLocalStorage(); const isAuthorized = useRequireSummaryDashboardEntitlement(); + const [activeFilters, setActiveFilters, activeFiltersCount] = useClinicPatientsFilters(); + const { patientTags } = activeFilters; const selectedClinicId = useSelector(state => state.blip.selectedClinicId); - const patientTags = useSelector(state => state.blip.clinicWorkspaceFilters.patientTags); const [offset, setOffset] = useState(0); const { data } = useGetDeviceIssuesPatientsQuery( @@ -116,11 +98,15 @@ const DeviceIssues = () => { const tableData = data?.data || []; + const handleFilterChange = (payload) => { + setActiveFilters({ ...activeFilters, ...payload }); + }; + return ( <> - - + + diff --git a/app/pages/clinicworkspace/Filters/ActiveFilterCount.js b/app/pages/clinicworkspace/Filters/ActiveFilterCount.js index 92c8c4db81..324e298a49 100644 --- a/app/pages/clinicworkspace/Filters/ActiveFilterCount.js +++ b/app/pages/clinicworkspace/Filters/ActiveFilterCount.js @@ -1,21 +1,14 @@ import React from 'react'; import { Flex, Text } from 'theme-ui'; import Pill from '../../../components/elements/Pill'; -import without from 'lodash/without'; import { borders } from '../../../themes/baseTheme'; import Icon from '../../../components/elements/Icon'; import FilterIcon from '../../../core/icons/FilterIcon.svg'; -import { useSelector } from 'react-redux'; import { useTranslation } from 'react-i18next'; -const ActiveFilterCount = () => { +const ActiveFilterCount = ({ count }) => { const { t } = useTranslation(); - const patientTags = useSelector(state => state.blip.clinicWorkspaceFilters.patientTags); - - const activeFiltersCount = without([ - patientTags?.length, - ], null, 0, undefined).length; return ( { pl={[0, 0, 2]} py={1} sx={{ - color: activeFiltersCount > 0 ? 'purpleMedium' : 'grays.4', + color: count > 0 ? 'purpleMedium' : 'grays.4', alignItems: 'center', gap: 1, borderLeft: ['none', null, borders.divider], flexShrink: 0, }} > - {activeFiltersCount > 0 ? ( + {count > 0 ? ( ) : ( noop; const prefixPopHealthMetric = () => noop; import { SPECIAL_FILTER_STATES } from '../ClinicPatients'; -import { setPatientTagsFilter } from '../clinicWorkspaceFiltersSlice'; const TagsFilterContent = ({ + patientTags = [], onClose = noop, + onChange = noop, }) => { const { t } = useTranslation(); - const dispatch = useDispatch(); const selectedClinicId = useSelector((state) => state.blip.selectedClinicId); const clinic = useSelector(state => state.blip.clinics?.[selectedClinicId]); - const clinicWorkspaceFilters = useSelector(state => state.blip.clinicWorkspaceFilters); - const { patientTags } = clinicWorkspaceFilters; const [pendingTags, setPendingTags] = useState(patientTags); @@ -52,6 +50,10 @@ const TagsFilterContent = ({ .toSorted((a, b) => utils.compareLabels(a.label, b.label)); }, [clinic?.patientTags]); + const handleApplyFilter = (payload) => { + onChange({ patientTags: payload }); + }; + return ( <> @@ -135,7 +137,7 @@ const TagsFilterContent = ({ onClick={() => { trackMetric(prefixPopHealthMetric('Patient tag filter clear'), { clinicId: selectedClinicId }); setPendingTags([]); - dispatch(setPatientTagsFilter([])); + handleApplyFilter([]); onClose(); }} > @@ -144,7 +146,7 @@ const TagsFilterContent = ({ - - - - } - - ); -}; - -const TagsFilter = ({ - patientTags = [], - onChange = noop, -}) => { - const { t } = useTranslation(); - const { showTideDashboard } = useFlags(); - - const patientTagsPopupFilterState = usePopupState({ - variant: 'popover', - popupId: 'patientTagFilters', - }); - - const selectedClinicId = useSelector((state) => state.blip.selectedClinicId); - const clinic = useSelector(state => state.blip.clinics?.[selectedClinicId]); - - const handleCloseDropdown = () => { - patientTagsPopupFilterState.close(); - }; - - return ( - <> - { - if (!patientTagsPopupFilterState.isOpen) trackMetric(prefixPopHealthMetric('patient tags filter open'), { clinicId: selectedClinicId }); - }} - sx={{ flexShrink: 0 }} - > - - - - { - trackMetric(prefixPopHealthMetric('Patient tag filter close'), { clinicId: selectedClinicId }); - }} - onClose={() => { - patientTagsPopupFilterState.close(); - }} - > - { patientTagsPopupFilterState.isOpen && - - } - - - ); -}; - -export default TagsFilter; From 5a68d811e7279eac141785621ad938db00d90f4c Mon Sep 17 00:00:00 2001 From: henry-tp Date: Tue, 24 Feb 2026 16:07:39 -0800 Subject: [PATCH 09/31] move useClinicPatientsFilters into own file --- app/components/clinic/PatientForm/SelectSites.js | 2 +- app/components/clinic/PatientForm/SelectTags.js | 2 +- app/pages/clinicworkspace/ClinicPatients.js | 2 +- app/pages/clinicworkspace/DeviceIssues/DeviceIssues.js | 2 +- .../clinicworkspace/{ => hooks}/useClinicPatientsFilters.js | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) rename app/pages/clinicworkspace/{ => hooks}/useClinicPatientsFilters.js (95%) diff --git a/app/components/clinic/PatientForm/SelectSites.js b/app/components/clinic/PatientForm/SelectSites.js index 0797729daa..6b71472a1d 100644 --- a/app/components/clinic/PatientForm/SelectSites.js +++ b/app/components/clinic/PatientForm/SelectSites.js @@ -4,7 +4,7 @@ import { useSelector } from 'react-redux'; import partition from 'lodash/partition'; import Select, { createFilter } from 'react-select'; import { useLocation } from 'react-router-dom'; -import useClinicPatientsFilters from '../../../pages/clinicworkspace/useClinicPatientsFilters'; +import useClinicPatientsFilters from '../../../pages/clinicworkspace/hooks/useClinicPatientsFilters'; import { useTranslation } from 'react-i18next'; import { noop } from 'lodash'; import utils from '../../../core/utils'; diff --git a/app/components/clinic/PatientForm/SelectTags.js b/app/components/clinic/PatientForm/SelectTags.js index 0544eaa9c1..1894b71471 100644 --- a/app/components/clinic/PatientForm/SelectTags.js +++ b/app/components/clinic/PatientForm/SelectTags.js @@ -5,7 +5,7 @@ import keyBy from 'lodash/keyBy'; import partition from 'lodash/partition'; import Select, { createFilter } from 'react-select'; import { useLocation } from 'react-router-dom'; -import useClinicPatientsFilters from '../../../pages/clinicworkspace/useClinicPatientsFilters'; +import useClinicPatientsFilters from '../../../pages/clinicworkspace/hooks/useClinicPatientsFilters'; import { useTranslation } from 'react-i18next'; import { noop } from 'lodash'; import utils from '../../../core/utils'; diff --git a/app/pages/clinicworkspace/ClinicPatients.js b/app/pages/clinicworkspace/ClinicPatients.js index 42451d6df2..cacb9b8b12 100644 --- a/app/pages/clinicworkspace/ClinicPatients.js +++ b/app/pages/clinicworkspace/ClinicPatients.js @@ -48,7 +48,7 @@ import { scroller } from 'react-scroll'; import { Formik, Form } from 'formik'; import { useFlags, useLDClient } from 'launchdarkly-react-client-sdk'; import { Link as RouterLink } from 'react-router-dom'; -import useClinicPatientsFilters, { defaultFilterState } from './useClinicPatientsFilters'; +import useClinicPatientsFilters, { defaultFilterState } from './hooks/useClinicPatientsFilters'; import { bindPopover, diff --git a/app/pages/clinicworkspace/DeviceIssues/DeviceIssues.js b/app/pages/clinicworkspace/DeviceIssues/DeviceIssues.js index 0e2a7e663d..fc1566fb70 100644 --- a/app/pages/clinicworkspace/DeviceIssues/DeviceIssues.js +++ b/app/pages/clinicworkspace/DeviceIssues/DeviceIssues.js @@ -9,7 +9,7 @@ import { DIABETES_TYPES } from '../../../core/constants'; import { RTKQueryApi } from '../../../redux/api/baseApi'; import { TagList } from '../../../components/elements/Tag'; -import useClinicPatientsFilters from '../useClinicPatientsFilters'; +import useClinicPatientsFilters from '../hooks/useClinicPatientsFilters'; import ActiveFilterCount from '../ActiveFilterCount'; import FilterByTags from './FilterByTags'; import FilterByCategory, { CATEGORY_TAB } from './FilterByCategory'; diff --git a/app/pages/clinicworkspace/useClinicPatientsFilters.js b/app/pages/clinicworkspace/hooks/useClinicPatientsFilters.js similarity index 95% rename from app/pages/clinicworkspace/useClinicPatientsFilters.js rename to app/pages/clinicworkspace/hooks/useClinicPatientsFilters.js index 2ecc2d4578..839239d4ce 100644 --- a/app/pages/clinicworkspace/useClinicPatientsFilters.js +++ b/app/pages/clinicworkspace/hooks/useClinicPatientsFilters.js @@ -1,5 +1,5 @@ import { useSelector } from 'react-redux'; -import { useLocalStorage } from '../../core/hooks'; +import { useLocalStorage } from '../../../core/hooks'; import without from 'lodash/without'; export const defaultFilterState = { From 0c8ed7ac0f82e757c94e19292af0a9dd6f382c48 Mon Sep 17 00:00:00 2001 From: henry-tp Date: Tue, 24 Feb 2026 16:31:24 -0800 Subject: [PATCH 10/31] add filter reset button --- .../clinicworkspace/ActiveFilterCount.js | 1 - .../DeviceIssues/DeviceIssues.js | 16 +++++++++--- .../components/ResetFiltersButton.js | 26 +++++++++++++++++++ 3 files changed, 38 insertions(+), 5 deletions(-) create mode 100644 app/pages/clinicworkspace/components/ResetFiltersButton.js diff --git a/app/pages/clinicworkspace/ActiveFilterCount.js b/app/pages/clinicworkspace/ActiveFilterCount.js index e7724e5526..13a0ece0fe 100644 --- a/app/pages/clinicworkspace/ActiveFilterCount.js +++ b/app/pages/clinicworkspace/ActiveFilterCount.js @@ -12,7 +12,6 @@ const ActiveFilterCount = ({ count }) => { return ( diff --git a/app/pages/clinicworkspace/DeviceIssues/DeviceIssues.js b/app/pages/clinicworkspace/DeviceIssues/DeviceIssues.js index fc1566fb70..79f67b4057 100644 --- a/app/pages/clinicworkspace/DeviceIssues/DeviceIssues.js +++ b/app/pages/clinicworkspace/DeviceIssues/DeviceIssues.js @@ -9,12 +9,13 @@ import { DIABETES_TYPES } from '../../../core/constants'; import { RTKQueryApi } from '../../../redux/api/baseApi'; import { TagList } from '../../../components/elements/Tag'; -import useClinicPatientsFilters from '../hooks/useClinicPatientsFilters'; +import useClinicPatientsFilters, { defaultFilterState } from '../hooks/useClinicPatientsFilters'; import ActiveFilterCount from '../ActiveFilterCount'; import FilterByTags from './FilterByTags'; import FilterByCategory, { CATEGORY_TAB } from './FilterByCategory'; import DashboardPagination from '../components/DashboardPagination'; import useRequireSummaryDashboardEntitlement from '../hooks/useRequireSummaryDashboardEntitlement'; +import ResetFiltersButton from '../components/ResetFiltersButton'; const LIMIT = 12; @@ -83,15 +84,22 @@ const DeviceIssues = () => { const tableData = data?.data || []; - const handleFilterChange = (payload) => { + const handleActiveFilterChange = (payload) => { setActiveFilters({ ...activeFilters, ...payload }); }; return ( <> - + - + + diff --git a/app/pages/clinicworkspace/components/ResetFiltersButton.js b/app/pages/clinicworkspace/components/ResetFiltersButton.js new file mode 100644 index 0000000000..f065ab934c --- /dev/null +++ b/app/pages/clinicworkspace/components/ResetFiltersButton.js @@ -0,0 +1,26 @@ +import React from 'react'; +import noop from 'lodash/noop'; +import { useTranslation } from 'react-i18next'; +import Button from '../../../components/elements/Button'; + +const ResetFiltersButton = ({ hidden = false, onClick = noop }) => { + const { t } = useTranslation(); + + if (hidden) return null; + + console.log('AYOOO') + + return ( + + ); +}; + +export default ResetFiltersButton; From 77dc9f27c49a8d497388e836338b4244021db09e Mon Sep 17 00:00:00 2001 From: henry-tp Date: Tue, 24 Feb 2026 16:35:51 -0800 Subject: [PATCH 11/31] rename ResetFilters --- app/pages/clinicworkspace/DeviceIssues/DeviceIssues.js | 4 ++-- .../components/{ResetFiltersButton.js => ResetFilters.js} | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) rename app/pages/clinicworkspace/components/{ResetFiltersButton.js => ResetFilters.js} (82%) diff --git a/app/pages/clinicworkspace/DeviceIssues/DeviceIssues.js b/app/pages/clinicworkspace/DeviceIssues/DeviceIssues.js index 79f67b4057..a6b6e7a0c2 100644 --- a/app/pages/clinicworkspace/DeviceIssues/DeviceIssues.js +++ b/app/pages/clinicworkspace/DeviceIssues/DeviceIssues.js @@ -15,7 +15,7 @@ import FilterByTags from './FilterByTags'; import FilterByCategory, { CATEGORY_TAB } from './FilterByCategory'; import DashboardPagination from '../components/DashboardPagination'; import useRequireSummaryDashboardEntitlement from '../hooks/useRequireSummaryDashboardEntitlement'; -import ResetFiltersButton from '../components/ResetFiltersButton'; +import ResetFilters from '../components/ResetFilters'; const LIMIT = 12; @@ -96,7 +96,7 @@ const DeviceIssues = () => { patientTags={patientTags} onChange={handleActiveFilterChange} /> -