Skip to content

fix(navbar): make the dashboard links work on every page - #110

Merged
udaycodespace merged 1 commit into
udaycodespace:mainfrom
MOHITKOURAV01:fix/105-navbar-dashboard-links
Aug 27, 2026
Merged

fix(navbar): make the dashboard links work on every page#110
udaycodespace merged 1 commit into
udaycodespace:mainfrom
MOHITKOURAV01:fix/105-navbar-dashboard-links

Conversation

@MOHITKOURAV01

Copy link
Copy Markdown
Contributor

Summary

NavBar drove the dashboard by calling a prop only Dashboard.jsx passed. CourseContent.jsx renders the same component bare, so on the course player every dashboard link threw a TypeError and did nothing. This moves the panel into the URL, which fixes that and three related problems at once.

Related Issue

Closes #105

What changed?

  • frontend/src/lib/dashboardPanels.js (new) — the panel names, who may see each, and how a panel maps to and from a URL. Held as data so the navbar renders from the same source the dashboard validates against.
  • frontend/src/components/common/NavBar.jsx — takes no props. The three role links become real <Link> anchors; Home becomes a <Link> instead of an <a href>.
  • frontend/src/components/common/Dashboard.jsx — reads the panel from useSearchParams() through resolvePanel.
  • frontend/src/lib/dashboardPanels.test.js (new) — 26 tests.
  • docs/issue-105-navbar-dashboard-links.md (new) — write-up.

CourseContent.jsx is deliberately untouched — two open PRs (#81, #98) are already editing that file, and it should not have to pass a prop for the navbar to work anyway.

Four problems, one cause

The panel lived in one component's useState:

  1. The crash. setSelectedComponent was undefined anywhere but the dashboard. React Router runs the caller's onClick before its own click handling, so the throw also stopped the navigation — the link was dead, not just broken.
  2. Links that were not links. Those <NavLink> elements had no to. React Router resolves undefined against the current location, so they rendered as anchors pointing at the page you were already on: no middle click, no open-in-new-tab, no keyboard route that did not go through the broken handler.
  3. Home reloaded the document. A raw <a href="/dashboard"> inside a BrowserRouter tears down AuthProvider, BookmarksProvider and ThemeProvider and re-fetches everything.
  4. No panel had an address. Reloading /dashboard while on Add Course dropped the user back to the catalogue, and there was no URL to link or share.

One piece of dead code removed

case 'cousreSection':
   return <CourseContent />

Nothing could reach it — grep finds only the case, no caller ever set that name — and CourseContent reads :courseId and :courseTitle from the route, which /dashboard does not have, so it would have rendered a broken page if anything had. Removed rather than ported.

Type

  • Bug fix
  • New feature
  • Refactor
  • Docs only
  • Tests
  • Config / workflow
  • Security
  • Breaking change

Areas touched

  • Frontend
  • Backend
  • Database
  • Docs
  • Workflow / GitHub Actions
  • Config / environment

Testing

  • Tested locally
  • Build passes
  • Lint passes
  • Tests added or updated
  • Docs only, no runtime testing needed

cd frontend && npm test138 pass, 0 fail (112 before, 26 added).
cd frontend && npm run build → clean.

npm run lint does not pass on main either — 69 pre-existing problems, almost all no-unused-vars on React imports and missing react/prop-types. This PR adds none, and removes two now-unused imports.

Test steps

  1. Sign in as a teacher, open any course so you land on /courseSection/<id>/<title>, open the console, click Add Course.
    → You arrive at /dashboard?panel=addcourse. Before: Uncaught TypeError: setSelectedComponent is not a function, and nothing moved.
  2. Reload that URL → still the Add Course form. Before: back to the catalogue.
  3. Right-click Add CourseOpen link in new tab → the form opens in a new tab. Before: the page you were already on.
  4. Click Home → no full page reload; the providers stay mounted.
  5. Sign in as a student and type /dashboard?panel=addcourse by hand → the student catalogue, not the educator's form.
  6. Repeat step 1 as a student with Enrolled Courses, and as an admin with Courses.

Screenshots

  • Not needed
  • Added below

No visual change — the same links in the same place, now working.

Edge cases checked

  • Empty or missing data
  • Loading / slow response
  • API failure / server error
  • Rate limit / throttling
  • Invalid or unexpected input
  • Permission / access denied
  • Partial or inconsistent data
  • Mobile / small screen behavior
  • Other

Other edge case details

  • Hand-typed panel — the value now comes from the query string, so it is untrusted. normalizePanel returns '' for anything unrecognised, and resolvePanel falls back to home. Tested with ?panel=../../etc/passwd and ?panel=<script>.
  • Privilege via URL — a student typing ?panel=addcourse gets the catalogue. The role guards moved into canSeePanel and are checked on render, not only on the link.
  • Legacy role casingcanSeePanel goes through lib/roles, so an account still storing "Teacher" (pre-[Security]: Registration lets a client self-assign the admin role, and raw card details are persisted #55) matches, per [Bug]: The dashboard is blank for every account — the UI compares roles as "Teacher" while the API stores "teacher" #84.
  • Old panel namescousres and enrolledcourese are accepted as aliases, so a bookmarked or in-flight value keeps working and nothing needs coordinating across a deploy.
  • No usable rolevisiblePanelLinks returns an empty list rather than throwing, and the dashboard renders <UserHome />, which already explains itself for that case.
  • Round-trip — a test asserts every address panelPath produces is read back to the same panel by readPanelFromSearch.

Checklist

  • Read CONTRIBUTING.md
  • Linked the issue
  • Assigned before starting or approved by maintainer
  • Changes are focused on one issue
  • No debug logs or unused code
  • Documentation updated if needed
  • No new warnings or console errors
  • Changes are meaningful, not trivial

Notes

lib/dashboardPanels.js imports ./roles.js with the extension: Vite resolves either form, but node --test runs these modules as plain ESM and will not guess one.

The navbar and the dashboard previously kept two separate lists of panel-name string literals that had to agree by hand — and three of the four were misspelled. They now read the same PANEL_LINKS, so a panel cannot be advertised that the dashboard would refuse to open. There is a test asserting exactly that.

NavBar drove the dashboard by calling a setSelectedComponent prop that only
Dashboard.jsx passed. CourseContent.jsx renders the same component bare, so on
the course player — the page a student spends the whole course on — Add Course,
Courses and Enrolled Courses all threw "setSelectedComponent is not a function"
on click. React Router runs the caller's onClick before its own click handling,
so the throw stopped the navigation too and the link was simply dead.

The same three links carried no `to`. React Router resolves undefined against
the current location, so they rendered as anchors pointing at the page you were
already on: no middle click, no open-in-new-tab, no keyboard route that did not
go through the broken handler. Home was a raw anchor, which inside a
BrowserRouter is a full document load that tears down every provider.

The panel is part of the URL now. The navbar navigates like any other link and
takes no props, the links are real anchors, and each panel has an address that
survives a reload.

The panel list moves to lib/dashboardPanels, so the navbar renders from the same
data the dashboard validates against instead of two lists of string literals
that had to agree by hand. The old misspelled names are accepted as aliases.

Also removes an unreachable `case 'cousreSection'` from the switch: nothing ever
set that name, and CourseContent reads route params /dashboard does not have.
@udaycodespace
udaycodespace self-requested a review August 27, 2026 06:52
@udaycodespace udaycodespace added ECSoC26 Required label for a PR to be eligible for Sentinel scoring good-pr PA-awarded bonus for an exceptionally executed PR — +15 XP and removed frontend documentation fullstack tests labels Aug 27, 2026
@udaycodespace

Copy link
Copy Markdown
Owner

@MOHITKOURAV01 LGTM! Dashboard navigation is working properly across pages, and the tests are passing.

Approved.

@udaycodespace
udaycodespace merged commit f02cc41 into udaycodespace:main Aug 27, 2026
2 of 10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ECSoC26 Required label for a PR to be eligible for Sentinel scoring good-pr PA-awarded bonus for an exceptionally executed PR — +15 XP

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: The navbar's dashboard links throw a TypeError on every page that is not the dashboard

2 participants