diff --git a/frontend/src/components/GroupSelector.vue b/frontend/src/components/GroupSelector.vue index 4f401dbe..2ae350d3 100644 --- a/frontend/src/components/GroupSelector.vue +++ b/frontend/src/components/GroupSelector.vue @@ -1,37 +1,81 @@ + diff --git a/frontend/src/i18n/locale/de.json b/frontend/src/i18n/locale/de.json index c8ed94cf..3740e5e5 100644 --- a/frontend/src/i18n/locale/de.json +++ b/frontend/src/i18n/locale/de.json @@ -46,5 +46,10 @@ "groups": "Gruppen", "learning-path": "Lernpfad", "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" } diff --git a/frontend/src/i18n/locale/en.json b/frontend/src/i18n/locale/en.json index 92ccb90b..63ccbf78 100644 --- a/frontend/src/i18n/locale/en.json +++ b/frontend/src/i18n/locale/en.json @@ -46,5 +46,10 @@ "groups": "Groups", "learning-path": "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" } diff --git a/frontend/src/i18n/locale/fr.json b/frontend/src/i18n/locale/fr.json index 1fb59349..9f9915c5 100644 --- a/frontend/src/i18n/locale/fr.json +++ b/frontend/src/i18n/locale/fr.json @@ -45,6 +45,11 @@ "previous": "précédent", "groups": "Groupes", "learning-path": "Parcours d'apprentissage", - "choose-lp": "Choisis un parcours d'apprentissage", - "choose-classes": "Choisis des classes" + "choose-lp": "Choisissez un parcours d'apprentissage", + "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" } diff --git a/frontend/src/i18n/locale/nl.json b/frontend/src/i18n/locale/nl.json index 1636300e..c707a354 100644 --- a/frontend/src/i18n/locale/nl.json +++ b/frontend/src/i18n/locale/nl.json @@ -46,5 +46,10 @@ "groups": "Groepen", "learning-path": "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" } diff --git a/frontend/src/utils/assignmentForm.ts b/frontend/src/utils/assignmentForm.ts new file mode 100644 index 00000000..05d7ce33 --- /dev/null +++ b/frontend/src/utils/assignmentForm.ts @@ -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.'; + }, +]; diff --git a/frontend/src/utils/tempData.ts b/frontend/src/utils/tempData.ts new file mode 100644 index 00000000..2c5f1430 --- /dev/null +++ b/frontend/src/utils/tempData.ts @@ -0,0 +1,58 @@ +// TODO : temp data until frontend controllers are ready +type Teacher = { + username: string; + firstName: string; + lastName: string; + classes: Array; +}; + +type Student = { + username: string; + firstName: string; + lastName: string; + classes: Array; +}; + +type Class = { + id: string; + displayName: string; + teachers: Array; + students: Array; +}; + +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 = [class01, class02, class03]; diff --git a/frontend/src/views/assignments/CreateAssignment.vue b/frontend/src/views/assignments/CreateAssignment.vue index 5c09e835..c764689a 100644 --- a/frontend/src/views/assignments/CreateAssignment.vue +++ b/frontend/src/views/assignments/CreateAssignment.vue @@ -2,49 +2,66 @@ import {useI18n} from "vue-i18n"; import {computed, onMounted, ref, watch} from "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 language = ref(locale.value); - const searchQuery = ref(""); + const searchQuery = ref(''); + const assignmentTitle = ref(''); const allLearningPaths = ref([]); const filteredLearningPaths = ref([]); 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 allStudents = ref([]); // Fetched students from each selected class - const groups = ref([]); // Each group is a list of student {names, id's} + const groups = ref([]); + + 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() { - //TODO: replace by function from controller try { + //TODO: replace by function from controller const response = await fetch(`http://localhost:3000/api/learningPath?language=${language.value}`); - - // Error 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(); allLearningPaths.value = data.map((lp: { hruid: string; title: string }) => ({ hruid: lp.hruid, title: lp.title })); - - // Get all the learning paths in the filtered list filteredLearningPaths.value = [...allLearningPaths.value]; } catch (error) { console.error(error); } } - // Re-fetch the learning paths when the language changes watch( () => locale.value, (newLocale) => { - // Check if the language is valid if (!["nl", "en"].includes(newLocale)) { language.value = "en"; } @@ -59,34 +76,31 @@ ); }); - // Fetch all learning paths on mount onMounted(fetchAllLearningPaths); - // All students that aren't already in a group - const availableStudents = computed(() => { - 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); - } + const submitFormHandler = () => { + submitForm(assignmentTitle.value, selectedLearningPath.value, selectedClasses.value, groups.value); }; - +