Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Dec 20, 2025

Implementation Plan for Task User Statistics Feature

  • Add TaskUserStats DTO type definitions to match the API response
  • Add method getTaskUserStats to ContestsManagementService to call the new endpoint
  • Create remote function for fetching task user stats in user-stats.remote.ts
  • Create new route /dashboard/teacher/contests/[contestId]/tasks/[taskId]/user-stats/+page.svelte
  • Create layout server file for the new route to provide contestId and taskId
  • Implement the user stats page UI following results page patterns (table, cards, etc.)
  • Add a "View User Stats" button to each task card on the tasks page
  • Add i18n messages for the new page (English and Polish)
  • Test the implementation manually
  • Verify with screenshots

Additional Feature Added (per user request)

  • Create similar view for contest-level user statistics at /dashboard/teacher/contests/[contestId]/user-stats
  • Add page server, remote function, and UI components
  • Add "View Contest Stats" button to tasks page header
  • Add 26 i18n messages (English and Polish) for contest stats
  • Build and validate all changes

PR Review Feedback Addressed

  • Use v.pipe(v.number(), v.integer()) for ID validation in task user stats remote
  • Add routes to getDashboardTitleTranslationFromPathname() function for proper page titles
  • Format href attribute as single line for better readability
  • Add "View User Stats" button to contest cards on /dashboard/teacher/contests
  • Fix schema validation for contestId in contest user-stats remote (use integer pipe)
  • CSS class formatting improvements
Original prompt

This section details on the original issue you should resolve

<issue_title>/contests-management/contests/{id}/tasks/{taskId}/user-stats Get user statistics for a specific task in a contest</issue_title>
<issue_description>Implement /contests-management/contests/{id}/tasks/{taskId}/user-stats
Get user statistics for a specific task in a contest for the teacher. when viewing tasks within contest the teacher should be able to click a button and view the user stats for a given task in a contest in another page. follow guidelines and styles from different pages. e.g. for the stats there was /results page. style etc. can be simillar</issue_description>

Comments on the Issue (you are @copilot in this section)


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

Copilot AI changed the title [WIP] Implement user statistics endpoint for contest tasks Add task-specific user statistics page for contest teachers Dec 20, 2025
Copilot AI requested a review from TheRealSeber December 20, 2025 18:28
Copilot AI and others added 2 commits December 20, 2025 23:25
Co-authored-by: TheRealSeber <111927572+TheRealSeber@users.noreply.github.com>
@TheRealSeber TheRealSeber force-pushed the copilot/add-user-stats-endpoint branch from 637fa48 to e2281d7 Compare December 20, 2025 22:25
@TheRealSeber TheRealSeber requested a review from Copilot December 20, 2025 22:43
@TheRealSeber
Copy link
Contributor

@copilot i like this. I would like also to have a very simillar view for the /contests-management/contests/{id}/user-stats
Get overall user statistics for a contest.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds a dedicated statistics page for teachers to view per-user performance on individual tasks within contests. The feature enables teachers to assess task difficulty and identify students who may need additional support.

Key changes:

  • New route /dashboard/teacher/contests/[contestId]/tasks/[taskId]/user-stats with complete UI including summary cards, top 3 podium, and paginated leaderboard
  • Backend integration via ContestsManagementService.getTaskUserStats() method
  • Complete i18n support with 25 translated strings in English and Polish

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/routes/dashboard/teacher/contests/[contestId]/tasks/[taskId]/user-stats/+page.svelte Main statistics page component with summary cards, podium display, sortable table, and pagination
src/routes/dashboard/teacher/contests/[contestId]/tasks/[taskId]/user-stats/+layout.server.ts Server-side layout that parses and validates route parameters (contestId, taskId)
src/routes/dashboard/teacher/contests/[contestId]/tasks/[taskId]/user-stats/user-stats.remote.ts Remote function implementing the query pattern for fetching task user statistics
src/routes/dashboard/teacher/contests/[contestId]/tasks/+page.svelte Added "View User Stats" button to task cards for navigation to the new statistics page
src/lib/services/ContestsManagementService.ts Added getTaskUserStats() method to integrate with the backend API endpoint
src/lib/dto/contest.ts Added TaskUserStats interface defining the data structure for user statistics
messages/en.json Added 25 English translations for the statistics page UI elements
messages/pl.json Added 25 Polish translations for the statistics page UI elements

Comment on lines 9 to 10
contestId: v.number(),
taskId: v.number()
Copy link

Copilot AI Dec 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The schema validation should use v.pipe(v.number(), v.integer()) for both contestId and taskId to ensure they are integers, not just numbers. This is consistent with other similar remote functions in the codebase (e.g., submissions.remote.ts, registration-requests.remote.ts) that validate ID parameters in object schemas.

Suggested change
contestId: v.number(),
taskId: v.number()
contestId: v.pipe(v.number(), v.integer()),
taskId: v.pipe(v.number(), v.integer())

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed. Updated schema validation to use v.pipe(v.number(), v.integer()) for both contestId and taskId parameters.

Commit: 1a06ded

Comment on lines +73 to +80
<div class="space-y-6 p-4 sm:p-6 lg:p-8">
<div class="space-y-2">
<h1 class="text-4xl font-bold tracking-tight text-foreground">
{m.task_user_stats_title()}
</h1>
<p class="text-lg text-muted-foreground">
{m.task_user_stats_subtitle({ contestId: data.contestId, taskId: data.taskId })}
</p>
Copy link

Copilot AI Dec 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to the project's coding guidelines for dashboard page title translations, this new route should be added to the getDashboardTitleTranslationFromPathname() function in /src/lib/components/dashboard/utils.ts. Add a pattern match for this dynamic route before the static route check, similar to how /dashboard/admin/contests/\d+/registration-requests is handled on line 29. The pattern should match /dashboard/teacher/contests/\d+/tasks/\d+/user-stats and return the appropriate message key (e.g., m.task_user_stats_title()).

Copilot generated this review using guidance from repository custom instructions.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added patterns for both statistics routes to getDashboardTitleTranslationFromPathname():

  • /dashboard/teacher/contests/\d+/tasks/\d+/user-statstask_user_stats_title()
  • /dashboard/teacher/contests/\d+/user-statscontest_user_stats_title()

Commit: 1a06ded

Comment on lines 78 to 79
href="/dashboard/teacher/contests/{data.contestId}/tasks/{contestTask.task
.id}/user-stats"
Copy link

Copilot AI Dec 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The href attribute is split across lines in an unusual way. Format this as a single line or use proper template literal formatting for better readability.

Suggested change
href="/dashboard/teacher/contests/{data.contestId}/tasks/{contestTask.task
.id}/user-stats"
href={`/dashboard/teacher/contests/${data.contestId}/tasks/${contestTask.task.id}/user-stats`}

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed. Formatted href as single line using template literal: href={/dashboard/teacher/contests/${data.contestId}/tasks/${contestTask.task.id}/user-stats}

Commit: 1a06ded

Co-authored-by: TheRealSeber <111927572+TheRealSeber@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Dec 20, 2025

@copilot i like this. I would like also to have a very simillar view for the /contests-management/contests/{id}/user-stats
Get overall user statistics for a contest.

Added contest-level user statistics view at /dashboard/teacher/contests/[contestId]/user-stats with similar design to the task-specific stats page.

Features:

  • Summary cards: total users, average score, total tasks solved/attempted
  • Top 3 podium display
  • Sortable table with rank, name, username, total score, solved/partial/attempted tasks
  • Pagination support
  • "View Contest Stats" button added to tasks page header

Commit: 8d3eb26

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • cdn.jsdelivr.net
    • Triggering command: /opt/hostedtoolcache/node/22.21.1/x64/bin/node node /home/REDACTED/work/frontend/frontend/node_modules/.bin/../@inlang/paraglide-js/bin/run.js compile --project ./project.inlang --outdir ./src/lib/paraglide (dns block)
    • Triggering command: /opt/hostedtoolcache/node/22.21.1/x64/bin/node node /home/REDACTED/work/frontend/frontend/node_modules/.bin/../vite/bin/vite.js build (dns block)
  • eu.posthog.com
    • Triggering command: /opt/hostedtoolcache/node/22.21.1/x64/bin/node node /home/REDACTED/work/frontend/frontend/node_modules/.bin/../@inlang/paraglide-js/bin/run.js compile --project ./project.inlang --outdir ./src/lib/paraglide (dns block)
    • Triggering command: /opt/hostedtoolcache/node/22.21.1/x64/bin/node node /home/REDACTED/work/frontend/frontend/node_modules/.bin/../vite/bin/vite.js build (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Copilot AI changed the title Add task-specific user statistics page for contest teachers Add task-specific and contest-level user statistics pages for teachers Dec 20, 2025
@TheRealSeber
Copy link
Contributor

@copilot you should have added also appropiate button on the contest card at dashboard/teacher/contests

…est card button

Co-authored-by: TheRealSeber <111927572+TheRealSeber@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Dec 20, 2025

@copilot you should have added also appropiate button on the contest card at dashboard/teacher/contests

Added "View User Stats" button to contest cards at /dashboard/teacher/contests. The button appears on each contest card in the AdminContestCard component and navigates to /dashboard/teacher/contests/{contestId}/user-stats.

Commit: 1a06ded

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • cdn.jsdelivr.net
    • Triggering command: /opt/hostedtoolcache/node/22.21.1/x64/bin/node node /home/REDACTED/work/frontend/frontend/node_modules/.bin/../@inlang/paraglide-js/bin/run.js compile --project ./project.inlang --outdir ./src/lib/paraglide (dns block)
    • Triggering command: /opt/hostedtoolcache/node/22.21.1/x64/bin/node node /home/REDACTED/work/frontend/frontend/node_modules/.bin/../vite/bin/vite.js build (dns block)
  • eu.posthog.com
    • Triggering command: /opt/hostedtoolcache/node/22.21.1/x64/bin/node node /home/REDACTED/work/frontend/frontend/node_modules/.bin/../@inlang/paraglide-js/bin/run.js compile --project ./project.inlang --outdir ./src/lib/paraglide (dns block)
    • Triggering command: /opt/hostedtoolcache/node/22.21.1/x64/bin/node node /home/REDACTED/work/frontend/frontend/node_modules/.bin/../vite/bin/vite.js build (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated 1 comment.

import type { UserContestStats } from '$lib/dto/contest';

const paramsSchema = v.object({
contestId: v.number()
Copy link

Copilot AI Dec 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The validation schema for contestId should use v.pipe(v.number(), v.integer()) instead of just v.number() for consistency with other remote functions in the codebase that validate IDs. This ensures that only integer values are accepted, preventing potential issues with non-integer numbers being passed to the API.

Suggested change
contestId: v.number()
contestId: v.pipe(v.number(), v.integer())

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed. Updated schema validation to use v.pipe(v.number(), v.integer()) for contestId parameter in contest user-stats remote function.

Commit: b8d34f2

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated 1 comment.

Comment on lines 84 to 85
class:
'bg-muted text-muted-foreground border-borderbg-muted text-muted-foreground border-border'
Copy link

Copilot AI Dec 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a typo in the CSS class string. The text 'border-borderbg-muted' appears to be a concatenation error, missing a space between 'border-border' and 'bg-muted'. This should be 'border-border bg-muted text-muted-foreground' to match the intended styling for the failed task status badge.

Suggested change
class:
'bg-muted text-muted-foreground border-borderbg-muted text-muted-foreground border-border'
class: 'border-border bg-muted text-muted-foreground'

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This CSS typo was already fixed in a previous commit (d93ba3f). The class is now correctly formatted as 'bg-muted text-muted-foreground border-border'.

@TheRealSeber
Copy link
Contributor

@copilot please if this is considerable adjust to other comments

Co-authored-by: TheRealSeber <111927572+TheRealSeber@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Dec 21, 2025

@copilot please if this is considerable adjust to other comments

Addressed all review comments:

  • Fixed schema validation for contestId (comment 2637429361)
  • CSS class typo was already fixed in previous commit

Commit: b8d34f2

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • cdn.jsdelivr.net
    • Triggering command: /opt/hostedtoolcache/node/22.21.1/x64/bin/node node /home/REDACTED/work/frontend/frontend/node_modules/.bin/../vite/bin/vite.js build (dns block)
  • eu.posthog.com
    • Triggering command: /opt/hostedtoolcache/node/22.21.1/x64/bin/node node /home/REDACTED/work/frontend/frontend/node_modules/.bin/../vite/bin/vite.js build (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

@TheRealSeber TheRealSeber marked this pull request as ready for review December 21, 2025 12:29
@TheRealSeber TheRealSeber merged commit e99b16d into master Dec 21, 2025
1 check passed
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.

/contests-management/contests/{id}/tasks/{taskId}/user-stats Get user statistics for a specific task in a contest

2 participants