11import CourseGraph from './CourseGraph' ;
22import { getAllCourses , getCourseByDeptAndNumber } from '../../../../../utils/courseApi' ;
3+ import { fetchOutlines } from '../../../../../utils/sfuOutlinesApi' ;
34
45interface PageProps {
56 params : Promise < {
@@ -11,61 +12,74 @@ interface PageProps {
1112// Generate static paths for all courses from API
1213export async function generateStaticParams ( ) {
1314 try {
14- const courses = await getAllCourses ( ) ;
15- const params = courses . map ( ( course ) => ( {
16- // Keep original casing to match links like /sfu/courses/CMPT/105W
17- dept : String ( course . dept ) ,
18- number : String ( course . number ) ,
15+ // Prefer official outlines API to enumerate ALL courses
16+ const outlines = await fetchOutlines ( ) ;
17+ const params = outlines . map ( ( o ) => ( {
18+ dept : String ( o . dept ) . toLowerCase ( ) ,
19+ number : String ( o . number ) . toLowerCase ( ) ,
1920 } ) ) ;
20- console . log ( `Generated ${ params . length } static params for courses` ) ;
21+ // Fallback: if outlines unexpectedly empty, use crowdsourced list
22+ if ( params . length === 0 ) {
23+ const courses = await getAllCourses ( ) ;
24+ return courses . map ( ( course ) => ( { dept : String ( course . dept ) . toLowerCase ( ) , number : String ( course . number ) . toLowerCase ( ) } ) ) ;
25+ }
2126 return params ;
2227 } catch ( error ) {
23- console . error ( 'Error generating static params:' , error ) ;
24- return [ ] ;
28+ console . error ( 'Error generating static params from outlines:' , error ) ;
29+ try {
30+ const courses = await getAllCourses ( ) ;
31+ return courses . map ( ( course ) => ( { dept : String ( course . dept ) . toLowerCase ( ) , number : String ( course . number ) . toLowerCase ( ) } ) ) ;
32+ } catch ( e ) {
33+ console . error ( 'Error falling back to crowdsourced params:' , e ) ;
34+ return [ ] ;
35+ }
2536 }
2637}
2738
2839// With static export, only the paths from generateStaticParams are valid
29- // export const dynamicParams = false;
40+ export const dynamicParams = false ;
3041// Ensure this route is fully static
31- // export const revalidate = false;
42+ export const revalidate = false ;
3243
3344export default async function CoursePage ( { params } : PageProps ) {
3445 const resolvedParams = await params ;
35- const courseId = `${ resolvedParams . dept . toUpperCase ( ) } ${ resolvedParams . number } ` ;
36-
37- // Fetch the course and all courses from API at build time
38- const [ course , allCourses ] = await Promise . all ( [
39- getCourseByDeptAndNumber ( resolvedParams . dept , resolvedParams . number ) ,
40- getAllCourses ( )
46+ const courseId = `${ resolvedParams . dept . toUpperCase ( ) } ${ resolvedParams . number . toUpperCase ( ) } ` ;
47+
48+ // Fetch the crowdsourced data (may not include every course)
49+ const [ allCourses , course ] = await Promise . all ( [
50+ getAllCourses ( ) ,
51+ getCourseByDeptAndNumber ( resolvedParams . dept , resolvedParams . number . toUpperCase ( ) ) ,
4152 ] ) ;
4253
54+ // If this course exists in outlines but not in our crowdsourced data, show a helpful message
4355 if ( ! course ) {
4456 return (
4557 < div className = "flex items-center justify-center h-screen bg-white dark:bg-black" >
46- < div className = "text-center" >
47- < h1 className = "text-2xl font-bold text-gray-900 dark:text-white mb-4 " >
48- Course Not Found
58+ < div className = "text-center px-6 max-w-xl " >
59+ < h1 className = "text-2xl font-bold text-gray-900 dark:text-white mb-3 " >
60+ No prerequisite data yet
4961 </ h1 >
50- < p className = "text-gray-600 dark:text-gray-400 " >
51- No prerequisite data available for { courseId }
62+ < p className = "text-gray-700 dark:text-gray-300 mb-2 " >
63+ We have not yet parsed { courseId } .
5264 </ p >
5365 < p className = "text-gray-600 dark:text-gray-400" >
54- Contribute today at{ ' ' }
66+ You can help by contributing at
67+ { ' ' }
5568 < a
5669 href = "https://crowdsource.sfucourses.com"
5770 target = "_blank"
5871 rel = "noopener noreferrer"
59- className = "text-blue-500 hover:underline "
72+ className = "underline hover:opacity-80 "
6073 >
6174 crowdsource.sfucourses.com
62- </ a >
75+ </ a > .
6376 </ p >
6477 </ div >
6578 </ div >
6679 ) ;
6780 }
6881
82+ // Render the graph regardless; the component will indicate when data is missing for a course
6983 return (
7084 < div className = "w-full h-screen bg-white dark:bg-black" >
7185 < CourseGraph courseId = { courseId } courses = { allCourses } />
0 commit comments