BankPanel.jsx UI component

The right sidebar. Toggles between two views: a searchable course bank (unplaced courses) and the graduation requirements panel. Also contains the placed-out section, substitution UI, and a user-resizable width handle.

Parent
Lines
~850
Children rendered
CourseCard (bank), GradPanel (grad tab)

View structure

graph TD BP["BankPanel"] BP --> TAB["Tab bar: 📚 Bank | 🎓 Grad"] TAB -->|"Bank tab"| BV["Course Bank View"] TAB -->|"Grad tab"| GP["GradPanel"] BV --> SEARCH["🔍 Search + Sort controls"] BV --> TABS2["All | Starred | Search results"] BV --> GROUPS["Course groups by subject"] GROUPS --> CC["CourseCard ×N (bank mode)"] BV --> COOP["Co-op/Internship templates"] BV --> PO["Placed-out section (collapsible)"] BV --> SUB["Substitution UI"]

Course bank — filtering and sorting

bankSearch
string
Current search query. Fuzzy-matched against course.id (e.g. "CS3500") and course.title. Stored in PlannerContext so the search state persists when switching tabs.
bankTab
string
"all" | "starred" | "search". Controls which course subset is shown.
bankSort
string
"az" | "za" | "shAsc" | "shDesc". Applied after filtering.

Courses are grouped by subject code (e.g., all "CS" courses under one header) when in "all" mode. In "search" and "starred" modes, they're shown as a flat list in the selected sort order.

Co-op and internship templates

Fixed blocks at the bottom of the bank, always visible regardless of search. Defined in constants.js → COOP_TERMS / INTERNSHIP_TERMS. Dragging one of these into a semester creates a work/internship block rather than a course placement. They're identified by a special prefix in their ID ("coop-" or "int-").

Placed-out section

Courses in placedOut are shown in a collapsible list at the bottom. They can be dragged back into semesters or back into the bank. Clicking the ✕ on a placed-out card calls onDropBank(courseId) to return it.

Substitution UI

Two search fields: "From course" and "To course." Setting both calls addSubstitution({ from, to }) in context. The substitution means "I took FROM, let it count as TO in graduation requirements." Stored as substitutions array in plan state.

Resizable width

A drag handle on the left edge of BankPanel lets users adjust the sidebar width. The width is stored in bankWidth (context state, persisted to localStorage). Min: 200px, max: 500px. Implemented with a mousedown / mousemove listener on the handle div.