@@ -5,159 +5,159 @@ import { supabase } from "../db/setupDb";
55const DEFAULT_COURSE_LIMIT = 1000 ;
66
77export default {
8- /**
9- * Get a list of courses based on various query parameters.
10- *
11- * @param {Request } req - The request object containing query parameters.
12- * @param {Response } res - The response object to send the filtered courses.
13- * @returns {Promise<Response> } - The response object with the filtered courses.
14- */
15- getCourses : asyncHandler ( async ( req : Request , res : Response ) => {
16- try {
17- // Get the query parameters
18- const {
19- limit,
20- search,
21- semester,
22- breadthRequirement,
23- creditWeight,
24- department,
25- yearLevel,
26- } = req . query ;
27-
28- // Query the courses, offerings tables from the database
29- let coursesQuery = supabase
30- . schema ( "course" )
31- . from ( "courses" )
32- . select ( )
33- . limit ( Number ( limit || DEFAULT_COURSE_LIMIT ) ) ;
34-
35- if ( ( search as string ) ?. trim ( ) ) {
36- coursesQuery = coursesQuery . or (
37- `code.ilike.%${ search } %,name.ilike.%${ search } %`
38- ) ;
39- }
40- let offeringsQuery = supabase . schema ( "course" ) . from ( "offerings" ) . select ( ) ;
41-
42- // Get the data and errors from the queries
43- const { data : coursesData , error : coursesError } = await coursesQuery ;
44- const { data : offeringsData , error : offeringsError } =
45- await offeringsQuery ;
46-
47- // Set the courses and offerings data
48- const courses = coursesData || [ ] ;
49- const offerings = offeringsData || [ ] ;
50-
51- // Create a map of course codes to semesters.
52- const courseCodesToSemestersMap : { [ key : string ] : string [ ] } = { } ;
53- offerings . forEach ( ( offering ) => {
54- const courseCode = offering . code ;
55- const semester = offering . offering ;
56- if ( courseCodesToSemestersMap [ courseCode ] ) {
57- courseCodesToSemestersMap [ courseCode ] . push ( semester ) ;
58- } else {
59- courseCodesToSemestersMap [ courseCode ] = [ semester ] ;
60- }
61- } ) ;
62-
63- // Filter the courses based on the breadth requirement, credit weight, semester, department, and year level
64- let filteredCourses = courses ;
65- if ( breadthRequirement ) {
66- filteredCourses = filteredCourses . filter ( ( course ) => {
67- return course . breadth_requirement === breadthRequirement ;
68- } ) ;
69- }
70- if ( creditWeight ) {
71- filteredCourses = filteredCourses . filter ( ( course ) => {
72- const courseCreditWeight =
73- course . code [ course . code . length - 2 ] === "H" ? 0.5 : 1 ;
74- return courseCreditWeight === Number ( creditWeight ) ;
75- } ) ;
76- }
77- if ( semester ) {
78- filteredCourses = filteredCourses . filter ( ( course ) => {
79- return courseCodesToSemestersMap [ course . code ] ?. includes (
80- semester as string
81- ) ;
82- } ) ;
83- }
84- if ( department ) {
85- filteredCourses = filteredCourses . filter ( ( course ) => {
86- const courseDepartment = course . code . substring ( 0 , 3 ) ;
87- return courseDepartment === department ;
88- } ) ;
89- }
90- if ( yearLevel ) {
91- filteredCourses = filteredCourses . filter ( ( course ) => {
92- const courseYearLevel =
93- course . code . charCodeAt ( 3 ) - "A" . charCodeAt ( 0 ) + 1 ;
94- return courseYearLevel === Number ( yearLevel ) ;
95- } ) ;
96- }
97-
98- // Return the filtered courses
99- return res . status ( 200 ) . send ( filteredCourses ) ;
100- } catch ( err ) {
101- return res . status ( 500 ) . send ( { err } ) ;
102- }
103- } ) ,
104-
105- /**
106- * Gets the total number of sections for a list of courses.
107- *
108- * @param {Request } req - The request object containing query parameters.
109- * @param {Response } res - The response object to send the total number of sections.
110- * @returns {Promise<Response> } - The response object with the total number of sections.
111- *
112- */
113- getNumberOfSections : asyncHandler ( async ( req : Request , res : Response ) => {
114- try {
115- const { course_ids, semester } = req . query ;
116-
117- if ( ! course_ids || ! semester ) {
118- return res . status ( 400 ) . send ( {
119- error : "Missing required parameters: course_ids, semester" ,
120- } ) ;
121- }
122-
123- const course_ids_array = ( course_ids as string ) . split ( "," ) ;
124-
125- let totalNumberOfCourseSections = 0 ;
126- const promises = course_ids_array . map ( async ( course_id ) => {
127- const { data : courseOfferingsData , error : courseOfferingsError } =
128- await supabase
129- . schema ( "course" )
130- . from ( "offerings" )
131- . select ( )
132- . eq ( "course_id" , course_id )
133- . eq ( "offering" , semester ) ;
134-
135- const offerings = courseOfferingsData || [ ] ;
136-
137- const hasLectures = offerings . some ( ( offering ) =>
138- offering . meeting_section . startsWith ( "LEC" )
139- ) ;
140- const hasTutorials = offerings . some ( ( offering ) =>
141- offering . meeting_section . startsWith ( "TUT" )
142- ) ;
143- const hasPracticals = offerings . some ( ( offering ) =>
144- offering . meeting_section . startsWith ( "PRA" )
145- ) ;
146- if ( hasLectures ) {
147- totalNumberOfCourseSections += 1 ;
148- }
149- if ( hasTutorials ) {
150- totalNumberOfCourseSections += 1 ;
151- }
152- if ( hasPracticals ) {
153- totalNumberOfCourseSections += 1 ;
154- }
155- } ) ;
156-
157- await Promise . all ( promises ) ;
158- return res . status ( 200 ) . send ( { totalNumberOfCourseSections } ) ;
159- } catch ( err ) {
160- return res . status ( 500 ) . send ( { err } ) ;
161- }
162- } ) ,
8+ /**
9+ * Get a list of courses based on various query parameters.
10+ *
11+ * @param {Request } req - The request object containing query parameters.
12+ * @param {Response } res - The response object to send the filtered courses.
13+ * @returns {Promise<Response> } - The response object with the filtered courses.
14+ */
15+ getCourses : asyncHandler ( async ( req : Request , res : Response ) => {
16+ try {
17+ // Get the query parameters
18+ const {
19+ limit,
20+ search,
21+ semester,
22+ breadthRequirement,
23+ creditWeight,
24+ department,
25+ yearLevel,
26+ } = req . query ;
27+
28+ // Query the courses, offerings tables from the database
29+ let coursesQuery = supabase
30+ . schema ( "course" )
31+ . from ( "courses" )
32+ . select ( )
33+ . limit ( Number ( limit || DEFAULT_COURSE_LIMIT ) ) ;
34+
35+ if ( ( search as string ) ?. trim ( ) ) {
36+ coursesQuery = coursesQuery . or (
37+ `code.ilike.%${ search } %,name.ilike.%${ search } %` ,
38+ ) ;
39+ }
40+ let offeringsQuery = supabase . schema ( "course" ) . from ( "offerings" ) . select ( ) ;
41+
42+ // Get the data and errors from the queries
43+ const { data : coursesData , error : coursesError } = await coursesQuery ;
44+ const { data : offeringsData , error : offeringsError } =
45+ await offeringsQuery ;
46+
47+ // Set the courses and offerings data
48+ const courses = coursesData || [ ] ;
49+ const offerings = offeringsData || [ ] ;
50+
51+ // Create a map of course codes to semesters.
52+ const courseCodesToSemestersMap : { [ key : string ] : string [ ] } = { } ;
53+ offerings . forEach ( ( offering ) => {
54+ const courseCode = offering . code ;
55+ const semester = offering . offering ;
56+ if ( courseCodesToSemestersMap [ courseCode ] ) {
57+ courseCodesToSemestersMap [ courseCode ] . push ( semester ) ;
58+ } else {
59+ courseCodesToSemestersMap [ courseCode ] = [ semester ] ;
60+ }
61+ } ) ;
62+
63+ // Filter the courses based on the breadth requirement, credit weight, semester, department, and year level
64+ let filteredCourses = courses ;
65+ if ( breadthRequirement ) {
66+ filteredCourses = filteredCourses . filter ( ( course ) => {
67+ return course . breadth_requirement === breadthRequirement ;
68+ } ) ;
69+ }
70+ if ( creditWeight ) {
71+ filteredCourses = filteredCourses . filter ( ( course ) => {
72+ const courseCreditWeight =
73+ course . code [ course . code . length - 2 ] === "H" ? 0.5 : 1 ;
74+ return courseCreditWeight === Number ( creditWeight ) ;
75+ } ) ;
76+ }
77+ if ( semester ) {
78+ filteredCourses = filteredCourses . filter ( ( course ) => {
79+ return courseCodesToSemestersMap [ course . code ] ?. includes (
80+ semester as string ,
81+ ) ;
82+ } ) ;
83+ }
84+ if ( department ) {
85+ filteredCourses = filteredCourses . filter ( ( course ) => {
86+ const courseDepartment = course . code . substring ( 0 , 3 ) ;
87+ return courseDepartment === department ;
88+ } ) ;
89+ }
90+ if ( yearLevel ) {
91+ filteredCourses = filteredCourses . filter ( ( course ) => {
92+ const courseYearLevel =
93+ course . code . charCodeAt ( 3 ) - "A" . charCodeAt ( 0 ) + 1 ;
94+ return courseYearLevel === Number ( yearLevel ) ;
95+ } ) ;
96+ }
97+
98+ // Return the filtered courses
99+ return res . status ( 200 ) . send ( filteredCourses ) ;
100+ } catch ( err ) {
101+ return res . status ( 500 ) . send ( { err } ) ;
102+ }
103+ } ) ,
104+
105+ /**
106+ * Gets the total number of sections for a list of courses.
107+ *
108+ * @param {Request } req - The request object containing query parameters.
109+ * @param {Response } res - The response object to send the total number of sections.
110+ * @returns {Promise<Response> } - The response object with the total number of sections.
111+ *
112+ */
113+ getNumberOfSections : asyncHandler ( async ( req : Request , res : Response ) => {
114+ try {
115+ const { course_ids, semester } = req . query ;
116+
117+ if ( ! course_ids || ! semester ) {
118+ return res . status ( 400 ) . send ( {
119+ error : "Missing required parameters: course_ids, semester" ,
120+ } ) ;
121+ }
122+
123+ const course_ids_array = ( course_ids as string ) . split ( "," ) ;
124+
125+ let totalNumberOfCourseSections = 0 ;
126+ const promises = course_ids_array . map ( async ( course_id ) => {
127+ const { data : courseOfferingsData , error : courseOfferingsError } =
128+ await supabase
129+ . schema ( "course" )
130+ . from ( "offerings" )
131+ . select ( )
132+ . eq ( "course_id" , course_id )
133+ . eq ( "offering" , semester ) ;
134+
135+ const offerings = courseOfferingsData || [ ] ;
136+
137+ const hasLectures = offerings . some ( ( offering ) =>
138+ offering . meeting_section . startsWith ( "LEC" ) ,
139+ ) ;
140+ const hasTutorials = offerings . some ( ( offering ) =>
141+ offering . meeting_section . startsWith ( "TUT" ) ,
142+ ) ;
143+ const hasPracticals = offerings . some ( ( offering ) =>
144+ offering . meeting_section . startsWith ( "PRA" ) ,
145+ ) ;
146+ if ( hasLectures ) {
147+ totalNumberOfCourseSections += 1 ;
148+ }
149+ if ( hasTutorials ) {
150+ totalNumberOfCourseSections += 1 ;
151+ }
152+ if ( hasPracticals ) {
153+ totalNumberOfCourseSections += 1 ;
154+ }
155+ } ) ;
156+
157+ await Promise . all ( promises ) ;
158+ return res . status ( 200 ) . send ( { totalNumberOfCourseSections } ) ;
159+ } catch ( err ) {
160+ return res . status ( 500 ) . send ( { err } ) ;
161+ }
162+ } ) ,
163163} ;
0 commit comments