feat(dashboard): add student performance & productivity dashboard (timer focus persistant, filtre période calendrier and…)#284
Conversation
… statistiques enrichies - Timer Pomodoro global (store Svelte) qui continue même hors de l'onglet Productivité, avec redirection automatique et blocage sidebar en pause - Mini badge timer visible dans la Navbar sur toutes les pages étudiantes - Statistiques et jauge de performance filtrées dynamiquement par mois ou par semaine selon la sélection dans le calendrier - Affichage du nombre de soutiens créés par matière et du total de points
|
Salam @brahim1818 |
📋 Backend Review — Request Changes 🔴Solid, well-structured feature — the 🔴 Must fix:
🟠 Should fix: |
|
Hi, thk for contuning dev. |
|
just the design style is note aligned woth opentutorai style |
There was a problem hiding this comment.
Pull request overview
This PR implements a unified Student Dashboard (Performance + Productivity) in the SvelteKit student area, backed by new FastAPI endpoints and persistence models for focus sessions and dashboard aggregates.
Changes:
- Add a tabbed student dashboard UI with performance stats (subjects, completion gauge, activity calendar) and productivity widgets (Pomodoro focus timer, streak, weekly study hours).
- Introduce a global, cross-page focus timer store + orchestrator to persist timer state and record completed focus sessions.
- Add backend dashboard/focus APIs plus new SQLAlchemy models to store focus settings and study sessions.
Reviewed changes
Copilot reviewed 21 out of 24 changed files in this pull request and generated 12 comments.
Show a summary per file
| File | Description |
|---|---|
| ui/src/routes/student/+layout.svelte | Mounts a global focus orchestrator component so the timer persists across student pages. |
| ui/src/lib/stores/focusTimer.ts | Adds global Svelte stores + timer interval logic, events, and derived displays for focus mode. |
| ui/src/lib/components/student/pages/Dashboard.svelte | Reworks the student dashboard into a tabbed Performance/Productivity layout and keeps support-request linkage logic. |
| ui/src/lib/components/student/elements/Sidebar.svelte | Blocks navigation during break phase and shows a toast with remaining break time. |
| ui/src/lib/components/student/elements/Navbar.svelte | Adds a mini focus timer pill that links back to the dashboard productivity tab. |
| ui/src/lib/components/student/dashboard/StudyHoursChart.svelte | New SVG bar chart component for daily study hours. |
| ui/src/lib/components/student/dashboard/ProductivityTab.svelte | New productivity tab with streak, sessions, weekly hours, chart, and focus timer widget. |
| ui/src/lib/components/student/dashboard/PerformanceTab.svelte | New performance tab fetching stats/performance/calendar and handling monthly/weekly filtering. |
| ui/src/lib/components/student/dashboard/PerformanceGauge.svelte | New semicircle gauge component for completion rate + points display. |
| ui/src/lib/components/student/dashboard/FocusTimer.svelte | New Pomodoro UI wired to the global focusTimer store and focus settings API. |
| ui/src/lib/components/student/dashboard/FocusOrchestrator.svelte | New invisible orchestrator that reacts to timer events, shows toasts, navigates, and records sessions. |
| ui/src/lib/components/student/dashboard/ActivityCalendar.svelte | New monthly/weekly activity calendar with navigation and activity markers. |
| ui/src/lib/apis/focus/index.ts | Adds frontend API client functions for focus sessions and focus settings. |
| ui/src/lib/apis/dashboard/index.ts | Adds frontend API client functions for dashboard statistics/performance/calendar/productivity. |
| ui/src/app.d.ts | Extends Window typing for the global event bus used for chat creation events. |
| ui/package-lock.json | Updates lockfile metadata (version field). |
| learning/dashboard/service.py | Adds dashboard service methods for statistics/performance/calendar/productivity and focus settings/session recording. |
| learning/dashboard/repository.py | Adds repository queries/aggregations for study sessions, streaks, subject stats, and activity days. |
| learning/dashboard/init.py | Initializes the new learning.dashboard module. |
| gateway/http/routers/dashboard.py | Adds new /api/v1/dashboard/* and /api/v1/focus/* endpoints. |
| gateway/http/app.py | Registers the new dashboard router under /api/v1. |
| data/models/study_session.py | New ORM model to persist focus/work sessions. |
| data/models/focus_settings.py | New ORM model to persist per-user focus timer settings. |
| data/models/init.py | Registers the new ORM models for metadata/table creation. |
Files not reviewed (1)
- ui/package-lock.json: Generated file
| main | ||
| import { chatId as storeChatId, isDemo, demoData, user } from '$lib/stores'; | ||
| import { dashboardTab } from '$lib/stores/focusTimer'; | ||
| import { getSupportRequests, type SupportResponse, updateSupportChatId } from '$lib/apis/supports'; | ||
|
|
| if (!window.openTutorEvents) window.openTutorEvents = new EventTarget(); | ||
| window.openTutorEvents.addEventListener('chatCreated', ((event: CustomEvent) => { | ||
| const newChatId = event.detail?.chatId; | ||
| if (newChatId && pendingSupportId) updateSupportWithChatId(pendingSupportId, newChatId); | ||
| }) as EventListener); |
| const supportData = JSON.parse(pendingSupportData || '{}'); | ||
| const attemptCount = (supportData.attempts || 0) + 1; | ||
| if (attemptCount >= 3) localStorage.removeItem('pendingSupportData'); | ||
| else { | ||
| ======= |
| <label for="dontShow" class="text-xs text-gray-500 dark:text-gray-400" | ||
| >{$i18n.t("Don't show me again")}</label | ||
| > |
| from .knowledge import KnowledgeBase, KnowledgeFile | ||
| main | ||
| from .study_session import StudySession | ||
| from .focus_settings import FocusSettings | ||
|
|
||
| from .model import ModelConfig |
| from datetime import datetime | ||
|
|
||
| from fastapi import APIRouter, Depends, Query | ||
| from pydantic import BaseModel | ||
| from sqlalchemy.orm import Session |
| def get_streak(self, user_id: str) -> int: | ||
| """Count consecutive days with at least one completed work session.""" | ||
| streak = 0 | ||
| now = datetime.utcnow() | ||
| for i in range(365): | ||
| day = now - timedelta(days=i) | ||
| start = day.replace(hour=0, minute=0, second=0, microsecond=0) | ||
| end = day.replace(hour=23, minute=59, second=59, microsecond=999999) | ||
| count = ( | ||
| self.session.query(StudySession) | ||
| .filter( | ||
| StudySession.user_id == user_id, | ||
| StudySession.session_type == "work", | ||
| StudySession.completed.is_(True), | ||
| StudySession.created_at >= start, | ||
| StudySession.created_at <= end, | ||
| ) | ||
| .count() | ||
| ) | ||
| if count > 0: | ||
| streak += 1 | ||
| elif i > 0: | ||
| break | ||
| return streak |
| <button | ||
| on:click={prevMonth} | ||
| class="w-6 h-6 flex items-center justify-center rounded-full hover:bg-gray-100 dark:hover:bg-gray-700 text-gray-500 dark:text-gray-400 text-sm font-bold transition" | ||
| >‹</button> |
| <button | ||
| on:click={nextMonth} | ||
| class="w-6 h-6 flex items-center justify-center rounded-full hover:bg-gray-100 dark:hover:bg-gray-700 text-gray-500 dark:text-gray-400 text-sm font-bold transition" | ||
| >›</button> |
| @router.get("/dashboard/statistics") | ||
| def get_statistics( | ||
| year: int = Query(None), | ||
| month: int = Query(None), | ||
| start_date: str = Query(None), | ||
| current_user: User = Depends(get_current_user), | ||
| svc: DashboardService = Depends(_svc), | ||
| ): | ||
| return svc.get_statistics(current_user.id, year, month, start_date) | ||
|
|
feat: Student Dashboard — Performance & Productivity
Description
Implements a unified student dashboard that merges academic performance
tracking with a productivity/focus workspace, as described in the
"Tableau de Bord Étudiant : Performance & Productivity" user story.
The dashboard is split into two tabs:
activity calendar.
hours chart.
This gives students a single place to see both their academic progress
and their study habits, so they can better organize their work and stay
consistent.
Added
subject, plus a "Support requests created per subject" breakdown
(count of soutiens per matière).
"Completed Tutorials" counter, points earned display, and a
Monthly / Weekly period selector.
homework, support requests) and previous/next month navigation.
1 min break, adjustable via +/− controls), circular countdown
display, Work/Pause state indicator, pause/reset controls.
week), streak counter (consecutive days with a completed session)
with per-day indicators, and successful (completed) Pomodoro
sessions counter.
same dashboard page.
Changed
productivity data in a single page via tab navigation, instead of
separate views.
Additional Information
OpenWebUI UI patterns.
is served via the FastAPI backend.
Screenshots or Videos
Productivity tab — Focus Mode, streak, and weekly study hours

Performance tab — Statistics by subject and support requests

Performance tab — Completion rate gauge and monthly calendar

Performance tab — Calendar navigation (activity markers)
