Skip to content

Commit

Permalink
fix(courses): enable notifications from courses in previous years (#580)
Browse files Browse the repository at this point in the history
* fix(courses): enable notifications from courses in previous years

* fix(courses): fix notifications from cross navigation

---------

Co-authored-by: Cristina Ferrian <54667563+Bri74@users.noreply.github.com>
  • Loading branch information
emacoricciati and Bri74 authored Feb 6, 2025
1 parent f2fd765 commit 65adfe4
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 53 deletions.
23 changes: 23 additions & 0 deletions src/core/hooks/useNotifications.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useCallback } from 'react';

import { CourseOverviewPreviousEditionsInner } from '@polito/api-client';
import { Notification } from '@polito/api-client/models/Notification';
import { useNavigation } from '@react-navigation/native';
import { NativeStackNavigationProp } from '@react-navigation/native-stack';
Expand Down Expand Up @@ -160,6 +161,27 @@ export const useNotifications = () => {
[unreadNotifications],
);

const getUnreadsCountPerCourse = useCallback(
(
courseId?: number | null,
prevEditions?: CourseOverviewPreviousEditionsInner[],
) => {
if (courseId === undefined || !prevEditions) return 0;
const courseIds = prevEditions.map(e => e.id);
if (courseId) {
courseIds.push(courseId);
}
return (
courseIds.reduce(
(acc, eid) =>
acc + (getUnreadsCount(['teaching', 'courses', eid]) ?? 0),
0,
) || undefined
);
},
[getUnreadsCount],
);

const navigateToUpdate = useCallback(
(notification?: RemoteMessage) => {
if (!notification || !notification.data?.polito_transazione) {
Expand Down Expand Up @@ -216,5 +238,6 @@ export const useNotifications = () => {
navigateToUpdate,
clearNotificationScope,
getUnreadsCount,
getUnreadsCountPerCourse,
};
};
35 changes: 7 additions & 28 deletions src/core/queries/courseHooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import {
CoursesApi,
UploadCourseAssignmentRequest,
} from '@polito/api-client';
import { MenuAction } from '@react-native-menu/menu';
import {
useMutation,
useQueries,
Expand Down Expand Up @@ -158,41 +157,21 @@ export const useGetCourseEditions = (courseId: number) => {
c =>
c.id === courseId || c.previousEditions.some(e => e.id === courseId),
);
const editions: MenuAction[] = [];
const editions: CourseOverviewPreviousEditionsInner[] = [];
if (!course || !course.previousEditions.length) return editions;
if (course.id) {
editions.push(
{
id: `${course.id}`,
title: course.year,
state: courseId === course?.id ? 'on' : undefined,
},
...course.previousEditions.map(
e =>
({
id: `${e.id}`,
title: e.year,
state: courseId === e.id ? 'on' : undefined,
} as MenuAction),
),
);
editions.push({
id: course.id,
year: course.year,
});
editions.push(...course.previousEditions);
} else {
const prevEditions = course.previousEditions
.filter(e => e.id !== null)
.sort((a, b) => +b.year - +a.year)
.slice(1);
editions.push(
...prevEditions.map(
e =>
({
id: `${e.id}`,
title: e.year,
state: courseId === e.id ? 'on' : undefined,
} as MenuAction),
),
);
editions.push(...prevEditions);
}

return editions;
},
{
Expand Down
2 changes: 0 additions & 2 deletions src/features/courses/components/CourseListItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,6 @@ export const CourseListItem = ({
screen: 'Course',
params: {
id: courseInfo?.id,
courseName: courseInfo?.name,
uniqueShortcode: courseInfo?.uniqueShortcode,
},
}
: undefined
Expand Down
1 change: 0 additions & 1 deletion src/features/courses/navigation/CourseNavigator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ export const CourseNavigator = ({ route, navigation }: Props) => {
const titleStyles = useTitlesStyles(theme);

const { id } = route.params;

const coursesQuery = useGetCourses();

useEffect(() => {
Expand Down
72 changes: 60 additions & 12 deletions src/features/courses/screens/CourseInfoScreen.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useCallback, useEffect, useState } from 'react';
import { useCallback, useEffect, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import {
Linking,
Expand All @@ -7,10 +7,13 @@ import {
StyleSheet,
View,
} from 'react-native';
import { Platform } from 'react-native';

import { faAngleDown } from '@fortawesome/free-solid-svg-icons';
import { faLink } from '@fortawesome/free-solid-svg-icons';
import { faCircle } from '@fortawesome/free-solid-svg-icons';
import { Card } from '@lib/ui/components/Card';
import { Col } from '@lib/ui/components/Col';
import { Grid } from '@lib/ui/components/Grid';
import { Icon } from '@lib/ui/components/Icon';
import { ListItem } from '@lib/ui/components/ListItem';
Expand All @@ -28,11 +31,13 @@ import { useStylesheet } from '@lib/ui/hooks/useStylesheet';
import { useTheme } from '@lib/ui/hooks/useTheme';
import { Theme } from '@lib/ui/types/Theme';
import { Person } from '@polito/api-client/models/Person';
import { MenuAction } from '@react-native-menu/menu';
import { useNavigation } from '@react-navigation/native';
import { NativeStackNavigationProp } from '@react-navigation/native-stack';
import { useQueryClient } from '@tanstack/react-query';

import { BottomBarSpacer } from '../../../core/components/BottomBarSpacer';
import { useNotifications } from '../../../core/hooks/useNotifications';
import { useOfflineDisabled } from '../../../core/hooks/useOfflineDisabled';
import {
CourseSectionEnum,
Expand All @@ -53,6 +58,8 @@ export const CourseInfoScreen = () => {
const { t } = useTranslation();
const courseId = useCourseContext();
const styles = useStylesheet(createStyles);
const { spacing, palettes } = useTheme();
const { getUnreadsCount, getUnreadsCountPerCourse } = useNotifications();
const { fontSizes } = useTheme();
const [staff, setStaff] = useState<StaffMember[]>([]);
const { data: editions } = useGetCourseEditions(courseId);
Expand All @@ -65,10 +72,31 @@ export const CourseInfoScreen = () => {
courseQuery.data?.staff.map(s => s.id),
);

const unreadsCurrentYear = getUnreadsCount(['teaching', 'courses', courseId]);
const unreadsPrevEditions =
(getUnreadsCountPerCourse(null, editions) ?? 0) - (unreadsCurrentYear ?? 0);

const isOffline = useOfflineDisabled();

const { getParent } = useNavigation();

const menuActions = useMemo(() => {
if (!editions) return [];
return editions.map(e => {
const editionsCount = getUnreadsCount(['teaching', 'courses', e.id]);
return {
id: `${e.id}`,
title: e.year,
state: courseId === e.id ? 'on' : undefined,
image: editionsCount
? Platform.select({ ios: 'circle.fill', android: 'circle' })
: undefined,
imageColor: editionsCount ? palettes.rose[600] : undefined,
} as MenuAction;
});
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [editions, courseId]);

useEffect(() => {
if (!courseQuery.data || isStaffLoading) {
return;
Expand Down Expand Up @@ -125,7 +153,7 @@ export const CourseInfoScreen = () => {
accessible={true}
>
<StatefulMenuView
actions={editions ?? []}
actions={menuActions}
onPressAction={async ({ nativeEvent: { event } }) => {
// replace current screen with same screen with event id as param
(
Expand All @@ -148,15 +176,30 @@ export const CourseInfoScreen = () => {
accessibilityLabel={`${t('degreeCourseScreen.period')}: ${
courseQuery.data?.teachingPeriod ?? '--'
} - ${courseQuery.data?.year ?? '--'}`}
style={styles.periodMetric}
/>
{(editions?.length ?? 0) > 0 && (
<Icon
icon={faAngleDown}
size={14}
style={styles.periodDropdownIcon}
color={styles.periodDropdownIcon.color}
/>
)}
<Col align="center">
{unreadsPrevEditions > 0 && (
<Icon
icon={faCircle}
size={8}
color={styles.dotIcon.color}
style={styles.dotIcon}
/>
)}
{(editions?.length ?? 0) > 0 && (
<Icon
icon={faAngleDown}
size={14}
style={{
marginTop: unreadsPrevEditions
? undefined
: spacing[4],
}}
color={styles.periodDropdownIcon.color}
/>
)}
</Col>
</Row>
</StatefulMenuView>
</View>
Expand Down Expand Up @@ -267,9 +310,14 @@ const createStyles = ({ palettes, spacing }: Theme) =>
marginTop: 0,
marginBottom: spacing[7],
},
periodMetric: {
marginRight: spacing[2],
},
periodDropdownIcon: {
marginLeft: spacing[2],
marginTop: spacing[4],
color: palettes.secondary['500'],
},
dotIcon: {
marginBottom: spacing[2],
color: palettes.rose['600'],
},
});
15 changes: 5 additions & 10 deletions src/features/teaching/screens/TeachingScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export const TeachingScreen = ({ navigation }: Props) => {
const styles = useStylesheet(createStyles);
const { courses: coursePreferences, hideGrades } = usePreferencesContext();
const isOffline = useOfflineDisabled();
const { getUnreadsCount } = useNotifications();
const { getUnreadsCountPerCourse } = useNotifications();
const surveyCategoriesQuery = useGetSurveyCategories();
const coursesQuery = useGetCourses();
const examsQuery = useGetExams();
Expand Down Expand Up @@ -147,15 +147,10 @@ export const TeachingScreen = ({ navigation }: Props) => {
<CourseListItem
key={course.shortcode + '' + course.id}
course={course}
badge={
course.id
? getUnreadsCount([
'teaching',
'courses',
course.id!.toString(),
])
: undefined
}
badge={getUnreadsCountPerCourse(
course.id,
course.previousEditions,
)}
/>
))}
</OverviewList>
Expand Down

0 comments on commit 65adfe4

Please sign in to comment.