@@ -12,6 +12,7 @@ import {
1212 IonIcon ,
1313 IonButton ,
1414 IonToast ,
15+ IonModal ,
1516} from '@ionic/react' ;
1617import { useTranslation } from 'react-i18next' ;
1718import { useHistory } from 'react-router-dom' ;
@@ -20,11 +21,13 @@ import { fetchAllReports, toggleReportBookmark } from 'common/api/reportService'
2021import { useMarkReportAsRead } from 'common/hooks/useReports' ;
2122import ReportItem from 'pages/Home/components/ReportItem/ReportItem' ;
2223import NoReportsMessage from 'pages/Home/components/NoReportsMessage/NoReportsMessage' ;
23- import { useState , useMemo , useEffect } from 'react' ;
24+ import { useState , useMemo , useEffect , useRef } from 'react' ;
2425import { MedicalReport } from 'common/models/medicalReport' ;
2526import { documentTextOutline } from 'ionicons/icons' ;
2627import sortSvg from 'assets/icons/sort.svg' ;
2728import filterOutlineIcon from 'assets/icons/filter-outline.svg' ;
29+ import FilterPanel , { CategoryOption } from './components/FilterPanel/FilterPanel' ;
30+ import CategoryTag from './components/CategoryTag/CategoryTag' ;
2831
2932import './ReportsListPage.scss' ;
3033
@@ -41,7 +44,18 @@ const ReportsListPage: React.FC = () => {
4144 const [ filter , setFilter ] = useState < FilterOption > ( 'all' ) ;
4245 const [ sortDirection , setSortDirection ] = useState < SortDirection > ( 'desc' ) ; // Default sort by newest first
4346 const [ showToast , setShowToast ] = useState ( false ) ;
44- const [ toastMessage , setToastMessage ] = useState ( '' ) ;
47+ const [ toastMessage ] = useState ( '' ) ;
48+ const [ showFilterModal , setShowFilterModal ] = useState ( false ) ;
49+ const [ selectedCategories , setSelectedCategories ] = useState < string [ ] > ( [ ] ) ;
50+ const filterModalRef = useRef < HTMLIonModalElement > ( null ) ;
51+
52+ // Define available categories
53+ const categories : CategoryOption [ ] = [
54+ { id : 'general' , label : t ( 'category.general' , { ns : 'report' } ) } ,
55+ { id : 'heart' , label : t ( 'category.heart' , { ns : 'report' } ) } ,
56+ { id : 'brain' , label : t ( 'category.brain' , { ns : 'report' } ) } ,
57+ // Add more categories as needed
58+ ] ;
4559
4660 const { data : reports = [ ] , isLoading, isError } = useQuery ( {
4761 queryKey : [ 'reports' ] ,
@@ -50,18 +64,25 @@ const ReportsListPage: React.FC = () => {
5064
5165 const { mutate : markAsRead } = useMarkReportAsRead ( ) ;
5266
53- // Filter and sort reports based on selected filter and sort direction
67+ // Filter and sort reports based on selected filter, categories, and sort direction
5468 const filteredReports = useMemo ( ( ) => {
55- // First, filter the reports
56- const filtered = filter === 'all' ? reports : reports . filter ( report => report . bookmarked ) ;
69+ // First, filter the reports by bookmark status
70+ let filtered = filter === 'all' ? reports : reports . filter ( report => report . bookmarked ) ;
71+
72+ // Then, filter by selected categories if any are selected
73+ if ( selectedCategories . length > 0 ) {
74+ filtered = filtered . filter ( report =>
75+ selectedCategories . includes ( report . category . toLowerCase ( ) )
76+ ) ;
77+ }
5778
58- // Then , sort the filtered reports by date
79+ // Finally , sort the filtered reports by date
5980 return [ ...filtered ] . sort ( ( a , b ) => {
6081 const dateA = new Date ( a . createdAt ) . getTime ( ) ;
6182 const dateB = new Date ( b . createdAt ) . getTime ( ) ;
6283 return sortDirection === 'desc' ? dateB - dateA : dateA - dateB ;
6384 } ) ;
64- } , [ reports , filter , sortDirection ] ) ;
85+ } , [ reports , filter , sortDirection , selectedCategories ] ) ;
6586
6687 // Check if there are any bookmarked reports
6788 const hasBookmarkedReports = useMemo ( ( ) => {
@@ -118,8 +139,44 @@ const ReportsListPage: React.FC = () => {
118139 } ;
119140
120141 const handleFilterClick = ( ) => {
121- setToastMessage ( t ( 'list.filterButton' , { ns : 'report' } ) ) ;
122- setShowToast ( true ) ;
142+ setShowFilterModal ( true ) ;
143+ } ;
144+
145+ const handleCloseFilterModal = ( ) => {
146+ filterModalRef . current ?. dismiss ( ) ;
147+ } ;
148+
149+ const handleApplyFilters = ( categories : string [ ] ) => {
150+ setSelectedCategories ( categories ) ;
151+ } ;
152+
153+ const handleRemoveCategory = ( categoryId : string ) => {
154+ setSelectedCategories ( prev => prev . filter ( id => id !== categoryId ) ) ;
155+ } ;
156+
157+ const handleClearAllCategories = ( ) => {
158+ setSelectedCategories ( [ ] ) ;
159+ } ;
160+
161+ const getCategoryLabel = ( categoryId : string ) : string => {
162+ const category = categories . find ( cat => cat . id === categoryId ) ;
163+ return category ? category . label : categoryId ;
164+ } ;
165+
166+ const renderCategoryTags = ( ) => {
167+ if ( selectedCategories . length === 0 ) return null ;
168+
169+ return (
170+ < div className = "reports-list-page__category-tags" >
171+ { selectedCategories . map ( categoryId => (
172+ < CategoryTag
173+ key = { categoryId }
174+ label = { getCategoryLabel ( categoryId ) }
175+ onRemove = { ( ) => handleRemoveCategory ( categoryId ) }
176+ />
177+ ) ) }
178+ </ div >
179+ ) ;
123180 } ;
124181
125182 const renderReportsList = ( ) => {
@@ -157,6 +214,14 @@ const ReportsListPage: React.FC = () => {
157214 < h3 > { t ( 'list.noBookmarksTitle' , { ns : 'report' } ) } </ h3 >
158215 < p > { t ( 'list.noBookmarksMessage' , { ns : 'report' } ) } </ p >
159216 </ div >
217+ ) : selectedCategories . length > 0 ? (
218+ < div className = "reports-list-page__no-matches" >
219+ < h3 > { t ( 'list.noMatchesTitle' , { ns : 'report' } ) } </ h3 >
220+ < p > { t ( 'list.noMatchesMessage' , { ns : 'report' } ) } </ p >
221+ < IonButton onClick = { handleClearAllCategories } >
222+ { t ( 'list.clearFilters' , { ns : 'report' } ) }
223+ </ IonButton >
224+ </ div >
160225 ) : (
161226 < NoReportsMessage
162227 onUpload = { handleUpload }
@@ -235,13 +300,32 @@ const ReportsListPage: React.FC = () => {
235300 </ div >
236301 </ div >
237302 ) }
303+
304+ { /* Display selected category tags */ }
305+ { renderCategoryTags ( ) }
306+
238307 < div className = "reports-list-page__content" >
239308 < IonList className = "reports-list-page__list" lines = "none" >
240309 { renderReportsList ( ) }
241310 </ IonList >
242311 </ div >
243312 </ IonContent >
244313
314+ { /* Filter Modal */ }
315+ < IonModal
316+ ref = { filterModalRef }
317+ isOpen = { showFilterModal }
318+ onDidDismiss = { ( ) => setShowFilterModal ( false ) }
319+ className = "reports-list-page__filter-modal"
320+ >
321+ < FilterPanel
322+ categories = { categories }
323+ selectedCategories = { selectedCategories }
324+ onApply = { handleApplyFilters }
325+ onClose = { handleCloseFilterModal }
326+ />
327+ </ IonModal >
328+
245329 < IonToast
246330 isOpen = { showToast }
247331 onDidDismiss = { ( ) => setShowToast ( false ) }
0 commit comments