feat(frontend): assignment pagina toont titel, link naar lp en beschrijving
This commit is contained in:
		
							parent
							
								
									4f09d004ab
								
							
						
					
					
						commit
						f847f6d606
					
				
					 6 changed files with 299 additions and 134 deletions
				
			
		|  | @ -20,13 +20,13 @@ type Class = { | ||||||
|     students: Array<Student>; |     students: Array<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: []}; | ||||||
| const student03: Student = { username: "id03", firstName: "Aaron", lastName: "Lewis", classes: [] }; | const student03: Student = {username: "id03", firstName: "Aaron", lastName: "Lewis", classes: []}; | ||||||
| 
 | 
 | ||||||
| const teacher01: Student = { username: "id11", firstName: "Mark", lastName: "Knopfler", classes: [] }; | const teacher01: Student = {username: "id11", firstName: "Mark", lastName: "Knopfler", classes: []}; | ||||||
| const teacher02: Student = { username: "id12", firstName: "John", lastName: "Hiat", classes: [] }; | const teacher02: Student = {username: "id12", firstName: "John", lastName: "Hiat", classes: []}; | ||||||
| const teacher03: Student = { username: "id13", firstName: "Aaron", lastName: "Lewis", classes: [] }; | const teacher03: Student = {username: "id13", firstName: "Aaron", lastName: "Lewis", classes: []}; | ||||||
| 
 | 
 | ||||||
| const class01: Class = { | const class01: Class = { | ||||||
|     id: "class01", |     id: "class01", | ||||||
|  | @ -61,13 +61,24 @@ type Assignment = { | ||||||
|     description: string; |     description: string; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| export const assignments: Assignment[] = Array.from({ length: 4 }, (_, i) => ({ | export const assignments: Assignment[] = Array.from({length: 4}, (_, i) => ({ | ||||||
|     id: `assignment${i}`, |     id: `assignment${i}`, | ||||||
|     title: `Assignment ${i}`, |     title: `Assignment ${i}`, | ||||||
|  |     learningPathHruid: 'lphruid', | ||||||
|     description: |     description: | ||||||
|         "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. " + |         "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. " + | ||||||
|         "Aenean commodo ligula eget dolor. Aenean massa. " + |         "Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, " + | ||||||
|         "Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus." |         "nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. " + | ||||||
|  |         "Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. " + | ||||||
|  |         "In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium. " + | ||||||
|  |         "Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus. " + | ||||||
|  |         "Aenean leo ligula, porttitor eu, consequat vitae, eleifend ac, enim. Aliquam lorem ante, dapibus in, viverra quis, feugiat a, tellus. " + | ||||||
|  |         "Phasellus viverra nulla ut metus varius laoreet. Quisque rutrum. Aenean imperdiet. Etiam ultricies nisi vel augue. " + | ||||||
|  |         "Curabitur ullamcorper ultricies nisi. Nam eget dui. Etiam rhoncus. Maecenas tempus, tellus eget condimentum rhoncus, sem quam semper libero, " + | ||||||
|  |         "sit amet adipiscing sem neque sed ipsum. Nam quam nunc, blandit vel, luctus pulvinar, hendrerit id, lorem. " + | ||||||
|  |         "Maecenas nec odio et ante tincidunt tempus. Donec vitae sapien ut libero venenatis faucibus. Nullam quis ante. " + | ||||||
|  |         "Etiam sit amet orci eget eros faucibus tincidunt. Duis leo. Sed fringilla mauris sit amet nibh. Donec sodales sagittis magna. " + | ||||||
|  |         "Sed consequat, leo eget bibendum sodales, augue velit cursus nunc,", | ||||||
| })); | })); | ||||||
| 
 | 
 | ||||||
| export const classes: Array<Class> = [class01, class02, class03]; | export const classes: Array<Class> = [class01, class02, class03]; | ||||||
|  |  | ||||||
|  | @ -1,87 +1,113 @@ | ||||||
| <script setup lang="ts"> | <script setup lang="ts"> | ||||||
| import {useI18n} from "vue-i18n"; |     import {useI18n} from "vue-i18n"; | ||||||
| import {computed, onMounted, ref, watch, defineProps, defineEmits} from "vue"; |     import {computed, onMounted, ref, watch, defineProps, defineEmits} from "vue"; | ||||||
| import GroupSelector from "@/components/GroupSelector.vue"; |     import GroupSelector from "@/components/GroupSelector.vue"; | ||||||
| import DeadlineSelector from "@/components/DeadlineSelector.vue"; |     import DeadlineSelector from "@/components/DeadlineSelector.vue"; | ||||||
| import { |     import { | ||||||
|     assignmentTitleRules, |         assignmentTitleRules, | ||||||
|     classesRules, |         classesRules, | ||||||
|     descriptionRules, |         descriptionRules, | ||||||
|     learningPathRules |         learningPathRules | ||||||
| } from "@/utils/assignmentForm.ts"; |     } from "@/utils/assignmentForm.ts"; | ||||||
|  |     import {classes} from "@/utils/tempData.ts"; | ||||||
| 
 | 
 | ||||||
| const {t, locale} = useI18n(); |     const {t, locale} = useI18n(); | ||||||
| const emit = defineEmits(["submit"]); |     const emit = defineEmits(["submit"]); | ||||||
| 
 | 
 | ||||||
| const props = defineProps({ |     const props = defineProps({ | ||||||
|     sort: {type: String}, |         sort: {type: String}, | ||||||
|     initialTitle: {type: String, default: ""}, |         initialTitle: {type: String, default: ""}, | ||||||
|     initialDeadline: {type: Date, default: null}, |         initialDeadline: {type: Date, default: null}, | ||||||
|     initialDescription: {type: String, default: ""}, |         initialDescription: {type: String, default: ""}, | ||||||
|     initialLearningPath: {type: Object, default: null}, |         initialLearningPath: {type: Object, default: null}, | ||||||
|     initialClass: {type: Object, default: null}, |         initialClass: {type: Object, default: null}, | ||||||
|     initialGroups: {type: Array, default: () => []} |         initialGroups: {type: Array, default: () => []} | ||||||
| }); |  | ||||||
| 
 |  | ||||||
| const form = ref(); |  | ||||||
| const language = ref(locale.value); |  | ||||||
| const searchQuery = ref(""); |  | ||||||
| const assignmentTitle = ref(props.initialTitle); |  | ||||||
| const deadline = ref(props.initialDeadline); |  | ||||||
| const description = ref(props.initialDescription); |  | ||||||
| const selectedLearningPath = ref(props.initialLearningPath); |  | ||||||
| const selectedClass = ref(props.initialClass); |  | ||||||
| const groups = ref(props.initialGroups); |  | ||||||
| const allLearningPaths = ref([]); |  | ||||||
| const filteredLearningPaths = ref([]); |  | ||||||
| const allClasses = ref([]); |  | ||||||
| 
 |  | ||||||
| const availableClass = computed(() => selectedClass.value); |  | ||||||
| const allStudents = computed(() => selectedClass.value ? selectedClass.value.students : []); |  | ||||||
| 
 |  | ||||||
| const addGroupToList = (students: string[]) => { |  | ||||||
|     if (students.length) { |  | ||||||
|         groups.value = [...groups.value, students]; |  | ||||||
|     } |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| async function fetchAllLearningPaths() { |  | ||||||
|     try { |  | ||||||
|         //TODO: replace by function from controller |  | ||||||
|         const response = await fetch(`http://localhost:3000/api/learningPath?language=${language.value}`); |  | ||||||
|         if (!response.ok) throw new Error("Failed to fetch learning paths"); |  | ||||||
|         const data = await response.json(); |  | ||||||
|         allLearningPaths.value = data.map((lp: { hruid: string; title: string }) => ({ |  | ||||||
|             hruid: lp.hruid, |  | ||||||
|             name: lp.title |  | ||||||
|         })); |  | ||||||
|         filteredLearningPaths.value = [...allLearningPaths.value]; |  | ||||||
|     } catch (error) { |  | ||||||
|         console.error(error); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| watch(() => locale.value, fetchAllLearningPaths, {immediate: true}); |  | ||||||
| watch(selectedClass, () => groups.value = []); |  | ||||||
| 
 |  | ||||||
| const searchResults = computed(() => filteredLearningPaths.value.filter((lp) => |  | ||||||
|     lp.title.toLowerCase().includes(searchQuery.value.toLowerCase()) |  | ||||||
| )); |  | ||||||
| 
 |  | ||||||
| onMounted(fetchAllLearningPaths); |  | ||||||
| 
 |  | ||||||
| const submitFormHandler = async () => { |  | ||||||
|     const {valid} = await form.value.validate(); |  | ||||||
|     if (!valid) return; |  | ||||||
|     emit("submit", { |  | ||||||
|         assignmentTitle: assignmentTitle.value, |  | ||||||
|         selectedLearningPath: selectedLearningPath.value, |  | ||||||
|         selectedClass: selectedClass.value, |  | ||||||
|         groups: groups.value, |  | ||||||
|         deadline: deadline.value, |  | ||||||
|         description: description.value |  | ||||||
|     }); |     }); | ||||||
| }; | 
 | ||||||
|  |     const form = ref(); | ||||||
|  |     const language = ref(locale.value); | ||||||
|  |     const searchQuery = ref(""); | ||||||
|  |     const assignmentTitle = ref(props.initialTitle); | ||||||
|  |     const deadline = ref(props.initialDeadline); | ||||||
|  |     const description = ref(props.initialDescription); | ||||||
|  |     const selectedLearningPath = ref(props.initialLearningPath); | ||||||
|  |     const selectedClass = ref(props.initialClass); | ||||||
|  |     const groups = ref(props.initialGroups); | ||||||
|  |     const allLearningPaths = ref([]); | ||||||
|  |     const filteredLearningPaths = ref([]); | ||||||
|  |     //TODO: replace by real data | ||||||
|  |     const allClasses = ref([...classes.map(cl => ({title: cl.displayName, value: cl.id}))]); | ||||||
|  | 
 | ||||||
|  |     const availableClass = computed(() => { | ||||||
|  |         //TODO: replace by real data | ||||||
|  |         return classes.find(cl => selectedClass.value?.value === cl.id) || null; | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     const allStudents = computed(() => { | ||||||
|  |         //TODO: replace by real data | ||||||
|  |         if (!selectedClass.value) return []; | ||||||
|  |         const cl = classes.find(c => c.id === selectedClass.value.value); | ||||||
|  |         return cl ? cl.students.map(st => ({ | ||||||
|  |             title: `${st.firstName} ${st.lastName}`, | ||||||
|  |             value: st.username, | ||||||
|  |             classes: cl | ||||||
|  |         })) : []; | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     const addGroupToList = (students: string[]) => { | ||||||
|  |         if (students.length) { | ||||||
|  |             groups.value = [...groups.value, students]; | ||||||
|  |         } | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     async function fetchAllLearningPaths() { | ||||||
|  |         try { | ||||||
|  |             //TODO: replace by function from controller | ||||||
|  |             const response = await fetch(`http://localhost:3000/api/learningPath?language=${language.value}`); | ||||||
|  |             if (!response.ok) throw new Error("Failed to fetch learning paths"); | ||||||
|  |             const data = await response.json(); | ||||||
|  |             allLearningPaths.value = data.map((lp: { hruid: string; title: string }) => ({ | ||||||
|  |                 hruid: lp.hruid, | ||||||
|  |                 title: lp.title | ||||||
|  |             })); | ||||||
|  |             filteredLearningPaths.value = [...allLearningPaths.value]; | ||||||
|  |         } catch (error) { | ||||||
|  |             console.error(error); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     watch( | ||||||
|  |         () => locale.value, | ||||||
|  |         (newLocale) => { | ||||||
|  |             if (!["nl", "en"].includes(newLocale)) { | ||||||
|  |                 language.value = "en"; | ||||||
|  |             } | ||||||
|  |             fetchAllLearningPaths(); | ||||||
|  |         }, | ||||||
|  |         {immediate: true} | ||||||
|  |     ); | ||||||
|  |     watch(selectedClass, () => groups.value = []); | ||||||
|  | 
 | ||||||
|  |     // Seach queries for the dropdown search bar | ||||||
|  |     const searchResults = computed(() => filteredLearningPaths.value.filter((lp) => | ||||||
|  |         lp.title.toLowerCase().includes(searchQuery.value.toLowerCase()) | ||||||
|  |     )); | ||||||
|  | 
 | ||||||
|  |     onMounted(fetchAllLearningPaths); | ||||||
|  | 
 | ||||||
|  |     const submitFormHandler = async () => { | ||||||
|  |         const {valid} = await form.value.validate(); | ||||||
|  |         if (!valid) return; | ||||||
|  |         emit("submit", { | ||||||
|  |             title: assignmentTitle.value, | ||||||
|  |             description: description, | ||||||
|  |             learningPathHruid: selectedLearningPath.value, | ||||||
|  |             class: selectedClass.value, | ||||||
|  |             groups: groups.value, | ||||||
|  |             deadline: deadline.value | ||||||
|  |         }); | ||||||
|  |     }; | ||||||
| </script> | </script> | ||||||
| 
 | 
 | ||||||
| <template> | <template> | ||||||
|  | @ -91,47 +117,60 @@ const submitFormHandler = async () => { | ||||||
|             <v-form ref="form" class="form-container" validate-on="submit lazy" @submit.prevent="submitFormHandler"> |             <v-form ref="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-card-text> | ||||||
|                         <v-text-field v-model="assignmentTitle" :label="t('title')" :rules="assignmentTitleRules" |                         <v-text-field | ||||||
|                                       density="compact" variant="outlined" clearable required></v-text-field> |                             v-model="assignmentTitle" | ||||||
|  |                             :label="t('title')" | ||||||
|  |                             :rules="assignmentTitleRules" | ||||||
|  |                             density="compact" | ||||||
|  |                             variant="outlined" | ||||||
|  |                             clearable | ||||||
|  |                             required | ||||||
|  |                         ></v-text-field> | ||||||
|                     </v-card-text> |                     </v-card-text> | ||||||
| 
 | 
 | ||||||
|                     <v-card-text> |                     <v-card-text> | ||||||
|                         <v-combobox v-model="selectedLearningPath" |                         <v-combobox | ||||||
|                                     :items="searchResults" |                             v-model="selectedLearningPath" | ||||||
|                                     item-title="name" |                             :items="searchResults" | ||||||
|                                     item-value="hruid" |                             :label="t('choose-lp')" | ||||||
|                                     :label="t('choose-lp')" |                             :rules="learningPathRules" | ||||||
|                                     :rules="learningPathRules" |                             variant="outlined" | ||||||
|                                     variant="outlined" |                             clearable | ||||||
|                                     clearable |                             hide-details | ||||||
|                                     hide-details density="compact" |                             density="compact" | ||||||
|                                     append-inner-icon="mdi-magnify" |                             append-inner-icon="mdi-magnify" | ||||||
|                                     required></v-combobox> |                             item-title="title" | ||||||
|  |                             item-value="value" | ||||||
|  |                             required | ||||||
|  |                             :filter="(item, query: string) => item.title.toLowerCase().includes(query.toLowerCase())" | ||||||
|  |                         ></v-combobox> | ||||||
|                     </v-card-text> |                     </v-card-text> | ||||||
| 
 | 
 | ||||||
|                     <v-card-text> |                     <v-card-text> | ||||||
|                         <v-combobox v-model="selectedClass" |                         <v-combobox | ||||||
|                                     :items="allClasses" |                             v-model="selectedClass" | ||||||
|                                     item-title="name" |                             :items="allClasses" | ||||||
|                                     item-value="id" |                             item-title="title" | ||||||
|                                     :label="t('pick-class')" |                             item-value="value" | ||||||
|                                     :rules="classesRules" |                             :label="t('pick-class')" | ||||||
|                                     variant="outlined" |                             :rules="classesRules" | ||||||
|                                     clearable |                             variant="outlined" | ||||||
|                                     hide-details |                             clearable | ||||||
|                                     density="compact" |                             hide-details | ||||||
|                                     append-inner-icon="mdi-magnify" |                             density="compact" | ||||||
|                                     required></v-combobox> |                             append-inner-icon="mdi-magnify" | ||||||
|  |                             required></v-combobox> | ||||||
|                     </v-card-text> |                     </v-card-text> | ||||||
| 
 | 
 | ||||||
|                     <DeadlineSelector v-model:deadline="deadline"/> |                     <DeadlineSelector v-model:deadline="deadline"/> | ||||||
| 
 | 
 | ||||||
|                     <h3>{{ t('create-groups') }}</h3> |                     <h3>{{ t('create-groups') }}</h3> | ||||||
| 
 | 
 | ||||||
|                     <GroupSelector :students="allStudents" |                     <GroupSelector | ||||||
|                                    :availableClass="availableClass" |                         :students="allStudents" | ||||||
|                                    :groups="groups" |                         :availableClass="availableClass" | ||||||
|                                    @groupCreated="addGroupToList"/> |                         :groups="groups" | ||||||
|  |                         @groupCreated="addGroupToList"/> | ||||||
| 
 | 
 | ||||||
|                     <v-card-text v-if="groups.length"> |                     <v-card-text v-if="groups.length"> | ||||||
|                         <strong>Created Groups: {{ groups.length }}</strong> |                         <strong>Created Groups: {{ groups.length }}</strong> | ||||||
|  |  | ||||||
|  | @ -1,11 +1,19 @@ | ||||||
| <script setup lang="ts"> | <script setup lang="ts"> | ||||||
|     import AssignmentForm from "@/views/assignments/AssignmentForm.vue"; |     import AssignmentForm from "@/views/assignments/AssignmentForm.vue"; | ||||||
| 
 |  | ||||||
|     const sort = "new"; |     const sort = "new"; | ||||||
|  | 
 | ||||||
|  |     const handleSubmit = async (formData) => { | ||||||
|  |         /*await fetch('/api/assignments', { | ||||||
|  |             method: 'POST', | ||||||
|  |             body: JSON.stringify(formData), | ||||||
|  |             headers: { 'Content-Type': 'application/json' } | ||||||
|  |         });*/ | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
| </script> | </script> | ||||||
| 
 | 
 | ||||||
| <template> | <template> | ||||||
|     <AssignmentForm :sort="sort"></AssignmentForm> |     <AssignmentForm :sort="sort" @submit="handleSubmit"></AssignmentForm> | ||||||
| </template> | </template> | ||||||
| 
 | 
 | ||||||
| <style scoped> | <style scoped> | ||||||
|  |  | ||||||
|  | @ -1,12 +1,20 @@ | ||||||
| <script setup lang="ts"> | <script setup lang="ts"> | ||||||
| import AssignmentForm from "@/views/assignments/AssignmentForm.vue"; |     import AssignmentForm from "@/views/assignments/AssignmentForm.vue"; | ||||||
|  |     import {ref} from "vue"; | ||||||
|  |     import {useRoute} from "vue-router"; | ||||||
|  | 
 | ||||||
|  |     const sort = "edit"; | ||||||
|  |     //TODO: use the id param to extract info about the assignment and pass them as props | ||||||
|  |     const route = useRoute(); | ||||||
|  |     const assignmentId = ref(route.params.id as string); | ||||||
|  | 
 | ||||||
|  |     const handleUpdate = async (formData) => { | ||||||
|  |     }; | ||||||
| 
 | 
 | ||||||
| const sort = "edit"; |  | ||||||
| //TODO: use the id param to extract info about the assignment |  | ||||||
| </script> | </script> | ||||||
| 
 | 
 | ||||||
| <template> | <template> | ||||||
|     <AssignmentForm :sort="sort"></AssignmentForm> |     <AssignmentForm :sort="sort" @submit="handleUpdate"></AssignmentForm> | ||||||
| </template> | </template> | ||||||
| 
 | 
 | ||||||
| <style scoped> | <style scoped> | ||||||
|  |  | ||||||
|  | @ -1,7 +1,90 @@ | ||||||
| <script setup lang="ts"></script> | <script setup lang="ts"> | ||||||
|  |     import { useRoute } from "vue-router"; | ||||||
|  |     import {ref, onMounted, computed} from "vue"; | ||||||
|  |     import {useI18n} from "vue-i18n"; | ||||||
|  |     import {assignments} from "@/utils/tempData.ts"; | ||||||
|  |     import auth from "@/services/auth/auth-service.ts"; | ||||||
|  | 
 | ||||||
|  |     const {t} = useI18n(); | ||||||
|  |     const route = useRoute(); | ||||||
|  |     const assignmentId = ref(route.params.id as string); | ||||||
|  |     const assignment = ref(null); | ||||||
|  | 
 | ||||||
|  |     const role = auth.authState.activeRole; | ||||||
|  |     const isTeacher = computed(() => role === 'teacher'); | ||||||
|  | 
 | ||||||
|  |     onMounted(async () => { | ||||||
|  |         try { | ||||||
|  |             // TODO: Replace with real data | ||||||
|  |             assignment.value = assignments[0]; | ||||||
|  |         } catch (error) { | ||||||
|  |             console.error(error); | ||||||
|  |         } | ||||||
|  |     }); | ||||||
|  | </script> | ||||||
| 
 | 
 | ||||||
| <template> | <template> | ||||||
|     <main></main> |     <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="edit-btn" | ||||||
|  |                     :to="`/assignment/${assignmentId}/edit`" | ||||||
|  |                 > | ||||||
|  |                     <v-icon>mdi-pencil</v-icon> | ||||||
|  |                 </v-btn> | ||||||
|  |             </div> | ||||||
|  |             <v-card-title class="text-h4">{{ assignment.title }}</v-card-title> | ||||||
|  |             <v-card-subtitle> | ||||||
|  |                 <v-btn | ||||||
|  |                     :to="`/learningPath/${assignment.learningPathHruid}`" | ||||||
|  |                     variant="tonal" | ||||||
|  |                     color="primary" | ||||||
|  |                 > | ||||||
|  |                     {{ t("learning-path") }} | ||||||
|  |                 </v-btn> | ||||||
|  |             </v-card-subtitle> | ||||||
|  | 
 | ||||||
|  |             <v-card-text class="description"> | ||||||
|  |                 {{ assignment.description }} | ||||||
|  |             </v-card-text> | ||||||
|  |         </v-card> | ||||||
|  |     </div> | ||||||
| </template> | </template> | ||||||
| 
 | 
 | ||||||
| <style scoped></style> | <style scoped> | ||||||
|  | .container { | ||||||
|  |     display: flex; | ||||||
|  |     justify-content: center; | ||||||
|  |     align-items: center; | ||||||
|  |     padding: 2%; | ||||||
|  |     min-height: 100vh; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .assignment-card { | ||||||
|  |     width: 90%; | ||||||
|  |     max-width: 900px; | ||||||
|  |     padding: 2%; | ||||||
|  |     border-radius: 12px; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .description { | ||||||
|  |     margin-top: 2%; | ||||||
|  |     line-height: 1.6; | ||||||
|  |     font-size: 1.1rem; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | </style> | ||||||
|  | 
 | ||||||
|  |  | ||||||
|  | @ -24,11 +24,11 @@ | ||||||
|         router.push('/assignment/create'); |         router.push('/assignment/create'); | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     const goToEditAssignment = (id: number) => { |     const goToEditAssignment = (id: string) => { | ||||||
|         router.push(`/assignment/edit/${id}`); |         router.push(`/assignment/${id}/edit`); | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     const goToAssignmentDetails = (id: number) => { |     const goToAssignmentDetails = (id: string) => { | ||||||
|         router.push(`/assignment/${id}`); |         router.push(`/assignment/${id}`); | ||||||
|     }; |     }; | ||||||
| </script> | </script> | ||||||
|  | @ -45,9 +45,9 @@ | ||||||
|             <v-row> |             <v-row> | ||||||
|                 <v-col v-for="assignment in allAssignments" :key="assignment.id" cols="12"> |                 <v-col v-for="assignment in allAssignments" :key="assignment.id" cols="12"> | ||||||
|                     <v-card class="assignment-card" variant="outlined"> |                     <v-card class="assignment-card" variant="outlined"> | ||||||
|                         <v-card-title>{{ assignment.title }}</v-card-title> |                         <v-card-title class="title">{{ assignment.title }}</v-card-title> | ||||||
|                         <v-divider></v-divider> |                         <v-divider></v-divider> | ||||||
|                         <v-card-text>{{ assignment.description }}</v-card-text> |                         <v-card-text class="description-text" >{{ assignment.description }}</v-card-text> | ||||||
| 
 | 
 | ||||||
|                         <v-card-actions> |                         <v-card-actions> | ||||||
|                             <v-btn color="primary" @click="goToAssignmentDetails(assignment.id)"> |                             <v-btn color="primary" @click="goToAssignmentDetails(assignment.id)"> | ||||||
|  | @ -70,11 +70,11 @@ | ||||||
|     display: flex; |     display: flex; | ||||||
|     flex-direction: column; |     flex-direction: column; | ||||||
|     align-items: center; |     align-items: center; | ||||||
|     padding: 20px; |     padding: 2%; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .assignment-card { | .assignment-card { | ||||||
|     padding: 16px; |     padding: 1%; | ||||||
|     display: flex; |     display: flex; | ||||||
|     flex-direction: column; |     flex-direction: column; | ||||||
|     justify-content: space-between; |     justify-content: space-between; | ||||||
|  | @ -84,4 +84,20 @@ h1 { | ||||||
|     text-align: left; |     text-align: left; | ||||||
|     width: 100%; |     width: 100%; | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | .title { | ||||||
|  |     flex-grow: 1; | ||||||
|  |     white-space: normal; | ||||||
|  |     overflow-wrap: break-word; | ||||||
|  |     word-break: break-word; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .description-text { | ||||||
|  |     display: -webkit-box; | ||||||
|  |     -webkit-line-clamp: 3;  /* Limit to 3 lines */ | ||||||
|  |     -webkit-box-orient: vertical; | ||||||
|  |     overflow: hidden; | ||||||
|  |     text-overflow: ellipsis; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| </style> | </style> | ||||||
|  |  | ||||||
		Reference in a new issue
	
	 Joyelle Ndagijimana
						Joyelle Ndagijimana