majorLoader.js + minorLoader.js Data adapters

Async-fetch graduation requirement trees from the graduatenu/ fork. Requirements are not bundled — they're fetched on demand when a user selects a major. Also provides the grouped option lists for the major/minor search dropdowns.

Parent
Called by
GradPanel.jsx (on major/minor selection)
Source data
graduatenu/packages/api/src/major/majors/**/*.json

graduatenu/ fork structure

graph TD A["graduatenu/\npackages/api/src/major/"] --> B["majors/"] A --> C["minors/"] B --> D["{year}/\ne.g. 2024/"] D --> E["{college-slug}/\ne.g. computer-information-science/"] E --> F["{major-slug}/\ne.g. computer_science_bscs/"] F --> G["parsed.initial.json\n← the requirement tree"] F --> H["concentrations/\n{conc-slug}/parsed.initial.json"]
File layout. loadMajor(path) fetches the parsed.initial.json at the given path.

Exported functions — majorLoader.js

loadMajor(path) → Promise<Major2>
Fetches a major's requirement tree JSON from {BASE_URL}{path}. The path argument is the relative path within the public/ directory, e.g. "graduatenu/packages/api/src/major/majors/2024/computer-information-science/computer_science_bscs/parsed.initial.json".
Returns: Promise<Major2> — the requirement tree JSON
getMajorOptionGroups() → OptionGroup[]
Reads the generated major index and returns a grouped option structure for the SearchCombo dropdown in GradPanel. Grouped by: location → college → major name → catalog year → optional concentrations.
Returns: OptionGroup[] — hierarchical dropdown data

Exported functions — minorLoader.js

loadMinor(path) → Promise<Minor2>
Identical to loadMajor() but for minor requirement files under graduatenu/.../minors/.
getMinorOptionGroups() → OptionGroup[]
Same structure as getMajorOptionGroups() but for minors.

Major2 schema (what loadMajor returns)

{
  "name": "Computer Science BSCS",
  "requirementSections": [
    {
      "title": "CS Required Courses",
      "requirements": [
        { "type": "COURSE", "classId": 3500, "subject": "CS" },
        {
          "type": "XOM", "numCreditsMin": 8,
          "courses": [
            { "type": "RANGE", "subject": "CS", "idRangeStart": 2500, "idRangeEnd": 9999 }
          ]
        }
      ],
      "minRequirementCount": 5
    },
    {
      "title": "Required General Electives",
      "requirements": [],
      "minRequirementCount": 0,
      "creditHoursRequired": 28   // may or may not be present
    }
  ]
}
⚠️
Parser inconsistencies: The upstream graduatenu scraper generates inconsistent structures across catalog years. See gradRequirements.js for the two known bugs and how they're fixed (one in data, one in code).