1- import type { Course } from '@/types/course' ;
1+ import type { Course , Prereq } from '@/types/course' ;
22import { useEffect , useRef } from 'react' ;
33
44interface Props {
@@ -16,6 +16,82 @@ interface Props {
1616// open/close behaviour (renders nothing when `course` is null), and the drawer
1717// shell. Rendering the actual course fields and styling is in scope for the ticket.
1818
19+ function renderPrereq ( node : Prereq , isRoot : boolean ) : React . ReactNode {
20+ switch ( node . kind ) {
21+ case 'course' : {
22+ if ( node . minGrade !== undefined ) {
23+ return (
24+ < span className = "break-words" >
25+ { node . code } [Grade ≥ { node . minGrade } ]
26+ </ span >
27+ ) ;
28+ }
29+
30+ return < span className = "break-words" > { node . code } </ span > ;
31+ }
32+
33+ case 'all' : {
34+ if ( node . of . length === 1 ) {
35+ return renderPrereq ( node . of [ 0 ] , false ) ;
36+ }
37+
38+ return (
39+ < >
40+ < p > { isRoot ? 'Complete all of the following: ' : 'All of: ' } </ p >
41+ < ul className = "list-disc pl-5 space-y-1" >
42+ { node . of . map ( ( prereq : Prereq ) => (
43+ < li > { renderPrereq ( prereq , false ) } </ li >
44+ ) ) }
45+ </ ul >
46+ </ >
47+ ) ;
48+ }
49+
50+ case 'any' : {
51+ if ( node . of . length === 1 ) {
52+ return renderPrereq ( node . of [ 0 ] , false ) ;
53+ }
54+
55+ return (
56+ < >
57+ < p > { isRoot ? 'Complete any of the following: ' : 'Any of: ' } </ p >
58+ < ul className = "list-disc pl-5 space-y-1" >
59+ { node . of . map ( ( prereq : Prereq ) => (
60+ < li > { renderPrereq ( prereq , false ) } </ li >
61+ ) ) }
62+ </ ul >
63+ </ >
64+ ) ;
65+ }
66+
67+ case 'credits' : {
68+ return (
69+ < >
70+ < p >
71+ { isRoot
72+ ? `Complete ${ node . credits } credit(s) from:`
73+ : `${ node . credits } credit(s) from:` }
74+ </ p >
75+ < ul className = "list-disc pl-5 space-y-1" >
76+ { node . from . map ( ( prereq : Prereq ) => (
77+ < li > { renderPrereq ( prereq , false ) } </ li >
78+ ) ) }
79+ </ ul >
80+ </ >
81+ ) ;
82+ }
83+
84+ case 'raw' : {
85+ return < span className = "italic text-gray-500" > { node . text } </ span > ;
86+ }
87+
88+ default : {
89+ const _exhaustive : never = node ;
90+ return _exhaustive ;
91+ }
92+ }
93+ }
94+
1995export default function CourseDetailPanel ( { course, onClose } : Props ) {
2096 const panelRef = useRef < HTMLElement > ( null ) ;
2197 const prevFocusRef = useRef < HTMLElement | null > ( null ) ;
@@ -84,10 +160,32 @@ export default function CourseDetailPanel({ course, onClose }: Props) {
84160 </ div >
85161 ) }
86162
163+ { course . prereqRaw && course . prereq && (
164+ < div >
165+ < h3 className = "font-semibold mb-2" > Prerequisite(s)</ h3 >
166+ < h4 className = "font-semibold ml-3" > Calendar text</ h4 >
167+ < p className = "ml-6 mb-2" > { course . prereqRaw } </ p >
168+ { course . prereq . kind !== 'raw' && (
169+ < >
170+ < h4 className = "font-semibold ml-3" > Structured view</ h4 >
171+ < div className = "ml-6" > { renderPrereq ( course . prereq , true ) } </ div >
172+ </ >
173+ ) }
174+ </ div >
175+ ) }
176+
87177 { course . prereqRaw && (
178+ < div >
179+ < h3 className = "font-semibold mb-2" > Prerequisite(s)</ h3 >
180+ < h4 className = "font-semibold ml-3" > Calendar text</ h4 >
181+ < p className = "ml-6 mb-2" > { course . prereqRaw } </ p >
182+ </ div >
183+ ) }
184+
185+ { course . prereqRaw === '' && course . prereq === null && (
88186 < div >
89187 < h3 className = "font-semibold" > Prerequisite(s)</ h3 >
90- < p > { course . prereqRaw } </ p >
188+ < p className = "ml-4" > None </ p >
91189 </ div >
92190 ) }
93191 </ div >
0 commit comments