Skip to content

Dev - #33

Merged
UGing265 merged 25 commits into
mainfrom
dev
Jul 14, 2026
Merged

Dev#33
UGing265 merged 25 commits into
mainfrom
dev

Conversation

@UGing265

@UGing265 UGing265 commented Jul 14, 2026

Copy link
Copy Markdown
Owner

Summary by CodeRabbit

  • New Features
    • Added AI-generated quizzes with lecturer publishing, student attempts, automatic grading, scoring, and attempt history.
    • Added document bookmarking, saved-document browsing, multi-document chat attachments, and improved Markdown responses.
    • Added document comparison results in Markdown with PDF export.
    • Added upload progress tracking and multi-filter document discovery.
  • Improvements
    • Updated navigation and refreshed layouts across administrative, lecturer, and student areas.
    • Simplified document and subject management by removing academic-term workflows.
  • Documentation
    • Expanded setup, architecture, requirements, design-system, and quiz documentation.

tgbaonguyen-dev and others added 25 commits July 11, 2026 12:10
…on handling, document filtering, and layout components
Disable document reporting functionality by setting canReport to false. Remove moderation page, components, and hooks:

- Delete moderation page and view component
- Remove moderation hook and API integration
- Remove "Báo Cáo Vi Phạm" from admin sidebar
- Update admin dashboard header with improved styling (icon box, serif title, subtitle)

This simplifies the admin interface by removing the violation reporting workflow.
Introduce RAG-powered quiz features and large UI updates: add frontend/src/api/quiz.ts for quiz client; implement AI quiz generator and preview in lecturer practice (UI redesign, modal, polling job status, publish flow); add student dashboard component and improve student practice view with tabbed layout; refactor TakeQuizView to work with API-driven quizzes, start/submit attempts and history modal; update hooks (use-practice, use-quiz) to call quizApi/ragApi, manage subjects, documents, quizzes, generation state and attempt lifecycle; minor sidebar nav label change and multiple UX/loading improvements.
Add IsCorrect to QuizOption model and update TeacherPracticeView to visually highlight correct answers. Uses cn utility to apply green styles, replaces option letter with a checkmark for correct choices, and displays a "Đáp án đúng" badge. Files changed: frontend/src/api/quiz.ts, frontend/src/components/lecturer/practice/practice-view.tsx.
Enable multi-choice questions and client-side persistence for ongoing quizzes. Frontend: update take-quiz UI to show multi-select badges, toggle selections, new leave-confirmation modal, completed-count submit validation, and small debug views; persist/restore active attempt, quiz detail, answers and subject to localStorage and clear them on submit/back/reset. Hook: change answers type to string[], map questionType from API, handle multi_choice logic and format payload for submission. Backend: minor import reorder and whitespace fix in generate_quiz.go. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
docs: update README with project architecture and setup instructions
@UGing265
UGing265 merged commit 33db500 into main Jul 14, 2026
1 check was pending
@coderabbitai

coderabbitai Bot commented Jul 14, 2026

Copy link
Copy Markdown

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 35b1d052-b0bb-47cc-90ef-93e1c4572a77

📥 Commits

Reviewing files that changed from the base of the PR and between 0b732f4 and 3d47ca9.

⛔ Files ignored due to path filters (6)
  • backend/go/api.exe is excluded by !**/*.exe
  • backend/go/tmp/main.exe is excluded by !**/*.exe
  • frontend/bun.lock is excluded by !**/*.lock
  • frontend/package-lock.json is excluded by !**/package-lock.json
  • frontend/pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
  • frontend/public/favicon.ico is excluded by !**/*.ico
📒 Files selected for processing (117)
  • README.md
  • backend/database/002_chat_tables.sql
  • backend/database/003_chat_session_documents.sql
  • backend/database/004_quiz_tables.sql
  • backend/database/swd391_dangerous_malware.sql
  • backend/go/docs/docs.go
  • backend/go/docs/quiz-implementation-plan.md
  • backend/go/docs/quiz.md
  • backend/go/docs/swagger.json
  • backend/go/docs/swagger.yaml
  • backend/go/internal/application/admin-usecase/manage_documents.go
  • backend/go/internal/application/chat-usecase/send-message.go
  • backend/go/internal/application/chat-usecase/stream-message.go
  • backend/go/internal/application/document-usecase/compare.go
  • backend/go/internal/application/document-usecase/manage.go
  • backend/go/internal/application/document-usecase/search.go
  • backend/go/internal/application/document-usecase/upload.go
  • backend/go/internal/application/dto.go
  • backend/go/internal/application/lookup-usecase/subjects.go
  • backend/go/internal/application/lookup-usecase/terms.go
  • backend/go/internal/application/lookup-usecase/usecase.go
  • backend/go/internal/application/quiz-usecase/generate_quiz.go
  • backend/go/internal/application/quiz-usecase/manage_quiz.go
  • backend/go/internal/application/quiz-usecase/take_quiz.go
  • backend/go/internal/application/quiz-usecase/usecase.go
  • backend/go/internal/domain/academicterm/entity.go
  • backend/go/internal/domain/academicterm/repository.go
  • backend/go/internal/domain/document/entity.go
  • backend/go/internal/domain/document/repository.go
  • backend/go/internal/domain/quiz/entity.go
  • backend/go/internal/domain/quiz/repository.go
  • backend/go/internal/domain/subject/entity.go
  • backend/go/internal/infrastructure/repository/postgres/academicterm-repository.go
  • backend/go/internal/infrastructure/repository/postgres/bookmark-repository.go
  • backend/go/internal/infrastructure/repository/postgres/document-repository.go
  • backend/go/internal/infrastructure/repository/postgres/quiz_repo.go
  • backend/go/internal/infrastructure/repository/postgres/subject-repository.go
  • backend/go/internal/interface/handler/admin-handler.go
  • backend/go/internal/interface/handler/document-handler.go
  • backend/go/internal/interface/handler/quiz-handler.go
  • backend/go/internal/interface/router/router.go
  • backend/go/pkg/prompt/system_prompt.go
  • docs/SRS.md
  • docs/bao/2. SRS.md
  • docs/bao/3. Pipeline.md
  • docs/bao/4. Architecture.md
  • docs/bao/Database Implementation Guide - PostgreSQL + pgvector.md
  • docs/bao/spreadsheet-content.md
  • docs/planing/plans/ui-redesign-plan.md
  • docs/system/DESIGN_SYSTEM.md
  • frontend/next.config.js
  • frontend/package.json
  • frontend/src/api/chat.ts
  • frontend/src/api/curriculum.ts
  • frontend/src/api/document.ts
  • frontend/src/api/quiz.ts
  • frontend/src/app/[role]/bookmarks/page.tsx
  • frontend/src/app/[role]/documents/[id]/page.tsx
  • frontend/src/app/[role]/explore/page.tsx
  • frontend/src/app/[role]/moderation/page.tsx
  • frontend/src/app/[role]/practice/quiz/page.tsx
  • frontend/src/app/[role]/progress/page.tsx
  • frontend/src/app/globals.css
  • frontend/src/app/layout.tsx
  • frontend/src/app/page.tsx
  • frontend/src/components/admin/assignment/admin-assignments-view.tsx
  • frontend/src/components/admin/curriculum/admin-curriculum-view.tsx
  • frontend/src/components/admin/dashboard/admin-dashboard-view.tsx
  • frontend/src/components/admin/documents/admin-documents-view.tsx
  • frontend/src/components/admin/metadata/admin-metadata-view.tsx
  • frontend/src/components/admin/moderation/admin-moderation-view.tsx
  • frontend/src/components/admin/settings/admin-settings-view.tsx
  • frontend/src/components/admin/users/admin-users-view.tsx
  • frontend/src/components/admin/users/user-table.tsx
  • frontend/src/components/common/chat/chat-view.tsx
  • frontend/src/components/common/chat/sessions-view.tsx
  • frontend/src/components/common/documents/bookmarks-view.tsx
  • frontend/src/components/common/documents/compare-view.tsx
  • frontend/src/components/common/documents/document-filters.tsx
  • frontend/src/components/common/documents/explore-view.tsx
  • frontend/src/components/common/documents/shared-documents-view.tsx
  • frontend/src/components/layout/admin-layout.tsx
  • frontend/src/components/layout/app-layout.tsx
  • frontend/src/components/layout/role-shell.tsx
  • frontend/src/components/layout/sidebar.tsx
  • frontend/src/components/lecturer/documents/document-detail-panel.tsx
  • frontend/src/components/lecturer/documents/documents-view.tsx
  • frontend/src/components/lecturer/documents/edit-document-view.tsx
  • frontend/src/components/lecturer/documents/inline-document-edit.tsx
  • frontend/src/components/lecturer/documents/my-documents-view.tsx
  • frontend/src/components/lecturer/documents/upload-modal.tsx
  • frontend/src/components/lecturer/documents/upload-view.tsx
  • frontend/src/components/lecturer/practice/practice-view.tsx
  • frontend/src/components/lecturer/progress/progress-view.tsx
  • frontend/src/components/lecturer/quiz/create-quiz-view.tsx
  • frontend/src/components/student/documents/student-documents-view.tsx
  • frontend/src/components/student/practice/student-dashboard.tsx
  • frontend/src/components/student/practice/student-practice-view.tsx
  • frontend/src/components/student/quiz/take-quiz-view.tsx
  • frontend/src/components/ui/action-modal.tsx
  • frontend/src/components/ui/data-table.tsx
  • frontend/src/components/ui/page-shell.tsx
  • frontend/src/hooks/admin/use-curriculum.ts
  • frontend/src/hooks/admin/use-moderation.ts
  • frontend/src/hooks/lecturer/use-bookmarks.ts
  • frontend/src/hooks/lecturer/use-create-quiz.ts
  • frontend/src/hooks/lecturer/use-documents.ts
  • frontend/src/hooks/lecturer/use-edit-document.ts
  • frontend/src/hooks/lecturer/use-explore.ts
  • frontend/src/hooks/lecturer/use-my-documents.ts
  • frontend/src/hooks/lecturer/use-practice.ts
  • frontend/src/hooks/lecturer/use-shared-documents.ts
  • frontend/src/hooks/lecturer/use-upload.ts
  • frontend/src/hooks/student/use-quiz.ts
  • frontend/src/hooks/use-auth.ts
  • frontend/src/middleware.ts
  • summary.md

📝 Walkthrough

Walkthrough

The pull request adds quiz generation, publishing, attempts, grading, and frontend quiz flows; introduces chat and session-document persistence; removes academic-term support; updates document filtering, comparison export, bookmarking, and upload progress; and applies broad frontend navigation, layout, and design-system changes.

Changes

Platform feature integration

Layer / File(s) Summary
Database schema and academic-term removal
backend/database/*.sql
Adds chat/session-document and quiz tables, indexes, cascading relationships, and removes academic-term columns and constraints.
Quiz domain, persistence, and application flow
backend/go/internal/domain/quiz/*, backend/go/internal/application/quiz-usecase/*, backend/go/internal/infrastructure/repository/postgres/quiz_repo.go, backend/go/internal/interface/handler/quiz-handler.go, backend/go/internal/interface/router/router.go
Adds quiz entities, repository operations, asynchronous LLM generation, publishing validation, attempt grading, HTTP handlers, and protected quiz routes.
Document and chat backend contracts
backend/go/internal/application/{chat-usecase,document-usecase}/*, backend/go/internal/interface/handler/{document-handler,admin-handler}.go, backend/go/internal/infrastructure/repository/postgres/*
Removes academic-term document handling, adds multi-value filters, changes comparison output to Markdown/PDF tables, updates bookmark queries, and searches attached chat documents per document.
API documentation and public contracts
backend/go/docs/swagger.*, backend/go/docs/docs.go
Documents quiz, bookmark, upload-job, audit-log, comparison-export, and revised document APIs and schemas.
Frontend API and state integration
frontend/src/api/*, frontend/src/hooks/*
Adds quiz and bookmark clients, API-backed quiz attempts and generation polling, document exploration/filtering, upload progress polling, chat attachments, and removes term state.
Frontend feature views
frontend/src/app/*, frontend/src/components/common/*, frontend/src/components/lecturer/*, frontend/src/components/student/*
Adds bookmark, explore, progress, quiz dashboard, quiz-taking, comparison, document-management, and chat interfaces.
Frontend layout and shared UI
frontend/src/components/admin/*, frontend/src/components/layout/*, frontend/src/components/ui/*, frontend/src/app/{globals.css,layout.tsx}
Adds shared layout primitives and sidebar navigation, refactors admin pages, and updates typography and visual styling.
Project documentation and design guidance
README.md, docs/*, backend/go/docs/*
Rewrites project documentation, SRS/design-system guidance, quiz plans, and UI redesign plans. Note: the full range coverage for these documentation-only files is represented in the review stack artifact.

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Lecturer
  participant Frontend
  participant QuizAPI
  participant QuizUsecase
  participant Database
  participant LLM
  Lecturer->>Frontend: configure documents and question counts
  Frontend->>QuizAPI: POST quiz generation request
  QuizAPI->>QuizUsecase: enqueue generation job
  QuizUsecase->>Database: save pending job
  QuizUsecase->>LLM: generate quiz from document chunks
  LLM-->>QuizUsecase: return quiz JSON
  QuizUsecase->>Database: save draft quiz and mark job completed
  Frontend->>QuizAPI: poll generation job status
  QuizAPI-->>Frontend: return job progress and result quiz
Loading

Possibly related PRs

Suggested reviewers: tgbaonguyen-dev, ro-nan-ho

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch dev

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 golangci-lint (2.12.2)

level=error msg="[linters_context] typechecking error: pattern ./...: directory prefix . does not contain main module or its selected dependencies"


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@qodo-code-review

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (7) 📘 Rule violations (4) 📜 Skill insights (0)

Context used
✅ Compliance rules (platform): 27 rules

Grey Divider


Action required

1. quiz-usecase imports infrastructure/llm 📘 Rule violation ⌂ Architecture
Description
The application-layer quiz-usecase depends directly on internal/infrastructure/llm, violating
the required four-layer dependency direction (application must not import infrastructure). This
makes the use case layer tightly coupled to a specific infra implementation instead of an
abstraction.
Code

backend/go/internal/application/quiz-usecase/generate_quiz.go[R11-13]

+	"github.com/google/uuid"
+	"swd392-chatbot-rag/internal/domain/quiz"
+	"swd392-chatbot-rag/internal/infrastructure/llm"
Evidence
PR Compliance ID 1333443 requires application-layer packages to not import infrastructure. The new
quiz-usecase file imports internal/infrastructure/llm directly in its import block.

Rule 1333443: Enforce four-layer architectural package structure in Go backend
backend/go/internal/application/quiz-usecase/generate_quiz.go[11-14]

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

## Issue description
`backend/go/internal/application/quiz-usecase/generate_quiz.go` is in the application layer but imports `swd392-chatbot-rag/internal/infrastructure/llm`, coupling application to infrastructure.

## Issue Context
Compliance requires a strict four-layer architecture where application depends on domain abstractions, not infrastructure packages.

## Fix Focus Areas
- backend/go/internal/application/quiz-usecase/generate_quiz.go[11-15]
- backend/go/internal/application/quiz-usecase/usecase.go[53-67]
- backend/go/internal/interface/router/router.go[74-99]

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


2. quiz-handler.go exceeds 200 lines 📘 Rule violation ⚙ Maintainability
Description
backend/go/internal/interface/handler/quiz-handler.go is 379 lines long, exceeding the 200-line
maximum for source files. This violates the file size limit even though it is a single new file.
Code

backend/go/internal/interface/handler/quiz-handler.go[R350-379]

+		return
+	}
+
+	userID := c.MustGet("user_id").(uuid.UUID)
+
+	attempts, err := h.quizUsecase.GetAttemptHistory(c.Request.Context(), quizID, userID)
+	if err != nil {
+		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
+		return
+	}
+
+	c.JSON(http.StatusOK, gin.H{"data": attempts})
+}
+
+// @Summary Get all subjects that have published quizzes
+// @Description Returns a list of subjects that contain at least one published quiz.
+// @Tags Quiz
+// @Produce json
+// @Success 200 {object} map[string]interface{}
+// @Failure 500 {object} map[string]interface{}
+// @Router /api/quizzes/subjects [get]
+func (h *QuizHandler) GetSubjectsWithQuizzes(c *gin.Context) {
+	subjects, err := h.quizUsecase.ListSubjectsWithPublishedQuizzes(c.Request.Context())
+	if err != nil {
+		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
+		return
+	}
+
+	c.JSON(http.StatusOK, gin.H{"data": subjects})
+}
Evidence
PR Compliance ID 736623 requires each added/modified source file to be ≤200 lines. The presence of
code at lines ~350-379 proves the file length exceeds the limit.

Rule 736623: Limit source files to 200 lines or fewer
backend/go/internal/interface/handler/quiz-handler.go[350-379]

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 source file exceeds the 200-line limit.

## Issue Context
The handler is currently implemented as a single large file; compliance requires source files to be 200 lines or fewer.

## Fix Focus Areas
- backend/go/internal/interface/handler/quiz-handler.go[1-379]

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


3. swd391_dangerous_malware.sql broken inserts 📘 Rule violation ≡ Correctness
Description
The PR removes the INSERT INTO public.academic_terms ... VALUES statement but leaves the tuple
list, producing invalid SQL that will fail to run. This violates the requirement that changed files
be free of syntax/compile errors.
Code

backend/database/swd391_dangerous_malware.sql[437]

-INSERT INTO public.academic_terms (id, name, term_order) VALUES
+
Evidence
PR Compliance ID 1333537 requires changed files to compile/parse successfully. The resulting SQL now
contains a bare tuple list beginning with ('b5d4a922-...') without any preceding `INSERT ...
VALUES`, which is invalid SQL.

Rule 1333537: Changed source files must be free of syntax errors and compile successfully
backend/database/swd391_dangerous_malware.sql[434-447]

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 SQL file contains orphaned value tuples because the `INSERT INTO ... VALUES` line was removed while the subsequent tuple rows remain.

## Issue Context
This makes the SQL file syntactically invalid and will fail when executed.

## Fix Focus Areas
- backend/database/swd391_dangerous_malware.sql[434-447]
- backend/database/swd391_dangerous_malware.sql[550-556]

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


View more (5)
4. Quiz usecases lack unit tests 📘 Rule violation ▣ Testability
Description
New core business logic was added under internal/application/quiz-usecase (e.g.,
GenerateQuizAsync) without any corresponding _test.go unit tests in the same package. This
reduces confidence in correctness of the use-case layer behavior and regressions.
Code

backend/go/internal/application/quiz-usecase/generate_quiz.go[R16-56]

+func (u *usecase) GenerateQuizAsync(ctx context.Context, req GenerateQuizReq) (*quiz.GenerationJob, error) {
+	// 1. Validate ownership & Subject consistency
+	if len(req.DocumentIDs) == 0 {
+		return nil, errors.New("at least one document must be selected")
+	}
+
+	for _, docID := range req.DocumentIDs {
+		doc, err := u.docRepo.FindByID(ctx, docID)
+		if err != nil {
+			return nil, fmt.Errorf("failed to fetch document %s: %v", docID, err)
+		}
+		
+		// 1. Quyền truy cập tài liệu: Public (school_wide) hoặc là của chính lecturer
+		if doc.Visibility != "school_wide" && doc.OwnerUserID != req.LecturerID {
+			return nil, fmt.Errorf("document %s is not public or owned by you", docID)
+		}
+
+		// 2. Tính đồng nhất môn học
+		if doc.SubjectID == nil || *doc.SubjectID != req.SubjectID {
+			return nil, errors.New("all selected documents must belong to the specified subject")
+		}
+	}
+
+	// 2. Create Background Job
+	job := &quiz.GenerationJob{
+		ID:         uuid.New(),
+		SubjectID:  req.SubjectID,
+		LecturerID: req.LecturerID,
+		Status:     quiz.JobStatusPending,
+		Progress:   0,
+	}
+
+	if err := u.quizRepo.CreateGenerationJob(ctx, job); err != nil {
+		return nil, err
+	}
+
+	// 3. Trigger Async Background Worker (In real app, this should use a queue like asynq/redis)
+	go u.runGenerationWorker(req, job.ID)
+
+	return job, nil
+}
Evidence
PR Compliance ID 736634 requires unit tests for core business logic in Go backend use-case packages.
The PR introduces exported use-case methods (e.g., GenerateQuizAsync) but no accompanying tests
were added for the quiz-usecase package.

Rule 736634: Require unit tests for core business logic in Go backend
backend/go/internal/application/quiz-usecase/generate_quiz.go[16-56]

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/modified application-layer use case logic lacks unit tests.

## Issue Context
Compliance requires at least one unit test per new/modified exported domain/use-case function/method in Go backend packages.

## Fix Focus Areas
- backend/go/internal/application/quiz-usecase/generate_quiz.go[16-56]
- backend/go/internal/application/quiz-usecase/manage_quiz.go[12-75]
- backend/go/internal/application/quiz-usecase/take_quiz.go[12-44]

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


5. Quiz answers exposed 🐞 Bug ⛨ Security
Description
Students can call the quiz detail endpoint and receive options containing IsCorrect, revealing the
correct answers and undermining quiz integrity. The shared route also does not enforce published
status for student access.
Code

backend/go/internal/interface/router/router.go[R147-166]

+		// Quiz routes
+		quizGroup := protected.Group("/quizzes")
+		{
+			// Shared
+			quizGroup.GET("/subjects", middleware.RequireRoles(2, 3), quizHandler.GetSubjectsWithQuizzes)
+			quizGroup.GET("/:quiz_id/detail", middleware.RequireRoles(2, 3), quizHandler.GetQuizDetail)
+			
+			// Lecturer
+			lecturerQuiz := quizGroup.Group("/lecturer", middleware.RequireRoles(2))
+			lecturerQuiz.POST("/generate", quizHandler.GenerateQuiz)
+			lecturerQuiz.GET("/jobs/:job_id", quizHandler.GetJobStatus)
+			lecturerQuiz.POST("/:quiz_id/publish", quizHandler.PublishQuiz)
+			lecturerQuiz.GET("/subject/:subject_id", quizHandler.ListQuizzesForLecturer)
+			
+			// Student
+			studentQuiz := quizGroup.Group("/student", middleware.RequireRoles(3))
+			studentQuiz.GET("/subject/:subject_id", quizHandler.ListQuizzesForStudent)
+			studentQuiz.POST("/:quiz_id/attempt", quizHandler.StartAttempt)
+			studentQuiz.POST("/attempt/submit", quizHandler.SubmitAttempt)
+			studentQuiz.GET("/:quiz_id/attempts", quizHandler.GetAttemptHistory)
Evidence
The router exposes the detail route to both lecturers and students; the handler returns questions
as-is; the usecase attaches options to each question; and Option.IsCorrect is an exported field so
it will be serialized to clients.

backend/go/internal/interface/router/router.go[147-166]
backend/go/internal/interface/handler/quiz-handler.go[214-231]
backend/go/internal/application/quiz-usecase/manage_quiz.go[70-89]
backend/go/internal/domain/quiz/entity.go[58-64]

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

## Issue description
`GET /api/quizzes/:quiz_id/detail` is accessible to role 3 (students) and returns `questions[].options[].IsCorrect`, exposing correct answers. The usecase also does not gate access to published-only for students.

## Issue Context
- Route is registered for roles (2,3).
- Handler returns `questions` directly.
- Domain `quiz.Option` includes exported `IsCorrect bool`, so Gin/JSON will serialize it by default.

## Fix Focus Areas
- backend/go/internal/interface/router/router.go[147-167]
- backend/go/internal/interface/handler/quiz-handler.go[203-232]
- backend/go/internal/application/quiz-usecase/manage_quiz.go[70-89]
- backend/go/internal/domain/quiz/entity.go[58-64]

## Suggested fix
1. Split endpoints or responses by role:
  - For students: return a DTO that omits `IsCorrect` (and possibly `Explanation`).
  - For lecturers: allow full detail (including correct answers) for authoring/preview.
2. Enforce status checks:
  - If requester is a student, require `quiz.status == 'published'`.
  - If requester is a lecturer, allow access only if `quiz.status == 'published'` OR `quiz.lecturer_id == requester`.
3. Implement role-aware logic in handler (using role from context) or add dedicated usecase methods like `GetQuizDetailForStudent` / `GetQuizDetailForLecturer`.

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


6. Preview bypasses publish 🐞 Bug ⛨ Security
Description
The student StartAttempt endpoint accepts a client-controlled ?preview=true, and the usecase
allows attempts on unpublished quizzes when isPreview is true. This lets students attempt
draft/unpublished quizzes if they know a quiz ID.
Code

backend/go/internal/interface/handler/quiz-handler.go[R245-258]

+func (h *QuizHandler) StartAttempt(c *gin.Context) {
+	quizIDStr := c.Param("quiz_id")
+	quizID, err := uuid.Parse(quizIDStr)
+	if err != nil {
+		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid quiz_id"})
+		return
+	}
+
+	userID := c.MustGet("user_id").(uuid.UUID)
+
+	isPreview := c.Query("preview") == "true"
+
+	attempt, err := h.quizUsecase.StartAttempt(c.Request.Context(), quizID, userID, isPreview)
+	if err != nil {
Evidence
The student handler reads preview from the query string and passes it through; the usecase
explicitly bypasses the published check when preview is true; and the router registers this endpoint
under the student-only group.

backend/go/internal/interface/handler/quiz-handler.go[245-258]
backend/go/internal/application/quiz-usecase/take_quiz.go[12-20]
backend/go/internal/interface/router/router.go[161-166]

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 student attempt endpoint treats `preview` as an authorization signal. A student can set `?preview=true` and bypass the published-only restriction.

## Issue Context
- Route is under `/api/quizzes/student/...` (role 3 only).
- Handler derives `isPreview` from query string.
- Usecase allows unpublished attempts when `!isPreview` is false.

## Fix Focus Areas
- backend/go/internal/interface/router/router.go[161-166]
- backend/go/internal/interface/handler/quiz-handler.go[245-264]
- backend/go/internal/application/quiz-usecase/take_quiz.go[12-21]

## Suggested fix
1. Remove `preview` support from student routes:
  - Hardcode `isPreview := false` in `QuizHandler.StartAttempt` for student group.
2. If preview is needed for lecturers, add a lecturer-only attempt route (middleware.RequireRoles(2)) and enforce:
  - `quiz.LecturerID == requesterID` for preview attempts.
3. In the usecase, treat preview as server-authorized (based on caller role/ownership), not client-provided.

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


7. Job status auth missing 🐞 Bug ⛨ Security
Description
GET /api/quizzes/lecturer/jobs/:job_id returns any generation job by ID without verifying the
authenticated lecturer owns the job. This allows one lecturer to query another lecturer’s job status
and metadata if job IDs are obtained.
Code

backend/go/internal/interface/handler/quiz-handler.go[R99-114]

+func (h *QuizHandler) GetJobStatus(c *gin.Context) {
+	jobIDStr := c.Param("job_id")
+	jobID, err := uuid.Parse(jobIDStr)
+	if err != nil {
+		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid job_id"})
+		return
+	}
+
+	job, err := h.quizUsecase.GetGenerationJobStatus(c.Request.Context(), jobID)
+	if err != nil {
+		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
+		return
+	}
+
+	c.JSON(http.StatusOK, job)
+}
Evidence
The handler parses the job ID and returns the job without reading requester identity; the usecase
method simply fetches by ID with no authorization checks.

backend/go/internal/interface/handler/quiz-handler.go[99-114]
backend/go/internal/application/quiz-usecase/generate_quiz.go[58-60]

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 job status endpoint fetches a generation job by `job_id` and returns it without checking `job.LecturerID == requesterID`.

## Issue Context
- Endpoint is lecturer-only, but still must enforce per-lecturer ownership.
- Usecase method is a direct passthrough to repository by ID.

## Fix Focus Areas
- backend/go/internal/interface/handler/quiz-handler.go[99-114]
- backend/go/internal/application/quiz-usecase/generate_quiz.go[58-60]

## Suggested fix
1. In `QuizHandler.GetJobStatus`, read `lecturerID := c.MustGet("user_id").(uuid.UUID)` and compare it with `job.LecturerID`.
2. If mismatch, return 404 (preferable to avoid resource enumeration) or 403.
3. Optionally, move the check into a new usecase method `GetGenerationJobStatusForLecturer(ctx, jobID, lecturerID)` to keep authz in the application layer.

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


8. Quiz generation ignores errors 🐞 Bug ☼ Reliability
Description
During quiz generation, errors from creating questions/options are ignored and the job is still
marked completed, which can produce incomplete/broken quizzes while reporting success. Writes are
also not wrapped in a transaction, so partial persistence is likely under failure.
Code

backend/go/internal/application/quiz-usecase/generate_quiz.go[R184-225]

+	for i, q := range llmResult.Questions {
+		qType := quiz.TypeSingleChoice
+		if q.Type == "multiple_choice" {
+			qType = quiz.TypeMultipleChoice
+		} else if q.Type == "true_false" {
+			qType = quiz.TypeTrueFalse
+		}
+
+		newQ := &quiz.Question{
+			ID:           uuid.New(),
+			QuizID:       newQuiz.ID,
+			QuestionType: qType,
+			Content:      q.Content,
+			OrderIndex:   i + 1,
+			CreatedAt:    time.Now(),
+		}
+		if q.Explanation != "" {
+			exp := q.Explanation
+			newQ.Explanation = &exp
+		}
+		_ = u.quizRepo.CreateQuestion(ctx, newQ)
+
+		for j, opt := range q.Options {
+			newOpt := &quiz.Option{
+				ID:         uuid.New(),
+				QuestionID: newQ.ID,
+				Content:    opt.Content,
+				IsCorrect:  opt.IsCorrect,
+				OrderIndex: j + 1,
+			}
+			_ = u.quizRepo.CreateOption(ctx, newOpt)
+		}
+	}
+
+	// 6. Update Job Status
+	job, _ := u.quizRepo.GetGenerationJobByID(ctx, jobID)
+	if job != nil {
+		job.Status = quiz.JobStatusCompleted
+		job.ResultQuizID = &newQuiz.ID
+		job.Progress = 100
+		_ = u.quizRepo.UpdateGenerationJob(ctx, job)
+	}
Evidence
The worker explicitly discards errors from CreateQuestion/CreateOption and then marks the job
completed with a result quiz ID, so failures can silently produce incomplete quizzes.

backend/go/internal/application/quiz-usecase/generate_quiz.go[184-225]

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

## Issue description
`runGenerationWorker` ignores persistence errors for questions/options and still updates the job to `completed`, potentially leaving corrupted/incomplete quiz data.

## Issue Context
- Question creation and option creation use `_ = ...` (error discarded).
- Job completion update happens regardless of those errors.

## Fix Focus Areas
- backend/go/internal/application/quiz-usecase/generate_quiz.go[168-225]
- backend/go/internal/infrastructure/repository/postgres/quiz_repo.go[22-260]

## Suggested fix
1. Stop discarding errors:
  - If `CreateQuestion` or `CreateOption` fails, call `failJob(err)` and return.
2. Make persistence atomic:
  - Add transaction support in quiz repository (e.g., methods that accept `pgx.Tx`), or add a `CreateQuizWithQuestionsAndOptions(...)` method that performs all inserts in a single transaction.
3. Update job status lifecycle:
  - Set job to `processing` at start and update progress.
  - Only set `completed` after *all* DB writes succeed.
4. Consider cleanup on failure:
  - If quiz row was created but later writes fail, delete the quiz (or roll back via transaction).

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



Remediation recommended

9. Chat chunk errors hidden 🐞 Bug ☼ Reliability
Description
When a chat session has multiple documents, per-document SearchSimilarChunks errors are silently
ignored, which can degrade grounding (missing context) without surfacing retrieval failures. This
makes failures hard to detect and can lead to lower-quality or misleading responses.
Code

backend/go/internal/application/chat-usecase/send-message.go[R69-83]

	// 5. Semantic search — find top-K similar chunks
-	chunks, err := uc.msgRepo.SearchSimilarChunks(ctx, queryEmbedding, session.CourseID, session.DocumentIDs, topKChunks)
-	if err != nil {
-		return nil, fmt.Errorf("failed to search chunks: %w", err)
+	var chunks []*message.SimilarChunk
+
+	if len(session.DocumentIDs) > 1 {
+		// Retrieve chunks for each document to ensure balanced representation in comparison
+		chunksPerDoc := 5
+		if len(session.DocumentIDs) > 2 {
+			chunksPerDoc = 3
+		}
+		for _, docID := range session.DocumentIDs {
+			docChunks, docErr := uc.msgRepo.SearchSimilarChunks(ctx, queryEmbedding, session.CourseID, []uuid.UUID{docID}, chunksPerDoc)
+			if docErr == nil {
+				chunks = append(chunks, docChunks...)
+			}
+		}
Evidence
The multi-document retrieval loop drops docErr and continues, so failures in retrieval are not
reported or logged and the remaining pipeline runs with partial context.

backend/go/internal/application/chat-usecase/send-message.go[69-83]

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

## Issue description
In multi-document sessions, chunk retrieval errors are ignored (`docErr` is dropped). This can cause partial/empty retrieval context without any error/log signal.

## Issue Context
- Code loops documents and appends chunks only when `docErr == nil`.
- No logging/metrics or error aggregation exists.

## Fix Focus Areas
- backend/go/internal/application/chat-usecase/send-message.go[69-89]
- backend/go/internal/application/chat-usecase/stream-message.go[51-72]

## Suggested fix
1. Track retrieval errors:
  - Accumulate `docErr`s and (at minimum) log them with docID/sessionID.
2. Decide policy:
  - If *any* document retrieval fails, return an error (strict) OR proceed with partial results but include a warning/metric.
3. If all retrieval attempts fail (chunks empty) and there were errors, return a 5xx (or a specific error) rather than silently proceeding as if retrieval succeeded.

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


10. Duplicate rows.Close defer 🐞 Bug ⚙ Maintainability
Description
FindAllAdmin redundantly checks err twice and defers rows.Close() twice, creating
unreachable/duplicated cleanup logic that makes the function harder to maintain. This should be
simplified to a single error check and a single defer.
Code

backend/go/internal/infrastructure/repository/postgres/document-repository.go[R405-412]

	}
	defer rows.Close()

+	if err != nil {
+		return nil, 0, err
+	}
+	defer rows.Close()
+
Evidence
The function already returns on err != nil after Query, yet it repeats the same check and `defer
rows.Close()` again, indicating an introduced duplication.

backend/go/internal/infrastructure/repository/postgres/document-repository.go[402-412]

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

## Issue description
After a successful `Query`, the function repeats `if err != nil` and `defer rows.Close()` a second time. This is redundant and confusing.

## Issue Context
The second `if err != nil` is unreachable because the earlier check already returns on error.

## Fix Focus Areas
- backend/go/internal/infrastructure/repository/postgres/document-repository.go[402-412]

## Suggested fix
Delete the second `if err != nil { ... }` block and the second `defer rows.Close()` so the control flow is:
- query
- error check
- single `defer rows.Close()`
- scan loop

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


11. Public docs blocked for quiz 🐞 Bug ≡ Correctness
Description
Quiz generation treats only visibility == "school_wide" as public, but the API documents
visibility as public|school_wide|private. This will incorrectly reject public documents during
quiz generation even though they are non-private.
Code

backend/go/internal/application/quiz-usecase/generate_quiz.go[R28-31]

+		// 1. Quyền truy cập tài liệu: Public (school_wide) hoặc là của chính lecturer
+		if doc.Visibility != "school_wide" && doc.OwnerUserID != req.LecturerID {
+			return nil, fmt.Errorf("document %s is not public or owned by you", docID)
+		}
Evidence
Quiz generation currently only allows school_wide as “public”, while the document upload API
states that public is also a supported visibility value.

backend/go/internal/application/quiz-usecase/generate_quiz.go[22-31]
backend/go/internal/interface/handler/document-handler.go[145-164]

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

## Issue description
`GenerateQuizAsync` rejects documents with `visibility == "public"` (documented as a valid non-private visibility) unless owned by the lecturer.

## Issue Context
The document upload API explicitly documents `visibility (public, school_wide, private)`.

## Fix Focus Areas
- backend/go/internal/application/quiz-usecase/generate_quiz.go[22-36]
- backend/go/internal/interface/handler/document-handler.go[145-164]

## Suggested fix
Change the visibility check to allow any non-private visibility, e.g.:
- allow `doc.Visibility != "private"` as public/school-wide
OR
- explicitly allow both `public` and `school_wide`.
Keep the ownership allowance for private docs (owner must match).

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


Grey Divider

Qodo Logo

Comment on lines +11 to +13
"github.com/google/uuid"
"swd392-chatbot-rag/internal/domain/quiz"
"swd392-chatbot-rag/internal/infrastructure/llm"

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. quiz-usecase imports infrastructure/llm 📘 Rule violation ⌂ Architecture

The application-layer quiz-usecase depends directly on internal/infrastructure/llm, violating
the required four-layer dependency direction (application must not import infrastructure). This
makes the use case layer tightly coupled to a specific infra implementation instead of an
abstraction.
Agent Prompt
## Issue description
`backend/go/internal/application/quiz-usecase/generate_quiz.go` is in the application layer but imports `swd392-chatbot-rag/internal/infrastructure/llm`, coupling application to infrastructure.

## Issue Context
Compliance requires a strict four-layer architecture where application depends on domain abstractions, not infrastructure packages.

## Fix Focus Areas
- backend/go/internal/application/quiz-usecase/generate_quiz.go[11-15]
- backend/go/internal/application/quiz-usecase/usecase.go[53-67]
- backend/go/internal/interface/router/router.go[74-99]

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

Comment on lines +350 to +379
return
}

userID := c.MustGet("user_id").(uuid.UUID)

attempts, err := h.quizUsecase.GetAttemptHistory(c.Request.Context(), quizID, userID)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}

c.JSON(http.StatusOK, gin.H{"data": attempts})
}

// @Summary Get all subjects that have published quizzes
// @Description Returns a list of subjects that contain at least one published quiz.
// @Tags Quiz
// @Produce json
// @Success 200 {object} map[string]interface{}
// @Failure 500 {object} map[string]interface{}
// @Router /api/quizzes/subjects [get]
func (h *QuizHandler) GetSubjectsWithQuizzes(c *gin.Context) {
subjects, err := h.quizUsecase.ListSubjectsWithPublishedQuizzes(c.Request.Context())
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}

c.JSON(http.StatusOK, gin.H{"data": subjects})
}

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. quiz-handler.go exceeds 200 lines 📘 Rule violation ⚙ Maintainability

backend/go/internal/interface/handler/quiz-handler.go is 379 lines long, exceeding the 200-line
maximum for source files. This violates the file size limit even though it is a single new file.
Agent Prompt
## Issue description
A source file exceeds the 200-line limit.

## Issue Context
The handler is currently implemented as a single large file; compliance requires source files to be 200 lines or fewer.

## Fix Focus Areas
- backend/go/internal/interface/handler/quiz-handler.go[1-379]

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

-- ALTER TABLE public.verification OWNER TO postgres;

--
INSERT INTO public.academic_terms (id, name, term_order) VALUES

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

3. swd391_dangerous_malware.sql broken inserts 📘 Rule violation ≡ Correctness

The PR removes the INSERT INTO public.academic_terms ... VALUES statement but leaves the tuple
list, producing invalid SQL that will fail to run. This violates the requirement that changed files
be free of syntax/compile errors.
Agent Prompt
## Issue description
The SQL file contains orphaned value tuples because the `INSERT INTO ... VALUES` line was removed while the subsequent tuple rows remain.

## Issue Context
This makes the SQL file syntactically invalid and will fail when executed.

## Fix Focus Areas
- backend/database/swd391_dangerous_malware.sql[434-447]
- backend/database/swd391_dangerous_malware.sql[550-556]

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

Comment on lines +16 to +56
func (u *usecase) GenerateQuizAsync(ctx context.Context, req GenerateQuizReq) (*quiz.GenerationJob, error) {
// 1. Validate ownership & Subject consistency
if len(req.DocumentIDs) == 0 {
return nil, errors.New("at least one document must be selected")
}

for _, docID := range req.DocumentIDs {
doc, err := u.docRepo.FindByID(ctx, docID)
if err != nil {
return nil, fmt.Errorf("failed to fetch document %s: %v", docID, err)
}

// 1. Quyền truy cập tài liệu: Public (school_wide) hoặc là của chính lecturer
if doc.Visibility != "school_wide" && doc.OwnerUserID != req.LecturerID {
return nil, fmt.Errorf("document %s is not public or owned by you", docID)
}

// 2. Tính đồng nhất môn học
if doc.SubjectID == nil || *doc.SubjectID != req.SubjectID {
return nil, errors.New("all selected documents must belong to the specified subject")
}
}

// 2. Create Background Job
job := &quiz.GenerationJob{
ID: uuid.New(),
SubjectID: req.SubjectID,
LecturerID: req.LecturerID,
Status: quiz.JobStatusPending,
Progress: 0,
}

if err := u.quizRepo.CreateGenerationJob(ctx, job); err != nil {
return nil, err
}

// 3. Trigger Async Background Worker (In real app, this should use a queue like asynq/redis)
go u.runGenerationWorker(req, job.ID)

return job, nil
}

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

4. Quiz usecases lack unit tests 📘 Rule violation ▣ Testability

New core business logic was added under internal/application/quiz-usecase (e.g.,
GenerateQuizAsync) without any corresponding _test.go unit tests in the same package. This
reduces confidence in correctness of the use-case layer behavior and regressions.
Agent Prompt
## Issue description
New/modified application-layer use case logic lacks unit tests.

## Issue Context
Compliance requires at least one unit test per new/modified exported domain/use-case function/method in Go backend packages.

## Fix Focus Areas
- backend/go/internal/application/quiz-usecase/generate_quiz.go[16-56]
- backend/go/internal/application/quiz-usecase/manage_quiz.go[12-75]
- backend/go/internal/application/quiz-usecase/take_quiz.go[12-44]

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

Comment on lines +147 to +166
// Quiz routes
quizGroup := protected.Group("/quizzes")
{
// Shared
quizGroup.GET("/subjects", middleware.RequireRoles(2, 3), quizHandler.GetSubjectsWithQuizzes)
quizGroup.GET("/:quiz_id/detail", middleware.RequireRoles(2, 3), quizHandler.GetQuizDetail)

// Lecturer
lecturerQuiz := quizGroup.Group("/lecturer", middleware.RequireRoles(2))
lecturerQuiz.POST("/generate", quizHandler.GenerateQuiz)
lecturerQuiz.GET("/jobs/:job_id", quizHandler.GetJobStatus)
lecturerQuiz.POST("/:quiz_id/publish", quizHandler.PublishQuiz)
lecturerQuiz.GET("/subject/:subject_id", quizHandler.ListQuizzesForLecturer)

// Student
studentQuiz := quizGroup.Group("/student", middleware.RequireRoles(3))
studentQuiz.GET("/subject/:subject_id", quizHandler.ListQuizzesForStudent)
studentQuiz.POST("/:quiz_id/attempt", quizHandler.StartAttempt)
studentQuiz.POST("/attempt/submit", quizHandler.SubmitAttempt)
studentQuiz.GET("/:quiz_id/attempts", quizHandler.GetAttemptHistory)

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

5. Quiz answers exposed 🐞 Bug ⛨ Security

Students can call the quiz detail endpoint and receive options containing IsCorrect, revealing the
correct answers and undermining quiz integrity. The shared route also does not enforce published
status for student access.
Agent Prompt
## Issue description
`GET /api/quizzes/:quiz_id/detail` is accessible to role 3 (students) and returns `questions[].options[].IsCorrect`, exposing correct answers. The usecase also does not gate access to published-only for students.

## Issue Context
- Route is registered for roles (2,3).
- Handler returns `questions` directly.
- Domain `quiz.Option` includes exported `IsCorrect bool`, so Gin/JSON will serialize it by default.

## Fix Focus Areas
- backend/go/internal/interface/router/router.go[147-167]
- backend/go/internal/interface/handler/quiz-handler.go[203-232]
- backend/go/internal/application/quiz-usecase/manage_quiz.go[70-89]
- backend/go/internal/domain/quiz/entity.go[58-64]

## Suggested fix
1. Split endpoints or responses by role:
   - For students: return a DTO that omits `IsCorrect` (and possibly `Explanation`).
   - For lecturers: allow full detail (including correct answers) for authoring/preview.
2. Enforce status checks:
   - If requester is a student, require `quiz.status == 'published'`.
   - If requester is a lecturer, allow access only if `quiz.status == 'published'` OR `quiz.lecturer_id == requester`.
3. Implement role-aware logic in handler (using role from context) or add dedicated usecase methods like `GetQuizDetailForStudent` / `GetQuizDetailForLecturer`.

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

Comment on lines +99 to +114
func (h *QuizHandler) GetJobStatus(c *gin.Context) {
jobIDStr := c.Param("job_id")
jobID, err := uuid.Parse(jobIDStr)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid job_id"})
return
}

job, err := h.quizUsecase.GetGenerationJobStatus(c.Request.Context(), jobID)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}

c.JSON(http.StatusOK, job)
}

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. Job status auth missing 🐞 Bug ⛨ Security

GET /api/quizzes/lecturer/jobs/:job_id returns any generation job by ID without verifying the
authenticated lecturer owns the job. This allows one lecturer to query another lecturer’s job status
and metadata if job IDs are obtained.
Agent Prompt
## Issue description
The job status endpoint fetches a generation job by `job_id` and returns it without checking `job.LecturerID == requesterID`.

## Issue Context
- Endpoint is lecturer-only, but still must enforce per-lecturer ownership.
- Usecase method is a direct passthrough to repository by ID.

## Fix Focus Areas
- backend/go/internal/interface/handler/quiz-handler.go[99-114]
- backend/go/internal/application/quiz-usecase/generate_quiz.go[58-60]

## Suggested fix
1. In `QuizHandler.GetJobStatus`, read `lecturerID := c.MustGet("user_id").(uuid.UUID)` and compare it with `job.LecturerID`.
2. If mismatch, return 404 (preferable to avoid resource enumeration) or 403.
3. Optionally, move the check into a new usecase method `GetGenerationJobStatusForLecturer(ctx, jobID, lecturerID)` to keep authz in the application layer.

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

Comment on lines +184 to +225
for i, q := range llmResult.Questions {
qType := quiz.TypeSingleChoice
if q.Type == "multiple_choice" {
qType = quiz.TypeMultipleChoice
} else if q.Type == "true_false" {
qType = quiz.TypeTrueFalse
}

newQ := &quiz.Question{
ID: uuid.New(),
QuizID: newQuiz.ID,
QuestionType: qType,
Content: q.Content,
OrderIndex: i + 1,
CreatedAt: time.Now(),
}
if q.Explanation != "" {
exp := q.Explanation
newQ.Explanation = &exp
}
_ = u.quizRepo.CreateQuestion(ctx, newQ)

for j, opt := range q.Options {
newOpt := &quiz.Option{
ID: uuid.New(),
QuestionID: newQ.ID,
Content: opt.Content,
IsCorrect: opt.IsCorrect,
OrderIndex: j + 1,
}
_ = u.quizRepo.CreateOption(ctx, newOpt)
}
}

// 6. Update Job Status
job, _ := u.quizRepo.GetGenerationJobByID(ctx, jobID)
if job != nil {
job.Status = quiz.JobStatusCompleted
job.ResultQuizID = &newQuiz.ID
job.Progress = 100
_ = u.quizRepo.UpdateGenerationJob(ctx, job)
}

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

8. Quiz generation ignores errors 🐞 Bug ☼ Reliability

During quiz generation, errors from creating questions/options are ignored and the job is still
marked completed, which can produce incomplete/broken quizzes while reporting success. Writes are
also not wrapped in a transaction, so partial persistence is likely under failure.
Agent Prompt
## Issue description
`runGenerationWorker` ignores persistence errors for questions/options and still updates the job to `completed`, potentially leaving corrupted/incomplete quiz data.

## Issue Context
- Question creation and option creation use `_ = ...` (error discarded).
- Job completion update happens regardless of those errors.

## Fix Focus Areas
- backend/go/internal/application/quiz-usecase/generate_quiz.go[168-225]
- backend/go/internal/infrastructure/repository/postgres/quiz_repo.go[22-260]

## Suggested fix
1. Stop discarding errors:
   - If `CreateQuestion` or `CreateOption` fails, call `failJob(err)` and return.
2. Make persistence atomic:
   - Add transaction support in quiz repository (e.g., methods that accept `pgx.Tx`), or add a `CreateQuizWithQuestionsAndOptions(...)` method that performs all inserts in a single transaction.
3. Update job status lifecycle:
   - Set job to `processing` at start and update progress.
   - Only set `completed` after *all* DB writes succeed.
4. Consider cleanup on failure:
   - If quiz row was created but later writes fail, delete the quiz (or roll back via transaction).

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

Comment on lines 69 to +83
// 5. Semantic search — find top-K similar chunks
chunks, err := uc.msgRepo.SearchSimilarChunks(ctx, queryEmbedding, session.CourseID, session.DocumentIDs, topKChunks)
if err != nil {
return nil, fmt.Errorf("failed to search chunks: %w", err)
var chunks []*message.SimilarChunk

if len(session.DocumentIDs) > 1 {
// Retrieve chunks for each document to ensure balanced representation in comparison
chunksPerDoc := 5
if len(session.DocumentIDs) > 2 {
chunksPerDoc = 3
}
for _, docID := range session.DocumentIDs {
docChunks, docErr := uc.msgRepo.SearchSimilarChunks(ctx, queryEmbedding, session.CourseID, []uuid.UUID{docID}, chunksPerDoc)
if docErr == nil {
chunks = append(chunks, docChunks...)
}
}

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

9. Chat chunk errors hidden 🐞 Bug ☼ Reliability

When a chat session has multiple documents, per-document SearchSimilarChunks errors are silently
ignored, which can degrade grounding (missing context) without surfacing retrieval failures. This
makes failures hard to detect and can lead to lower-quality or misleading responses.
Agent Prompt
## Issue description
In multi-document sessions, chunk retrieval errors are ignored (`docErr` is dropped). This can cause partial/empty retrieval context without any error/log signal.

## Issue Context
- Code loops documents and appends chunks only when `docErr == nil`.
- No logging/metrics or error aggregation exists.

## Fix Focus Areas
- backend/go/internal/application/chat-usecase/send-message.go[69-89]
- backend/go/internal/application/chat-usecase/stream-message.go[51-72]

## Suggested fix
1. Track retrieval errors:
   - Accumulate `docErr`s and (at minimum) log them with docID/sessionID.
2. Decide policy:
   - If *any* document retrieval fails, return an error (strict) OR proceed with partial results but include a warning/metric.
3. If all retrieval attempts fail (chunks empty) and there were errors, return a 5xx (or a specific error) rather than silently proceeding as if retrieval succeeded.

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

Comment on lines 405 to +412
}
defer rows.Close()

if err != nil {
return nil, 0, err
}
defer rows.Close()

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

10. Duplicate rows.close defer 🐞 Bug ⚙ Maintainability

FindAllAdmin redundantly checks err twice and defers rows.Close() twice, creating
unreachable/duplicated cleanup logic that makes the function harder to maintain. This should be
simplified to a single error check and a single defer.
Agent Prompt
## Issue description
After a successful `Query`, the function repeats `if err != nil` and `defer rows.Close()` a second time. This is redundant and confusing.

## Issue Context
The second `if err != nil` is unreachable because the earlier check already returns on error.

## Fix Focus Areas
- backend/go/internal/infrastructure/repository/postgres/document-repository.go[402-412]

## Suggested fix
Delete the second `if err != nil { ... }` block and the second `defer rows.Close()` so the control flow is:
- query
- error check
- single `defer rows.Close()`
- scan loop

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

Comment on lines +28 to +31
// 1. Quyền truy cập tài liệu: Public (school_wide) hoặc là của chính lecturer
if doc.Visibility != "school_wide" && doc.OwnerUserID != req.LecturerID {
return nil, fmt.Errorf("document %s is not public or owned by you", docID)
}

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

11. Public docs blocked for quiz 🐞 Bug ≡ Correctness

Quiz generation treats only visibility == "school_wide" as public, but the API documents
visibility as public|school_wide|private. This will incorrectly reject public documents during
quiz generation even though they are non-private.
Agent Prompt
## Issue description
`GenerateQuizAsync` rejects documents with `visibility == "public"` (documented as a valid non-private visibility) unless owned by the lecturer.

## Issue Context
The document upload API explicitly documents `visibility (public, school_wide, private)`.

## Fix Focus Areas
- backend/go/internal/application/quiz-usecase/generate_quiz.go[22-36]
- backend/go/internal/interface/handler/document-handler.go[145-164]

## Suggested fix
Change the visibility check to allow any non-private visibility, e.g.:
- allow `doc.Visibility != "private"` as public/school-wide
OR
- explicitly allow both `public` and `school_wide`.
Keep the ownership allowance for private docs (owner must match).

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

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Add AI quiz system, redesign UI, and remove academic term/moderation features

✨ Enhancement 🐞 Bug fix 🕐 40+ Minutes

Grey Divider

AI Description

• Introduces a full quiz module: DB schema, domain entities, repository, use cases, handlers, and
 routes for AI-generated quizzes, publishing, attempts, and grading.
• Reworks document management: multi-select filters (subject/type/language/source), document explore
 & bookmarking views, upload/detail/inline-edit UI, and markdown-table-based document comparison with
 PDF export.
• Removes the "academic term" concept end-to-end (DB columns, domain fields, repositories, handlers,
 frontend) and removes document reporting/moderation functionality.
• Overhauls frontend UI/layout (sidebar, app-layout, admin views, chat, practice/progress views)
 with a new dark-themed shared design system.
• Adds chat session/document linkage tables and refines chat streaming/send-message use cases.
Diagram

graph TD
  FE["Frontend Views/Hooks"] --> API["REST API /api/quizzes /api/documents"]
  API --> Router["Gin Router"] --> QuizHandler["Quiz Handler"] --> QuizUsecase["Quiz Usecase"] --> QuizRepo[(Quiz Tables)]
  Router --> DocHandler["Document Handler"] --> DocUsecase["Document Usecase"] --> DocRepo[(Documents Table)]
  QuizUsecase --> LLM{{"Gemini LLM Client"}}
  DocUsecase --> LLM
  subgraph Legend
    direction LR
    _svc([Service]) ~~~ _db[(Database)] ~~~ _ext{{External}}
  end
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. In-process goroutine (current approach)
  • ➕ Simple to implement, no extra infra
  • ➕ Fast to ship
  • ➖ Jobs lost on server restart/crash
  • ➖ No retry or concurrency limits
  • ➖ Hard to scale horizontally
2. Dedicated job queue (asynq/Redis, Sidekiq-style)
  • ➕ Persistent, retryable jobs
  • ➕ Scales across workers
  • ➕ Better observability
  • ➖ Requires additional infrastructure (Redis)
  • ➖ More setup and operational overhead

Recommendation: The async quiz-generation worker is spawned with a bare go statement using context.Background(), with no job queue, retry, or backpressure control — acceptable for a prototype but risky for production load or process restarts. Using a persistent job queue (e.g., Redis/asynq, as the code comment itself acknowledges) would be more resilient. Given the current scope and team velocity, keeping the goroutine-based approach for now is reasonable, but should be flagged as tech debt.

Files changed (118) +16310 / -10438

Enhancement (27) +4259 / -2491
router.goWire up quiz routes and remove academic-term routes +30/-7

Wire up quiz routes and remove academic-term routes

• Registers new /quizzes route group (shared/lecturer/student) and removes admin academic-term CRUD routes and term repository wiring.

backend/go/internal/interface/router/router.go

compare.goRework document comparison to return Markdown table via LLM +308/-84

Rework document comparison to return Markdown table via LLM

• Replaces structured JSON comparison result with a Markdown-table-based LLM prompt/response, adds cleanup helpers, and rewrites PDF export to render the Markdown table with custom fonts and landscape layout.

backend/go/internal/application/document-usecase/compare.go

send-message.goExtend chat send-message use case +24/-5

Extend chat send-message use case

• Adds logic tied to chat session document linkage / additional handling for send-message flow.

backend/go/internal/application/chat-usecase/send-message.go

stream-message.goExtend chat stream-message use case +23/-4

Extend chat stream-message use case

• Adds logic tied to chat session document linkage / additional handling for streaming responses.

backend/go/internal/application/chat-usecase/stream-message.go

system_prompt.goTweak system prompt content +2/-2

Tweak system prompt content

• Minor updates to the chat system prompt text.

backend/go/pkg/prompt/system_prompt.go

document.tsAdd bookmark/export/public document APIs; simplify comparison type +33/-10

Add bookmark/export/public document APIs; simplify comparison type

• Adds getPublicDocuments, getBookmarks, toggleBookmark, exportCompareDocuments methods and simplifies ComparisonResult to a markdown string.

frontend/src/api/document.ts

chat.tsExtend chat API client +3/-1

Extend chat API client

• Minor additions to chat API to support session/document linkage.

frontend/src/api/chat.ts

page.tsxRedesign document detail page and disable reporting +149/-106

Redesign document detail page and disable reporting

• Reworks layout to sticky header + content sections, adds bookmark toggle UI, removes academic term references, and hardcodes canReport to false.

frontend/src/app/[role]/documents/[id]/page.tsx

globals.cssUpdate global styles for dark theme +5/-19

Update global styles for dark theme

• Adjusts global CSS variables/rules to support the new shared design system.

frontend/src/app/globals.css

layout.tsxUpdate root layout for new theme/providers +10/-3

Update root layout for new theme/providers

• Adjusts root layout markup/providers to support new UI framework.

frontend/src/app/layout.tsx

page.tsxMinor landing page update +1/-1

Minor landing page update

• Small tweak to the root page component.

frontend/src/app/page.tsx

page-shell.tsxUpdate page shell styling +19/-15

Update page shell styling

• Adjusts shared page shell component to match new design system.

frontend/src/components/ui/page-shell.tsx

compare-view.tsxRework compare view to render Markdown table +435/-204

Rework compare view to render Markdown table

• Replaces structured comparison UI with Markdown table rendering and export controls matching the new backend response shape.

frontend/src/components/common/documents/compare-view.tsx

chat-view.tsxOverhaul chat view UI and session/document handling +633/-411

Overhaul chat view UI and session/document handling

• Large rework of the chat interface styling and logic, including session-document association support.

frontend/src/components/common/chat/chat-view.tsx

sessions-view.tsxUpdate chat sessions view +72/-93

Update chat sessions view

• Adjusts sessions list UI/logic to align with new chat/session-document features.

frontend/src/components/common/chat/sessions-view.tsx

admin-dashboard-view.tsxRedesign admin dashboard +175/-225

Redesign admin dashboard

• Large rework of the admin dashboard layout/styling to match the new design system.

frontend/src/components/admin/dashboard/admin-dashboard-view.tsx

admin-documents-view.tsxUpdate admin documents view for multi-subject filtering +50/-38

Update admin documents view for multi-subject filtering

• Adjusts admin document management UI to use multi-select subject filters and new styling.

frontend/src/components/admin/documents/admin-documents-view.tsx

admin-settings-view.tsxUpdate admin settings view styling +18/-8

Update admin settings view styling

• Minor styling/layout updates consistent with the new design system.

frontend/src/components/admin/settings/admin-settings-view.tsx

admin-users-view.tsxUpdate admin users view styling and table +58/-49

Update admin users view styling and table

• Updates the admin users management UI to match the redesigned layout/table components.

frontend/src/components/admin/users/admin-users-view.tsx

user-table.tsxUpdate user table component +34/-42

Update user table component

• Restyles/reworks the shared user table to align with new data-table patterns.

frontend/src/components/admin/users/user-table.tsx

admin-assignments-view.tsxUpdate admin assignments view styling +17/-9

Update admin assignments view styling

• Minor styling/layout adjustments consistent with new design system.

frontend/src/components/admin/assignment/admin-assignments-view.tsx

my-documents-view.tsxOverhaul my-documents view for lecturers +576/-297

Overhaul my-documents view for lecturers

• Large rework integrating new filters, upload modal, inline edit, and detail panel components.

frontend/src/components/lecturer/documents/my-documents-view.tsx

practice-view.tsxOverhaul lecturer practice/quiz management view +642/-403

Overhaul lecturer practice/quiz management view

• Large rework integrating the new quiz generation, publishing, and listing flows into the practice view.

frontend/src/components/lecturer/practice/practice-view.tsx

student-documents-view.tsxUpdate student documents view for multi-filters +38/-32

Update student documents view for multi-filters

• Adjusts student document browsing UI to use the new shared filters component.

frontend/src/components/student/documents/student-documents-view.tsx

take-quiz-view.tsxRework take-quiz view for real quiz API and grading +456/-302

Rework take-quiz view for real quiz API and grading

• Overhauls the quiz-taking UI to integrate with real attempt start/submit endpoints and multi-answer question types.

frontend/src/components/student/quiz/take-quiz-view.tsx

use-practice.tsExtend practice hook for quiz management +204/-1

Extend practice hook for quiz management

• Adds logic for generating, publishing, and listing quizzes within the lecturer practice flow.

frontend/src/hooks/lecturer/use-practice.ts

use-quiz.tsRework student quiz hook for real API integration +244/-120

Rework student quiz hook for real API integration

• Replaces mock quiz/history data with real subject/quiz/attempt fetching, submission, and grading via the new quiz API.

frontend/src/hooks/student/use-quiz.ts

Bug fix (3) +11 / -8
bookmark-repository.goDedupe bookmarks and drop academic term join +9/-6

Dedupe bookmarks and drop academic term join

• Groups user_bookmarks by user/document to avoid duplicates and removes academic_terms join from bookmarked documents query.

backend/go/internal/infrastructure/repository/postgres/bookmark-repository.go

use-auth.tsMinor auth hook tweak +1/-1

Minor auth hook tweak

• Small adjustment to the authentication hook.

frontend/src/hooks/use-auth.ts

middleware.tsMinor middleware tweak +1/-1

Minor middleware tweak

• Small adjustment to Next.js middleware logic (routing/auth guard).

frontend/src/middleware.ts

Refactor (42) +904 / -3499
swd391_dangerous_malware.sqlRemove academic_terms table and references from schema dump +19/-19

Remove academic_terms table and references from schema dump

• Strips academic_terms table, foreign keys, and seed data from the reference SQL dump as part of removing the academic term concept.

backend/database/swd391_dangerous_malware.sql

admin-handler.goRemove academic term admin endpoints; support multi-subject filtering +10/-109

Remove academic term admin endpoints; support multi-subject filtering

• Deletes CreateAcademicTerm/UpdateAcademicTerm/DeleteAcademicTerm handlers and switches subject filtering to comma-separated multi-value IDs.

backend/go/internal/interface/handler/admin-handler.go

document-handler.goSupport multi-value filters and remove academic term params +39/-88

Support multi-value filters and remove academic term params

• Introduces parseUUIDs helper for comma-separated filter query params (subject/type/language/source) and strips academic_term_id from upload/edit/list flows.

backend/go/internal/interface/handler/document-handler.go

manage.goDrop term ID param from UpdateDocument +2/-3

Drop term ID param from UpdateDocument

• Removes termID parameter and assignment from document update logic.

backend/go/internal/application/document-usecase/manage.go

search.goSwitch document filters to multi-ID arrays; drop academic term +13/-18

Switch document filters to multi-ID arrays; drop academic term

• GetMyDocuments/GetAllDocuments/GetDocumentDetails now accept slices of subject/type/language/source IDs instead of single pointers and no longer reference academic term.

backend/go/internal/application/document-usecase/search.go

upload.goRemove academic term from upload flow +1/-2

Remove academic term from upload flow

• Drops academic term handling from the document upload use case.

backend/go/internal/application/document-usecase/upload.go

manage_documents.goSupport multi-subject filtering for admin documents +3/-4

Support multi-subject filtering for admin documents

• GetAdminDocuments now accepts a slice of subject IDs and drops academic term field from the DTO mapping.

backend/go/internal/application/admin-usecase/manage_documents.go

terms.goRemove academic term lookup use case +0/-108

Remove academic term lookup use case

• Deletes CRUD operations (Get/Create/Update/Delete) for academic terms.

backend/go/internal/application/lookup-usecase/terms.go

usecase.goRemove term repository dependency from lookup usecase +1/-4

Remove term repository dependency from lookup usecase

• Removes termRepo field and wiring from LookupUseCase constructor.

backend/go/internal/application/lookup-usecase/usecase.go

subjects.goRemove academic term from subject create/update +10/-18

Remove academic term from subject create/update

• Drops term ID parameter from CreateSubject/UpdateSubject signatures and logic.

backend/go/internal/application/lookup-usecase/subjects.go

entity.goDelete academic term domain entity +0/-14

Delete academic term domain entity

• Removes the AcademicTerm struct entirely.

backend/go/internal/domain/academicterm/entity.go

repository.goDelete academic term repository interface +0/-15

Delete academic term repository interface

• Removes the AcademicTermRepository interface.

backend/go/internal/domain/academicterm/repository.go

academicterm-repository.goDelete Postgres academic term repository implementation +0/-94

Delete Postgres academic term repository implementation

• Removes the Postgres-backed academic term repository entirely.

backend/go/internal/infrastructure/repository/postgres/academicterm-repository.go

entity.goRemove academic term fields from document entity +0/-2

Remove academic term fields from document entity

• Strips AcademicTermID/AcademicTermName fields from the Document struct.

backend/go/internal/domain/document/entity.go

repository.goChange FilterParams to support multi-value ID filters +8/-9

Change FilterParams to support multi-value ID filters

• Replaces single *uuid.UUID filter fields with []uuid.UUID slices and removes AcademicTermID.

backend/go/internal/domain/document/repository.go

entity.goRemove academic term fields from subject entity +4/-8

Remove academic term fields from subject entity

• Drops term-related fields from the Subject domain struct.

backend/go/internal/domain/subject/entity.go

document-repository.goRewrite document queries for multi-value filters, drop term joins +87/-96

Rewrite document queries for multi-value filters, drop term joins

• Updates Create/FindByID/FindBySlug/FindAllPublic/FindAllOwned queries to use ANY($n) array filters and removes academic_terms joins and columns.

backend/go/internal/infrastructure/repository/postgres/document-repository.go

subject-repository.goRemove academic term column handling in subject repository +20/-24

Remove academic term column handling in subject repository

• Updates subject CRUD queries to drop academic_term_id column references.

backend/go/internal/infrastructure/repository/postgres/subject-repository.go

dto.goUpdate DTOs for document/comparison changes +7/-16

Update DTOs for document/comparison changes

• Removes academic term fields and old comparison DTO structures to align with new filtering and Markdown-based comparison result.

backend/go/internal/application/dto.go

curriculum.tsRemove academic term API calls +5/-27

Remove academic term API calls

• Strips term-related endpoints from curriculum API client.

frontend/src/api/curriculum.ts

page.tsxRemove moderation page route +0/-23

Remove moderation page route

• Deletes the admin moderation page entirely as part of removing document reporting.

frontend/src/app/[role]/moderation/page.tsx

page.tsxReplace mock quiz page with real quiz flow redirect/integration +17/-319

Replace mock quiz page with real quiz flow redirect/integration

• Removes the large mock-data quiz page implementation in favor of the new real quiz components/hooks.

frontend/src/app/[role]/practice/quiz/page.tsx

app-layout.tsxRework shared app layout +89/-207

Rework shared app layout

• Simplifies/reworks the app layout to integrate the new sidebar and design system.

frontend/src/components/layout/app-layout.tsx

admin-layout.tsxRemove standalone admin layout +0/-268

Remove standalone admin layout

• Deletes the admin-specific layout component in favor of the shared app layout.

frontend/src/components/layout/admin-layout.tsx

role-shell.tsxSimplify role shell component +1/-5

Simplify role shell component

• Minor trimming of role-shell logic to align with unified layout.

frontend/src/components/layout/role-shell.tsx

shared-documents-view.tsxRework shared documents view for multi-filters +275/-331

Rework shared documents view for multi-filters

• Updates shared documents listing to use the new DocumentFilters component and multi-value filter state.

frontend/src/components/common/documents/shared-documents-view.tsx

admin-moderation-view.tsxRemove admin moderation view +0/-151

Remove admin moderation view

• Deletes the report review/resolve UI entirely as moderation is removed.

frontend/src/components/admin/moderation/admin-moderation-view.tsx

admin-curriculum-view.tsxUpdate admin curriculum view, remove term references +46/-35

Update admin curriculum view, remove term references

• Removes academic term UI and updates styling/layout.

frontend/src/components/admin/curriculum/admin-curriculum-view.tsx

admin-metadata-view.tsxUpdate admin metadata view, remove term management +20/-10

Update admin metadata view, remove term management

• Removes academic term CRUD UI section from metadata management.

frontend/src/components/admin/metadata/admin-metadata-view.tsx

documents-view.tsxSimplify lecturer documents view wrapper +20/-370

Simplify lecturer documents view wrapper

• Trims the documents view component in favor of delegating to my-documents-view and shared components.

frontend/src/components/lecturer/documents/documents-view.tsx

upload-view.tsxSimplify upload view +4/-7

Simplify upload view

• Trims the standalone upload view now that upload-modal handles the flow.

frontend/src/components/lecturer/documents/upload-view.tsx

edit-document-view.tsxAdjust edit document view for new filters +5/-4

Adjust edit document view for new filters

• Minor updates to remove academic term field and align with multi-value filters.

frontend/src/components/lecturer/documents/edit-document-view.tsx

create-quiz-view.tsxSimplify create-quiz view for new API +6/-22

Simplify create-quiz view for new API

• Adjusts quiz creation UI to use the new generate-quiz API and request shape.

frontend/src/components/lecturer/quiz/create-quiz-view.tsx

student-practice-view.tsxSimplify student practice view +41/-360

Simplify student practice view

• Reduces the practice view in favor of delegating to the new student-dashboard and quiz components.

frontend/src/components/student/practice/student-practice-view.tsx

use-documents.tsRework documents hook for multi-value filters +96/-279

Rework documents hook for multi-value filters

• Large refactor to support array-based filter state and remove academic term filter.

frontend/src/hooks/lecturer/use-documents.ts

use-my-documents.tsUpdate my-documents hook +10/-25

Update my-documents hook

• Adjusts hook to align with new filter shape and document management components.

frontend/src/hooks/lecturer/use-my-documents.ts

use-shared-documents.tsUpdate shared-documents hook for multi-filters +18/-33

Update shared-documents hook for multi-filters

• Adjusts hook to use array-based filter params instead of single IDs.

frontend/src/hooks/lecturer/use-shared-documents.ts

use-edit-document.tsRemove academic term from edit-document hook +5/-12

Remove academic term from edit-document hook

• Strips term ID handling from the document edit hook.

frontend/src/hooks/lecturer/use-edit-document.ts

use-upload.tsSimplify upload hook for new upload modal +11/-51

Simplify upload hook for new upload modal

• Adjusts upload hook logic to work with the new upload-modal component and removes term handling.

frontend/src/hooks/lecturer/use-upload.ts

use-create-quiz.tsSimplify create-quiz hook for new API +3/-15

Simplify create-quiz hook for new API

• Adjusts hook to call the real generate-quiz endpoint instead of mock data.

frontend/src/hooks/lecturer/use-create-quiz.ts

use-curriculum.tsRemove academic term logic from curriculum hook +8/-221

Remove academic term logic from curriculum hook

• Strips term CRUD state/handlers from the admin curriculum management hook.

frontend/src/hooks/admin/use-curriculum.ts

use-moderation.tsRemove moderation hook +0/-73

Remove moderation hook

• Deletes the hook that fetched and resolved document reports.

frontend/src/hooks/admin/use-moderation.ts

Documentation (15) +5388 / -4409
docs.goRegenerate Swagger docs (Go) +1000/-299

Regenerate Swagger docs (Go)

• Auto-generated Swagger documentation updated to reflect quiz endpoints and removed academic-term/document endpoints.

backend/go/docs/docs.go

swagger.jsonRegenerate Swagger docs (JSON) +1000/-299

Regenerate Swagger docs (JSON)

• Auto-generated Swagger JSON updated for new quiz API and removed academic-term endpoints.

backend/go/docs/swagger.json

swagger.yamlRegenerate Swagger docs (YAML) +622/-168

Regenerate Swagger docs (YAML)

• Auto-generated Swagger YAML updated for new quiz API and removed academic-term endpoints.

backend/go/docs/swagger.yaml

quiz-implementation-plan.mdAdd quiz implementation plan document +855/-0

Add quiz implementation plan document

• New planning document describing the quiz feature's design and implementation steps.

backend/go/docs/quiz-implementation-plan.md

quiz.mdAdd quiz feature documentation +384/-0

Add quiz feature documentation

• New markdown documentation describing the quiz subsystem.

backend/go/docs/quiz.md

SRS.mdUpdate SRS to reflect new features +148/-52

Update SRS to reflect new features

• Updates system requirements specification with quiz feature and other scope changes.

docs/SRS.md

2. SRS.mdRemove outdated SRS document +0/-444

Remove outdated SRS document

• Deletes stale duplicate SRS documentation file.

docs/bao/2. SRS.md

3. Pipeline.mdRemove outdated pipeline document +0/-804

Remove outdated pipeline document

• Deletes stale pipeline documentation file.

docs/bao/3. Pipeline.md

4. Architecture.mdRemove outdated architecture document +0/-555

Remove outdated architecture document

• Deletes stale architecture documentation file.

docs/bao/4. Architecture.md

Database Implementation Guide - PostgreSQL + pgvector.mdRemove outdated database guide +0/-1489

Remove outdated database guide

• Deletes stale database implementation guide.

docs/bao/Database Implementation Guide - PostgreSQL + pgvector.md

spreadsheet-content.mdRemove outdated spreadsheet content notes +0/-93

Remove outdated spreadsheet content notes

• Deletes stale content notes file.

docs/bao/spreadsheet-content.md

ui-redesign-plan.mdAdd UI redesign plan document +1217/-0

Add UI redesign plan document

• New planning document detailing the dark-theme/shared-layout UI redesign strategy.

docs/planing/plans/ui-redesign-plan.md

DESIGN_SYSTEM.mdUpdate design system documentation +130/-78

Update design system documentation

• Revises design system guidelines to match the new UI styling and shared layout components.

docs/system/DESIGN_SYSTEM.md

README.mdUpdate project README +32/-1

Update project README

• Adds notes/documentation covering new quiz feature and updated setup instructions.

README.md

summary.mdRemove summary.md +0/-127

Remove summary.md

• Deletes an outdated summary document no longer needed.

summary.md

Other (31) +5748 / -31
004_quiz_tables.sqlAdd quiz, question, option, attempt, and generation job tables +89/-0

Add quiz, question, option, attempt, and generation job tables

• New migration creating quizzes, quiz_questions, quiz_options, quiz_attempts, quiz_attempt_answers, and quiz_generation_jobs tables with supporting indexes.

backend/database/004_quiz_tables.sql

002_chat_tables.sqlAdd chat session, message, and citation tables +50/-0

Add chat session, message, and citation tables

• New migration for chat_sessions, messages, and message_citations tables with indexes for chat history persistence.

backend/database/002_chat_tables.sql

003_chat_session_documents.sqlLink chat sessions to documents +10/-0

Link chat sessions to documents

• Adds chat_session_documents join table and drops the legacy message_attachments table.

backend/database/003_chat_session_documents.sql

entity.goDefine quiz domain entities +95/-0

Define quiz domain entities

• New Quiz, Question, Option, Attempt, AttemptAnswer, and GenerationJob structs with status/type enums.

backend/go/internal/domain/quiz/entity.go

repository.goDefine quiz repository interface +38/-0

Define quiz repository interface

• New repository contract covering CRUD for quizzes, questions, options, attempts, and generation jobs.

backend/go/internal/domain/quiz/repository.go

quiz_repo.goImplement Postgres quiz repository +341/-0

Implement Postgres quiz repository

• New Postgres-backed implementation of the quiz repository, including listing quizzes by subject and subjects with published quizzes.

backend/go/internal/infrastructure/repository/postgres/quiz_repo.go

usecase.goDefine quiz usecase interface and constructor +67/-0

Define quiz usecase interface and constructor

• New Usecase interface aggregating generate/manage/take quiz operations with request DTOs.

backend/go/internal/application/quiz-usecase/usecase.go

generate_quiz.goImplement async AI quiz generation +226/-0

Implement async AI quiz generation

• Validates document ownership/subject consistency, creates a background job, and runs an async worker that calls the LLM to generate quiz questions/options and persists them.

backend/go/internal/application/quiz-usecase/generate_quiz.go

manage_quiz.goImplement quiz publish/list/detail logic +103/-0

Implement quiz publish/list/detail logic

• Adds publish validation (per question-type correctness rules), quiz detail retrieval with options, and listing for lecturers/students.

backend/go/internal/application/quiz-usecase/manage_quiz.go

take_quiz.goImplement quiz attempt start/submit/grading +145/-0

Implement quiz attempt start/submit/grading

• Adds attempt creation, auto-grading logic per question type (single/true-false/multiple choice), and attempt history retrieval.

backend/go/internal/application/quiz-usecase/take_quiz.go

quiz-handler.goAdd HTTP handlers for quiz endpoints +379/-0

Add HTTP handlers for quiz endpoints

• New handler exposing generate, job status, publish, list (lecturer/student), attempt start/submit, and attempt history endpoints.

backend/go/internal/interface/handler/quiz-handler.go

next.config.jsSimplify Next.js config +0/-11

Simplify Next.js config

• Removes custom configuration options from next.config.js.

frontend/next.config.js

package.jsonAdd frontend dependencies +2/-0

Add frontend dependencies

• Adds new npm packages required by the UI redesign/quiz features.

frontend/package.json

pnpm-lock.yamlUpdate pnpm lockfile +894/-20

Update pnpm lockfile

• Regenerates lockfile to match new/updated dependencies.

frontend/pnpm-lock.yaml

quiz.tsAdd quiz API client +162/-0

Add quiz API client

• New client module wrapping all quiz-related REST endpoints (generate, publish, list, attempts).

frontend/src/api/quiz.ts

page.tsxAdd bookmarks page route +12/-0

Add bookmarks page route

• New page rendering the bookmarks view for a given role.

frontend/src/app/[role]/bookmarks/page.tsx

page.tsxAdd explore page route +12/-0

Add explore page route

• New page rendering the document explore view for a given role.

frontend/src/app/[role]/explore/page.tsx

page.tsxAdd progress page route +5/-0

Add progress page route

• New page wiring for the lecturer progress view.

frontend/src/app/[role]/progress/page.tsx

sidebar.tsxAdd new shared sidebar component +279/-0

Add new shared sidebar component

• New sidebar component implementing the redesigned dark-themed navigation shared across roles.

frontend/src/components/layout/sidebar.tsx

action-modal.tsxAdd reusable action modal component +27/-0

Add reusable action modal component

• New shared modal component used across document/quiz management views.

frontend/src/components/ui/action-modal.tsx

data-table.tsxAdd reusable data table component +44/-0

Add reusable data table component

• New shared table component for consistent tabular UI across admin/lecturer views.

frontend/src/components/ui/data-table.tsx

document-filters.tsxAdd shared multi-select document filters component +350/-0

Add shared multi-select document filters component

• New component providing search, multi-select subject/type/language/source filters, and drawer UI shared across explore/my-documents views.

frontend/src/components/common/documents/document-filters.tsx

explore-view.tsxAdd document explore view +296/-0

Add document explore view

• New component implementing subject-grouped exploration of shared documents with bookmarking.

frontend/src/components/common/documents/explore-view.tsx

bookmarks-view.tsxAdd bookmarks view component +173/-0

Add bookmarks view component

• New component listing and managing a user's bookmarked documents.

frontend/src/components/common/documents/bookmarks-view.tsx

upload-modal.tsxAdd document upload modal +398/-0

Add document upload modal

• New modal component for uploading documents with metadata selection, replacing the previous upload flow.

frontend/src/components/lecturer/documents/upload-modal.tsx

document-detail-panel.tsxAdd document detail side panel +275/-0

Add document detail side panel

• New component showing document details in a panel used within the documents management views.

frontend/src/components/lecturer/documents/document-detail-panel.tsx

inline-document-edit.tsxAdd inline document edit component +259/-0

Add inline document edit component

• New component enabling inline editing of document metadata without navigating away.

frontend/src/components/lecturer/documents/inline-document-edit.tsx

progress-view.tsxAdd lecturer progress view +319/-0

Add lecturer progress view

• New component showing student progress/quiz statistics for lecturers.

frontend/src/components/lecturer/progress/progress-view.tsx

student-dashboard.tsxAdd student practice dashboard +314/-0

Add student practice dashboard

• New dashboard component summarizing available quizzes/subjects for students.

frontend/src/components/student/practice/student-dashboard.tsx

use-explore.tsAdd explore hook +331/-0

Add explore hook

• New hook managing subject/document data, filters, and bookmarking state for the explore view.

frontend/src/hooks/lecturer/use-explore.ts

use-bookmarks.tsAdd bookmarks hook +53/-0

Add bookmarks hook

• New hook fetching and toggling bookmarked documents.

frontend/src/hooks/lecturer/use-bookmarks.ts

This was referenced Jul 16, 2026
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.

5 participants