Replace the throwaway planner scaffold with a term-by-term grid of course boxes, like a degree flowchart — where each box is an editable text field you type a course code into. This is the first, structural step — keep it minimal.
🧠 Context
The planner today is a temporary 2-column grid: src/pages/Planner.tsx renders a grid-cols-2 of TermCells, each with a single text input plus a list of added courses. This ticket replaces that with a proper term grid: columns for terms, and within each column a stack of fixed course slot boxes.
Think of the Carleton engineering flowchart layout (see reference image below): years across the top, Fall/Winter columns under each, and a grid of course boxes lining up in rows. The difference for our MVP: instead of pre-filled tiles, each box is an empty text field the student types a course code into. (Drag-and-drop course tiles onto slots is a deliberate later ticket — text boxes stand in for now. We're not rendering arrows between courses yet either.)
The data model is already shaped for this. Each Term (in src/store/plannerStore.ts) carries structured year: number and season: 'fall' | 'winter' | 'summer', and termLabel(term) derives the display string — so the year grouping and Fall/Winter sub-labels come straight from the data; don't parse them out of a label string.
Keep this version minimal: a grid of typeable boxes (see out of scope below)
🛠️ Target layout
- Year headers across the top ("First Year", "Second Year", …), each split into Fall / Winter sub-columns (derived from
term.year / term.season).
- One column per term, ordered earliest-first.
- Within each column, a fixed number of course slot boxes stacked vertically, aligned in rows across columns so the grid lines up.
- Each slot box is a text input. A filled box shows its course code (still editable); an empty box is blank and typeable. All boxes look the same.
🛠️ Implementation Plan
- Rework
src/pages/Planner.tsx from the grid-cols-2 into the term grid above, driven by the terms array — never hardcode 8 columns. Group columns by term.year for the year header band, with the season as the sub-label.
- Render a fixed number of slot boxes per column (pick a sensible default, e.g. 5). Each box is a controlled text input.
- Wire the boxes to the store: typing a course code into a box and committing (blur / Enter) sets that course in the term; clearing a box removes it. You'll likely want a small store action to set/clear the course at a given slot — see if you can adapt the existing
addCourse / removeEntry in plannerStore.ts (TermCell.tsx shows the current add/remove pattern to build from). You can also just make your own implementation depending on what makes sense as you build this out, the scaffold may/may not be compatible.
- Keep boxes aligned in rows across columns so it reads as a grid.
- Responsive: allow horizontal scrolling on narrow screens so the layout doesn't break, or some other mobile friendly UI.
- Run
pnpm dev to check it, then pnpm typecheck, pnpm test, pnpm lint.
🚫 Out of scope (future enhancements)
- Drag-and-drop course tiles onto slots — the text boxes are the stand-in for now.
- Elective / "choose" entries, and any preset courses or categories — boxes only hold a typed course code; don't render the
elective / choose entry kinds.
- Prerequisite validation — no violation list or validation banner in this version; it returns in a later ticket.
- Prereq connector lines between boxes (the dependency arrows in the flowchart).
- Add / remove terms and slots (summer terms, year 5+, variable course counts) — additive follow-up; the
Term model already supports it.
✅ Acceptance Criteria
Replace the throwaway planner scaffold with a term-by-term grid of course boxes, like a degree flowchart — where each box is an editable text field you type a course code into. This is the first, structural step — keep it minimal.
🧠 Context
The planner today is a temporary 2-column grid:
src/pages/Planner.tsxrenders agrid-cols-2ofTermCells, each with a single text input plus a list of added courses. This ticket replaces that with a proper term grid: columns for terms, and within each column a stack of fixed course slot boxes.Think of the Carleton engineering flowchart layout (see reference image below): years across the top, Fall/Winter columns under each, and a grid of course boxes lining up in rows. The difference for our MVP: instead of pre-filled tiles, each box is an empty text field the student types a course code into. (Drag-and-drop course tiles onto slots is a deliberate later ticket — text boxes stand in for now. We're not rendering arrows between courses yet either.)
The data model is already shaped for this. Each
Term(insrc/store/plannerStore.ts) carries structuredyear: numberandseason: 'fall' | 'winter' | 'summer', andtermLabel(term)derives the display string — so the year grouping and Fall/Winter sub-labels come straight from the data; don't parse them out of a label string.Keep this version minimal: a grid of typeable boxes (see out of scope below)
🛠️ Target layout
term.year/term.season).🛠️ Implementation Plan
src/pages/Planner.tsxfrom thegrid-cols-2into the term grid above, driven by thetermsarray — never hardcode 8 columns. Group columns byterm.yearfor the year header band, with the season as the sub-label.addCourse/removeEntryinplannerStore.ts(TermCell.tsxshows the current add/remove pattern to build from). You can also just make your own implementation depending on what makes sense as you build this out, the scaffold may/may not be compatible.pnpm devto check it, thenpnpm typecheck,pnpm test,pnpm lint.🚫 Out of scope (future enhancements)
elective/chooseentry kinds.Termmodel already supports it.✅ Acceptance Criteria
termsarray (no hardcoded count of 8)pnpm typecheck,pnpm test, andpnpm lintpass