From 4e7e44169b170ba96708cd0bbcf71425ece47fac Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 18 Dec 2025 19:19:29 +0000 Subject: [PATCH 1/4] Initial plan From 8e986ab954d62b720fa0bb8fe4ea878ce309d325 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 18 Dec 2025 19:27:10 +0000 Subject: [PATCH 2/4] Add groups listing functionality with remote function and UI components Co-authored-by: TheRealSeber <111927572+TheRealSeber@users.noreply.github.com> --- messages/en.json | 11 +++ messages/pl.json | 11 +++ .../dashboard/admin/groups/GroupsList.svelte | 16 ++++ .../dashboard/admin/groups/index.ts | 1 + .../dashboard/groups/AdminGroupCard.svelte | 77 +++++++++++++++++++ src/lib/dto/group.ts | 7 ++ src/lib/services/GroupsManagementService.ts | 30 ++++++++ src/lib/services/index.ts | 1 + .../dashboard/teacher/groups/+page.svelte | 38 +++++++++ .../dashboard/teacher/groups/groups.remote.ts | 17 ++++ 10 files changed, 209 insertions(+) create mode 100644 src/lib/components/dashboard/admin/groups/GroupsList.svelte create mode 100644 src/lib/components/dashboard/admin/groups/index.ts create mode 100644 src/lib/components/dashboard/groups/AdminGroupCard.svelte create mode 100644 src/lib/dto/group.ts create mode 100644 src/lib/services/GroupsManagementService.ts create mode 100644 src/routes/dashboard/teacher/groups/+page.svelte create mode 100644 src/routes/dashboard/teacher/groups/groups.remote.ts diff --git a/messages/en.json b/messages/en.json index 7e4a072..4886664 100644 --- a/messages/en.json +++ b/messages/en.json @@ -559,6 +559,17 @@ "admin_tasks_remove_cancel_button": "Cancel", "admin_tasks_remove_success": "Task deleted successfully!", "admin_tasks_remove_error": "Failed to delete task", + "admin_groups_title": "Groups Management", + "admin_groups_all_groups": "All Groups", + "admin_groups_card_created": "Created:", + "admin_groups_card_updated": "Updated:", + "admin_groups_card_created_by": "Created By:", + "admin_groups_card_id_prefix": "#", + "admin_groups_card_user_prefix": "User #", + "admin_groups_card_view_details": "View Group", + "admin_groups_load_error_title": "Failed to load groups", + "admin_groups_no_groups_title": "No groups yet", + "admin_groups_no_groups_description": "Create your first group to get started", "task_collaborators_add_title": "Add Collaborator", "task_collaborators_add_description": "Add a new collaborator to this task", "task_collaborators_add_dialog_title": "Add Collaborator", diff --git a/messages/pl.json b/messages/pl.json index ef78b41..a1bc1c0 100644 --- a/messages/pl.json +++ b/messages/pl.json @@ -559,6 +559,17 @@ "admin_tasks_remove_cancel_button": "Anuluj", "admin_tasks_remove_success": "Zadanie zostało pomyślnie usunięte!", "admin_tasks_remove_error": "Nie udało się usunąć zadania", + "admin_groups_title": "Zarządzanie Grupami", + "admin_groups_all_groups": "Wszystkie Grupy", + "admin_groups_card_created": "Utworzono:", + "admin_groups_card_updated": "Zaktualizowano:", + "admin_groups_card_created_by": "Utworzone przez:", + "admin_groups_card_id_prefix": "#", + "admin_groups_card_user_prefix": "Użytkownik #", + "admin_groups_card_view_details": "Zobacz Grupę", + "admin_groups_load_error_title": "Nie udało się załadować grup", + "admin_groups_no_groups_title": "Brak grup", + "admin_groups_no_groups_description": "Utwórz swoją pierwszą grupę, aby zacząć", "task_collaborators_add_title": "Dodaj Współpracownika", "task_collaborators_add_description": "Dodaj nowego współpracownika do tego zadania", "task_collaborators_add_dialog_title": "Dodaj Współpracownika", diff --git a/src/lib/components/dashboard/admin/groups/GroupsList.svelte b/src/lib/components/dashboard/admin/groups/GroupsList.svelte new file mode 100644 index 0000000..59e1181 --- /dev/null +++ b/src/lib/components/dashboard/admin/groups/GroupsList.svelte @@ -0,0 +1,16 @@ + + +
+ {#each groups as group (group.id)} + + {/each} +
diff --git a/src/lib/components/dashboard/admin/groups/index.ts b/src/lib/components/dashboard/admin/groups/index.ts new file mode 100644 index 0000000..47bd09b --- /dev/null +++ b/src/lib/components/dashboard/admin/groups/index.ts @@ -0,0 +1 @@ +export { default as GroupsList } from './GroupsList.svelte'; diff --git a/src/lib/components/dashboard/groups/AdminGroupCard.svelte b/src/lib/components/dashboard/groups/AdminGroupCard.svelte new file mode 100644 index 0000000..b08a08f --- /dev/null +++ b/src/lib/components/dashboard/groups/AdminGroupCard.svelte @@ -0,0 +1,77 @@ + + + + +
+ + +
+ + {m.admin_groups_card_id_prefix()}{group.id} + +
+ + + {group.name} + +
+ + + +
+
+ + {m.admin_groups_card_created()} + {formatDate(group.createdAt)} +
+ +
+ + {m.admin_groups_card_updated()} + {formatDate(group.updatedAt)} +
+ +
+ + {m.admin_groups_card_created_by()} + {m.admin_groups_card_user_prefix()}{group.createdBy} +
+
+ + +
+ +
+
+
diff --git a/src/lib/dto/group.ts b/src/lib/dto/group.ts new file mode 100644 index 0000000..b3142f4 --- /dev/null +++ b/src/lib/dto/group.ts @@ -0,0 +1,7 @@ +export interface Group { + id: number; + name: string; + createdAt: string; + updatedAt: string; + createdBy: number; +} diff --git a/src/lib/services/GroupsManagementService.ts b/src/lib/services/GroupsManagementService.ts new file mode 100644 index 0000000..445418e --- /dev/null +++ b/src/lib/services/GroupsManagementService.ts @@ -0,0 +1,30 @@ +import { ApiError, type ApiService } from './ApiService'; +import type { ApiResponse, PaginatedData } from '../dto/response'; +import type { Group } from '../dto/group'; + +export class GroupsManagementService { + constructor(private apiClient: ApiService) {} + + async getGroups(): Promise<{ + success: boolean; + status: number; + data?: Group[]; + error?: string; + }> { + try { + const response = await this.apiClient.get>>({ + url: '/groups-management/groups' + }); + return { success: true, data: response.data.items, status: 200 }; + } catch (error) { + if (error instanceof ApiError) { + return { + success: false, + error: error.getApiMessage(), + status: error.getStatus() + }; + } + throw error; + } + } +} diff --git a/src/lib/services/index.ts b/src/lib/services/index.ts index 444f203..843b69e 100644 --- a/src/lib/services/index.ts +++ b/src/lib/services/index.ts @@ -6,6 +6,7 @@ export { ContestsManagementService, createContestsManagementService } from './ContestsManagementService'; +export { GroupsManagementService } from './GroupsManagementService'; export { SubmissionService } from './SubmissionService'; export { TaskService, createTaskService } from './TaskService'; export { TasksManagementService } from './TasksManagementService'; diff --git a/src/routes/dashboard/teacher/groups/+page.svelte b/src/routes/dashboard/teacher/groups/+page.svelte new file mode 100644 index 0000000..69811e8 --- /dev/null +++ b/src/routes/dashboard/teacher/groups/+page.svelte @@ -0,0 +1,38 @@ + + +
+
+

{m.admin_groups_title()}

+
+ + +
+

{m.admin_groups_all_groups()}

+ + {#if groupsQuery.error} + groupsQuery.refresh()} + /> + {:else if groupsQuery.loading} + + {:else if groupsQuery.current && groupsQuery.current.length === 0} + + {:else if groupsQuery.current} + + {/if} +
+
diff --git a/src/routes/dashboard/teacher/groups/groups.remote.ts b/src/routes/dashboard/teacher/groups/groups.remote.ts new file mode 100644 index 0000000..dfdd025 --- /dev/null +++ b/src/routes/dashboard/teacher/groups/groups.remote.ts @@ -0,0 +1,17 @@ +import { query, getRequestEvent } from '$app/server'; +import { createApiClient } from '$lib/services/ApiService'; +import { GroupsManagementService } from '$lib/services/GroupsManagementService'; +import { error } from '@sveltejs/kit'; + +export const getGroups = query(async () => { + const event = getRequestEvent(); + const apiClient = createApiClient(event.cookies); + const groupsManagementService = new GroupsManagementService(apiClient); + + const result = await groupsManagementService.getGroups(); + if (!result.success || !result.data) { + error(result.status, { message: result.error || 'Failed to fetch groups.' }); + } + + return result.data; +}); From 5f10c24416bfff19aeac90649be55e148fc7ac8c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 18 Dec 2025 19:29:08 +0000 Subject: [PATCH 3/4] Fix GroupsManagementService to expect array response instead of paginated data Co-authored-by: TheRealSeber <111927572+TheRealSeber@users.noreply.github.com> --- src/lib/services/GroupsManagementService.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/services/GroupsManagementService.ts b/src/lib/services/GroupsManagementService.ts index 445418e..15b1361 100644 --- a/src/lib/services/GroupsManagementService.ts +++ b/src/lib/services/GroupsManagementService.ts @@ -12,10 +12,10 @@ export class GroupsManagementService { error?: string; }> { try { - const response = await this.apiClient.get>>({ + const response = await this.apiClient.get>({ url: '/groups-management/groups' }); - return { success: true, data: response.data.items, status: 200 }; + return { success: true, data: response.data, status: 200 }; } catch (error) { if (error instanceof ApiError) { return { From 49027e3b8c2de2e4aed6ad23f2de2fb54f5b9a40 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 18 Dec 2025 19:32:35 +0000 Subject: [PATCH 4/4] Remove unused PaginatedData import from GroupsManagementService Co-authored-by: TheRealSeber <111927572+TheRealSeber@users.noreply.github.com> --- src/lib/services/GroupsManagementService.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/services/GroupsManagementService.ts b/src/lib/services/GroupsManagementService.ts index 15b1361..69da877 100644 --- a/src/lib/services/GroupsManagementService.ts +++ b/src/lib/services/GroupsManagementService.ts @@ -1,5 +1,5 @@ import { ApiError, type ApiService } from './ApiService'; -import type { ApiResponse, PaginatedData } from '../dto/response'; +import type { ApiResponse } from '../dto/response'; import type { Group } from '../dto/group'; export class GroupsManagementService {