feat(frontend): progress van assignment wordt ook getoond voor studenten
This commit is contained in:
parent
5b17bad368
commit
1d29adaa31
7 changed files with 138 additions and 64 deletions
|
@ -71,9 +71,7 @@
|
|||
"class": "klasse",
|
||||
"delete": "löschen",
|
||||
"view-assignment": "Auftrag anzeigen",
|
||||
"legendTeacherExclusive": "Information für Lehrkräfte",
|
||||
"code": "code",
|
||||
"class": "Klasse",
|
||||
"invitations": "Einladungen",
|
||||
"createClass": "Klasse erstellen",
|
||||
"createClassInstructions": "Geben Sie einen Namen für Ihre Klasse ein und klicken Sie auf „Erstellen“. Es erscheint ein Fenster mit einem Code, den Sie kopieren können. Geben Sie diesen Code an Ihre Schüler weiter und sie können Ihrer Klasse beitreten.",
|
||||
|
@ -90,5 +88,10 @@
|
|||
"sent": "sent",
|
||||
"failed": "gescheitert",
|
||||
"wrong": "etwas ist schief gelaufen",
|
||||
"created": "erstellt"
|
||||
"created": "erstellt",
|
||||
"group": "Gruppe",
|
||||
"description": "Beschreibung",
|
||||
"no-submission": "keine vorlage",
|
||||
"submission": "einreichung",
|
||||
"progress": "Fortschritte"
|
||||
}
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
"welcome": "Welcome",
|
||||
"student": "student",
|
||||
"teacher": "teacher",
|
||||
"assignments": "assignments",
|
||||
"classes": "classes",
|
||||
"assignments": "Assignments",
|
||||
"classes": "Classes",
|
||||
"discussions": "discussions",
|
||||
"logout": "log out",
|
||||
"error_title": "Error",
|
||||
|
@ -88,5 +88,10 @@
|
|||
"sent": "sent",
|
||||
"failed": "failed",
|
||||
"wrong": "something went wrong",
|
||||
"created": "created"
|
||||
"created": "created",
|
||||
"group": "Group",
|
||||
"description": "Description",
|
||||
"no-submission": "no submission",
|
||||
"submission": "submission",
|
||||
"progress": "Progress"
|
||||
}
|
||||
|
|
|
@ -71,9 +71,7 @@
|
|||
"class": "classe",
|
||||
"delete": "supprimer",
|
||||
"view-assignment": "Voir le travail",
|
||||
"read-more": "En savoir plus",
|
||||
"code": "code",
|
||||
"class": "classe",
|
||||
"invitations": "invitations",
|
||||
"createClass": "créer une classe",
|
||||
"createClassInstructions": "Entrez un nom pour votre classe et cliquez sur créer. Une fenêtre apparaît avec un code que vous pouvez copier. Donnez ce code à vos élèves et ils pourront rejoindre votre classe.",
|
||||
|
@ -90,5 +88,10 @@
|
|||
"sent": "envoyé",
|
||||
"failed": "échoué",
|
||||
"wrong": "quelque chose n'a pas fonctionné",
|
||||
"created": "créé"
|
||||
"created": "créé",
|
||||
"group": "Groupe",
|
||||
"description": "Description",
|
||||
"no-submission": "aucune soumission",
|
||||
"submission": "soumission",
|
||||
"progress": "Progrès"
|
||||
}
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
"welcome": "Welkom",
|
||||
"student": "leerling",
|
||||
"teacher": "leerkracht",
|
||||
"assignments": "opdrachten",
|
||||
"classes": "klassen",
|
||||
"assignments": "Opdrachten",
|
||||
"classes": "Klassen",
|
||||
"discussions": "discussies",
|
||||
"logout": "log uit",
|
||||
"error_title": "Fout",
|
||||
|
@ -71,9 +71,7 @@
|
|||
"class": "klas",
|
||||
"delete": "verwijderen",
|
||||
"view-assignment": "Opdracht bekijken",
|
||||
"read-more": "Lees meer",
|
||||
"code": "code",
|
||||
"class": "klas",
|
||||
"invitations": "uitnodigingen",
|
||||
"createClass": "klas aanmaken",
|
||||
"createClassInstructions": "Voer een naam in voor je klas en klik op create. Er verschijnt een venster met een code die je kunt kopiëren. Geef deze code aan je leerlingen en ze kunnen deelnemen aan je klas.",
|
||||
|
@ -90,5 +88,10 @@
|
|||
"sent": "verzonden",
|
||||
"failed": "mislukt",
|
||||
"wrong": "er ging iets verkeerd",
|
||||
"created": "gecreëerd"
|
||||
"created": "gecreëerd",
|
||||
"group": "Groep",
|
||||
"description": "Beschrijving",
|
||||
"no-submission": "geen indiening",
|
||||
"submission": "indiening",
|
||||
"progress": "Vooruitgang"
|
||||
}
|
||||
|
|
|
@ -1,10 +1,14 @@
|
|||
<script setup lang="ts">
|
||||
|
||||
import auth from "@/services/auth/auth-service.ts";
|
||||
import {computed, ref} from "vue";
|
||||
import {computed, reactive, type Ref, ref, watchEffect} from "vue";
|
||||
import StudentAssignment from "@/views/assignments/StudentAssignment.vue";
|
||||
import TeacherAssignment from "@/views/assignments/TeacherAssignment.vue";
|
||||
import {useRoute} from "vue-router";
|
||||
import type {Language} from "@/data-objects/language.ts";
|
||||
import {useGetLearningPathQuery} from "@/queries/learning-paths.ts";
|
||||
import type {LearningPath} from "@/data-objects/learning-paths/learning-path.ts";
|
||||
import type {GroupDTO} from "@dwengo-1/common/interfaces/group";
|
||||
|
||||
const role = auth.authState.activeRole;
|
||||
const isTeacher = computed(() => role === 'teacher');
|
||||
|
@ -13,18 +17,57 @@ const route = useRoute();
|
|||
const classId = ref<string>(route.params.classId as string);
|
||||
const assignmentId = ref(Number(route.params.id));
|
||||
|
||||
function useGroupsWithProgress(
|
||||
groups: Ref<GroupDTO[]>,
|
||||
hruid: Ref<string>,
|
||||
language: Ref<string>
|
||||
): { groupProgressMap: Record<string, number> } {
|
||||
const groupProgressMap: Record<string, number> = reactive({});
|
||||
|
||||
watchEffect(() => {
|
||||
// Clear existing entries to avoid stale data
|
||||
for (const key in groupProgressMap) {
|
||||
delete groupProgressMap[key];
|
||||
}
|
||||
|
||||
const lang = language.value as Language;
|
||||
|
||||
groups.value.forEach((group) => {
|
||||
const groupKey = group.groupNumber.toString();
|
||||
|
||||
const query = useGetLearningPathQuery(hruid.value, lang, {
|
||||
forGroup: groupKey,
|
||||
});
|
||||
|
||||
const data = query.data.value;
|
||||
|
||||
groupProgressMap[groupKey] = data ? calculateProgress(data) : 0;
|
||||
});
|
||||
});
|
||||
|
||||
return {
|
||||
groupProgressMap,
|
||||
};
|
||||
}
|
||||
|
||||
function calculateProgress(lp: LearningPath): number {
|
||||
return ((lp.amountOfNodes - lp.amountOfNodesLeft) / lp.amountOfNodes) * 100;
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<TeacherAssignment
|
||||
:class-id="classId"
|
||||
:assignment-id="assignmentId"
|
||||
:use-groups-with-progress="useGroupsWithProgress"
|
||||
v-if="isTeacher"
|
||||
>
|
||||
</TeacherAssignment>
|
||||
<StudentAssignment
|
||||
:class-id="classId"
|
||||
:assignment-id="assignmentId"
|
||||
:use-groups-with-progress="useGroupsWithProgress"
|
||||
v-else
|
||||
>
|
||||
</StudentAssignment>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script setup lang="ts">
|
||||
import {ref, computed, defineProps} from "vue";
|
||||
import {ref, computed, defineProps, type Ref} from "vue";
|
||||
import auth from "@/services/auth/auth-service.ts";
|
||||
import {useI18n} from "vue-i18n";
|
||||
import {useAssignmentQuery} from "@/queries/assignments.ts";
|
||||
|
@ -10,14 +10,21 @@ import {useStudentsByUsernamesQuery} from "@/queries/students.ts";
|
|||
import {useGroupsQuery} from "@/queries/groups.ts";
|
||||
import {useGetLearningPathQuery} from "@/queries/learning-paths.ts";
|
||||
import type {Language} from "@/data-objects/language.ts";
|
||||
import type {GroupDTO} from "@dwengo-1/common/interfaces/group";
|
||||
|
||||
const props = defineProps<{
|
||||
classId: string
|
||||
assignmentId: number
|
||||
assignmentId: number,
|
||||
useGroupsWithProgress: (
|
||||
groups: Ref<GroupDTO[]>,
|
||||
hruid: Ref<string>,
|
||||
language: Ref<Language>
|
||||
) => { groupProgressMap: Record<string, number> };
|
||||
}>();
|
||||
|
||||
const {t, locale} = useI18n();
|
||||
const language = computed(() => locale.value);
|
||||
const language = ref<Language>(locale.value as Language);
|
||||
const learningPath = ref();
|
||||
// Get the user's username/id
|
||||
const username = asyncComputed(async () => {
|
||||
const user = await auth.loadUser();
|
||||
|
@ -25,13 +32,16 @@ const username = asyncComputed(async () => {
|
|||
});
|
||||
|
||||
const assignmentQueryResult = useAssignmentQuery(() => props.classId, props.assignmentId);
|
||||
learningPath.value = assignmentQueryResult.data.value?.assignment?.learningPath;
|
||||
|
||||
const submitted = ref(false);//TODO: update by fetching submissions and check if group submitted
|
||||
|
||||
const lpQueryResult = useGetLearningPathQuery(
|
||||
computed(() => assignmentQueryResult.data.value?.assignment?.learningPath ?? ""),
|
||||
computed(() => language.value as Language)
|
||||
computed(() => language.value)
|
||||
);
|
||||
|
||||
|
||||
const groupsQueryResult = useGroupsQuery(props.classId, props.assignmentId, true);
|
||||
const group = computed(() =>
|
||||
groupsQueryResult?.data.value?.groups.find(group =>
|
||||
|
@ -39,6 +49,18 @@ const group = computed(() =>
|
|||
)
|
||||
);
|
||||
|
||||
|
||||
const groupArray = computed(() => (group.value ? [group.value] : []));
|
||||
const progressValue = ref(0);
|
||||
/* Crashes right now cause api data has inexistent hruid TODO: uncomment later and use it in progress bar
|
||||
Const {groupProgressMap} = props.useGroupsWithProgress(
|
||||
groupArray,
|
||||
learningPath,
|
||||
language
|
||||
);
|
||||
*/
|
||||
|
||||
|
||||
// Assuming group.value.members is a list of usernames TODO: case when it's StudentDTO's
|
||||
const studentQueries = useStudentsByUsernamesQuery(() => group.value?.members as string[]);
|
||||
|
||||
|
@ -71,6 +93,7 @@ const studentQueries = useStudentsByUsernamesQuery(() => group.value?.members as
|
|||
</v-chip>
|
||||
</div>
|
||||
<v-card-title class="text-h4">{{ data.assignment.title }}</v-card-title>
|
||||
|
||||
<v-card-subtitle class="subtitle-section">
|
||||
<using-query-result
|
||||
:query-result="lpQueryResult"
|
||||
|
@ -89,6 +112,25 @@ const studentQueries = useStudentsByUsernamesQuery(() => group.value?.members as
|
|||
<v-card-text class="description">
|
||||
{{ data.assignment.description }}
|
||||
</v-card-text>
|
||||
<v-card-text>
|
||||
<v-row align="center" no-gutters>
|
||||
<v-col cols="auto">
|
||||
<span class="progress-label">{{ t("progress") + ": " }}</span>
|
||||
</v-col>
|
||||
<v-col>
|
||||
<v-progress-linear
|
||||
:model-value="progressValue"
|
||||
color="primary"
|
||||
height="20"
|
||||
class="progress-bar"
|
||||
>
|
||||
<template v-slot:default="{ value }">
|
||||
<strong>{{ Math.ceil(value) }}%</strong>
|
||||
</template>
|
||||
</v-progress-linear>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-card-text>
|
||||
|
||||
<v-card-text class="group-section">
|
||||
<h3>{{ t("group") }}</h3>
|
||||
|
@ -101,7 +143,6 @@ const studentQueries = useStudentsByUsernamesQuery(() => group.value?.members as
|
|||
</div>
|
||||
|
||||
</v-card-text>
|
||||
|
||||
</v-card>
|
||||
</using-query-result>
|
||||
</div>
|
||||
|
@ -110,5 +151,14 @@ const studentQueries = useStudentsByUsernamesQuery(() => group.value?.members as
|
|||
<style scoped>
|
||||
@import "@/assets/assignment.css";
|
||||
|
||||
.progress-label {
|
||||
font-weight: bold;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.progress-bar {
|
||||
width: 40%;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
|
|
|
@ -1,19 +1,23 @@
|
|||
<script setup lang="ts">
|
||||
import {computed, defineProps, reactive, type Ref, ref, watchEffect} from "vue";
|
||||
import {computed, defineProps, type Ref, ref} from "vue";
|
||||
import {useI18n} from "vue-i18n";
|
||||
import {useAssignmentQuery, useDeleteAssignmentMutation} from "@/queries/assignments.ts";
|
||||
import UsingQueryResult from "@/components/UsingQueryResult.vue";
|
||||
import {useGroupsQuery} from "@/queries/groups.ts";
|
||||
import {useGetLearningPathQuery} from "@/queries/learning-paths.ts";
|
||||
import type {Language} from "@/data-objects/language.ts";
|
||||
import type {LearningPath} from "@/data-objects/learning-paths/learning-path.ts";
|
||||
import type {GroupDTO} from "@dwengo-1/common/interfaces/group";
|
||||
import router from "@/router";
|
||||
import type {AssignmentResponse} from "@/controllers/assignments.ts";
|
||||
import type {GroupDTO} from "@dwengo-1/common/interfaces/group";
|
||||
|
||||
const props = defineProps<{
|
||||
classId: string
|
||||
assignmentId: number
|
||||
assignmentId: number,
|
||||
useGroupsWithProgress: (
|
||||
groups: Ref<GroupDTO[]>,
|
||||
hruid: Ref<string>,
|
||||
language: Ref<Language>
|
||||
) => { groupProgressMap: Record<string, number> };
|
||||
}>();
|
||||
|
||||
const {t, locale} = useI18n();
|
||||
|
@ -21,43 +25,6 @@ const language = computed(() => locale.value);
|
|||
const groups = ref();
|
||||
const learningPath = ref();
|
||||
|
||||
function useGroupsWithProgress(
|
||||
groups: Ref<GroupDTO[]>,
|
||||
hruid: Ref<string>,
|
||||
language: Ref<string>
|
||||
): { groupProgressMap: Record<string, number> } {
|
||||
const groupProgressMap: Record<string, number> = reactive({});
|
||||
|
||||
watchEffect(() => {
|
||||
// Clear existing entries to avoid stale data
|
||||
for (const key in groupProgressMap) {
|
||||
delete groupProgressMap[key];
|
||||
}
|
||||
|
||||
const lang = language.value as Language;
|
||||
|
||||
groups.value.forEach((group) => {
|
||||
const groupKey = group.groupNumber.toString();
|
||||
|
||||
const query = useGetLearningPathQuery(hruid.value, lang, {
|
||||
forGroup: groupKey,
|
||||
});
|
||||
|
||||
const data = query.data.value;
|
||||
|
||||
groupProgressMap[groupKey] = data ? calculateProgress(data) : 0;
|
||||
});
|
||||
});
|
||||
|
||||
return {
|
||||
groupProgressMap,
|
||||
};
|
||||
}
|
||||
|
||||
function calculateProgress(lp: LearningPath): number {
|
||||
return ((lp.amountOfNodes - lp.amountOfNodesLeft) / lp.amountOfNodes) * 100;
|
||||
}
|
||||
|
||||
const assignmentQueryResult = useAssignmentQuery(() => props.classId, props.assignmentId);
|
||||
learningPath.value = assignmentQueryResult.data.value?.assignment?.learningPath;
|
||||
// Get learning path object
|
||||
|
@ -70,8 +37,8 @@ const lpQueryResult = useGetLearningPathQuery(
|
|||
const groupsQueryResult = useGroupsQuery(props.classId, props.assignmentId, true);
|
||||
groups.value = groupsQueryResult.data.value?.groups;
|
||||
|
||||
/* Crashes right now cause api data has inexistent hruid TODO: uncomment later
|
||||
Const {groupProgressMap} = useGroupsWithProgress(
|
||||
/* Crashes right now cause api data has inexistent hruid TODO: uncomment later and use it in progress bar
|
||||
Const {groupProgressMap} = props.useGroupsWithProgress(
|
||||
groups,
|
||||
learningPath,
|
||||
language
|
||||
|
@ -200,7 +167,7 @@ async function deleteAssignment(num: number, clsId: string): Promise<void> {
|
|||
variant="text"
|
||||
class="text-capitalize"
|
||||
>
|
||||
{{ item.submitted ? t('see-submission') : t('not-submitted') }}
|
||||
{{ item.submitted ? t('see-submission') : t('no-submission') }}
|
||||
</v-btn>
|
||||
</template>
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue