feat(frontend): echte assignment titel, description en klas worden getoond
This commit is contained in:
		
							parent
							
								
									5d69ea9aa4
								
							
						
					
					
						commit
						9aae5a3a46
					
				
					 7 changed files with 166 additions and 61 deletions
				
			
		|  | @ -18,6 +18,7 @@ | ||||||
|     "dependencies": { |     "dependencies": { | ||||||
|         "@tanstack/react-query": "^5.69.0", |         "@tanstack/react-query": "^5.69.0", | ||||||
|         "@tanstack/vue-query": "^5.69.0", |         "@tanstack/vue-query": "^5.69.0", | ||||||
|  |         "@vueuse/core": "^13.1.0", | ||||||
|         "axios": "^1.8.2", |         "axios": "^1.8.2", | ||||||
|         "oidc-client-ts": "^3.1.0", |         "oidc-client-ts": "^3.1.0", | ||||||
|         "vue": "^3.5.13", |         "vue": "^3.5.13", | ||||||
|  |  | ||||||
|  | @ -13,6 +13,8 @@ import type {LearningPath} from "@/data-objects/learning-paths/learning-path.ts" | ||||||
| import type {ClassesResponse} from "@/controllers/classes.ts"; | import type {ClassesResponse} from "@/controllers/classes.ts"; | ||||||
| import type {AssignmentDTO} from "@dwengo-1/common/interfaces/assignment"; | import type {AssignmentDTO} from "@dwengo-1/common/interfaces/assignment"; | ||||||
| import {AssignmentController} from "@/controllers/assignments.ts"; | import {AssignmentController} from "@/controllers/assignments.ts"; | ||||||
|  | import type {GroupDTO} from "@dwengo-1/common/interfaces/group"; | ||||||
|  | import {GroupController} from "@/controllers/groups.ts"; | ||||||
| 
 | 
 | ||||||
| /*** | /*** | ||||||
|  TODO: when clicking the assign button from lp page pass the lp-object like this: |  TODO: when clicking the assign button from lp page pass the lp-object like this: | ||||||
|  | @ -28,17 +30,7 @@ const props = defineProps<{ | ||||||
| const router = useRouter(); | const router = useRouter(); | ||||||
| const {t, locale} = useI18n(); | const {t, locale} = useI18n(); | ||||||
| const role = ref(auth.authState.activeRole); | const role = ref(auth.authState.activeRole); | ||||||
| const username = ref<string | null>(null); | const username = ref<string>(""); | ||||||
| 
 |  | ||||||
| interface FormData { |  | ||||||
|     assignmentTitle: string; |  | ||||||
|     selectedLearningPath: string; |  | ||||||
|     selectedClass: string; |  | ||||||
|     groups: string[][]; |  | ||||||
|     deadline: string; |  | ||||||
|     description: string; |  | ||||||
|     currentLanguage: string; |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| async function submitForm(assignmentTitle: string, | async function submitForm(assignmentTitle: string, | ||||||
|                           selectedLearningPath: string, |                           selectedLearningPath: string, | ||||||
|  | @ -60,7 +52,27 @@ async function submitForm(assignmentTitle: string, | ||||||
| 
 | 
 | ||||||
|     //TODO: replace with query function |     //TODO: replace with query function | ||||||
|     const controller: AssignmentController = new AssignmentController(selectedClass); |     const controller: AssignmentController = new AssignmentController(selectedClass); | ||||||
|     await controller.createAssignment(assignmentDTO); |     const response = await controller.createAssignment(assignmentDTO); | ||||||
|  |     // Create groups | ||||||
|  |     for (let i = 0; i < groups.length; i++) { | ||||||
|  |         const group: GroupDTO = { | ||||||
|  |             assignment: response.id, | ||||||
|  |             groupNumber: i, | ||||||
|  |             members: groups[i] | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |         console.log("Posting group:", group); | ||||||
|  | 
 | ||||||
|  |         const groupController: GroupController = new GroupController(selectedClass, response.id); | ||||||
|  | 
 | ||||||
|  |         try { | ||||||
|  |             await groupController.createGroup(group); | ||||||
|  |             console.log("Group successfully posted:", group); | ||||||
|  |         } catch (err) { | ||||||
|  |             console.error("Group POST failed:", err); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     await router.push('/user/assignment'); |     await router.push('/user/assignment'); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -72,7 +84,7 @@ onMounted(async () => { | ||||||
| 
 | 
 | ||||||
|     // Get the user's username |     // Get the user's username | ||||||
|     const user = await auth.loadUser(); |     const user = await auth.loadUser(); | ||||||
|     username.value = user?.profile?.preferred_username ?? null; |     username.value = user?.profile?.preferred_username ?? ""; | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -11,7 +11,7 @@ export abstract class BaseController { | ||||||
| 
 | 
 | ||||||
|     private static assertSuccessResponse(response: AxiosResponse<unknown, unknown>): void { |     private static assertSuccessResponse(response: AxiosResponse<unknown, unknown>): void { | ||||||
|         if (response.status / 100 !== 2) { |         if (response.status / 100 !== 2) { | ||||||
|             throw new HttpErrorResponseException(response); |             //throw new HttpErrorResponseException(response);
 | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,14 +1,15 @@ | ||||||
| import {useMutation, useQueryClient, type UseMutationReturnType} from "@tanstack/vue-query"; | import {useMutation, useQueryClient, type UseMutationReturnType} from "@tanstack/vue-query"; | ||||||
| import {AssignmentController, type AssignmentResponse} from "@/controllers/assignments.ts"; | import {AssignmentController, type AssignmentResponse} from "@/controllers/assignments.ts"; | ||||||
| import type {AssignmentDTO} from "@dwengo-1/common/interfaces/assignment"; | import type {AssignmentDTO} from "@dwengo-1/common/interfaces/assignment"; | ||||||
|  | import {toValue} from "vue"; | ||||||
| 
 | 
 | ||||||
| export function useCreateAssignmentMutation(classId: string): UseMutationReturnType<AssignmentResponse, Error, AssignmentDTO, unknown> { | export function useCreateAssignmentMutation(classId: string): UseMutationReturnType<AssignmentResponse, Error, AssignmentDTO, unknown> { | ||||||
|     const queryClient = useQueryClient(); |     const queryClient = useQueryClient(); | ||||||
| 
 | 
 | ||||||
|     const assignmentController = new AssignmentController(classId); |     const assignmentController = new AssignmentController(toValue(classId)); | ||||||
| 
 | 
 | ||||||
|     return useMutation({ |     return useMutation({ | ||||||
|         mutationFn: async (data: AssignmentDTO) => assignmentController.createAssignment(data), |         mutationFn: async (data) => assignmentController.createAssignment(data), | ||||||
|         onSuccess: async () => { |         onSuccess: async () => { | ||||||
|             await queryClient.invalidateQueries({queryKey: ["assignments"]}); |             await queryClient.invalidateQueries({queryKey: ["assignments"]}); | ||||||
|         }, |         }, | ||||||
|  |  | ||||||
|  | @ -1,26 +1,30 @@ | ||||||
| <script setup lang="ts"> | <script setup lang="ts"> | ||||||
|     import { useRoute } from "vue-router"; |     import { useRoute } from "vue-router"; | ||||||
|     import {ref, onMounted, computed} from "vue"; |     import {ref, computed} from "vue"; | ||||||
|     import {useI18n} from "vue-i18n"; |     import {useI18n} from "vue-i18n"; | ||||||
|     import {assignments} from "@/utils/tempData.ts"; |  | ||||||
|     import auth from "@/services/auth/auth-service.ts"; |     import auth from "@/services/auth/auth-service.ts"; | ||||||
|  |     import {AssignmentController} from "@/controllers/assignments.ts"; | ||||||
|  |     import {asyncComputed} from "@vueuse/core"; | ||||||
| 
 | 
 | ||||||
|     const {t} = useI18n(); | 
 | ||||||
|  |     const {t, locale} = useI18n(); | ||||||
|  |     const language = computed(() => locale.value); | ||||||
|     const route = useRoute(); |     const route = useRoute(); | ||||||
|     const assignmentId = ref(route.params.id as string); |     const assignmentId = ref(Number(route.params.id)); | ||||||
|     const assignment = ref(null); |     const classId = window.history.state?.class_id; | ||||||
|  |     //const assignment = ref(null); | ||||||
|  |     const controller = new AssignmentController(classId); | ||||||
| 
 | 
 | ||||||
|     const role = auth.authState.activeRole; |     const role = auth.authState.activeRole; | ||||||
|     const isTeacher = computed(() => role === 'teacher'); |     const isTeacher = computed(() => role === 'teacher'); | ||||||
| 
 | 
 | ||||||
|     const loadAssignment = async () => { |     const assignment = asyncComputed(async () => { | ||||||
|         // TODO: Replace with real data |         return await controller.getByNumber(assignmentId.value) | ||||||
|         assignment.value = assignments[0]; |     }, null); | ||||||
|     }; |  | ||||||
| 
 |  | ||||||
|     const myUsername = "id01"; //TODO: replace by username of logged in user |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|  |     /*** | ||||||
|     // Display group members |     // Display group members | ||||||
|     const myGroup = computed(() => { |     const myGroup = computed(() => { | ||||||
|         if (!assignment.value || !assignment.value.groups) return null; |         if (!assignment.value || !assignment.value.groups) return null; | ||||||
|  | @ -29,13 +33,13 @@ | ||||||
|             group.members.some(m => m.username === myUsername) |             group.members.some(m => m.username === myUsername) | ||||||
|         ); |         ); | ||||||
|     }); |     }); | ||||||
|  |         */ | ||||||
| 
 | 
 | ||||||
|     const deleteAssignment = () => { |     const deleteAssignment = () => { | ||||||
|         console.log('Delete assignment:', assignmentId.value); |         console.log('Delete assignment:', assignmentId.value); | ||||||
|  |         //controller.deleteAssignment(assignmentId); | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     onMounted(loadAssignment); |  | ||||||
| 
 |  | ||||||
| </script> | </script> | ||||||
| 
 | 
 | ||||||
| <template> | <template> | ||||||
|  | @ -64,7 +68,7 @@ | ||||||
|             <v-card-title class="text-h4">{{ assignment.title }}</v-card-title> |             <v-card-title class="text-h4">{{ assignment.title }}</v-card-title> | ||||||
|             <v-card-subtitle> |             <v-card-subtitle> | ||||||
|                 <v-btn |                 <v-btn | ||||||
|                     :to="`/learningPath/${assignment.learningPathHruid}`" |                     :to="`/learningPath/${language}/${assignment.learningPath}`" | ||||||
|                     variant="tonal" |                     variant="tonal" | ||||||
|                     color="primary" |                     color="primary" | ||||||
|                 > |                 > | ||||||
|  | @ -79,7 +83,7 @@ | ||||||
|             <v-card-text class="group-section"> |             <v-card-text class="group-section"> | ||||||
|                 <h3>{{ t("group") }}</h3> |                 <h3>{{ t("group") }}</h3> | ||||||
| 
 | 
 | ||||||
|                 <!-- Student view --> |                 <!-- Student view | ||||||
|                 <div v-if="!isTeacher"> |                 <div v-if="!isTeacher"> | ||||||
|                     <div v-if="myGroup"> |                     <div v-if="myGroup"> | ||||||
|                         <ul> |                         <ul> | ||||||
|  | @ -88,10 +92,10 @@ | ||||||
|                             </li> |                             </li> | ||||||
|                         </ul> |                         </ul> | ||||||
|                     </div> |                     </div> | ||||||
|                 </div> |                 </div>--> | ||||||
| 
 | 
 | ||||||
|                 <!-- Teacher view --> |                 <!-- Teacher view | ||||||
|                 <div v-else> |                 <div v-if="isTeacher"> | ||||||
|                     <v-expansion-panels> |                     <v-expansion-panels> | ||||||
|                         <v-expansion-panel |                         <v-expansion-panel | ||||||
|                             v-for="(group, index) in assignment.groups" |                             v-for="(group, index) in assignment.groups" | ||||||
|  | @ -109,7 +113,7 @@ | ||||||
|                             </v-expansion-panel-text> |                             </v-expansion-panel-text> | ||||||
|                         </v-expansion-panel> |                         </v-expansion-panel> | ||||||
|                     </v-expansion-panels> |                     </v-expansion-panels> | ||||||
|                 </div> |                 </div>--> | ||||||
|             </v-card-text> |             </v-card-text> | ||||||
| 
 | 
 | ||||||
|         </v-card> |         </v-card> | ||||||
|  |  | ||||||
|  | @ -4,33 +4,75 @@ | ||||||
| import {useRouter} from 'vue-router'; | import {useRouter} from 'vue-router'; | ||||||
| import auth from "@/services/auth/auth-service.ts"; | import auth from "@/services/auth/auth-service.ts"; | ||||||
| import {assignments} from "@/utils/tempData.ts"; | import {assignments} from "@/utils/tempData.ts"; | ||||||
|  | import {useTeacherClassesQuery} from "@/queries/teachers.ts"; | ||||||
|  | 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"; | ||||||
| 
 | 
 | ||||||
| const {t} = useI18n(); | const {t} = useI18n(); | ||||||
| const router = useRouter(); | const router = useRouter(); | ||||||
| 
 | 
 | ||||||
|     const role = auth.authState.activeRole; | const role = ref(auth.authState.activeRole); | ||||||
|  | const username = ref<string>(""); | ||||||
| 
 | 
 | ||||||
|     const allAssignments = ref(assignments); | const isTeacher = computed(() => role.value === 'teacher'); | ||||||
|     const isTeacher = computed(() => role === 'teacher'); |  | ||||||
| 
 | 
 | ||||||
|     const loadAssignments = async () => { | // Fetch and store all the teacher's classes | ||||||
|         //TODO: replace with controller function | let classesQueryResults = undefined; | ||||||
|         // fetch all student's or teacher's assignments | 
 | ||||||
|  | if (isTeacher.value) { | ||||||
|  |     classesQueryResults = useTeacherClassesQuery(username, true) | ||||||
|  | } else { | ||||||
|  |     classesQueryResults = useStudentClassesQuery(username, true); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | const classController = new ClassController(); | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | const assignments = asyncComputed(async () => { | ||||||
|  |     const classes = classesQueryResults?.data?.value?.classes; | ||||||
|  |     if (!classes) return []; | ||||||
|  |     const result = await Promise.all( | ||||||
|  |         (classes as ClassDTO[]).map(async (cls) => { | ||||||
|  |             const { assignments } = await classController.getAssignments(cls.id); | ||||||
|  |             return assignments.map(a => ({ | ||||||
|  |                 id: a.id, | ||||||
|  |                 class: cls, // replace by the whole ClassDTO object | ||||||
|  |                 title: a.title, | ||||||
|  |                 description: a.description, | ||||||
|  |                 learningPath: a.learningPath, | ||||||
|  |                 language: a.language, | ||||||
|  |                 groups: [] | ||||||
|  |             })); | ||||||
|  |         }) | ||||||
|  |     ); | ||||||
|  | 
 | ||||||
|  |     return result.flat(); | ||||||
|  | }, []); | ||||||
|  | 
 | ||||||
|  | console.log(assignments); | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | const goToCreateAssignment = async () => { | ||||||
|  |     await router.push('/assignment/create'); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const goToAssignmentDetails = async (id: number, class_id: number) => { | ||||||
|  |     await router.push({ | ||||||
|  |         path: `/assignment/${id}`, | ||||||
|  |         state: { class_id }, | ||||||
|  |     }); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|     onMounted(loadAssignments); | const goToDeleteAssignment = (id: number) => { | ||||||
| 
 |  | ||||||
|     const goToCreateAssignment = () => { |  | ||||||
|         router.push('/assignment/create'); |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|     const goToAssignmentDetails = (id: string) => { | onMounted(async () => { | ||||||
|         router.push(`/assignment/${id}`); |     const user = await auth.loadUser(); | ||||||
|     }; |     username.value = user?.profile?.preferred_username ?? ""; | ||||||
| 
 | }); | ||||||
|     const goToDeleteAssignment = (id: string) => { |  | ||||||
|     }; |  | ||||||
| </script> | </script> | ||||||
| 
 | 
 | ||||||
| <template> | <template> | ||||||
|  | @ -49,7 +91,7 @@ | ||||||
|         <v-container> |         <v-container> | ||||||
|             <v-row> |             <v-row> | ||||||
|                 <v-col |                 <v-col | ||||||
|                     v-for="assignment in allAssignments" |                     v-for="assignment in assignments" | ||||||
|                     :key="assignment.id" |                     :key="assignment.id" | ||||||
|                     cols="12" |                     cols="12" | ||||||
|                 > |                 > | ||||||
|  | @ -60,13 +102,13 @@ | ||||||
|                                 <div class="assignment-class"> |                                 <div class="assignment-class"> | ||||||
|                                     {{ t('class') }}: |                                     {{ t('class') }}: | ||||||
|                                     <span class="class-name"> |                                     <span class="class-name"> | ||||||
|                                         {{ assignment.class }} |                                         {{ assignment.class.displayName }} | ||||||
|                                     </span> |                                     </span> | ||||||
|                                 </div> |                                 </div> | ||||||
|                             </div> |                             </div> | ||||||
|                             <div class="right-content"> |                             <div class="right-content"> | ||||||
|                                 <v-card-actions> |                                 <v-card-actions> | ||||||
|                                     <v-btn color="primary" @click="goToAssignmentDetails(assignment.id)"> |                                     <v-btn color="primary" @click="goToAssignmentDetails(assignment.id, assignment.class.id)"> | ||||||
|                                         {{ t('view-assignment') }} |                                         {{ t('view-assignment') }} | ||||||
|                                     </v-btn> |                                     </v-btn> | ||||||
|                                     <v-btn v-if="isTeacher" color="red" @click="goToDeleteAssignment(assignment.id)"> |                                     <v-btn v-if="isTeacher" color="red" @click="goToDeleteAssignment(assignment.id)"> | ||||||
|  |  | ||||||
							
								
								
									
										45
									
								
								package-lock.json
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										45
									
								
								package-lock.json
									
										
									
										generated
									
									
									
								
							|  | @ -103,6 +103,7 @@ | ||||||
|             "dependencies": { |             "dependencies": { | ||||||
|                 "@tanstack/react-query": "^5.69.0", |                 "@tanstack/react-query": "^5.69.0", | ||||||
|                 "@tanstack/vue-query": "^5.69.0", |                 "@tanstack/vue-query": "^5.69.0", | ||||||
|  |                 "@vueuse/core": "^13.1.0", | ||||||
|                 "axios": "^1.8.2", |                 "axios": "^1.8.2", | ||||||
|                 "oidc-client-ts": "^3.1.0", |                 "oidc-client-ts": "^3.1.0", | ||||||
|                 "vue": "^3.5.13", |                 "vue": "^3.5.13", | ||||||
|  | @ -3030,6 +3031,12 @@ | ||||||
|             "license": "MIT", |             "license": "MIT", | ||||||
|             "optional": true |             "optional": true | ||||||
|         }, |         }, | ||||||
|  |         "node_modules/@types/web-bluetooth": { | ||||||
|  |             "version": "0.0.21", | ||||||
|  |             "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.21.tgz", | ||||||
|  |             "integrity": "sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA==", | ||||||
|  |             "license": "MIT" | ||||||
|  |         }, | ||||||
|         "node_modules/@typescript-eslint/eslint-plugin": { |         "node_modules/@typescript-eslint/eslint-plugin": { | ||||||
|             "version": "8.28.0", |             "version": "8.28.0", | ||||||
|             "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.28.0.tgz", |             "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.28.0.tgz", | ||||||
|  | @ -3774,6 +3781,44 @@ | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|  |         "node_modules/@vueuse/core": { | ||||||
|  |             "version": "13.1.0", | ||||||
|  |             "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-13.1.0.tgz", | ||||||
|  |             "integrity": "sha512-PAauvdRXZvTWXtGLg8cPUFjiZEddTqmogdwYpnn60t08AA5a8Q4hZokBnpTOnVNqySlFlTcRYIC8OqreV4hv3Q==", | ||||||
|  |             "license": "MIT", | ||||||
|  |             "dependencies": { | ||||||
|  |                 "@types/web-bluetooth": "^0.0.21", | ||||||
|  |                 "@vueuse/metadata": "13.1.0", | ||||||
|  |                 "@vueuse/shared": "13.1.0" | ||||||
|  |             }, | ||||||
|  |             "funding": { | ||||||
|  |                 "url": "https://github.com/sponsors/antfu" | ||||||
|  |             }, | ||||||
|  |             "peerDependencies": { | ||||||
|  |                 "vue": "^3.5.0" | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         "node_modules/@vueuse/metadata": { | ||||||
|  |             "version": "13.1.0", | ||||||
|  |             "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-13.1.0.tgz", | ||||||
|  |             "integrity": "sha512-+TDd7/a78jale5YbHX9KHW3cEDav1lz1JptwDvep2zSG8XjCsVE+9mHIzjTOaPbHUAk5XiE4jXLz51/tS+aKQw==", | ||||||
|  |             "license": "MIT", | ||||||
|  |             "funding": { | ||||||
|  |                 "url": "https://github.com/sponsors/antfu" | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         "node_modules/@vueuse/shared": { | ||||||
|  |             "version": "13.1.0", | ||||||
|  |             "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-13.1.0.tgz", | ||||||
|  |             "integrity": "sha512-IVS/qRRjhPTZ6C2/AM3jieqXACGwFZwWTdw5sNTSKk2m/ZpkuuN+ri+WCVUP8TqaKwJYt/KuMwmXspMAw8E6ew==", | ||||||
|  |             "license": "MIT", | ||||||
|  |             "funding": { | ||||||
|  |                 "url": "https://github.com/sponsors/antfu" | ||||||
|  |             }, | ||||||
|  |             "peerDependencies": { | ||||||
|  |                 "vue": "^3.5.0" | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|         "node_modules/abbrev": { |         "node_modules/abbrev": { | ||||||
|             "version": "1.1.1", |             "version": "1.1.1", | ||||||
|             "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", |             "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", | ||||||
|  |  | ||||||
		Reference in a new issue
	
	 Joyelle Ndagijimana
						Joyelle Ndagijimana