diff --git a/backend/app/crud/tasks.py b/backend/app/crud/tasks.py index e3dbd2a326ce328719aaba002bd78212856d6a71..f487f1b86cedad49ab21d0589a9fd96d91ba3875 100644 --- a/backend/app/crud/tasks.py +++ b/backend/app/crud/tasks.py @@ -49,3 +49,12 @@ def get_task_status_session(db: Session, session_id: int) -> models.TaskStatus | .order_by(models.TaskStatus.created_at.desc()) .first() ) + + +def get_task_status_completed(db: Session, student_id: int) -> list[models.TaskStatus]: + return ( + db.query(models.TaskStatus) + .filter(models.TaskStatus.student_id == student_id) + .filter(models.TaskStatus.status == "finish") + .all() + ) diff --git a/backend/app/routes/tasks.py b/backend/app/routes/tasks.py index 68eede8c07c6c50e024e018371e4c7d02eff2fba..043143e826f563afc4ff790ccb3e187a1c185c7d 100644 --- a/backend/app/routes/tasks.py +++ b/backend/app/routes/tasks.py @@ -67,6 +67,21 @@ def get_task_status_session( return task_status +@taskRouter.get( + "/status/completed/students/{student_id}", response_model=list[schemas.TaskStatus] +) +def get_task_status_completed( + student_id: int, + db: Session = Depends(get_db), +): + task_status = crud.get_task_status_completed(db, student_id) + if task_status is None: + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, detail="Task status not found" + ) + return task_status + + @taskRouter.get("/{task_id}", response_model=schemas.Task) def get_task( task_id: int, diff --git a/frontend/src/lib/api/tasks.ts b/frontend/src/lib/api/tasks.ts index a2ed536fd8f86a1bd6c4a6e7aeb87ef60fbd5f97..0f99fe8fb7fde256d131f7ebbc35fd5732159b10 100644 --- a/frontend/src/lib/api/tasks.ts +++ b/frontend/src/lib/api/tasks.ts @@ -97,3 +97,12 @@ export async function getTaskStatusFromSessionAPI( if (!response.ok) return null; return await response.json(); } + +export async function getTaskStatusCompletedFromStudentAPI( + fetch: fetchType, + student_id: number +): Promise<any> { + const response = await fetch(`/api/tasks/status/completed/students/${student_id}`); + if (!response.ok) return null; + return await response.json(); +} diff --git a/frontend/src/routes/sessions/[id]/+page.svelte b/frontend/src/routes/sessions/[id]/+page.svelte index 36ed70bbce0b0004a05995b38b11df8c165c22cd..3b9f6b5aac3f8264347aa23113fb100a9e4a9764 100644 --- a/frontend/src/routes/sessions/[id]/+page.svelte +++ b/frontend/src/routes/sessions/[id]/+page.svelte @@ -9,7 +9,7 @@ let { data }: { data: PageData } = $props(); let user = data.user!; - let { session, jwt, tasks } = data; + let { session, jwt, tasks, completedTasks } = data; let { onlineUsers } = session; let level = $state('all'); @@ -70,6 +70,8 @@ toastAlert($t('tasks.statusFail')); return; } + completedTasks.push(currentTask); + taskInProgress = false; currentTask = null; toastSuccess($t('tasks.taskFinished')); @@ -134,7 +136,12 @@ {#if level === 'all' || l === level} <optgroup label={l}> {#each tasks.filter((task: Task) => task.level === l) as task (task.id)} - <option value={task}>{task.shortTitle}</option> + <option value={task}> + {#if completedTasks.includes(task)} + ✓ + {/if} + {task.shortTitle} + </option> {/each} </optgroup> {/if} diff --git a/frontend/src/routes/sessions/[id]/+page.ts b/frontend/src/routes/sessions/[id]/+page.ts index 08494fa31ac70d77b62e67b4e190657ba44d99de..fd99a73f44317e601b6c480201547230452774f8 100644 --- a/frontend/src/routes/sessions/[id]/+page.ts +++ b/frontend/src/routes/sessions/[id]/+page.ts @@ -1,5 +1,9 @@ import { getSessionAPI } from '$lib/api/sessions'; -import { getTasksAPI, getTaskStatusFromSessionAPI } from '$lib/api/tasks'; +import { + getTasksAPI, + getTaskStatusCompletedFromStudentAPI, + getTaskStatusFromSessionAPI +} from '$lib/api/tasks'; import Session from '$lib/types/session'; import Task, { TaskStatus } from '$lib/types/tasks'; import { error, type Load } from '@sveltejs/kit'; @@ -38,5 +42,20 @@ export const load: Load = async ({ params, fetch, data }) => { } } - return { session, jwt, tasks, currentTask }; + let completedTasks: Task[] = []; + + if (session.student) { + const completedTasksStatusRaw = await getTaskStatusCompletedFromStudentAPI( + fetch, + session.student.id + ); + if (completedTasksStatusRaw) { + const completedTasksStatus = TaskStatus.parseAll(completedTasksStatusRaw); + completedTasks = completedTasksStatus + .map((taskStatus) => tasks.find((task) => task.id === taskStatus.task_id)) + .filter((task) => task !== undefined) as Task[]; + } + } + + return { session, jwt, tasks, currentTask, completedTasks }; };