Skip to content

Course planner page (/plan) with GPA calculator and degree checklists - #281

Draft
jerryzhou196 wants to merge 5 commits into
mainfrom
feat/course-planner
Draft

Course planner page (/plan) with GPA calculator and degree checklists#281
jerryzhou196 wants to merge 5 commits into
mainfrom
feat/course-planner

Conversation

@jerryzhou196

Copy link
Copy Markdown
Member

Frontend half of the course planner feature — requires backend PR UWFlow/uwflow#197 (transcript grades in the parse response + user_course_plan/checklist tables).

What it does

New /plan page (linked from the navbar):

  • Term grid populated from the transcript import: taken terms show a green "✓ taken" chip and per-term unit badges; future terms are generated by continuing the 1A–4B level sequence over Fall/Winter terms.
  • Plan future terms: add courses via search (reuses CourseSearchDropdown, generalized and moved to components/input/), remove, and drag courses between terms (native HTML5 DnD, no new dependency). Persisted in user_course_plan with optimistic UI; moves run as a single-transaction Hasura mutation.
  • Prerequisite warnings ("⚠ needs MATH 138") from structured course_prerequisite data — warns only when none of a course's prereqs appear in an earlier term, since the table flattens AND/OR.
  • GPA calculator on the OMSAS 4.0 scale (conversion table adapted from caseOfCamel/uwaterloo-gpa-calculator, whose own parsing is broken), credit-weighted, cumulative + per-term. Grades come from the extended /parse/transcript response and live only in localStorage — never sent to or stored on the server.
  • Degree requirement checklists: import any number of the backend-maintained checklists; per-category progress, "one of" alternatives, met items show the course that satisfied them.
  • First visit without a transcript shows the existing transcript-upload flow (same overlay pattern as the swap page); logged-out visitors get the login lock card.

Tailwind-only styling using the design tokens from AGENTS.md; no new styled-components.

Notes

  • Types for the new GraphQL documents are hand-written in graphql/queries/planner/Planner.tsx since codegen needs a live Hasura with the new migration; swap for generated types on the next bun run generate.
  • Deliberate simplifications are marked with ponytail: comments (default 0.5 units — the DB stores no per-course units; flat "one of" checklist requirements).

Testing

🤖 Generated with Claude Code

…ists

- New /plan page: transcript-imported terms in a grid (taken terms with
  unit badges), future terms through 4B with add/remove and native HTML5
  drag-and-drop between terms, persisted in user_course_plan via Hasura.
- Prerequisite warnings ("needs MATH 138") from structured
  course_prerequisite data; warns only when no alternative appears in an
  earlier term.
- GPA calculator on the OMSAS 4.0 scale, credit-weighted, computed from
  grades in the extended /parse/transcript response; grades are kept in
  localStorage only and never sent to the server.
- Degree requirement checklist sidebar: import any of the
  backend-maintained checklists, per-category progress with "one of"
  alternatives.
- CourseSearchDropdown generalized (moved to components/input) to search
  all courses when no term is given; reused for "Add course".
- Plan link in the navbar; grades saved from the transcript upload modal.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Jul 1, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
uwflow-frontend Ready Ready Preview, Comment Jul 14, 2026 3:01pm

The user_course_plan cache typePolicy keys rows by
(user_id, term_id, course_id), but the planner query didn't select
user_id — Apollo threw while normalizing the result, the query never
delivered data, and the page's `loading || !data` branch spun forever.

- select user_id in GET_PLANNER_DATA
- render an error state with a Retry button instead of spinning on
  query errors
- regression test: writeQuery of a getPlannerData result against the
  real cache config

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Vercel sets CI=true, which makes the CRA build treat eslint warnings as
errors; planner.ts had six no-non-null-assertion warnings.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
jerryzhou196 and others added 2 commits July 14, 2026 08:59
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Extract Card/CardHeader, LoginPromptCard, PageOverlay, and RemoveButton
from markup duplicated across the plan and swap pages; adopt the existing
ui/Button (accent variant) for all gold CTAs; replace the arbitrary
modal shadow with a named shadow-modal token.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant