Labels
Frontend
Description
Quiz submissions and lesson completions in ByteChain Academy are processed entirely in the browser with no backend involvement. submitQuiz() in learning-context.tsx scores the quiz locally and stores the result in component state that disappears on refresh. markLessonComplete() mutates local state only. This means user progress is never persisted, XP is never awarded, certificates are never triggered, and all learning history is lost on every page reload. This issue wires both actions to the real backend endpoints.
Background & Context
frontend/contexts/learning-context.tsx — submitQuiz() does client-side scoring with no API call
frontend/contexts/learning-context.tsx — markLessonComplete() calls setState only, never POST /api/v1/progress/complete
- Backend
POST /api/v1/quizzes/:id/submit accepts { answers: Record<string, string> } and returns { score, passed, correctAnswers, totalQuestions }
- Backend
POST /api/v1/progress/complete accepts { courseId, lessonId } and triggers XP award and certificate check
frontend/app/courses/[id]/quizzes/[quizId]/page.tsx — has the quiz UI and calls submitQuiz() from context
frontend/app/courses/[id]/lessons/[lessonId]/page.tsx — has the "Mark Complete" button calling markLessonComplete()
Requirements
- Replace
submitQuiz() with a real call to POST /api/v1/quizzes/:id/submit — pass the user's answers, receive and store the server-scored result
- Replace
markLessonComplete() with a real call to POST /api/v1/progress/complete — pass courseId and lessonId
- After a successful lesson completion, refresh the course progress state so the UI reflects the updated completion status immediately
- After a successful quiz submission, navigate to the result page with the server-returned score data
- Handle errors gracefully — if the submission fails (e.g. network error or duplicate submission
409), show a toast with a descriptive message and do not navigate away
- Show a loading state on the "Submit Quiz" and "Mark Complete" buttons while the request is in flight to prevent double submissions
quizResults stored in context should reflect the server response shape, not the locally computed one
Suggested Execution
Branch: git checkout -b feat/wire-quiz-submission-and-progress
Files to touch:
frontend/contexts/learning-context.tsx
frontend/app/courses/[id]/quizzes/[quizId]/page.tsx
frontend/app/courses/[id]/lessons/[lessonId]/page.tsx
frontend/lib/api.ts
Implement:
submitQuiz(quizId, answers) — POST /api/v1/quizzes/:id/submit, map answer format from Record<string, number> (option index) to Record<string, string> (option value) before sending
markLessonComplete(courseId, lessonId) — POST /api/v1/progress/complete, on success call getCourseProgress(courseId) to refresh state
- Add
isSubmittingQuiz and isCompletingLesson loading flags to context
- Update quiz page to disable the submit button while
isSubmittingQuiz is true
- Update lesson page to disable the complete button while
isCompletingLesson is true
- Handle
409 Conflict on quiz re-submission — show "You have already completed this quiz" toast
Test & Validate:
- Submit a quiz with correct answers → server returns score → result page shows server score
- Submit a quiz a second time →
409 is handled gracefully with a toast
- Mark a lesson complete → progress bar on course detail page updates immediately
- Complete all lessons in a course → verify certificate is issued (check backend logs or
GET /api/v1/certificates)
- Refresh the page after completing a lesson → completion state persists (this depends on Issue 9 being merged first)
Acceptance Criteria
Example Commit Message
feat: wire quiz submission and lesson completion to backend progress and quiz endpoints
Guidelines
- Assignment required before starting
- PR description must include
Closes #[issue_id]
- Join our Telegram: https://t.me/ByteChainAcademy
- Complexity: High (200 pts)
Labels
FrontendDescription
Quiz submissions and lesson completions in ByteChain Academy are processed entirely in the browser with no backend involvement.
submitQuiz()inlearning-context.tsxscores the quiz locally and stores the result in component state that disappears on refresh.markLessonComplete()mutates local state only. This means user progress is never persisted, XP is never awarded, certificates are never triggered, and all learning history is lost on every page reload. This issue wires both actions to the real backend endpoints.Background & Context
frontend/contexts/learning-context.tsx—submitQuiz()does client-side scoring with no API callfrontend/contexts/learning-context.tsx—markLessonComplete()callssetStateonly, neverPOST /api/v1/progress/completePOST /api/v1/quizzes/:id/submitaccepts{ answers: Record<string, string> }and returns{ score, passed, correctAnswers, totalQuestions }POST /api/v1/progress/completeaccepts{ courseId, lessonId }and triggers XP award and certificate checkfrontend/app/courses/[id]/quizzes/[quizId]/page.tsx— has the quiz UI and callssubmitQuiz()from contextfrontend/app/courses/[id]/lessons/[lessonId]/page.tsx— has the "Mark Complete" button callingmarkLessonComplete()Requirements
submitQuiz()with a real call toPOST /api/v1/quizzes/:id/submit— pass the user's answers, receive and store the server-scored resultmarkLessonComplete()with a real call toPOST /api/v1/progress/complete— passcourseIdandlessonId409), show a toast with a descriptive message and do not navigate awayquizResultsstored in context should reflect the server response shape, not the locally computed oneSuggested Execution
Branch:
git checkout -b feat/wire-quiz-submission-and-progressFiles to touch:
frontend/contexts/learning-context.tsxfrontend/app/courses/[id]/quizzes/[quizId]/page.tsxfrontend/app/courses/[id]/lessons/[lessonId]/page.tsxfrontend/lib/api.tsImplement:
submitQuiz(quizId, answers)—POST /api/v1/quizzes/:id/submit, map answer format fromRecord<string, number>(option index) toRecord<string, string>(option value) before sendingmarkLessonComplete(courseId, lessonId)—POST /api/v1/progress/complete, on success callgetCourseProgress(courseId)to refresh stateisSubmittingQuizandisCompletingLessonloading flags to contextisSubmittingQuizis trueisCompletingLessonis true409 Conflicton quiz re-submission — show "You have already completed this quiz" toastTest & Validate:
409is handled gracefully with a toastGET /api/v1/certificates)Acceptance Criteria
submitQuiz()callsPOST /api/v1/quizzes/:id/submitwith correctly formatted answersmarkLessonComplete()callsPOST /api/v1/progress/completeExample Commit Message
feat: wire quiz submission and lesson completion to backend progress and quiz endpointsGuidelines
Closes #[issue_id]