feat(frontend): nieuwe "cancel" knop bij create assignment
This commit is contained in:
		
							parent
							
								
									1d29adaa31
								
							
						
					
					
						commit
						800f6433d6
					
				
					 10 changed files with 44 additions and 238 deletions
				
			
		|  | @ -11,7 +11,7 @@ | ||||||
| 
 | 
 | ||||||
|     const role = auth.authState.activeRole; |     const role = auth.authState.activeRole; | ||||||
| 
 | 
 | ||||||
|     const name: string = "";//auth.authState.user!.profile.name!; |     const name = "";//Auth.authState.user!.profile.name!; | ||||||
|     const initials: string = name |     const initials: string = name | ||||||
|         .split(" ") |         .split(" ") | ||||||
|         .map((n) => n[0]) |         .map((n) => n[0]) | ||||||
|  |  | ||||||
|  | @ -92,6 +92,6 @@ | ||||||
|     "group": "Gruppe", |     "group": "Gruppe", | ||||||
|     "description": "Beschreibung", |     "description": "Beschreibung", | ||||||
|     "no-submission": "keine vorlage", |     "no-submission": "keine vorlage", | ||||||
|     "submission": "einreichung", |     "submission": "Einreichung", | ||||||
|     "progress": "Fortschritte" |     "progress": "Fortschritte" | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -33,7 +33,7 @@ | ||||||
|     "JoinClassExplanation": "Enter the code the teacher has given you to join the class.", |     "JoinClassExplanation": "Enter the code the teacher has given you to join the class.", | ||||||
|     "invalidFormat": "Invalid format.", |     "invalidFormat": "Invalid format.", | ||||||
|     "submitCode": "submit", |     "submitCode": "submit", | ||||||
|     "members": "members", |     "members": "Members", | ||||||
|     "themes": "Themes", |     "themes": "Themes", | ||||||
|     "choose-theme": "Select a theme", |     "choose-theme": "Select a theme", | ||||||
|     "choose-age": "Select age", |     "choose-age": "Select age", | ||||||
|  | @ -92,6 +92,6 @@ | ||||||
|     "group": "Group", |     "group": "Group", | ||||||
|     "description": "Description", |     "description": "Description", | ||||||
|     "no-submission": "no submission", |     "no-submission": "no submission", | ||||||
|     "submission": "submission", |     "submission": "Submission", | ||||||
|     "progress": "Progress" |     "progress": "Progress" | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -33,7 +33,7 @@ | ||||||
|     "JoinClassExplanation": "Entrez le code que l'enseignant vous a donné pour rejoindre la classe.", |     "JoinClassExplanation": "Entrez le code que l'enseignant vous a donné pour rejoindre la classe.", | ||||||
|     "invalidFormat": "Format non valide.", |     "invalidFormat": "Format non valide.", | ||||||
|     "submitCode": "envoyer", |     "submitCode": "envoyer", | ||||||
|     "members": "membres", |     "members": "Membres", | ||||||
|     "themes": "Thèmes", |     "themes": "Thèmes", | ||||||
|     "choose-theme": "Choisis un thème", |     "choose-theme": "Choisis un thème", | ||||||
|     "choose-age": "Choisis un âge", |     "choose-age": "Choisis un âge", | ||||||
|  | @ -92,6 +92,6 @@ | ||||||
|     "group": "Groupe", |     "group": "Groupe", | ||||||
|     "description": "Description", |     "description": "Description", | ||||||
|     "no-submission": "aucune soumission", |     "no-submission": "aucune soumission", | ||||||
|     "submission": "soumission", |     "submission": "Soumission", | ||||||
|     "progress": "Progrès" |     "progress": "Progrès" | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -33,7 +33,7 @@ | ||||||
|     "JoinClassExplanation": "Voer de code in die je van de docent hebt gekregen om lid te worden van de klas.", |     "JoinClassExplanation": "Voer de code in die je van de docent hebt gekregen om lid te worden van de klas.", | ||||||
|     "invalidFormat": "Ongeldig formaat.", |     "invalidFormat": "Ongeldig formaat.", | ||||||
|     "submitCode": "verzenden", |     "submitCode": "verzenden", | ||||||
|     "members": "leden", |     "members": "Leden", | ||||||
|     "themes": "Lesthema's", |     "themes": "Lesthema's", | ||||||
|     "choose-theme": "Kies een thema", |     "choose-theme": "Kies een thema", | ||||||
|     "choose-age": "Kies een leeftijd", |     "choose-age": "Kies een leeftijd", | ||||||
|  | @ -92,6 +92,6 @@ | ||||||
|     "group": "Groep", |     "group": "Groep", | ||||||
|     "description": "Beschrijving", |     "description": "Beschrijving", | ||||||
|     "no-submission": "geen indiening", |     "no-submission": "geen indiening", | ||||||
|     "submission": "indiening", |     "submission": "Indiening", | ||||||
|     "progress": "Vooruitgang" |     "progress": "Vooruitgang" | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -4,7 +4,7 @@ | ||||||
|  * Ensures that the title is not empty. |  * Ensures that the title is not empty. | ||||||
|  */ |  */ | ||||||
| export const assignmentTitleRules = [ | export const assignmentTitleRules = [ | ||||||
|     (value: string) => { |     (value: string): string | boolean => { | ||||||
|         if (value?.length >= 1) return true;  // Title must not be empty
 |         if (value?.length >= 1) return true;  // Title must not be empty
 | ||||||
|         return 'Title cannot be empty.'; |         return 'Title cannot be empty.'; | ||||||
|     }, |     }, | ||||||
|  | @ -16,7 +16,7 @@ export const assignmentTitleRules = [ | ||||||
|  * Ensures that a valid learning path is selected. |  * Ensures that a valid learning path is selected. | ||||||
|  */ |  */ | ||||||
| export const learningPathRules = [ | export const learningPathRules = [ | ||||||
|     (value: { hruid: string; title: string }) => { |     (value: { hruid: string; title: string }): string | boolean => { | ||||||
|         if (value && value.hruid) { |         if (value && value.hruid) { | ||||||
|             return true;  // Valid if hruid is present
 |             return true;  // Valid if hruid is present
 | ||||||
|         } |         } | ||||||
|  | @ -30,7 +30,7 @@ export const learningPathRules = [ | ||||||
|  * Ensures that at least one class is selected. |  * Ensures that at least one class is selected. | ||||||
|  */ |  */ | ||||||
| export const classRules = [ | export const classRules = [ | ||||||
|     (value: string) => { |     (value: string): string | boolean => { | ||||||
|         if (value) return true; |         if (value) return true; | ||||||
|         return 'You must select at least one class.'; |         return 'You must select at least one class.'; | ||||||
|     }, |     }, | ||||||
|  | @ -42,7 +42,7 @@ export const classRules = [ | ||||||
|  * Ensures that a valid deadline is selected and is in the future. |  * Ensures that a valid deadline is selected and is in the future. | ||||||
|  */ |  */ | ||||||
| export const deadlineRules = [ | export const deadlineRules = [ | ||||||
|     (value: string) => { |     (value: string): string | boolean => { | ||||||
|         if (!value) return "You must set a deadline."; |         if (!value) return "You must set a deadline."; | ||||||
| 
 | 
 | ||||||
|         const selectedDateTime = new Date(value); |         const selectedDateTime = new Date(value); | ||||||
|  | @ -57,7 +57,7 @@ export const deadlineRules = [ | ||||||
| ]; | ]; | ||||||
| 
 | 
 | ||||||
| export const descriptionRules = [ | export const descriptionRules = [ | ||||||
|     (value: string) => { |     (value: string): string | boolean => { | ||||||
|         if (!value || value.trim() === "") return "Description cannot be empty."; |         if (!value || value.trim() === "") return "Description cannot be empty."; | ||||||
|         return true; |         return true; | ||||||
|     }, |     }, | ||||||
|  |  | ||||||
|  | @ -1,24 +1,24 @@ | ||||||
| // TODO : temp data until frontend controllers are ready
 | // TODO : temp data until frontend controllers are ready
 | ||||||
| type Teacher = { | interface Teacher { | ||||||
|     username: string; |     username: string; | ||||||
|     firstName: string; |     firstName: string; | ||||||
|     lastName: string; |     lastName: string; | ||||||
|     classes: Array<Class>; |     classes: Class[]; | ||||||
| }; | } | ||||||
| 
 | 
 | ||||||
| type Student = { | interface Student { | ||||||
|     username: string; |     username: string; | ||||||
|     firstName: string; |     firstName: string; | ||||||
|     lastName: string; |     lastName: string; | ||||||
|     classes: Array<Class>; |     classes: Class[]; | ||||||
| }; | } | ||||||
| 
 | 
 | ||||||
| type Class = { | interface Class { | ||||||
|     id: string; |     id: string; | ||||||
|     displayName: string; |     displayName: string; | ||||||
|     teachers: Array<Teacher>; |     teachers: Teacher[]; | ||||||
|     students: Array<Student>; |     students: Student[]; | ||||||
| }; | } | ||||||
| 
 | 
 | ||||||
| const student01: Student = {username: "id01", firstName: "Mark", lastName: "Knopfler", classes: []}; | const student01: Student = {username: "id01", firstName: "Mark", lastName: "Knopfler", classes: []}; | ||||||
| const student02: Student = {username: "id02", firstName: "John", lastName: "Hiat", classes: []}; | const student02: Student = {username: "id02", firstName: "John", lastName: "Hiat", classes: []}; | ||||||
|  | @ -55,11 +55,11 @@ teacher01.classes = [class01]; | ||||||
| teacher02.classes = [class02]; | teacher02.classes = [class02]; | ||||||
| teacher03.classes = [class03]; | teacher03.classes = [class03]; | ||||||
| 
 | 
 | ||||||
| type Assignment = { | interface Assignment { | ||||||
|     id: string; |     id: string; | ||||||
|     title: string; |     title: string; | ||||||
|     description: string; |     description: string; | ||||||
| }; | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| export const assignments: Assignment[] = Array.from({length: 4}, (_, i) => ({ | export const assignments: Assignment[] = Array.from({length: 4}, (_, i) => ({ | ||||||
|  | @ -100,4 +100,4 @@ export const assignments: Assignment[] = Array.from({length: 4}, (_, i) => ({ | ||||||
| })); | })); | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| export const classes: Array<Class> = [class01, class02, class03]; | export const classes: Class[] = [class01, class02, class03]; | ||||||
|  |  | ||||||
|  | @ -1,200 +0,0 @@ | ||||||
| <script setup lang="ts"> |  | ||||||
| import { useRoute } from "vue-router"; |  | ||||||
| import {ref, computed} from "vue"; |  | ||||||
| import {useI18n} from "vue-i18n"; |  | ||||||
| import auth from "@/services/auth/auth-service.ts"; |  | ||||||
| import {AssignmentController} from "@/controllers/assignments.ts"; |  | ||||||
| import {asyncComputed} from "@vueuse/core"; |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| const {t, locale} = useI18n(); |  | ||||||
| const language = computed(() => locale.value); |  | ||||||
| const route = useRoute(); |  | ||||||
| const assignmentId = ref(Number(route.params.id)); |  | ||||||
| const classId = window.history.state?.class_id; |  | ||||||
| const controller = new AssignmentController(classId); |  | ||||||
| 
 |  | ||||||
| const role = auth.authState.activeRole; |  | ||||||
| const isTeacher = computed(() => role === 'teacher'); |  | ||||||
| 
 |  | ||||||
| const assignment = asyncComputed(async () => { |  | ||||||
|     return await controller.getByNumber(assignmentId.value) |  | ||||||
| }, null); |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| const submitted = ref(true);//TODO: update by fetching submissions and check group |  | ||||||
| 
 |  | ||||||
| const submitAssignment = async () => { |  | ||||||
|     //TODO |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| /*** |  | ||||||
|  // Display group members |  | ||||||
|  const myGroup = computed(() => { |  | ||||||
|  if (!assignment.value || !assignment.value.groups) return null; |  | ||||||
|  console.log(assignment.value.groups) |  | ||||||
|  return assignment.value.groups.find(group => |  | ||||||
|  group.members.some(m => m.username === myUsername) |  | ||||||
|  ); |  | ||||||
|  }); |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| const deleteAssignment = async () => { |  | ||||||
|     await controller.deleteAssignment(assignmentId.value); |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| </script> |  | ||||||
| 
 |  | ||||||
| <template> |  | ||||||
|     <div class="container"> |  | ||||||
|         <v-card v-if="assignment" class="assignment-card"> |  | ||||||
|             <div class="top-buttons"> |  | ||||||
|                 <v-btn |  | ||||||
|                     icon |  | ||||||
|                     variant="text" |  | ||||||
|                     class="back-btn" |  | ||||||
|                     to="/user/assignment" |  | ||||||
|                 > |  | ||||||
|                     <v-icon>mdi-arrow-left</v-icon> |  | ||||||
|                 </v-btn> |  | ||||||
| 
 |  | ||||||
|                 <v-btn |  | ||||||
|                     v-if="isTeacher" |  | ||||||
|                     icon |  | ||||||
|                     variant="text" |  | ||||||
|                     class="top-right-btn" |  | ||||||
|                     @click="deleteAssignment" |  | ||||||
|                 > |  | ||||||
|                     <v-icon>mdi-delete</v-icon> |  | ||||||
|                 </v-btn> |  | ||||||
|                 <v-chip |  | ||||||
|                     v-if="!isTeacher" |  | ||||||
|                     class="ma-2 top-right-btn" |  | ||||||
|                     label |  | ||||||
|                     color="success" |  | ||||||
|                 > |  | ||||||
|                     {{ t("submitted") }} |  | ||||||
|                 </v-chip> |  | ||||||
|             </div> |  | ||||||
|             <v-card-title class="text-h4">{{ assignment.title }}</v-card-title> |  | ||||||
|             <v-card-subtitle class="subtitle-section"> |  | ||||||
|                 <v-btn |  | ||||||
|                     :to="`/learningPath/${language}/${assignment.learningPath}`" |  | ||||||
|                     variant="tonal" |  | ||||||
|                     color="primary" |  | ||||||
|                 > |  | ||||||
|                     {{ t("learning-path") }} |  | ||||||
|                 </v-btn> |  | ||||||
|             </v-card-subtitle> |  | ||||||
| 
 |  | ||||||
|             <v-card-text class="description"> |  | ||||||
|                 {{ assignment.description }} |  | ||||||
|             </v-card-text> |  | ||||||
| 
 |  | ||||||
|             <v-card-text class="group-section"> |  | ||||||
|                 <h3>{{ t("group") }}</h3> |  | ||||||
| 
 |  | ||||||
|                 <!-- Student view |  | ||||||
|                 <div v-if="!isTeacher"> |  | ||||||
|                     <div v-if="myGroup"> |  | ||||||
|                         <ul> |  | ||||||
|                             <li v-for="student in myGroup.members" :key="student.username"> |  | ||||||
|                                 {{ student.firstName + ' ' + student.lastName}} |  | ||||||
|                             </li> |  | ||||||
|                         </ul> |  | ||||||
|                     </div> |  | ||||||
|                 </div>--> |  | ||||||
| 
 |  | ||||||
|                 <!-- Teacher view |  | ||||||
|                 <div v-if="isTeacher"> |  | ||||||
|                     <v-expansion-panels> |  | ||||||
|                         <v-expansion-panel |  | ||||||
|                             v-for="(group, index) in assignment.groups" |  | ||||||
|                             :key="group.id" |  | ||||||
|                         > |  | ||||||
|                             <v-expansion-panel-title> |  | ||||||
|                                 {{ t("group") }} {{ index + 1 }} |  | ||||||
|                             </v-expansion-panel-title> |  | ||||||
|                             <v-expansion-panel-text> |  | ||||||
|                                 <ul> |  | ||||||
|                                     <li v-for="student in group.members" :key="student.username"> |  | ||||||
|                                         {{ student.firstName + ' ' + student.lastName }} |  | ||||||
|                                     </li> |  | ||||||
|                                 </ul> |  | ||||||
|                             </v-expansion-panel-text> |  | ||||||
|                         </v-expansion-panel> |  | ||||||
|                     </v-expansion-panels> |  | ||||||
|                 </div>--> |  | ||||||
|             </v-card-text > |  | ||||||
|             <v-card-actions class="justify-end"> |  | ||||||
|                 <v-btn |  | ||||||
|                     v-if="!isTeacher" |  | ||||||
|                     size="large" |  | ||||||
|                     color="success" |  | ||||||
|                     variant="flat" |  | ||||||
|                     @click="submitAssignment" |  | ||||||
|                 > |  | ||||||
|                     {{ t("submit") }} |  | ||||||
|                 </v-btn> |  | ||||||
|                 <v-btn |  | ||||||
|                     v-if="isTeacher" |  | ||||||
|                     size="large" |  | ||||||
|                     color="success" |  | ||||||
|                     variant="text" |  | ||||||
|                 > |  | ||||||
|                     {{ t("view-submissions") }} |  | ||||||
|                 </v-btn> |  | ||||||
|             </v-card-actions> |  | ||||||
| 
 |  | ||||||
|         </v-card> |  | ||||||
|     </div> |  | ||||||
| </template> |  | ||||||
| 
 |  | ||||||
| <style scoped> |  | ||||||
| .container { |  | ||||||
|     display: flex; |  | ||||||
|     justify-content: center; |  | ||||||
|     align-items: center; |  | ||||||
|     padding: 2%; |  | ||||||
|     min-height: 100vh; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| .assignment-card { |  | ||||||
|     width: 85%; |  | ||||||
|     padding: 2%; |  | ||||||
|     border-radius: 12px; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| .description { |  | ||||||
|     margin-top: 2%; |  | ||||||
|     line-height: 1.6; |  | ||||||
|     font-size: 1.1rem; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| .top-right-btn { |  | ||||||
|     position: absolute; |  | ||||||
|     right: 2%; |  | ||||||
|     color: red; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| .group-section { |  | ||||||
|     margin-top: 2rem; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| .group-section h3 { |  | ||||||
|     margin-bottom: 0.5rem; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| .group-section ul { |  | ||||||
|     padding-left: 1.2rem; |  | ||||||
|     list-style-type: disc; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| .subtitle-section { |  | ||||||
|     display: flex; |  | ||||||
|     align-items: center; |  | ||||||
|     justify-content: space-between; |  | ||||||
| } |  | ||||||
| </style> |  | ||||||
| 
 |  | ||||||
|  | @ -18,12 +18,12 @@ import {useRoute} from "vue-router"; | ||||||
| /*** | /*** | ||||||
|  TODO: when clicking the assign button from lp page pass the lp-hruid in a query like this: |  TODO: when clicking the assign button from lp page pass the lp-hruid in a query like this: | ||||||
|  router.push({ |  router.push({ | ||||||
|      path: "/assignment/create, |  path: "/assignment/create, | ||||||
|          query: { |  query: { | ||||||
|          ...route.query, |  ...route.query, | ||||||
|          lp: hruid, |  lp: hruid, | ||||||
|         }, |  }, | ||||||
|      }); |  }); | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| const route = useRoute(); | const route = useRoute(); | ||||||
|  | @ -176,7 +176,12 @@ async function submitFormHandler(): Promise<void> { | ||||||
|                             :rules="descriptionRules" |                             :rules="descriptionRules" | ||||||
|                         ></v-textarea> |                         ></v-textarea> | ||||||
|                     </v-card-text> |                     </v-card-text> | ||||||
|                     <v-btn class="mt-2" color="secondary" type="submit" block>Submit</v-btn> |                     <v-card-text> | ||||||
|  |                         <v-btn class="mt-2" color="secondary" type="submit" block>{{ t("submit") }}</v-btn> | ||||||
|  |                         <v-btn to="/user/assignment" color="grey" block>{{ t("cancel") }}</v-btn> | ||||||
|  |                     </v-card-text> | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|                 </v-container> |                 </v-container> | ||||||
|             </v-form> |             </v-form> | ||||||
|         </v-card> |         </v-card> | ||||||
|  |  | ||||||
|  | @ -66,13 +66,14 @@ function openGroupDetails(group): void { | ||||||
|     dialog.value = true; |     dialog.value = true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| const headers = ref([ | const headers = computed(() => [ | ||||||
|     {title: t('group'), align: 'start', key: 'name'}, |     { title: t('group'), align: 'start', key: 'name' }, | ||||||
|     {title: t('progress'), align: 'center', key: 'progress'}, |     { title: t('progress'), align: 'center', key: 'progress' }, | ||||||
|     {title: t('submission'), align: 'center', key: 'submission'} |     { title: t('submission'), align: 'center', key: 'submission' } | ||||||
| ]); | ]); | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| const {mutate, isSuccess} = useDeleteAssignmentMutation(); | const {mutate, isSuccess} = useDeleteAssignmentMutation(); | ||||||
| 
 | 
 | ||||||
| async function deleteAssignment(num: number, clsId: string): Promise<void> { | async function deleteAssignment(num: number, clsId: string): Promise<void> { | ||||||
|  | @ -177,7 +178,7 @@ async function deleteAssignment(num: number, clsId: string): Promise<void> { | ||||||
| 
 | 
 | ||||||
|                 <v-dialog v-model="dialog" max-width="50%"> |                 <v-dialog v-model="dialog" max-width="50%"> | ||||||
|                     <v-card> |                     <v-card> | ||||||
|                         <v-card-title class="headline">Group Members</v-card-title> |                         <v-card-title class="headline">{{t("members")}}</v-card-title> | ||||||
|                         <v-card-text> |                         <v-card-text> | ||||||
|                             <v-list> |                             <v-list> | ||||||
|                                 <v-list-item |                                 <v-list-item | ||||||
|  |  | ||||||
		Reference in a new issue
	
	 Joyelle Ndagijimana
						Joyelle Ndagijimana