context/ State layer

The bridge between UI and logic. Two React Contexts: PlannerContext owns all application state (placements, drag-drop, undo, plans), and ThemeContext manages CSS variable injection. Every UI component reads from here — nothing else.

Parent
Imports from
core/, data/
Consumed by
All UI components via usePlanner() / useTheme()

Children

How UI components consume context

graph LR PC["PlannerContext"] TC["ThemeContext"] PC -->|"usePlanner()"| H["Header"] PC -->|"usePlanner()"| BP["BankPanel"] PC -->|"usePlanner()"| GP["GradPanel"] PC -->|"usePlanner()"| SR["SemRow / SummerRow"] PC -->|"usePlanner()"| CC["CourseCard"] PC -->|"usePlanner()"| IP["InfoPanel"] TC -->|"useTheme()"| H TC -->|"useTheme()"| App["App.jsx"] style PC fill:#fbefff,stroke:#8250df style TC fill:#fbefff,stroke:#8250df
Every UI component calls usePlanner(). ThemeContext is only read by App.jsx and Header.

The no-prop-drilling contract

No component passes state down via props (except trivial configuration like semId to a row). All shared state comes from usePlanner(). This makes it easy to add features — any component can read or mutate any state without threading props through the tree.

The trade-off: adding new state means editing PlannerContext.jsx, which is already large. When adding state, check first whether it belongs in the context (shared across components) or as local component state (only needed in one place).

Context initialization sequence

sequenceDiagram participant App participant TC as ThemeContext participant PC as PlannerContext participant CL as courseLoader participant PS as persistence App->>TC: mount ThemeProvider TC->>TC: read ncp-theme from localStorage TC->>TC: inject CSS variables onto <html> App->>PC: mount PlannerProvider PC->>PS: loadSaved() PS-->>PC: saved plan state (or defaults) PC->>PC: hydrate placements, cohort, major, etc. PC->>CL: fetchCourses() CL-->>PC: Course[] (from all-courses.json) PC->>PC: normalize → courseMap PC->>PC: compute derived state (SEMESTERS, violations)
Startup sequence. Theme is injected synchronously; courses load asynchronously.