feat: create assignment form is klaar
This commit is contained in:
		
							parent
							
								
									05fa69f0c7
								
							
						
					
					
						commit
						db7c5409fc
					
				
					 8 changed files with 273 additions and 69 deletions
				
			
		|  | @ -1,37 +1,81 @@ | ||||||
| <script setup lang="ts"> | <script setup lang="ts"> | ||||||
|     import { ref, defineProps, defineEmits } from 'vue'; | import { ref, defineProps, defineEmits, computed } from 'vue'; | ||||||
|     import { useI18n } from 'vue-i18n'; | import { useI18n } from 'vue-i18n'; | ||||||
| 
 | 
 | ||||||
|     const props = defineProps({ | const props = defineProps({ | ||||||
|         students: Array, |     students: Array, // All students | ||||||
|     }); |     availableClasses: Array, // Selected classes | ||||||
|     const emit = defineEmits(['groupCreated']); |     groups: Array, // All groups | ||||||
|     const { t } = useI18n(); | }); | ||||||
|     const selectedStudents = ref([]); | const emit = defineEmits(['groupCreated']); | ||||||
|  | const { t } = useI18n(); | ||||||
| 
 | 
 | ||||||
|     const createGroup = () => { | const selectedClass = ref(null); | ||||||
|         if (selectedStudents.value.length) { | const selectedStudents = ref([]); | ||||||
|             emit('groupCreated', selectedStudents.value); | 
 | ||||||
|             selectedStudents.value = []; // Reset selection after creating group | // Filter students based on the selected class and exclude students already in a group | ||||||
|  | const filteredStudents = computed(() => { | ||||||
|  |     if (selectedClass.value) { | ||||||
|  |         // Find the class based on selectedClass id | ||||||
|  |         const selected = props.availableClasses.find(cl => cl.id === selectedClass.value.id); | ||||||
|  |         if (selected) { | ||||||
|  |             // Get all students from the selected class | ||||||
|  |             const studentsInClass = selected.students.map(st => ({ | ||||||
|  |                 title: `${st.firstName} ${st.lastName}`, | ||||||
|  |                 value: st.username, | ||||||
|  |             })); | ||||||
|  | 
 | ||||||
|  |             // Get the list of students already in any group | ||||||
|  |             const studentsInGroups = props.groups.flat(); | ||||||
|  | 
 | ||||||
|  |             // Filter out students that are already in a group | ||||||
|  |             return studentsInClass.filter(student => !studentsInGroups.includes(student.value)); | ||||||
|         } |         } | ||||||
|     }; |     } | ||||||
|  |     return []; | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | const createGroup = () => { | ||||||
|  |     if (selectedStudents.value.length) { | ||||||
|  |         // Extract only usernames (student.value) | ||||||
|  |         const usernames = selectedStudents.value.map(student => student.value); | ||||||
|  |         emit('groupCreated', usernames); | ||||||
|  |         selectedStudents.value = []; // Reset selection after creating group | ||||||
|  |     } | ||||||
|  | }; | ||||||
| </script> | </script> | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| <template> | <template> | ||||||
|     <v-card-text> |     <v-card-text> | ||||||
|  |         <v-combobox | ||||||
|  |             v-model="selectedClass" | ||||||
|  |             :items="props.availableClasses" | ||||||
|  |             item-title="displayName" | ||||||
|  |             item-value="id" | ||||||
|  |             :label="t('pick-class')" | ||||||
|  |             variant="solo" | ||||||
|  |             clearable | ||||||
|  |             hide-details | ||||||
|  |             density="compact" | ||||||
|  |             class="mb-4" | ||||||
|  |         ></v-combobox> | ||||||
|  | 
 | ||||||
|         <v-combobox |         <v-combobox | ||||||
|             v-model="selectedStudents" |             v-model="selectedStudents" | ||||||
|             :items="props.students" |             :items="filteredStudents" | ||||||
|             :label="t('choose-groups')" |             item-title="title" | ||||||
|  |             item-value="value" | ||||||
|  |             :label="t('choose-students')" | ||||||
|             variant="solo" |             variant="solo" | ||||||
|             clearable |             clearable | ||||||
|             multiple |             multiple | ||||||
|             hide-details |             hide-details | ||||||
|  |             density="compact" | ||||||
|             chips |             chips | ||||||
|             append-inner-icon="mdi-magnify" |             append-inner-icon="mdi-magnify" | ||||||
|             item-title="title" |  | ||||||
|             item-value="value" |  | ||||||
|         ></v-combobox> |         ></v-combobox> | ||||||
|  | 
 | ||||||
|         <v-btn @click="createGroup" color="primary" class="mt-2" size="small">{{ t('create-group') }}</v-btn> |         <v-btn @click="createGroup" color="primary" class="mt-2" size="small">{{ t('create-group') }}</v-btn> | ||||||
|     </v-card-text> |     </v-card-text> | ||||||
| </template> | </template> | ||||||
|  |  | ||||||
|  | @ -46,5 +46,10 @@ | ||||||
|     "groups": "Gruppen", |     "groups": "Gruppen", | ||||||
|     "learning-path": "Lernpfad", |     "learning-path": "Lernpfad", | ||||||
|     "choose-lp": "Einen lernpfad auswählen", |     "choose-lp": "Einen lernpfad auswählen", | ||||||
|     "choose-classes": "Klassen wählen" |     "choose-classes": "Klassen wählen", | ||||||
|  |     "create-groups": "Gruppen erstellen", | ||||||
|  |     "title": "Titel", | ||||||
|  |     "pick-class": "Wählen Sie eine klasse", | ||||||
|  |     "choose-students": "Studenten auswählen", | ||||||
|  |     "create-group": "Gruppe erstellen" | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -46,5 +46,10 @@ | ||||||
|     "groups": "Groups", |     "groups": "Groups", | ||||||
|     "learning-path": "Learning path", |     "learning-path": "Learning path", | ||||||
|     "choose-lp": "Select a learning path", |     "choose-lp": "Select a learning path", | ||||||
|     "choose-classes": "Select classes" |     "choose-classes": "Select classes", | ||||||
|  |     "create-groups": "Create groups", | ||||||
|  |     "title": "Title", | ||||||
|  |     "pick-class": "Pick a class", | ||||||
|  |     "choose-students": "Select students", | ||||||
|  |     "create-group": "Create group" | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -45,6 +45,11 @@ | ||||||
|     "previous": "précédent", |     "previous": "précédent", | ||||||
|     "groups": "Groupes", |     "groups": "Groupes", | ||||||
|     "learning-path": "Parcours d'apprentissage", |     "learning-path": "Parcours d'apprentissage", | ||||||
|     "choose-lp": "Choisis un parcours d'apprentissage", |     "choose-lp": "Choisissez un parcours d'apprentissage", | ||||||
|     "choose-classes": "Choisis des classes" |     "choose-classes": "Choisissez des classes", | ||||||
|  |     "create-groups": "Crée des groupes", | ||||||
|  |     "title": "Titre", | ||||||
|  |     "pick-class": "Choisissez une classe", | ||||||
|  |     "choose-students": "Sélectionnez des élèves", | ||||||
|  |     "create-group": "Créer un groupe" | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -46,5 +46,10 @@ | ||||||
|     "groups": "Groepen", |     "groups": "Groepen", | ||||||
|     "learning-path": "Leerpad", |     "learning-path": "Leerpad", | ||||||
|     "choose-lp": "Kies een leerpad", |     "choose-lp": "Kies een leerpad", | ||||||
|     "choose-classes": "Kies klassen" |     "choose-classes": "Kies klassen", | ||||||
|  |     "create-groups": "Groepen maken", | ||||||
|  |     "title": "Titel", | ||||||
|  |     "pick-class": "Kies een klas", | ||||||
|  |     "choose-students": "Studenten selecteren", | ||||||
|  |     "create-group": "Groep aanmaken" | ||||||
| } | } | ||||||
|  |  | ||||||
							
								
								
									
										73
									
								
								frontend/src/utils/assignmentForm.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								frontend/src/utils/assignmentForm.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,73 @@ | ||||||
|  | /** | ||||||
|  |  * Submits the form data to the backend. | ||||||
|  |  * | ||||||
|  |  * @param assignmentTitle - The title of the assignment. | ||||||
|  |  * @param selectedLearningPath - The selected learning path, containing hruid and title. | ||||||
|  |  * @param selectedClasses - The selected classes, an array of class objects. | ||||||
|  |  * @param groups - An array of groups, each containing student IDs. | ||||||
|  |  * | ||||||
|  |  * Sends a POST request to the backend with the form data. | ||||||
|  |  */ | ||||||
|  | export const submitForm = async ( | ||||||
|  |     assignmentTitle: string, | ||||||
|  |     selectedLearningPath: any, | ||||||
|  |     selectedClasses: any[], | ||||||
|  |     groups: string[][] | ||||||
|  | ) => { | ||||||
|  |     const formData = { | ||||||
|  |         title: assignmentTitle, | ||||||
|  |         hruid: selectedLearningPath?.hruid, | ||||||
|  |         classes: selectedClasses.map(cl => cl.value), | ||||||
|  |         groups: groups | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     try { | ||||||
|  |         const response = await fetch(/*"http://localhost:3000/api/assignment"*/"", { | ||||||
|  |             method: "POST", | ||||||
|  |             headers: { "Content-Type": "application/json" }, | ||||||
|  |             body: JSON.stringify(formData) | ||||||
|  |         }); | ||||||
|  |         const data = await response.json(); | ||||||
|  |         console.log("Form submitted successfully:", data); | ||||||
|  |     } catch (error) { | ||||||
|  |         console.error("Error submitting form:", error); | ||||||
|  |     } | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Validation rule for the assignment title. | ||||||
|  |  * | ||||||
|  |  * Ensures that the title is not empty. | ||||||
|  |  */ | ||||||
|  | export const assignmentTitleRules = [ | ||||||
|  |     (value: string) => { | ||||||
|  |         if (value?.length >= 1) return true;  // Title must not be empty
 | ||||||
|  |         return 'Title cannot be empty.'; | ||||||
|  |     }, | ||||||
|  | ]; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Validation rule for the learning path selection. | ||||||
|  |  * | ||||||
|  |  * Ensures that a valid learning path is selected. | ||||||
|  |  */ | ||||||
|  | export const learningPathRules = [ | ||||||
|  |     (value: { hruid: string; title: string }) => { | ||||||
|  |         if (value && value.hruid) { | ||||||
|  |             return true;  // Valid if hruid is present
 | ||||||
|  |         } | ||||||
|  |         return 'You must select a learning path.'; | ||||||
|  |     }, | ||||||
|  | ]; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Validation rule for the classes selection. | ||||||
|  |  * | ||||||
|  |  * Ensures that at least one class is selected. | ||||||
|  |  */ | ||||||
|  | export const classesRules = [ | ||||||
|  |     (value: any[]) => { | ||||||
|  |         if (value?.length >= 1) return true; | ||||||
|  |         return 'You must select at least one class.'; | ||||||
|  |     }, | ||||||
|  | ]; | ||||||
							
								
								
									
										58
									
								
								frontend/src/utils/tempData.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								frontend/src/utils/tempData.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,58 @@ | ||||||
|  | // TODO : temp data until frontend controllers are ready
 | ||||||
|  | type Teacher = { | ||||||
|  |     username: string; | ||||||
|  |     firstName: string; | ||||||
|  |     lastName: string; | ||||||
|  |     classes: Array<Class>; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | type Student = { | ||||||
|  |     username: string; | ||||||
|  |     firstName: string; | ||||||
|  |     lastName: string; | ||||||
|  |     classes: Array<Class>; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | type Class = { | ||||||
|  |     id: string; | ||||||
|  |     displayName: string; | ||||||
|  |     teachers: Array<Teacher>; | ||||||
|  |     students: Array<Student>; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const student01: Student = { username: "id01", firstName: "Mark", lastName: "Knopfler", classes: [] }; | ||||||
|  | const student02: Student = { username: "id02", firstName: "John", lastName: "Hiat", classes: [] }; | ||||||
|  | const student03: Student = { username: "id03", firstName: "Aaron", lastName: "Lewis", classes: [] }; | ||||||
|  | 
 | ||||||
|  | const teacher01: Student = { username: "id11", firstName: "Mark", lastName: "Knopfler", classes: [] }; | ||||||
|  | const teacher02: Student = { username: "id12", firstName: "John", lastName: "Hiat", classes: [] }; | ||||||
|  | const teacher03: Student = { username: "id13", firstName: "Aaron", lastName: "Lewis", classes: [] }; | ||||||
|  | 
 | ||||||
|  | const class01: Class = { | ||||||
|  |     id: "class01", | ||||||
|  |     displayName: "class 01", | ||||||
|  |     teachers: [teacher01], | ||||||
|  |     students: [student01, student02], | ||||||
|  | }; | ||||||
|  | const class02: Class = { | ||||||
|  |     id: "class02", | ||||||
|  |     displayName: "class 02", | ||||||
|  |     teachers: [teacher02], | ||||||
|  |     students: [student01, student03], | ||||||
|  | }; | ||||||
|  | const class03: Class = { | ||||||
|  |     id: "class03", | ||||||
|  |     displayName: "class 03", | ||||||
|  |     teachers: [teacher03], | ||||||
|  |     students: [student02, student03], | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | student01.classes = [class01, class02]; | ||||||
|  | student02.classes = [class01, class03]; | ||||||
|  | student03.classes = [class02, class03]; | ||||||
|  | 
 | ||||||
|  | teacher01.classes = [class01]; | ||||||
|  | teacher02.classes = [class02]; | ||||||
|  | teacher03.classes = [class03]; | ||||||
|  | 
 | ||||||
|  | export const classes: Array<Class> = [class01, class02, class03]; | ||||||
|  | @ -2,49 +2,66 @@ | ||||||
|     import {useI18n} from "vue-i18n"; |     import {useI18n} from "vue-i18n"; | ||||||
|     import {computed, onMounted, ref, watch} from "vue"; |     import {computed, onMounted, ref, watch} from "vue"; | ||||||
|     import GroupSelector from "@/components/GroupSelector.vue"; |     import GroupSelector from "@/components/GroupSelector.vue"; | ||||||
|  |     import {classes} from "@/utils/tempData.ts"; | ||||||
|  |     import {assignmentTitleRules, classesRules, learningPathRules, submitForm} from "@/utils/assignmentForm.ts";  // Assuming your tempData.ts has the required classes | ||||||
| 
 | 
 | ||||||
|     const {t, locale} = useI18n(); |     const {t, locale} = useI18n(); | ||||||
| 
 | 
 | ||||||
|     const language = ref(locale.value); |     const language = ref(locale.value); | ||||||
| 
 | 
 | ||||||
|     const searchQuery = ref(""); |     const searchQuery = ref(''); | ||||||
| 
 | 
 | ||||||
|  |     const assignmentTitle = ref(''); | ||||||
|     const allLearningPaths = ref([]); |     const allLearningPaths = ref([]); | ||||||
|     const filteredLearningPaths = ref([]); |     const filteredLearningPaths = ref([]); | ||||||
|     const selectedLearningPath = ref(null); |     const selectedLearningPath = ref(null); | ||||||
|     const allClasses = ref(["f", "r"]); |     const allClasses = ref([...classes.map(cl => ({title: cl.displayName, value: cl.id}))]); | ||||||
|     const selectedClasses = ref([]); |     const selectedClasses = ref([]); | ||||||
|     const allStudents = ref([]); // Fetched students from each selected class |     const groups = ref<string[][]>([]); | ||||||
|     const groups = ref<string[][]>([]);  // Each group is a list of student {names, id's} | 
 | ||||||
|  |     const availableClasses = computed(() => { | ||||||
|  |         //TODO: replace by real data | ||||||
|  |         return classes.filter(cl => selectedClasses.value.some(c => c.value === cl.id)); | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     const allStudents = computed(() => { | ||||||
|  |         //TODO: replace by real data | ||||||
|  |         return classes | ||||||
|  |             .filter(cl => selectedClasses.value.some(c => c.value === cl.id)) | ||||||
|  |             .flatMap(cl => cl.students.map(st => ({ | ||||||
|  |                 title: `${st.firstName} ${st.lastName}`, | ||||||
|  |                 value: st.username, | ||||||
|  |                 classes: cl | ||||||
|  |             }))); | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     // New group is added to the list | ||||||
|  |     const addGroupToList = (students: string[]) => { | ||||||
|  |         if (students.length) { | ||||||
|  |             groups.value = [...groups.value, students]; | ||||||
|  |         } | ||||||
|  |     }; | ||||||
| 
 | 
 | ||||||
|     // Fetch all learning paths initially |  | ||||||
|     async function fetchAllLearningPaths() { |     async function fetchAllLearningPaths() { | ||||||
|         //TODO: replace by function from controller |  | ||||||
|         try { |         try { | ||||||
|  |             //TODO: replace by function from controller | ||||||
|             const response = await fetch(`http://localhost:3000/api/learningPath?language=${language.value}`); |             const response = await fetch(`http://localhost:3000/api/learningPath?language=${language.value}`); | ||||||
| 
 |  | ||||||
|             // Error |  | ||||||
|             if (!response.ok) throw new Error("Failed to fetch learning paths"); |             if (!response.ok) throw new Error("Failed to fetch learning paths"); | ||||||
| 
 |  | ||||||
|             // Collect all the learning paths and store them in a list by hruid and title |  | ||||||
|             const data = await response.json(); |             const data = await response.json(); | ||||||
|             allLearningPaths.value = data.map((lp: { hruid: string; title: string }) => ({ |             allLearningPaths.value = data.map((lp: { hruid: string; title: string }) => ({ | ||||||
|                 hruid: lp.hruid, |                 hruid: lp.hruid, | ||||||
|                 title: lp.title |                 title: lp.title | ||||||
|             })); |             })); | ||||||
| 
 |  | ||||||
|             // Get all the learning paths in the filtered list |  | ||||||
|             filteredLearningPaths.value = [...allLearningPaths.value]; |             filteredLearningPaths.value = [...allLearningPaths.value]; | ||||||
|         } catch (error) { |         } catch (error) { | ||||||
|             console.error(error); |             console.error(error); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // Re-fetch the learning paths when the language changes |  | ||||||
|     watch( |     watch( | ||||||
|         () => locale.value, |         () => locale.value, | ||||||
|         (newLocale) => { |         (newLocale) => { | ||||||
|             // Check if the language is valid |  | ||||||
|             if (!["nl", "en"].includes(newLocale)) { |             if (!["nl", "en"].includes(newLocale)) { | ||||||
|                 language.value = "en"; |                 language.value = "en"; | ||||||
|             } |             } | ||||||
|  | @ -59,34 +76,31 @@ | ||||||
|         ); |         ); | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     // Fetch all learning paths on mount |  | ||||||
|     onMounted(fetchAllLearningPaths); |     onMounted(fetchAllLearningPaths); | ||||||
| 
 | 
 | ||||||
|     // All students that aren't already in a group |     const submitFormHandler = () => { | ||||||
|     const availableStudents = computed(() => { |         submitForm(assignmentTitle.value, selectedLearningPath.value, selectedClasses.value, groups.value); | ||||||
|         const groupedStudents = new Set(groups.value.flat()); |  | ||||||
|         return allStudents.value.filter(student => !groupedStudents.has(student)); |  | ||||||
|     }); |  | ||||||
| 
 |  | ||||||
|     const addGroupToList = (students: string[]) => { |  | ||||||
|         if (students.length) { |  | ||||||
|             groups.value.push(students); |  | ||||||
|         } |  | ||||||
|     }; |     }; | ||||||
| 
 |  | ||||||
| </script> | </script> | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| <template> | <template> | ||||||
|     <div class="main-container"> |     <div class="main-container"> | ||||||
|         <h1 class="title">{{ t("new-assignment") }}</h1> |         <h1 class="title">{{ t("new-assignment") }}</h1> | ||||||
|         <v-card class="form-card"> |         <v-card class="form-card"> | ||||||
|             <v-form class="form-container"> |             <v-form class="form-container" validate-on="submit lazy" @submit.prevent="submitFormHandler"> | ||||||
|                 <v-container class="step-container"> |                 <v-container class="step-container"> | ||||||
|  |                     <v-card-text> | ||||||
|  |                         <v-text-field :v-model="assignmentTitle" :label="t('title')" :rules="assignmentTitleRules" | ||||||
|  |                                       density="compact" variant="solo" clearable required></v-text-field> | ||||||
|  |                     </v-card-text> | ||||||
|  | 
 | ||||||
|                     <v-card-text> |                     <v-card-text> | ||||||
|                         <v-combobox |                         <v-combobox | ||||||
|                             v-model="selectedLearningPath" |                             v-model="selectedLearningPath" | ||||||
|                             :items="searchResults" |                             :items="searchResults" | ||||||
|                             :label="t('choose-lp')" |                             :label="t('choose-lp')" | ||||||
|  |                             :rules="learningPathRules" | ||||||
|                             variant="solo" |                             variant="solo" | ||||||
|                             clearable |                             clearable | ||||||
|                             hide-details |                             hide-details | ||||||
|  | @ -94,6 +108,7 @@ | ||||||
|                             append-inner-icon="mdi-magnify" |                             append-inner-icon="mdi-magnify" | ||||||
|                             item-title="title" |                             item-title="title" | ||||||
|                             item-value="value" |                             item-value="value" | ||||||
|  |                             required | ||||||
|                             :filter="(item, query: string) => item.title.toLowerCase().includes(query.toLowerCase())" |                             :filter="(item, query: string) => item.title.toLowerCase().includes(query.toLowerCase())" | ||||||
|                         ></v-combobox> |                         ></v-combobox> | ||||||
|                     </v-card-text> |                     </v-card-text> | ||||||
|  | @ -103,39 +118,33 @@ | ||||||
|                             v-model="selectedClasses" |                             v-model="selectedClasses" | ||||||
|                             :items="allClasses" |                             :items="allClasses" | ||||||
|                             :label="t('choose-classes')" |                             :label="t('choose-classes')" | ||||||
|  |                             :rules="classesRules" | ||||||
|                             variant="solo" |                             variant="solo" | ||||||
|                             clearable |                             clearable | ||||||
|                             multiple |                             multiple | ||||||
|                             hide-details |                             hide-details | ||||||
|  |                             density="compact" | ||||||
|                             chips |                             chips | ||||||
|                             append-inner-icon="mdi-magnify" |                             append-inner-icon="mdi-magnify" | ||||||
|                             item-title="title" |                             item-title="title" | ||||||
|                             item-value="value" |                             item-value="value" | ||||||
|  |                             required | ||||||
|                         ></v-combobox> |                         ></v-combobox> | ||||||
|                     </v-card-text> |                     </v-card-text> | ||||||
| 
 | 
 | ||||||
|                     <v-container> |                     <h3>{{ t('create-groups') }}</h3> | ||||||
|                         <h3>{{ t('create-groups') }}</h3> |  | ||||||
| 
 | 
 | ||||||
|                         <GroupSelector |                     <GroupSelector | ||||||
|                             :students="availableStudents" |                         :students="allStudents" | ||||||
|                             @groupCreated="addGroupToList" |                         :availableClasses="availableClasses" | ||||||
|                         /> |                         :groups="groups" | ||||||
|  |                         @groupCreated="addGroupToList" | ||||||
|  |                     /> | ||||||
| 
 | 
 | ||||||
|                         <!-- Counter for created groups --> |                     <!-- Counter for created groups --> | ||||||
|                         <v-card-text v-if="groups.length"> |                     <v-card-text v-if="groups.length"> | ||||||
|                             <strong>{{ t('created-groups') }}: {{ groups.length }}</strong> |                         <strong>Created Groups: {{ groups.length }}</strong> | ||||||
|                         </v-card-text> |                     </v-card-text> | ||||||
| 
 |  | ||||||
|                         <!-- Display created groups --> |  | ||||||
|                         <v-card-text v-if="groups.length"> |  | ||||||
|                             <ul> |  | ||||||
|                                 <li v-for="(group, index) in groups" :key="index"> |  | ||||||
|                                     {{ group.join(', ') }} |  | ||||||
|                                 </li> |  | ||||||
|                             </ul> |  | ||||||
|                         </v-card-text> |  | ||||||
|                     </v-container> |  | ||||||
| 
 | 
 | ||||||
|                 </v-container> |                 </v-container> | ||||||
|                 <v-btn class="mt-2" type="submit" block>Submit</v-btn> |                 <v-btn class="mt-2" type="submit" block>Submit</v-btn> | ||||||
|  |  | ||||||
		Reference in a new issue
	
	 Joyelle Ndagijimana
						Joyelle Ndagijimana