Skip to content

Roadmap fixed - #8

Merged
Niro0526 merged 3 commits into
masterfrom
niroja
Sep 8, 2026
Merged

Niro0526 merged 3 commits into
masterfrom
niroja

Conversation

@Niro0526

@Niro0526 Niro0526 commented Sep 8, 2026

Copy link
Copy Markdown
Collaborator

No description provided.

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Expand roadmaps, historical cutoffs, and student settings

✨ Enhancement 🐞 Bug fix 📝 Documentation ⚙️ Configuration changes 🕐 40+ Minutes

Grey Divider

AI Description

• Expands AI roadmaps with resilient Gemini fallback and richer Sri Lankan career guidance.
• Adds multi-year handbook cutoffs, searchable courses, and historical trend displays.
• Introduces unified settings, profile preferences, themes, and a redesigned dashboard.
Diagram

graph TD
  U["Student"] --> S["App Shell"] --> D["Dashboard Settings"] --> A["Backend APIs"]
  S --> R["Roadmap Courses"] --> A --> G["Gemini Models"]
  H[("Handbook Data")] --> A
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Backend-backed settings and account management
  • ➕ Synchronizes preferences across devices instead of relying primarily on browser storage.
  • ➕ Makes password changes, deactivation, and deletion perform real authenticated operations.
  • ➕ Provides a single authoritative profile model for recommendations and roadmap personalization.
  • ➖ Requires database migrations and additional authenticated endpoints.
  • ➖ Increases delivery scope and requires careful authorization and account-recovery design.

Recommendation: Keep the handbook and roadmap reliability approach, including multi-year normalization and Gemini fallback. Before presenting account controls as complete, back password changes, deactivation, deletion, notifications, and recommendation preferences with authenticated APIs; retain local persistence only for guest defaults and appearance settings.

Files changed (21) +3086 / -649

Enhancement (12) +2435 / -361
normalize-handbook-2025.tsNormalize cutoff data from three academic years +14/-4

Normalize cutoff data from three academic years

• Loads and combines staging records for 2024/25, 2023/24, and 2022/23 cutoffs instead of using only the latest source.

backend/src/db/normalize-handbook-2025.ts

saved.tsImprove recent-search storage and management +34/-10

Improve recent-search storage and management

• Returns up to five case-insensitive unique searches, rejects undersized queries, and trims stored search text. Adds an authenticated endpoint for clearing a user's complete search history.

backend/src/routes/saved.ts

App.tsxRegister the unified settings route +2/-0

Register the unified settings route

• Adds the new settings page at '/settings' while retaining the existing profile route.

frontend/src/App.tsx

index.tsExpose the shared custom fetch client +1/-1

Expose the shared custom fetch client

• Exports 'customFetch' so frontend features can call endpoints not yet represented by generated API hooks.

frontend/src/api/index.ts

language-switcher.tsxCompact and improve the language selector +10/-7

Compact and improve the language selector

• Reworks the selector into an icon-based control with accessible labeling, clearer options, and updated interaction styling.

frontend/src/components/language-switcher.tsx

layout.tsxAdd settings navigation and an authenticated user menu +99/-27

Add settings navigation and an authenticated user menu

• Adds settings to primary navigation and replaces separate profile/logout controls with an avatar dropdown. The menu links directly to profile and preference tabs and closes when clicking outside.

frontend/src/components/layout.tsx

use-profile.tsExpand persisted student profile and preference state +86/-2

Expand persisted student profile and preference state

• Adds personal details, interests, careers, skills, university preferences, notifications, and theme state to the Zustand profile store. Applies the selected theme during updates and state rehydration.

frontend/src/hooks/use-profile.ts

index.cssDefine application-wide dark theme tokens +26/-0

Define application-wide dark theme tokens

• Adds dark-mode color variables for backgrounds, cards, controls, accents, borders, and destructive states.

frontend/src/index.css

i18n.tsLocalize settings and expanded profile fields +219/-3

Localize settings and expanded profile fields

• Adds settings navigation, profile sections, preferences, notification, account, and theme text in English, Sinhala, and Tamil.

frontend/src/lib/i18n.ts

dashboard.tsxRedesign the personalized student dashboard +563/-199

Redesign the personalized student dashboard

• Adds profile completion, recommendation summaries, saved-item tabs, roadmap progress, programme statistics, and searchable history links. Integrates clearing recent searches and routes profile editing through settings.

frontend/src/pages/dashboard.tsx

roadmap.tsxImprove roadmap discovery, rendering, and PDF export +350/-108

Improve roadmap discovery, rendering, and PDF export

• Makes all courses searchable, prevents unintended auto-generation, passes Z-scores, and adds clearer loading and result layouts. Expands PDFs with institution details, wrapped content, pagination, and postgraduate career trajectories.

frontend/src/pages/roadmap.tsx

settings.tsxAdd unified profile, preferences, and account settings +1031/-0

Add unified profile, preferences, and account settings

• Introduces a tabbed settings experience for academic profiles, recommendations, languages, notifications, themes, and account controls. Core profile fields sync through the existing profile API while extended preferences persist in the local profile store.

frontend/src/pages/settings.tsx

Bug fix (5) +265 / -75
gemini.tsStrengthen Gemini roadmap generation and response parsing +113/-28

Strengthen Gemini roadmap generation and response parsing

• Upgrades Gemini model selection, adds a fallback model cascade, requests JSON responses, and tolerates alternate response shapes. The prompt now requests detailed Sri Lankan academic, employment, salary, internship, and postgraduate guidance.

backend/src/lib/gemini.ts

load-env.tsPopulate environment variables that are present but empty +3/-2

Populate environment variables that are present but empty

• Allows values from the local environment file to replace undefined or empty process environment variables.

backend/src/load-env.ts

roadmaps.tsHandle AI roadmap failures without breaking generation +17/-9

Handle AI roadmap failures without breaking generation

• Wraps Gemini roadmap generation in error handling and adds diagnostic logging so template fallback remains available when AI generation fails.

backend/src/routes/roadmaps.ts

course-detail.tsxHarden course details and visualize cutoff trends +113/-32

Harden course details and visualize cutoff trends

• Validates route identifiers and optional API fields to avoid rendering failures. Displays multi-year cutoff history with latest-year labeling, four-decimal precision, and year-over-year trend indicators.

frontend/src/pages/course-detail.tsx

courses.tsxRestore course searches from URLs and record submissions +19/-4

Restore course searches from URLs and record submissions

• Initializes search and eligibility filters from query parameters. Records authenticated searches only when users submit a valid query with Enter, avoiding history entries for every keystroke.

frontend/src/pages/courses.tsx

Refactor (1) +4 / -205
profile.tsxRedirect legacy profiles into unified settings +4/-205

Redirect legacy profiles into unified settings

• Replaces the standalone profile form with a compatibility redirect to the settings profile tab.

frontend/src/pages/profile.tsx

Documentation (1) +380 / -6
data_quality_report.mdReport expanded historical cutoff normalization results +380/-6

Report expanded historical cutoff normalization results

• Updates normalization totals after incorporating three handbook years and documents additional unmatched, non-numeric, and review-required cutoff rows.

HandBook/2025/data_quality_report.md

Other (2) +2 / -2
pnpm-lock.yamlEnable automatic peer dependency installation +1/-1

Enable automatic peer dependency installation

• Changes the backend pnpm lockfile setting to automatically install peer dependencies.

backend/pnpm-lock.yaml

pnpm-lock.yamlEnable automatic peer dependency installation +1/-1

Enable automatic peer dependency installation

• Changes the frontend pnpm lockfile setting to automatically install peer dependencies.

frontend/pnpm-lock.yaml

@Niro0526
Niro0526 merged commit c5f9f1e into master Sep 8, 2026
1 of 2 checks passed
@qodo-code-review

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (8) 📘 Rule violations (0) 📜 Skill insights (0)

Grey Divider


Action required

1. Accounts survive destructive actions 🐞 Bug ≡ Correctness
Description
handleDeactivateAccount and handleDeleteAccount invoke only the client-side logout function
before displaying success messages that claim the requested account operation completed. After
either confirmation, no request has reached the server, so the user row and associated saved data
remain available and the same credentials can immediately sign in again.
Code

frontend/src/pages/settings.tsx[R198-201]

+    logout();
+    toast({
+      title: "Account Deactivated",
+      description: "Your account has been deactivated. Sign in anytime to reactivate.",
Evidence
Both handlers contain no account-operation API call and invoke only logout, which merely clears
the local token and user authentication state. The registered backend user routes expose no
deactivation or deletion operation, confirming that neither the account nor its associated data is
changed on the server.

frontend/src/pages/settings.tsx[193-217]
frontend/src/hooks/use-auth.ts[14-24]
backend/src/routes/users.ts[8-39]
frontend/src/pages/settings.tsx[206-218]
frontend/src/hooks/use-auth.ts[19-23]
backend/src/routes/index.ts[19-32]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The Deactivate Account and Delete Account controls only clear local authentication while claiming that the requested account operation succeeded, leaving the server-side account and associated data intact.

## Issue Context
Add authenticated backend operations for account deactivation and permanent deletion, including appropriate handling of all user-owned and associated records. Permanent deletion should delete or appropriately anonymize the account and related data transactionally. Invoke the relevant operation from the UI before clearing local authentication, and show the corresponding success state only after the server confirms completion.

## Fix Focus Areas
- frontend/src/pages/settings.tsx[193-218]
- frontend/src/hooks/use-auth.ts[14-24]
- backend/src/routes/users.ts[8-39]
- backend/src/routes/index.ts[19-32]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Another user's profile drives matches 🐞 Bug ≡ Correctness
Description
The settings synchronization now copies authenticated profile fields only when the persisted local
values are empty, and the default district is already nonempty. When another account signs in
through the same browser, the previous account's stream, score, and district remain preferred by the
dashboard and drive its recommendations.
Code

frontend/src/pages/settings.tsx[R226-228]

+    if (authUser?.stream && !stream) setStream(authUser.stream);
+    if (authUser?.zscore != null && zscore === null) setZscore(authUser.zscore);
+    if (authUser?.district && !district) setDistrict(authUser.district);
Evidence
The profile store persists under one browser-wide key and logout does not clear it, while the
dashboard explicitly selects local profile values before authenticated user values. Because the
local district defaults to Colombo, the new !district condition can never import a different
authenticated district into a fresh store.

frontend/src/pages/settings.tsx[222-234]
frontend/src/hooks/use-profile.ts[40-94]
frontend/src/hooks/use-auth.ts[14-24]
frontend/src/pages/dashboard.tsx[48-79]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
A browser-wide persisted profile can override the profile belonging to the currently authenticated account.

## Issue Context
Treat authenticated server fields as canonical for core recommendation inputs, or key persisted profile data by user ID. Clear or switch user-scoped values during logout and account changes without destroying intentional guest-profile behavior.

## Fix Focus Areas
- frontend/src/pages/settings.tsx[222-234]
- frontend/src/hooks/use-profile.ts[40-94]
- frontend/src/hooks/use-auth.ts[14-24]
- frontend/src/pages/dashboard.tsx[48-79]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Passwords remain unchanged after update 🐞 Bug ⛨ Security
Description
handleChangePassword validates fields but never checks currentPassword or sends a backend
request, instead waiting 800 ms before clearing the form and showing a success toast. Every
authenticated submission therefore appears to succeed while the stored password remains valid,
including submissions with an incorrect current password.
Code

frontend/src/pages/settings.tsx[R180-183]

+    setPasswordLoading(true);
+    setTimeout(() => {
+      setPasswordLoading(false);
+      setCurrentPassword("");
Evidence
The handler performs only local state changes after a timeout, with no network call or password
verification, and unconditionally emits a success toast. The registered backend routes expose
registration, login, and identity lookup but no password-change endpoint, confirming that no
credential update can occur.

frontend/src/pages/settings.tsx[153-190]
backend/src/routes/auth.ts[54-115]
backend/src/routes/index.ts[19-32]
backend/src/routes/auth.ts[11-115]
backend/src/routes/users.ts[10-39]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The settings password form reports success without changing the authenticated user's password or validating the supplied current password.

## Issue Context
Add an authenticated backend password-change endpoint that verifies the current password, validates and hashes the replacement password, persists it to the user record, and returns an error on failure. Call this endpoint from the settings form, and only clear the form and display the success message after the request succeeds.

## Fix Focus Areas
- frontend/src/pages/settings.tsx[153-190]
- backend/src/routes/auth.ts[54-115]
- backend/src/routes/index.ts[19-32]
- backend/src/db/schema/users.ts[5-16]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View high (1)
4. Students create duplicate roadmaps 🐞 Bug ≡ Correctness
Description
The URL-driven effect calls generateRoadmap whenever courseIdParam is present, including links
newly added for an already saved roadmap. Each authenticated generation unconditionally inserts a
row, so using Continue Roadmap repeatedly creates records for the same course and replaces the
dashboard's newest active entry.
Code

frontend/src/pages/roadmap.tsx[R204-210]

+  // Auto-generate ONLY when arriving with a specific courseId in the URL
  useEffect(() => {
    if (courseIdParam) {
      setSelectedCourseId(courseIdParam);
-    }
-  }, [courseIdParam]);
-
-  useEffect(() => {
-    if (selectedCourseId && !roadmap) {
      generateRoadmap({
        data: {
-          courseId: parseInt(selectedCourseId),
+          courseId: parseInt(courseIdParam),
Evidence
The changed effect regenerates on every URL course parameter, and the endpoint inserts every
authenticated result without looking up an existing roadmap; dashboard links now supply that
parameter for saved roadmaps.

frontend/src/pages/roadmap.tsx[204-216]
frontend/src/pages/dashboard.tsx[314-319]
frontend/src/pages/dashboard.tsx[513-519]
backend/src/routes/roadmaps.ts[247-260]
backend/src/routes/saved.ts[198-223]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Opening a roadmap with a `courseId` query parameter always regenerates it, even when the user selected an existing saved roadmap from the dashboard. Generation inserts a fresh database row each time.

## Issue Context
The dashboard's Continue Roadmap links use `courseId`, and the backend does not deduplicate roadmap inserts. Fetch and render the existing user roadmap for that course, or add an explicit regenerate action with an upsert/replace policy.

## Fix Focus Areas
- frontend/src/pages/roadmap.tsx[204-216]
- frontend/src/pages/dashboard.tsx[316-318]
- frontend/src/pages/dashboard.tsx[515-519]
- backend/src/routes/roadmaps.ts[247-260]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

5. Saved preferences never shape results 🐞 Bug ≡ Correctness
Description
The recommendation-preference button writes the three inputs only into otherwise unconsumed Zustand
fields and then says recommendations were updated. Subsequent dashboard recommendation requests
still contain only stream, score, district, and year mode, so every saved university, study-area,
and career preference is ignored.
Code

frontend/src/pages/settings.tsx[R693-696]

+                  onClick={() => {
+                    setPreferredUniversities(parseCommaSeparated(inputUnis));
+                    setPreferredStudyAreas(parseCommaSeparated(inputAreas));
+                    setPreferredCareers(parseCommaSeparated(inputCareersPref));
Evidence
Repository references show preferred universities and study areas are only declared, persisted, and
edited by the settings page. The dashboard API request does not read any of these new values.

frontend/src/pages/settings.tsx[641-704]
frontend/src/hooks/use-profile.ts[15-16]
frontend/src/hooks/use-profile.ts[52-53]
frontend/src/pages/dashboard.tsx[69-80]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Saved recommendation preferences do not affect any recommendation result despite the success confirmation.

## Issue Context
Pass the preferences into the recommendation API and implement backend filtering or ranking, or remove/label the controls until this behavior exists. Ensure authenticated preferences are also stored server-side if they are expected to follow the account.

## Fix Focus Areas
- frontend/src/pages/settings.tsx[641-704]
- frontend/src/hooks/use-profile.ts[15-16]
- frontend/src/pages/dashboard.tsx[69-80]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


6. Every account appears newly created 🐞 Bug ≡ Correctness
Description
The account information panel renders new Date() rather than an account creation value. Each visit
therefore displays the current date even though the user record has a persistent createdAt
timestamp.
Code

frontend/src/pages/settings.tsx[R850-853]

+                        <p className="text-sm font-medium mt-1">
+                          {new Date().toLocaleDateString(undefined, {
+                            year: "numeric",
+                            month: "long",
Evidence
The UI constructs the displayed date at render time, while the database already stores the actual
creation timestamp and current authentication responses omit it.

frontend/src/pages/settings.tsx[844-855]
backend/src/db/schema/users.ts[5-16]
backend/src/routes/auth.ts[80-115]
frontend/src/api/generated/api.schemas.ts[313-327]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The account creation date is always rendered as today's date.

## Issue Context
Expose the stored user creation timestamp through authentication responses and the frontend `User` schema, then format that value in settings. Do not synthesize a date when the field is unavailable.

## Fix Focus Areas
- frontend/src/pages/settings.tsx[844-855]
- frontend/src/api/generated/api.schemas.ts[313-327]
- backend/src/routes/auth.ts[80-115]
- backend/src/db/schema/users.ts[5-16]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


7. System theme stops following the OS 🐞 Bug ≡ Correctness
Description
applyTheme samples prefers-color-scheme only when the setting is selected or the store
rehydrates, without subscribing to media-query changes. While the theme remains set to system,
changing the operating-system appearance leaves the application in the previous mode until another
application action or reload reapplies it.
Code

frontend/src/hooks/use-profile.ts[R99-101]

+  const isDark =
+    theme === "dark" ||
+    (theme === "system" && window.matchMedia("(prefers-color-scheme: dark)").matches);
Evidence
The implementation calls matchMedia(...).matches as a one-time read and only invokes applyTheme
from setTheme or rehydration; the newly added settings UI presents system mode as an ongoing
appearance choice.

frontend/src/hooks/use-profile.ts[79-107]
frontend/src/pages/settings.tsx[782-812]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
System theme mode does not react when the operating-system color scheme changes.

## Issue Context
When `theme` is `system`, attach a change listener to the `prefers-color-scheme: dark` media query and clean it up when leaving system mode or unmounting. Keep the existing immediate application behavior.

## Fix Focus Areas
- frontend/src/hooks/use-profile.ts[79-107]
- frontend/src/pages/settings.tsx[782-812]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View medium (1)
8. New profile details do not sync 🐞 Bug ≡ Correctness
Description
onSubmit stores education stage, interests, preferred careers, and skills only in the local
Zustand profile store, then omits them from the profile-update payload. Signed-in students therefore
see a successful profile update but lose those new details on another device or after browser
storage is cleared.
Code

frontend/src/pages/settings.tsx[R276-283]

+    setFullName(data.fullName);
+    setEducationStage(data.educationStage);
+    setStream(data.stream);
+    setZscore(data.zscore);
+    setDistrict(data.district);
+    setInterests(interestsList);
+    setPreferredCareers(preferredCareersList);
+    setSkills(skillsList);
Evidence
The new fields are assigned to the local store, but the request sends only name, stream, z-score,
district, and language; the backend validation and update route accept and persist only that same
subset.

frontend/src/pages/settings.tsx[271-295]
frontend/src/hooks/use-profile.ts[40-95]
backend/src/api-zod/generated/api.ts[447-453]
backend/src/routes/users.ts[17-36]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
New profile fields are saved only in browser-local Zustand state and are not included in the authenticated profile update request.

## Issue Context
Extend the database model, API validation, and user update route to support the added profile data, then include those values in the frontend mutation and hydrate them from the authenticated user response.

## Fix Focus Areas
- frontend/src/pages/settings.tsx[271-295]
- frontend/src/hooks/use-profile.ts[4-95]
- backend/src/routes/users.ts[17-36]
- backend/src/api-zod/generated/api.ts[447-453]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context sources
✅ Web pages:
  +5 more
Review mode: 🧠 Deep: This is a broad, logic-dense cross-stack change spanning backend routes, AI integration, shared state, localization, and multiple frontend pages, with 57 independent edit sites and substantial new behavior where a redundant pass could catch independent defects.

Grey Divider

Tip of the day
💡 Did you know, you can tweak Display preferences with a live preview to see your comment before it ships

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment on lines +198 to +201
logout();
toast({
title: "Account Deactivated",
description: "Your account has been deactivated. Sign in anytime to reactivate.",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. Accounts survive destructive actions 🐞 Bug ≡ Correctness

handleDeactivateAccount and handleDeleteAccount invoke only the client-side logout function
before displaying success messages that claim the requested account operation completed. After
either confirmation, no request has reached the server, so the user row and associated saved data
remain available and the same credentials can immediately sign in again.
Agent Prompt
## Issue description
The Deactivate Account and Delete Account controls only clear local authentication while claiming that the requested account operation succeeded, leaving the server-side account and associated data intact.

## Issue Context
Add authenticated backend operations for account deactivation and permanent deletion, including appropriate handling of all user-owned and associated records. Permanent deletion should delete or appropriately anonymize the account and related data transactionally. Invoke the relevant operation from the UI before clearing local authentication, and show the corresponding success state only after the server confirms completion.

## Fix Focus Areas
- frontend/src/pages/settings.tsx[193-218]
- frontend/src/hooks/use-auth.ts[14-24]
- backend/src/routes/users.ts[8-39]
- backend/src/routes/index.ts[19-32]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +226 to +228
if (authUser?.stream && !stream) setStream(authUser.stream);
if (authUser?.zscore != null && zscore === null) setZscore(authUser.zscore);
if (authUser?.district && !district) setDistrict(authUser.district);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

2. Another user's profile drives matches 🐞 Bug ≡ Correctness

The settings synchronization now copies authenticated profile fields only when the persisted local
values are empty, and the default district is already nonempty. When another account signs in
through the same browser, the previous account's stream, score, and district remain preferred by the
dashboard and drive its recommendations.
Agent Prompt
## Issue description
A browser-wide persisted profile can override the profile belonging to the currently authenticated account.

## Issue Context
Treat authenticated server fields as canonical for core recommendation inputs, or key persisted profile data by user ID. Clear or switch user-scoped values during logout and account changes without destroying intentional guest-profile behavior.

## Fix Focus Areas
- frontend/src/pages/settings.tsx[222-234]
- frontend/src/hooks/use-profile.ts[40-94]
- frontend/src/hooks/use-auth.ts[14-24]
- frontend/src/pages/dashboard.tsx[48-79]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +693 to +696
onClick={() => {
setPreferredUniversities(parseCommaSeparated(inputUnis));
setPreferredStudyAreas(parseCommaSeparated(inputAreas));
setPreferredCareers(parseCommaSeparated(inputCareersPref));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remediation recommended

3. Saved preferences never shape results 🐞 Bug ≡ Correctness

The recommendation-preference button writes the three inputs only into otherwise unconsumed Zustand
fields and then says recommendations were updated. Subsequent dashboard recommendation requests
still contain only stream, score, district, and year mode, so every saved university, study-area,
and career preference is ignored.
Agent Prompt
## Issue description
Saved recommendation preferences do not affect any recommendation result despite the success confirmation.

## Issue Context
Pass the preferences into the recommendation API and implement backend filtering or ranking, or remove/label the controls until this behavior exists. Ensure authenticated preferences are also stored server-side if they are expected to follow the account.

## Fix Focus Areas
- frontend/src/pages/settings.tsx[641-704]
- frontend/src/hooks/use-profile.ts[15-16]
- frontend/src/pages/dashboard.tsx[69-80]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +850 to +853
<p className="text-sm font-medium mt-1">
{new Date().toLocaleDateString(undefined, {
year: "numeric",
month: "long",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remediation recommended

4. Every account appears newly created 🐞 Bug ≡ Correctness

The account information panel renders new Date() rather than an account creation value. Each visit
therefore displays the current date even though the user record has a persistent createdAt
timestamp.
Agent Prompt
## Issue description
The account creation date is always rendered as today's date.

## Issue Context
Expose the stored user creation timestamp through authentication responses and the frontend `User` schema, then format that value in settings. Do not synthesize a date when the field is unavailable.

## Fix Focus Areas
- frontend/src/pages/settings.tsx[844-855]
- frontend/src/api/generated/api.schemas.ts[313-327]
- backend/src/routes/auth.ts[80-115]
- backend/src/db/schema/users.ts[5-16]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +99 to +101
const isDark =
theme === "dark" ||
(theme === "system" && window.matchMedia("(prefers-color-scheme: dark)").matches);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remediation recommended

5. System theme stops following the os 🐞 Bug ≡ Correctness

applyTheme samples prefers-color-scheme only when the setting is selected or the store
rehydrates, without subscribing to media-query changes. While the theme remains set to system,
changing the operating-system appearance leaves the application in the previous mode until another
application action or reload reapplies it.
Agent Prompt
## Issue description
System theme mode does not react when the operating-system color scheme changes.

## Issue Context
When `theme` is `system`, attach a change listener to the `prefers-color-scheme: dark` media query and clean it up when leaving system mode or unmounting. Keep the existing immediate application behavior.

## Fix Focus Areas
- frontend/src/hooks/use-profile.ts[79-107]
- frontend/src/pages/settings.tsx[782-812]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +180 to +183
setPasswordLoading(true);
setTimeout(() => {
setPasswordLoading(false);
setCurrentPassword("");

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

6. Passwords remain unchanged after update 🐞 Bug ⛨ Security

handleChangePassword validates fields but never checks currentPassword or sends a backend
request, instead waiting 800 ms before clearing the form and showing a success toast. Every
authenticated submission therefore appears to succeed while the stored password remains valid,
including submissions with an incorrect current password.
Agent Prompt
## Issue description
The settings password form reports success without changing the authenticated user's password or validating the supplied current password.

## Issue Context
Add an authenticated backend password-change endpoint that verifies the current password, validates and hashes the replacement password, persists it to the user record, and returns an error on failure. Call this endpoint from the settings form, and only clear the form and display the success message after the request succeeds.

## Fix Focus Areas
- frontend/src/pages/settings.tsx[153-190]
- backend/src/routes/auth.ts[54-115]
- backend/src/routes/index.ts[19-32]
- backend/src/db/schema/users.ts[5-16]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +204 to +210
// Auto-generate ONLY when arriving with a specific courseId in the URL
useEffect(() => {
if (courseIdParam) {
setSelectedCourseId(courseIdParam);
}
}, [courseIdParam]);

useEffect(() => {
if (selectedCourseId && !roadmap) {
generateRoadmap({
data: {
courseId: parseInt(selectedCourseId),
courseId: parseInt(courseIdParam),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

7. Students create duplicate roadmaps 🐞 Bug ≡ Correctness

The URL-driven effect calls generateRoadmap whenever courseIdParam is present, including links
newly added for an already saved roadmap. Each authenticated generation unconditionally inserts a
row, so using Continue Roadmap repeatedly creates records for the same course and replaces the
dashboard's newest active entry.
Agent Prompt
## Issue description
Opening a roadmap with a `courseId` query parameter always regenerates it, even when the user selected an existing saved roadmap from the dashboard. Generation inserts a fresh database row each time.

## Issue Context
The dashboard's Continue Roadmap links use `courseId`, and the backend does not deduplicate roadmap inserts. Fetch and render the existing user roadmap for that course, or add an explicit regenerate action with an upsert/replace policy.

## Fix Focus Areas
- frontend/src/pages/roadmap.tsx[204-216]
- frontend/src/pages/dashboard.tsx[316-318]
- frontend/src/pages/dashboard.tsx[515-519]
- backend/src/routes/roadmaps.ts[247-260]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +276 to +283
setFullName(data.fullName);
setEducationStage(data.educationStage);
setStream(data.stream);
setZscore(data.zscore);
setDistrict(data.district);
setInterests(interestsList);
setPreferredCareers(preferredCareersList);
setSkills(skillsList);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remediation recommended

8. New profile details do not sync 🐞 Bug ≡ Correctness

onSubmit stores education stage, interests, preferred careers, and skills only in the local
Zustand profile store, then omits them from the profile-update payload. Signed-in students therefore
see a successful profile update but lose those new details on another device or after browser
storage is cleared.
Agent Prompt
## Issue description
New profile fields are saved only in browser-local Zustand state and are not included in the authenticated profile update request.

## Issue Context
Extend the database model, API validation, and user update route to support the added profile data, then include those values in the frontend mutation and hydrate them from the authenticated user response.

## Fix Focus Areas
- frontend/src/pages/settings.tsx[271-295]
- frontend/src/hooks/use-profile.ts[4-95]
- backend/src/routes/users.ts[17-36]
- backend/src/api-zod/generated/api.ts[447-453]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

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