feat(frontend): progress van assignment wordt getoond
This commit is contained in:
		
							parent
							
								
									20cf276faf
								
							
						
					
					
						commit
						5b17bad368
					
				
					 4 changed files with 113 additions and 34 deletions
				
			
		|  | @ -12,13 +12,21 @@ import UsingQueryResult from "@/components/UsingQueryResult.vue"; | |||
| import type {LearningPath} from "@/data-objects/learning-paths/learning-path.ts"; | ||||
| import type {ClassesResponse} from "@/controllers/classes.ts"; | ||||
| import type {AssignmentDTO} from "@dwengo-1/common/interfaces/assignment"; | ||||
| import {AssignmentController} from "@/controllers/assignments.ts"; | ||||
| import {useCreateAssignmentMutation} from "@/queries/assignments.ts"; | ||||
| import {useRoute} from "vue-router"; | ||||
| 
 | ||||
| /*** | ||||
|  TODO: when clicking the assign button from lp page pass the lp-object in a state: | ||||
|  TODO: when clicking the assign button from lp page pass the lp-hruid in a query like this: | ||||
|  router.push({ | ||||
|      path: "/assignment/create, | ||||
|          query: { | ||||
|          ...route.query, | ||||
|          lp: hruid, | ||||
|         }, | ||||
|      }); | ||||
|  */ | ||||
| 
 | ||||
| const route = useRoute(); | ||||
| const router = useRouter(); | ||||
| const {t, locale} = useI18n(); | ||||
| const role = ref(auth.authState.activeRole); | ||||
|  | @ -48,10 +56,10 @@ const classesQueryResults = useTeacherClassesQuery(username, true); | |||
| const selectedClass = ref(undefined); | ||||
| 
 | ||||
| const assignmentTitle = ref(''); | ||||
| const selectedLearningPath = ref<LearningPath | null>(window.history.state?.learningPath ?? null); | ||||
| const selectedLearningPath = ref(route.query.lp || undefined); | ||||
| 
 | ||||
| // Disable combobox when learningPath prop is passed | ||||
| const lpIsSelected = window.history.state?.learningPath !== undefined; | ||||
| const lpIsSelected = route.query.lp !== undefined; | ||||
| const deadline = ref(null); | ||||
| const description = ref(''); | ||||
| const groups = ref<string[][]>([]); | ||||
|  |  | |||
|  | @ -8,6 +8,8 @@ import type {AssignmentResponse} from "@/controllers/assignments.ts"; | |||
| import {asyncComputed} from "@vueuse/core"; | ||||
| 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"; | ||||
| 
 | ||||
| const props = defineProps<{ | ||||
|     classId: string | ||||
|  | @ -25,16 +27,16 @@ const username = asyncComputed(async () => { | |||
| const assignmentQueryResult = useAssignmentQuery(() => props.classId, props.assignmentId); | ||||
| 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) | ||||
| ); | ||||
| 
 | ||||
| const groupsQueryResult = useGroupsQuery(props.classId, props.assignmentId, true); | ||||
| const group = computed(() => | ||||
|     groupsQueryResult?.data.value?.groups.find(group => | ||||
|         group.members?.some(m => m.username === username.value) | ||||
|     ) | ||||
|     /** For testing | ||||
|      return {assignment: 1, | ||||
|      groupNumber: 1, | ||||
|      members: ["testleerling1"]} | ||||
|      */ | ||||
| ); | ||||
| 
 | ||||
| // Assuming group.value.members is a list of usernames TODO: case when it's StudentDTO's | ||||
|  | @ -70,13 +72,18 @@ const studentQueries = useStudentsByUsernamesQuery(() => group.value?.members as | |||
|                 </div> | ||||
|                 <v-card-title class="text-h4">{{ data.assignment.title }}</v-card-title> | ||||
|                 <v-card-subtitle class="subtitle-section"> | ||||
|                     <v-btn | ||||
|                         :to="`/learningPath/${language}/${data.assignment.learningPath}`" | ||||
|                     <using-query-result | ||||
|                         :query-result="lpQueryResult" | ||||
|                         v-slot="{ data: lpData }" | ||||
|                     > | ||||
|                         <v-btn v-if="lpData" | ||||
|                                :to="`/learningPath/${lpData.hruid}/${language}/${lpData.startNode.learningobjectHruid}`" | ||||
|                                variant="tonal" | ||||
|                                color="primary" | ||||
|                         > | ||||
|                             {{ t("learning-path") }} | ||||
|                         </v-btn> | ||||
|                     </using-query-result> | ||||
|                 </v-card-subtitle> | ||||
| 
 | ||||
|                 <v-card-text class="description"> | ||||
|  |  | |||
|  | @ -1,13 +1,15 @@ | |||
| <script setup lang="ts"> | ||||
| import {computed, defineProps, ref} from "vue"; | ||||
| import {computed, defineProps, reactive, type Ref, ref, watchEffect} from "vue"; | ||||
| import {useI18n} from "vue-i18n"; | ||||
| import {AssignmentController, type AssignmentResponse} from "@/controllers/assignments.ts"; | ||||
| import {useAssignmentQuery} from "@/queries/assignments.ts"; | ||||
| 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"; | ||||
| 
 | ||||
| const props = defineProps<{ | ||||
|     classId: string | ||||
|  | @ -16,23 +18,74 @@ const props = defineProps<{ | |||
| 
 | ||||
| const {t, locale} = useI18n(); | ||||
| const language = computed(() => locale.value); | ||||
| const controller = new AssignmentController(props.classId); | ||||
| 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); | ||||
| const groupsQueryResult = useGroupsQuery(props.classId, props.assignmentId, true); | ||||
| 
 | ||||
| learningPath.value = assignmentQueryResult.data.value?.assignment?.learningPath; | ||||
| // Get learning path object | ||||
| const lpQueryResult = useGetLearningPathQuery( | ||||
|     computed(() => assignmentQueryResult.data.value?.assignment?.learningPath ?? ""), | ||||
|     computed(() => language.value as Language) | ||||
| ); | ||||
| 
 | ||||
| // Get all the groups withing the assignment | ||||
| 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( | ||||
|     groups, | ||||
|     learningPath, | ||||
|     language | ||||
| ); | ||||
| */ | ||||
| 
 | ||||
| 
 | ||||
| const allGroups = computed(() => { | ||||
|     const groups = groupsQueryResult.data.value?.groups; | ||||
|     if (!groups) return []; | ||||
| 
 | ||||
|     return groups.map(group => ({ | ||||
|         name: `${t('group')} ${group.groupNumber}`, | ||||
|         progress: 0, | ||||
|         progress: 0,//GroupProgressMap[group.groupNumber], | ||||
|         members: group.members, | ||||
|         submitted: false,//TODO: fetch from submission | ||||
|     })); | ||||
|  | @ -53,8 +106,15 @@ const headers = ref([ | |||
| ]); | ||||
| 
 | ||||
| 
 | ||||
| async function deleteAssignment(): Promise<void> { | ||||
|     await controller.deleteAssignment(props.assignmentId); | ||||
| const {mutate, isSuccess} = useDeleteAssignmentMutation(); | ||||
| 
 | ||||
| async function deleteAssignment(num: number, clsId: string): Promise<void> { | ||||
|     mutate({ | ||||
|         cid: clsId, | ||||
|         an: num | ||||
|     }); | ||||
| 
 | ||||
|     if (isSuccess) await router.push("/user/assignments"); | ||||
| } | ||||
| 
 | ||||
| </script> | ||||
|  | @ -80,7 +140,7 @@ async function deleteAssignment(): Promise<void> { | |||
|                         icon | ||||
|                         variant="text" | ||||
|                         class="top-right-btn" | ||||
|                         @click="deleteAssignment" | ||||
|                         @click="deleteAssignment(data.assignment.id, data.assignment.within)" | ||||
|                     > | ||||
|                         <v-icon>mdi-delete</v-icon> | ||||
|                     </v-btn> | ||||
|  | @ -92,7 +152,7 @@ async function deleteAssignment(): Promise<void> { | |||
|                         v-slot="{ data: lpData }" | ||||
|                     > | ||||
|                         <v-btn v-if="lpData" | ||||
|                                :to="`/learningPath/${language}/${lpData.hruid}/${lpData.startNode.learningobjectHruid}`" | ||||
|                                :to="`/learningPath/${lpData.hruid}/${language}/${lpData.startNode.learningobjectHruid}`" | ||||
|                                variant="tonal" | ||||
|                                color="primary" | ||||
|                         > | ||||
|  |  | |||
|  | @ -8,7 +8,7 @@ import {useStudentClassesQuery} from "@/queries/students.ts"; | |||
| import {ClassController} from "@/controllers/classes.ts"; | ||||
| import type {ClassDTO} from "@dwengo-1/common/interfaces/class"; | ||||
| import {asyncComputed} from "@vueuse/core"; | ||||
| import {AssignmentController} from "@/controllers/assignments.ts"; | ||||
| import {useDeleteAssignmentMutation} from "@/queries/assignments.ts"; | ||||
| 
 | ||||
| const {t} = useI18n(); | ||||
| const router = useRouter(); | ||||
|  | @ -62,11 +62,15 @@ async function goToAssignmentDetails(id: number, clsId: string): Promise<void> { | |||
|     await router.push(`/assignment/${clsId}/${id}`); | ||||
| } | ||||
| 
 | ||||
| const {mutate, isSuccess} = useDeleteAssignmentMutation(); | ||||
| 
 | ||||
| async function goToDeleteAssignment(id: number, clsId: string): Promise<void> { | ||||
|     //TODO: replace with query | ||||
|     const controller = new AssignmentController(clsId); | ||||
|     await controller.deleteAssignment(id); | ||||
| async function goToDeleteAssignment(num: number, clsId: string): Promise<void> { | ||||
|     mutate({ | ||||
|         cid: clsId, | ||||
|         an: num | ||||
|     }); | ||||
| 
 | ||||
|     if (isSuccess) await router.push("/user/assignment"); | ||||
| } | ||||
| 
 | ||||
| onMounted(async () => { | ||||
|  |  | |||
		Reference in a new issue
	
	 Joyelle Ndagijimana
						Joyelle Ndagijimana