Skip to content

Commit 13caca1

Browse files
authored
Add support for 2026 timetable data alongside 2025 (#1090)
* Add support for multiple years at a time * Revert broken changes for default term * Update new timetable promotional popup * Switch back to production GraphQL API
1 parent b4e899e commit 13caca1

File tree

6 files changed

+30
-17
lines changed

6 files changed

+30
-17
lines changed

client/src/App.tsx

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import Timetable from './components/timetable/Timetable';
1919
import { TimetableTabs } from './components/timetableTabs/TimetableTabs';
2020
import { contentPadding, rightContentPadding, themes } from './constants/theme';
2121
import {
22+
convertToTermName,
2223
daysLong,
2324
getAvailableTermDetails,
2425
getDefaultEndTime,
@@ -180,8 +181,8 @@ const App: React.FC = () => {
180181
const fetchTermData = async () => {
181182
const { term, termName, year, firstDayOfTerm, termsData } = await getAvailableTermDetails();
182183
setTerm(term);
183-
setTermName(termName);
184184
setYear(year);
185+
setTermName(termName);
185186
setFirstDayOfTerm(firstDayOfTerm);
186187
const termsSortedList: TermDataList = sortTerms(termsData);
187188
setTermsData(termsSortedList);
@@ -212,7 +213,7 @@ const App: React.FC = () => {
212213
* Retrieves the list of all courses from the scraper backend
213214
*/
214215
const fetchCoursesList = async () => {
215-
const { courses } = await getCoursesList(term.substring(0, 2));
216+
const { courses } = await getCoursesList(parseInt(year, 10), term.substring(0, 2));
216217
setCoursesList(courses);
217218
};
218219

@@ -301,9 +302,11 @@ const App: React.FC = () => {
301302
const codes: string[] = Array.isArray(data) ? data : [data];
302303
Promise.all(
303304
codes.map((code) =>
304-
getCourseInfo(term.substring(0, 2), code, term.substring(2), isConvertToLocalTimezone).catch((err) => {
305-
return err;
306-
}),
305+
getCourseInfo(term.substring(0, 2), code, parseInt(term.substring(2), 10), isConvertToLocalTimezone).catch(
306+
(err) => {
307+
return err;
308+
},
309+
),
307310
),
308311
).then((result) => {
309312
const addedCourses = result.filter((course) => course.code !== undefined) as CourseData[];
@@ -644,7 +647,7 @@ const App: React.FC = () => {
644647
<SubcomPromotion />
645648
<PromotionPopup
646649
imgSrc={T3SelectGif}
647-
title="Next term's timetable has been released! 🎉"
650+
title="The 2026 Term 1 timetable has been released! 🎉"
648651
subTitle="Organise, plan and schedule with newly released timetable"
649652
bullets={[
650653
{

client/src/api/getCourseInfo.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ import { dbCourseToCourseData } from '../utils/DbCourse';
99
import { graphQLCourseToDbCourse } from '../utils/graphQLCourseToDbCourse';
1010

1111
const GET_COURSE_INFO = gql`
12-
query GetCourseInfo($courseCode: String!, $term: String!, $year: String!) {
13-
courses(where: { course_code: { _eq: $courseCode } }) {
12+
query GetCourseInfo($courseCode: String!, $term: String!, $year: Int!) {
13+
courses(where: { course_code: { _eq: $courseCode }, year: { _eq: $year } }) {
1414
course_code
1515
course_name
1616
classes(where: { term: { _eq: $term }, year: { _eq: $year }, activity: { _neq: "Course Enrolment" } }) {
@@ -105,7 +105,7 @@ const sortUnique = (arr: number[]): number[] => {
105105
const getCourseInfo = async (
106106
term: string,
107107
courseCode: CourseCode,
108-
year: string,
108+
year: number,
109109
isConvertToLocalTimezone: boolean,
110110
): Promise<CourseData> => {
111111
try {

client/src/api/getCoursesList.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,16 @@ const toCoursesList = (data: FetchedCourse[]): CoursesList =>
1515
}));
1616

1717
const GET_COURSE_LIST = gql`
18-
query GetCoursesByTerm($term: String!) {
19-
courses(where: { terms: { _ilike: $term } }) {
18+
query GetCoursesByTerm {
19+
courses {
2020
campus
2121
career
2222
faculty
2323
modes
2424
school
2525
course_code
2626
course_name
27+
year
2728
terms
2829
uoc
2930
}
@@ -42,13 +43,14 @@ const GET_COURSE_LIST = gql`
4243
* @example
4344
* const coursesList = await getCoursesList('T1')
4445
*/
45-
const getCoursesList = async (term: string): Promise<CoursesListWithDate> => {
46+
const getCoursesList = async (year: number, term: string): Promise<CoursesListWithDate> => {
4647
try {
4748
const termWithWildcard = `%${term}%`;
48-
const { data } = await client.query({ query: GET_COURSE_LIST, variables: { term: termWithWildcard } });
49+
const { data } = await client.query({ query: GET_COURSE_LIST });
50+
const courses = data.courses.filter((course: any) => course.terms.includes(term) && course.year === year);
4951

5052
return {
51-
courses: toCoursesList(data.courses),
53+
courses: toCoursesList(courses),
5254
};
5355
} catch (error) {
5456
throw new NetworkError('Could not connect to server');

client/src/components/controls/CustomEvent.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ const CustomEvent: React.FC = () => {
6565
useEffect(() => {
6666
const tutoringActivities = ['Tutorial', 'Laboratory', 'Tutorial-Laboratory', 'Workshop', 'Seminar', 'Project'];
6767
if (courseCode !== '') {
68-
getCourseInfo(term.substring(0, 2), courseCode, term.substring(2), isConvertToLocalTimezone)
68+
getCourseInfo(term.substring(0, 2), courseCode, parseInt(term.substring(2), 10), isConvertToLocalTimezone)
6969
.catch((err) => {
7070
return err;
7171
})

client/src/components/promotions/PromotionPopup.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ const StyledMedia = styled('img')`
4949
`;
5050

5151
// Note: this hard-coded value must be incremented for each new release of a promotional banner
52-
const CURRENT_PROMO_VERSION = 1;
52+
const CURRENT_PROMO_VERSION = 2;
5353
const NEW_FEATURE_PROMOTION_KEY = 'newfeatpromo';
5454

5555
const NewFeaturePromotion = ({ imgSrc, title, subTitle, bullets }: PromotionPopupProps) => {

client/src/constants/timetable.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,15 @@ export const getAvailableTermDetails = async () => {
127127
firstDayOfTerm =
128128
termMapInfo.get(currTermId)?.startDate?.toLocaleDateString().split('/').reverse().join('-') || 'default-date';
129129

130-
const termsSortedList: TermDataList = sortTerms(Array.from(termMapInfo.keys()));
130+
const termsSortedList: TermDataList = sortTerms(Array.from(termMapInfo.keys())).filter((termId) => {
131+
const term = termId.substring(0, 2);
132+
const termYear = parseInt(termId.substring(2), 10);
133+
if (termYear > parseInt(currTermId.substring(2), 10) && term !== 'U1' && term !== 'T1') {
134+
return false;
135+
}
136+
return true;
137+
});
138+
131139
// Store the term details in local storage.
132140
localStorage.setItem(
133141
'termData',

0 commit comments

Comments
 (0)