Skip to content

Commit f6aa05c

Browse files
author
hselvaka
committed
Prereq implementation
1 parent 8f5c28f commit f6aa05c

1 file changed

Lines changed: 100 additions & 2 deletions

File tree

src/components/CourseDetailPanel.tsx

Lines changed: 100 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { Course } from '@/types/course';
1+
import type { Course, Prereq } from '@/types/course';
22
import { useEffect, useRef } from 'react';
33

44
interface 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 &ge; {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+
1995
export 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

Comments
 (0)