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 @@
+
+
+
+
{{ t('create-group') }}
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);
};
-
+
{{ t("new-assignment") }}
-
+
+
+
+
+
@@ -103,39 +118,33 @@
v-model="selectedClasses"
:items="allClasses"
:label="t('choose-classes')"
+ :rules="classesRules"
variant="solo"
clearable
multiple
hide-details
+ density="compact"
chips
append-inner-icon="mdi-magnify"
item-title="title"
item-value="value"
+ required
>
-
- {{ t('create-groups') }}
+ {{ t('create-groups') }}
-
+
-
-
- {{ t('created-groups') }}: {{ groups.length }}
-
-
-
-
-
- -
- {{ group.join(', ') }}
-
-
-
-
+
+
+ Created Groups: {{ groups.length }}
+
Submit