diff --git a/api/handlers_test.go b/api/handlers_test.go index 05a4819..9dba79c 100644 --- a/api/handlers_test.go +++ b/api/handlers_test.go @@ -1039,3 +1039,81 @@ func TestDashboardStatsArePerUser(t *testing.T) { } } } + +// TestGetProgressHandlerQuizzesLast7Days verifies the quizzes_last_7_days field +// counts only quiz attempts started within the last 7 days. +func TestGetProgressHandlerQuizzesLast7Days(t *testing.T) { +db := database.NewInMemoryDB() +handler := NewHandler(db) + +user := &models.User{Username: "testuser7days", Email: "7days@example.com"} +if err := db.CreateUser(user); err != nil { +t.Fatalf("Failed to create user: %v", err) +} + +now := time.Now() + +// Attempt started 3 days ago (within last 7 days) +recent1 := &models.QuizAttempt{ +UserID: user.ID, +StartTime: now.AddDate(0, 0, -3), +TotalQuestions: 5, +CorrectAnswers: 3, +QuestionIDs: []string{}, +QuestionResults: map[string]bool{}, +} +if err := db.CreateQuizAttempt(recent1); err != nil { +t.Fatalf("Failed to create recent quiz attempt: %v", err) +} + +// Attempt started 6 days ago (within last 7 days) +recent2 := &models.QuizAttempt{ +UserID: user.ID, +StartTime: now.AddDate(0, 0, -6), +TotalQuestions: 5, +CorrectAnswers: 4, +QuestionIDs: []string{}, +QuestionResults: map[string]bool{}, +} +if err := db.CreateQuizAttempt(recent2); err != nil { +t.Fatalf("Failed to create recent quiz attempt: %v", err) +} + +// Attempt started 10 days ago (older than 7 days, should NOT be counted) +old := &models.QuizAttempt{ +UserID: user.ID, +StartTime: now.AddDate(0, 0, -10), +TotalQuestions: 5, +CorrectAnswers: 2, +QuestionIDs: []string{}, +QuestionResults: map[string]bool{}, +} +if err := db.CreateQuizAttempt(old); err != nil { +t.Fatalf("Failed to create old quiz attempt: %v", err) +} + +req := httptest.NewRequest(http.MethodGet, "/progress?user_id="+strconv.Itoa(user.ID), nil) +w := httptest.NewRecorder() +handler.GetProgressHandler(w, req) + +if w.Code != http.StatusOK { +t.Errorf("Expected status %d, got %d", http.StatusOK, w.Code) +} + +var progress map[string]interface{} +if err := json.NewDecoder(w.Body).Decode(&progress); err != nil { +t.Fatalf("Failed to decode response: %v", err) +} + +// total_quizzes should include all 3 attempts +totalQuizzes := int(progress["total_quizzes"].(float64)) +if totalQuizzes != 3 { +t.Errorf("Expected total_quizzes to be 3, got %d", totalQuizzes) +} + +// quizzes_last_7_days should only count the 2 recent ones +quizzesLast7Days := int(progress["quizzes_last_7_days"].(float64)) +if quizzesLast7Days != 2 { +t.Errorf("Expected quizzes_last_7_days to be 2 (3-day and 6-day old), got %d", quizzesLast7Days) +} +} diff --git a/api/quiz.go b/api/quiz.go index a4a9306..b5c77e1 100644 --- a/api/quiz.go +++ b/api/quiz.go @@ -715,7 +715,13 @@ func (h *Handler) GetProgressHandler(w http.ResponseWriter, r *http.Request) { // Calculate statistics totalQuestions := 0 totalCorrect := 0 + sevenDaysAgo := time.Now().AddDate(0, 0, -7) + quizzesLast7Days := 0 for _, qa := range quizAttempts { + // Count quizzes started in the last 7 days (inclusive of exactly 7 days ago) + if !qa.StartTime.Before(sevenDaysAgo) { + quizzesLast7Days++ + } // Count questions answered from all quizzes (completed and in-progress) // For completed quizzes, all questions were answered // For in-progress quizzes, count only the questions that have been answered @@ -732,13 +738,14 @@ func (h *Handler) GetProgressHandler(w http.ResponseWriter, r *http.Request) { } progress := map[string]interface{}{ - "user": user, - "total_points": user.TotalPoints, - "total_quizzes": len(quizAttempts), - "total_questions": totalQuestions, - "total_correct": totalCorrect, - "quiz_attempts": quizAttempts, - "question_attempts": questionAttempts, + "user": user, + "total_points": user.TotalPoints, + "total_quizzes": len(quizAttempts), + "quizzes_last_7_days": quizzesLast7Days, + "total_questions": totalQuestions, + "total_correct": totalCorrect, + "quiz_attempts": quizAttempts, + "question_attempts": questionAttempts, } w.Header().Set("Content-Type", "application/json") diff --git a/static/dashboard.html b/static/dashboard.html index 127b259..0eec8ce 100644 --- a/static/dashboard.html +++ b/static/dashboard.html @@ -94,36 +94,44 @@

📝 Assigned Exams

-
-
-
-
-
Total Points
-

0

+
+
+
+
+
Total Points
+

0

-
-
-
-
Quizzes Taken
-

0

+
+
+
+
Quizzes Taken
+

0

-
-
-
-
Questions Answered
-

0

+
+
+
+
Quizzes Taken (last 7 days)
+

0

-
-
-
-
Correct Answers
-

0

+
+
+
+
Questions Answered
+

0

+
+
+
+
+
+
+
Correct Answers
+

0

diff --git a/static/js/dashboard.js b/static/js/dashboard.js index e82df91..eb7c661 100644 --- a/static/js/dashboard.js +++ b/static/js/dashboard.js @@ -30,6 +30,7 @@ async function loadDashboard() { // Update stats document.getElementById('totalPoints').textContent = progressData.total_points || 0; document.getElementById('totalQuizzes').textContent = progressData.total_quizzes || 0; + document.getElementById('quizzesLast7Days').textContent = progressData.quizzes_last_7_days || 0; document.getElementById('totalQuestions').textContent = progressData.total_questions || 0; document.getElementById('totalCorrect').textContent = progressData.total_correct || 0;