Skip to content
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
18 changes: 14 additions & 4 deletions frontend/src/common/utils/i18n/resources/en/report.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,20 @@
"filterBookmarked": "Bookmarked",
"noBookmarksTitle": "No Bookmarked Reports",
"noBookmarksMessage": "Bookmark reports to find them quickly here",
"noMatchesTitle": "No Matching Reports",
"noMatchesMessage": "No reports match your current filters. Try changing or clearing your filters.",
"clearFilters": "Clear Filters",
"sortButton": "Sort reports",
"filterButton": "Filter reports",
"generalCategory": "General",
"brainCategory": "Brain",
"heartCategory": "Heart"
"filterButton": "Filter reports"
},
"filter": {
"title": "Filter",
"category": "Category",
"apply": "Apply"
},
"category": {
"general": "General",
"heart": "Heart",
"brain": "Brain"
}
}
17 changes: 16 additions & 1 deletion frontend/src/common/utils/i18n/resources/es/report.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,21 @@
"filterAll": "Todos",
"filterBookmarked": "Guardados",
"noBookmarksTitle": "No Hay Informes Guardados",
"noBookmarksMessage": "Guarda informes como favoritos para encontrarlos rápidamente aquí"
"noBookmarksMessage": "Guarda informes como favoritos para encontrarlos rápidamente aquí",
"noMatchesTitle": "No Hay Informes Coincidentes",
"noMatchesMessage": "Ningún informe coincide con los filtros actuales. Intenta cambiar o eliminar los filtros.",
"clearFilters": "Eliminar Filtros",
"sortButton": "Ordenar informes",
"filterButton": "Filtrar informes"
},
"filter": {
"title": "Filtrar",
"category": "Categoría",
"apply": "Aplicar"
},
"category": {
"general": "General",
"heart": "Corazón",
"brain": "Cerebro"
}
}
17 changes: 16 additions & 1 deletion frontend/src/common/utils/i18n/resources/fr/report.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,21 @@
"filterAll": "Tous",
"filterBookmarked": "Favoris",
"noBookmarksTitle": "Aucun Rapport en Favoris",
"noBookmarksMessage": "Marquez des rapports comme favoris pour les trouver rapidement ici"
"noBookmarksMessage": "Marquez des rapports comme favoris pour les trouver rapidement ici",
"noMatchesTitle": "Aucun Rapport Correspondant",
"noMatchesMessage": "Aucun rapport ne correspond à vos filtres actuels. Essayez de modifier ou de supprimer vos filtres.",
"clearFilters": "Effacer les Filtres",
"sortButton": "Trier les rapports",
"filterButton": "Filtrer les rapports"
},
"filter": {
"title": "Filtrer",
"category": "Catégorie",
"apply": "Appliquer"
},
"category": {
"general": "Général",
"heart": "Cœur",
"brain": "Cerveau"
}
}
30 changes: 30 additions & 0 deletions frontend/src/pages/Home/HomePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ import { useHistory } from 'react-router-dom';
import { useState } from 'react';
import { useGetLatestReports, useMarkReportAsRead } from 'common/hooks/useReports';
import { useCurrentUser } from 'common/hooks/useAuth';
import { toggleReportBookmark } from 'common/api/reportService';
import { useQueryClient } from '@tanstack/react-query';
import { MedicalReport } from 'common/models/medicalReport';
import Avatar from 'common/components/Icon/Avatar';
import ReportItem from './components/ReportItem/ReportItem';
import NoReportsMessage from './components/NoReportsMessage/NoReportsMessage';
Expand All @@ -27,6 +30,7 @@ import './HomePage.scss';
const HomePage: React.FC = () => {
const { t } = useTranslation('home');
const history = useHistory();
const queryClient = useQueryClient();
const { data: reports, isLoading, isError } = useGetLatestReports(3);
const { mutate: markAsRead } = useMarkReportAsRead();
const currentUser = useCurrentUser();
Expand All @@ -43,6 +47,31 @@ const HomePage: React.FC = () => {
history.push(`/tabs/reports/${reportId}`);
};

const handleToggleBookmark = async (reportId: string, isCurrentlyBookmarked: boolean) => {
try {
// Toggle the bookmark status
const updatedReport = await toggleReportBookmark(reportId, !isCurrentlyBookmarked);

// Update the reports in the cache
queryClient.setQueryData<MedicalReport[]>(['reports'], (oldReports) => {
if (!oldReports) return [];
return oldReports.map((report) =>
report.id === updatedReport.id ? updatedReport : report,
);
});

// Update the latest reports cache with the correct query key including the limit
queryClient.setQueryData<MedicalReport[]>(['latestReports', 3], (oldReports) => {
if (!oldReports) return [];
return oldReports.map((report) =>
report.id === updatedReport.id ? updatedReport : report,
);
});
} catch (error) {
console.error('Failed to toggle bookmark:', error);
}
};

const handleUpload = () => {
history.push('/upload');
};
Expand Down Expand Up @@ -92,6 +121,7 @@ const HomePage: React.FC = () => {
key={report.id}
report={report}
onClick={() => handleReportClick(report.id)}
onToggleBookmark={() => handleToggleBookmark(report.id, report.bookmarked)}
showBookmarkButton={true}
/>
));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
padding: 16px;
border-radius: 12px;
margin-bottom: 12px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
position: relative;
cursor: pointer;

Expand Down Expand Up @@ -67,6 +66,7 @@
&--active {
color: white;
background-color: #4355b9;
box-shadow: none;
}
}
}
Expand All @@ -81,7 +81,6 @@
flex-shrink: 0;
background-color: white;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
border: 1px solid rgba(0, 0, 0, 0.03);

&--general,
&--brain,
Expand Down
8 changes: 4 additions & 4 deletions frontend/src/pages/Home/components/ReportItem/ReportItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,13 @@ const ReportItem: React.FC<ReportItemProps> = ({
// Get category translation key based on category value
const getCategoryTranslationKey = () => {
if (categoryStr === ReportCategory.GENERAL.toLowerCase()) {
return 'list.generalCategory';
return 'category.general';
} else if (categoryStr === ReportCategory.BRAIN.toLowerCase()) {
return 'list.brainCategory';
return 'category.brain';
} else if (categoryStr === ReportCategory.HEART.toLowerCase()) {
return 'list.heartCategory';
return 'category.heart';
}
return 'list.generalCategory'; // Default to general if not found
return 'category.general'; // Default to general if not found
};

// Get the appropriate icon for the category
Expand Down
152 changes: 59 additions & 93 deletions frontend/src/pages/Reports/ReportsListPage.scss
Original file line number Diff line number Diff line change
Expand Up @@ -19,150 +19,116 @@
}

&__title-icon {
margin-right: 12px;
color: #333;
padding: 8px;
background-color: #f0f2f5;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
width: 18px;
height: 18px;
font-size: 1.5rem;
margin-right: 0.5rem;
color: var(--ion-color-primary);
}

&__title {
font-size: 18px;
font-size: 1.25rem;
font-weight: 600;
margin: 0;
color: #333;
}

&__actions {
display: flex;
align-items: center;
justify-content: flex-end;
}

&__sort-button,
&__filter-button {
--padding-start: 0;
--padding-end: 0;
--padding-start: 0.5rem;
--padding-end: 0.5rem;
margin: 0;
height: 36px;
width: 36px;
--background: transparent;
--color: #4355b9;
--box-shadow: none;
--ripple-color: transparent;
margin-left: 10px;

.custom-icon-wrapper {
width: 36px;
height: 36px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 50%;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
border: 1px solid rgba(0, 0, 0, 0.03);
}
}

.custom-icon {
width: 22px;
height: 22px;
}
.custom-icon-wrapper {
display: flex;
align-items: center;
justify-content: center;
}

&__content-container {
--padding-top: 0;
.custom-icon {
width: 20px;
height: 20px;
}

&__filter {
padding: 8px 16px;
margin-bottom: 1rem;
}

&__segment-wrapper {
ion-segment {
--background: #ebeef9;
border-radius: 50px;
height: 40px;
overflow: hidden;
--border-radius: 50px;

ion-segment-button {
--color: #777;
--color-checked: #000;
--indicator-color: white;
--background-checked: white;
--border-radius: 50px;
--border-color: transparent;
text-transform: none;
font-weight: 500;
letter-spacing: normal;
font-size: 14px;
min-height: 36px;

&::part(indicator) {
border-radius: 50px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
}
}
padding: 0 1rem;
}

&__category-tags {
display: flex;
flex-wrap: wrap;
padding: 0.75rem 1rem;
margin-bottom: 0.5rem;
background-color: #f9f9f9;
border-bottom: 1px solid var(--ion-color-light);
}

&__content-container {
--padding-top: 0;
--background: var(--ion-background-color);
}

&__content {
padding: 0;
padding-bottom: 1rem;
}

&__list {
background-color: transparent;
padding: 12px;
margin: 0;

ion-item {
--padding-start: 0;
--inner-padding-end: 0;
--background: transparent;
}
padding: 0;
background: transparent;
}

&__empty-state {
padding: 2rem;
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 2rem;
text-align: center;
}

&__no-bookmarks {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
&__no-bookmarks,
&__no-matches {
text-align: center;
padding: 2rem 1rem;
padding: 2rem;

h3 {
font-size: 1.2rem;
margin-bottom: 0.5rem;
color: #333;
font-weight: 600;
margin-bottom: 0.5rem;
}

p {
font-size: 0.9rem;
color: #666;
margin: 0;
color: var(--ion-color-medium);
margin-bottom: 1.5rem;
}
}

&__filter-modal {
--height: auto;
--width: 100%;
--border-radius: 20px 20px 0 0;
--box-shadow: 0 -4px 16px rgba(0, 0, 0, 0.1);

&::part(content) {
border-radius: 20px 20px 0 0;
}
}

// Skeleton loading styles
.skeleton {
width: 48px;
height: 48px;
border-radius: 50%;
background-color: #ebeef9;
margin-right: 16px;
background-color: rgba(var(--ion-color-medium-rgb), 0.2);
border-radius: 4px;
height: 40px;
width: 40px;
margin-right: 1rem;
}
}

Loading