Skip to content

Update the carrers, roadmap, reviews - #7

Merged
Kiruthiyan merged 1 commit into
masterfrom
kiru
Sep 7, 2026
Merged

Kiruthiyan merged 1 commit into
masterfrom
kiru

Conversation

@Kiruthiyan

Copy link
Copy Markdown
Owner

No description provided.

Copilot AI lite review requested due to automatic review settings September 7, 2026 14:38
@Kiruthiyan
Kiruthiyan merged commit 5aef8e6 into master Sep 7, 2026
2 of 3 checks passed
@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Fix official course roadmaps and review rendering

🐞 Bug fix ⚙️ Configuration changes 🕐 20-40 Minutes

Grey Divider

AI Description

• Generates roadmaps from official handbook courses with normalized durations and category-aware
 fallbacks.
• Aligns review rendering with the current API and improves verified-alumni accessibility.
• Provides status-specific roadmap errors and disables pnpm peer auto-installation.
Diagram

sequenceDiagram
  actor U as User
  participant UI as Roadmap Page
  participant API as Roadmap API
  participant H as Handbook Query
  participant AI as Gemini AI
  participant DB as Roadmap Store
  U->>UI: Select course
  UI->>API: Generate roadmap
  API->>H: Fetch official course
  H-->>API: Course metadata
  API->>AI: Generate milestones
  alt AI succeeds
    AI-->>API: Custom roadmap
  else AI unavailable
    API->>API: Apply template fallback
  end
  opt Authenticated user
    API->>DB: Persist roadmap
  end
  API-->>UI: Roadmap or status error
  UI-->>U: Display result
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Normalize duration in the handbook mapper
  • ➕ Populates the existing numeric durationYears field for every official-course consumer
  • ➕ Centralizes textual duration parsing and makes it easier to test consistently
  • ➖ Broadens the behavioral impact beyond roadmap generation
  • ➖ Requires deciding how all consumers should handle malformed or missing durations

Recommendation: Keep the route-local parser for this focused compatibility fix because it limits impact while moving roadmap generation onto the official handbook source. If additional consumers need numeric durations, move the conversion into the official-course mapper and add parsing tests rather than duplicating the logic.

Files changed (5) +34 / -50

Bug fix (3) +32 / -48
roadmaps.tsGenerate roadmaps from official handbook courses +18/-23

Generate roadmaps from official handbook courses

• Replaces legacy degree and university joins with the shared official handbook course query. Parses textual course durations, derives an AI and fallback category from faculty or degree name, and sizes generated roadmaps to the resolved duration.

backend/src/routes/roadmaps.ts

reviews.tsxAlign review cards with the current review API +4/-12

Align review cards with the current review API

• Displays reviewerName instead of the obsolete authorName field and removes unsupported pros and cons content. Adds accessible labeling and an SVG title to the verified-alumni icon.

frontend/src/pages/reviews.tsx

roadmap.tsxImprove roadmap request compatibility and error feedback +10/-13

Improve roadmap request compatibility and error feedback

• Removes unsupported target-career and language-context request fields and the corresponding result display. Uses ApiError statuses to distinguish missing courses, rate limits, and generic generation failures.

frontend/src/pages/roadmap.tsx

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

Disable automatic peer dependency installation

• Sets pnpm's autoInstallPeers option to false for deterministic backend dependency installation.

backend/pnpm-lock.yaml

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

Disable automatic peer dependency installation

• Sets pnpm's autoInstallPeers option to false for deterministic frontend dependency installation.

frontend/pnpm-lock.yaml

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Changes recommended

The backend change introduces a potential per-request full-course-list scan via getOfficialCourseDetail(), and the roadmap page effect dependencies risk using a stale hydrated profile.stream value.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR updates the roadmap and reviews pages, and changes the backend roadmap-generation route to source course metadata from the official handbook query helper rather than the previous degree-programmes tables.

Changes:

  • Frontend roadmap page: improves toast error messaging and removes unused language/target-career UI.
  • Frontend reviews page: switches to reviewerName, improves verified badge accessibility markup, and removes pros/cons rendering.
  • Backend roadmap generation: uses getOfficialCourseDetail() and derives durationYears from the official duration string.
File summaries
File Description
frontend/src/pages/roadmap.tsx Updates roadmap generation UX/error handling and removes unused language/target career display.
frontend/src/pages/reviews.tsx Uses reviewerName, adjusts verified badge accessibility, and simplifies review content.
backend/src/routes/roadmaps.ts Switches roadmap generation to official handbook course detail and parses duration from strings.
frontend/pnpm-lock.yaml Aligns lockfile settings (autoInstallPeers: false) with repo .npmrc.
backend/pnpm-lock.yaml Aligns lockfile settings (autoInstallPeers: false) with repo .npmrc.
Review details

Files not reviewed (2)

  • backend/pnpm-lock.yaml: Generated file
  • frontend/pnpm-lock.yaml: Generated file
  • Files reviewed: 3/5 changed files
  • Comments generated: 4
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

eq(degreeProgrammesTable.universityId, universitiesTable.id),
)
.where(eq(degreeProgrammesTable.id, courseId));
const courseRow = await getOfficialCourseDetail(courseId, { district: "All Island" });
Comment on lines 107 to 111
if (selectedCourseId && !roadmap) {
const langName = language === "si" ? "Sinhala" : language === "ta" ? "Tamil" : "English";
generateRoadmap({
data: {
courseId: parseInt(selectedCourseId),
stream: profile.stream || undefined,
Comment on lines 2 to +3
import { db } from "../db";
import { degreeProgrammesTable, universitiesTable, roadmapsTable } from "../db";
import { eq } from "drizzle-orm";
import { roadmapsTable } from "../db";
Comment on lines +84 to +88
onError: (error) => {
const description =
error instanceof ApiError && error.status === 404
? "This course could not be found. Please pick a different course."
: error instanceof ApiError && error.status === 429
@qodo-code-review

Copy link
Copy Markdown

Code Review by Qodo

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

Grey Divider


Action required

1. Saved roadmaps lose course identity 🐞 Bug ≡ Correctness
Description
The /roadmaps/generate handler now stores the official-handbook courseId, but /roadmaps still
joins that value to the unrelated legacy degree-programme primary key. For authenticated generations
whose independent numeric IDs do not coincide, the saved-roadmap response returns a null or
unrelated degreeName, violating its string contract and leaving the dashboard entry blank or
mislabeled.
Code

backend/src/routes/roadmaps.ts[197]

+  const courseRow = await getOfficialCourseDetail(courseId, { district: "All Island" });
Evidence
The changed lookup resolves an official course whose public ID is computed from uni_code, and that
ID is persisted in the roadmap row. Saved roadmap retrieval still equates the persisted value with
degreeProgrammesTable.id, while its generated API contract requires a non-null name and the
dashboard renders that field directly.

backend/src/routes/roadmaps.ts[197-205]
backend/src/routes/roadmaps.ts[239-250]
backend/src/db/official-handbook-query.ts[132-134]
backend/src/db/official-handbook-query.ts[240-252]
backend/src/routes/saved.ts[198-221]
frontend/src/api/generated/api.schemas.ts[358-364]
frontend/src/pages/dashboard.tsx[261-270]

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

## Issue description
Generated roadmaps now use official-handbook course IDs, while the saved-roadmaps route resolves names by joining those IDs to the legacy degree-programme table. Update saved roadmap retrieval so course identity and names use the same official ID namespace as generation.

## Issue Context
Official course IDs are derived from handbook `uni_code` values and are not degree-programme primary keys. The dashboard displays the top-level `degreeName` returned by the saved-roadmaps endpoint.

## Fix Focus Areas
- backend/src/routes/roadmaps.ts[197-250]
- backend/src/routes/saved.ts[198-223]
- backend/src/db/official-handbook-query.ts[132-134]
- frontend/src/pages/dashboard.tsx[261-270]

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



Remediation recommended

2. Roadmaps slow as the catalog grows 🐞 Bug ➹ Performance
Description
The generation handler calls getOfficialCourseDetail, whose implementation fetches every official
course and scans the resulting array to find one ID. Each generation therefore runs two correlated
cutoff lookups for every catalog row before making the AI request, increasing database work and
endpoint latency with the entire catalog rather than the selected course.
Code

backend/src/routes/roadmaps.ts[197]

+  const courseRow = await getOfficialCourseDetail(courseId, { district: "All Island" });
Evidence
The changed route adds getOfficialCourseDetail to generation. That helper invokes the unfiltered
fetchCourseRows, whose SQL selects the full academic-year catalog and calculates two cutoff
subqueries per row, then uses rows.find to select the requested course.

backend/src/routes/roadmaps.ts[197-205]
backend/src/db/official-handbook-query.ts[272-323]
backend/src/db/official-handbook-query.ts[375-390]

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

## Issue description
Roadmap generation now obtains one course through a helper that queries and materializes the complete official catalog. Add or use a targeted official-course query so generation loads only the selected course and its required details.

## Issue Context
`fetchCourseRows` has no course-ID predicate and contains two correlated cutoff subqueries. `getOfficialCourseDetail` then searches the complete result in application code.

## Fix Focus Areas
- backend/src/routes/roadmaps.ts[197-205]
- backend/src/db/official-handbook-query.ts[272-323]
- backend/src/db/official-handbook-query.ts[375-391]

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


Grey Divider

Context sources
Review mode: ⚖️ Balanced: This PR changes backend roadmap data retrieval and duration logic plus frontend generation behavior and displayed fields across multiple paths, creating meaningful behavioral risk but not enough dense independent logic to warrant extended review.

Grey Divider

Tip of the day
💡 Did you know, you can copy the agent prompt from any finding and feed it to your IDE agent

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

eq(degreeProgrammesTable.universityId, universitiesTable.id),
)
.where(eq(degreeProgrammesTable.id, courseId));
const courseRow = await getOfficialCourseDetail(courseId, { district: "All Island" });

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. Saved roadmaps lose course identity 🐞 Bug ≡ Correctness

The /roadmaps/generate handler now stores the official-handbook courseId, but /roadmaps still
joins that value to the unrelated legacy degree-programme primary key. For authenticated generations
whose independent numeric IDs do not coincide, the saved-roadmap response returns a null or
unrelated degreeName, violating its string contract and leaving the dashboard entry blank or
mislabeled.
Agent Prompt
## Issue description
Generated roadmaps now use official-handbook course IDs, while the saved-roadmaps route resolves names by joining those IDs to the legacy degree-programme table. Update saved roadmap retrieval so course identity and names use the same official ID namespace as generation.

## Issue Context
Official course IDs are derived from handbook `uni_code` values and are not degree-programme primary keys. The dashboard displays the top-level `degreeName` returned by the saved-roadmaps endpoint.

## Fix Focus Areas
- backend/src/routes/roadmaps.ts[197-250]
- backend/src/routes/saved.ts[198-223]
- backend/src/db/official-handbook-query.ts[132-134]
- frontend/src/pages/dashboard.tsx[261-270]

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

eq(degreeProgrammesTable.universityId, universitiesTable.id),
)
.where(eq(degreeProgrammesTable.id, courseId));
const courseRow = await getOfficialCourseDetail(courseId, { district: "All Island" });

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

2. Roadmaps slow as the catalog grows 🐞 Bug ➹ Performance

The generation handler calls getOfficialCourseDetail, whose implementation fetches every official
course and scans the resulting array to find one ID. Each generation therefore runs two correlated
cutoff lookups for every catalog row before making the AI request, increasing database work and
endpoint latency with the entire catalog rather than the selected course.
Agent Prompt
## Issue description
Roadmap generation now obtains one course through a helper that queries and materializes the complete official catalog. Add or use a targeted official-course query so generation loads only the selected course and its required details.

## Issue Context
`fetchCourseRows` has no course-ID predicate and contains two correlated cutoff subqueries. `getOfficialCourseDetail` then searches the complete result in application code.

## Fix Focus Areas
- backend/src/routes/roadmaps.ts[197-205]
- backend/src/db/official-handbook-query.ts[272-323]
- backend/src/db/official-handbook-query.ts[375-391]

ⓘ 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.

2 participants