Skip to content

Course progress sync: implement GET /api/progress/courses and PUT /api/progress/course/:courseId #387

Description

@zeemscript

Background

The frontend course-progress hook (hooks/useCourseProgress.ts) syncs a learner's video/course progress to:

  • GET /api/progress/courses — fetch all of the current user's course progress
  • PUT /api/progress/course/:courseId — upsert progress for one course

Neither exists. /api/progress is not mounted (app.js has no such app.use), so both calls 404:

statusCode":404,"message":"Can't find /api/progress/courses on this server!"

The frontend degrades gracefully (on 404 it falls back to localStorage), so progress works on a single device but is never persisted server-side or synced across devices, and the 404s spam server logs. The per-course endpoints GET/POST /api/courses/:id/progress exist but do not match this contract, and there is no aggregate "all my progress" endpoint.

Scope

Add a progressRoutes module mounted at /api/progress (authenticated with protect), reusing the existing src/models/CourseProgress.js model:

  1. GET /api/progress/courses — return every CourseProgress document for the authenticated user. Response shape must match the frontend exactly:
    { "success": true, "progress": [ { "courseId": "<id>", "positionSeconds": 0, "durationSeconds": 0, "completed": false } ] }
  2. PUT /api/progress/course/:courseId — upsert the caller's progress for that course from body { positionSeconds, durationSeconds, completed, lessonId }. Return the updated entry ({ success: true, progress: {...} }).
  3. Mount the router in app.js next to the other course routes.
  4. Reuse existing per-course progress logic where sensible; do not duplicate the model.

Out of scope

  • Frontend changes (the contract above is fixed by the client).
  • Reading/book progress (/api/books/.../progress) — separate feature.

Acceptance criteria

  • GET /api/progress/courses returns the authenticated user's progress in the exact { success, progress: [...] } shape
  • PUT /api/progress/course/:courseId upserts and returns the entry; only affects the caller's own progress
  • Router mounted at /api/progress; both routes behind protect
  • Reuses CourseProgress model (no schema duplication)
  • Tests: aggregate fetch, upsert create + update, auth required, user isolation
  • Suite + lint green; PR targets dev

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions