feat: theme card component aangemaakt
This commit is contained in:
		
							parent
							
								
									501ea6259c
								
							
						
					
					
						commit
						03a9e513a8
					
				
					 7 changed files with 143 additions and 20 deletions
				
			
		|  | @ -1,9 +1,57 @@ | ||||||
| <script setup lang="ts"> | <script setup lang="ts"> | ||||||
|     // This component contains a list with all themes and will be shown on a student's and teacher's homepage. |     // This component contains a list with all themes and will be shown on a student's and teacher's homepage. | ||||||
|  |     import ThemeCard from "@/components/ThemeCard.vue"; | ||||||
|  |     const cards = [ | ||||||
|  |         { | ||||||
|  |             key: "1", | ||||||
|  |             title: "Card 1", | ||||||
|  |             description: "This is card 1", | ||||||
|  |             image: "https://via.placeholder.com/150", | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             key: "2", | ||||||
|  |             title: "Card 2", | ||||||
|  |             description: "This is card 2", | ||||||
|  |             image: "https://via.placeholder.com/150", | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             key: "3", | ||||||
|  |             title: "Card 3", | ||||||
|  |             description: "This is card 3", | ||||||
|  |             image: "https://via.placeholder.com/150", | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             key: "4", | ||||||
|  |             title: "Card 4", | ||||||
|  |             description: "This is card 4", | ||||||
|  |             image: "https://via.placeholder.com/150", | ||||||
|  |         }, | ||||||
|  |     ]; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| </script> | </script> | ||||||
| 
 | 
 | ||||||
| <template> | <template> | ||||||
|     <main></main> |     <v-container> | ||||||
|  |         <v-row> | ||||||
|  |             <v-col | ||||||
|  |                 v-for="(card, index) in cards" | ||||||
|  |                 :key="index" | ||||||
|  |                 cols="12" | ||||||
|  |                 sm="6" | ||||||
|  |                 md="4" | ||||||
|  |                 lg="3" | ||||||
|  |             > | ||||||
|  |                 <ThemeCard | ||||||
|  |                     :path="card.key" | ||||||
|  |                     :title="card.title" | ||||||
|  |                     :description="card.description" | ||||||
|  |                     :image="card.image" | ||||||
|  |                 /> | ||||||
|  |             </v-col> | ||||||
|  |         </v-row> | ||||||
|  |     </v-container> | ||||||
| </template> | </template> | ||||||
| 
 | 
 | ||||||
| <style scoped></style> | <style scoped></style> | ||||||
|  |  | ||||||
							
								
								
									
										27
									
								
								frontend/src/components/ThemeCard.vue
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								frontend/src/components/ThemeCard.vue
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,27 @@ | ||||||
|  | <script setup lang="ts"> | ||||||
|  |     import { useI18n } from "vue-i18n"; | ||||||
|  | 
 | ||||||
|  |     const { t } = useI18n(); | ||||||
|  | 
 | ||||||
|  |     defineProps<{ | ||||||
|  |         path: string; | ||||||
|  |         title: string; | ||||||
|  |         description: string; | ||||||
|  |         image: string; | ||||||
|  |     }>(); | ||||||
|  | </script> | ||||||
|  | 
 | ||||||
|  | <template> | ||||||
|  |     <v-card :title="t(`${title}`)" :text="t(`${description}`)" variant="outlined"> | ||||||
|  |         <v-img v-if="image" :src="image" height="200px" cover></v-img> | ||||||
|  |         <v-card-actions> | ||||||
|  |             <v-btn :to="`theme/${path}`" variant="text"> | ||||||
|  |                 {{ t("read-more") }} | ||||||
|  |             </v-btn> | ||||||
|  | 
 | ||||||
|  |         </v-card-actions> | ||||||
|  |     </v-card> | ||||||
|  | </template> | ||||||
|  | 
 | ||||||
|  | <style scoped> | ||||||
|  | </style> | ||||||
|  | @ -28,5 +28,6 @@ | ||||||
|         "upper-secondary": "14-16 years old", |         "upper-secondary": "14-16 years old", | ||||||
|         "high-school": "16-18 years old", |         "high-school": "16-18 years old", | ||||||
|         "older": "18 and older" |         "older": "18 and older" | ||||||
|     } |     }, | ||||||
|  |     "read-more": "read-more" | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -13,6 +13,7 @@ import UserClasses from "@/views/classes/UserClasses.vue"; | ||||||
| import UserAssignments from "@/views/classes/UserAssignments.vue"; | import UserAssignments from "@/views/classes/UserAssignments.vue"; | ||||||
| import authState from "@/services/auth/auth-service.ts"; | import authState from "@/services/auth/auth-service.ts"; | ||||||
| import UserHomePage from "@/views/homepage/UserHomePage.vue"; | import UserHomePage from "@/views/homepage/UserHomePage.vue"; | ||||||
|  | import SingleTheme from "@/views/SingleTheme.vue"; | ||||||
| 
 | 
 | ||||||
| const router = createRouter({ | const router = createRouter({ | ||||||
|     history: createWebHistory(import.meta.env.BASE_URL), |     history: createWebHistory(import.meta.env.BASE_URL), | ||||||
|  | @ -63,6 +64,12 @@ const router = createRouter({ | ||||||
|             ], |             ], | ||||||
|         }, |         }, | ||||||
| 
 | 
 | ||||||
|  |         { | ||||||
|  |             path: "/theme/:id", | ||||||
|  |             name: "Theme", | ||||||
|  |             component: SingleTheme, | ||||||
|  |             meta: { requiresAuth: true }, | ||||||
|  |         }, | ||||||
|         { |         { | ||||||
|             path: "/assignment/create", |             path: "/assignment/create", | ||||||
|             name: "CreateAssigment", |             name: "CreateAssigment", | ||||||
|  | @ -112,7 +119,7 @@ router.beforeEach(async (to, from, next) => { | ||||||
|     // Verify if user is logged in before accessing certain routes
 |     // Verify if user is logged in before accessing certain routes
 | ||||||
|     if (to.meta.requiresAuth) { |     if (to.meta.requiresAuth) { | ||||||
|         if (!authState.isLoggedIn.value) { |         if (!authState.isLoggedIn.value) { | ||||||
|             //next("/login");
 |             //Next("/login");
 | ||||||
|             next(); |             next(); | ||||||
|         } else { |         } else { | ||||||
|             next(); |             next(); | ||||||
|  |  | ||||||
							
								
								
									
										22
									
								
								frontend/src/utils/constants.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								frontend/src/utils/constants.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,22 @@ | ||||||
|  | import { ref } from "vue"; | ||||||
|  | 
 | ||||||
|  | export const THEMESITEMS = ref([ | ||||||
|  |     "all-themes", | ||||||
|  |     "culture", | ||||||
|  |     "electricity-and-mechanics", | ||||||
|  |     "nature-and-climate", | ||||||
|  |     "agriculture", | ||||||
|  |     "society", | ||||||
|  |     "math", | ||||||
|  |     "technology", | ||||||
|  |     "algorithms", | ||||||
|  | ]); | ||||||
|  | 
 | ||||||
|  | export const AGEITEMS = ref([ | ||||||
|  |     "all-ages", | ||||||
|  |     "primary-school", | ||||||
|  |     "lower-secondary", | ||||||
|  |     "upper-secondary", | ||||||
|  |     "high-school", | ||||||
|  |     "older", | ||||||
|  | ]); | ||||||
							
								
								
									
										11
									
								
								frontend/src/views/SingleTheme.vue
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								frontend/src/views/SingleTheme.vue
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,11 @@ | ||||||
|  | <script setup lang="ts"> | ||||||
|  | 
 | ||||||
|  | </script> | ||||||
|  | 
 | ||||||
|  | <template> | ||||||
|  | 
 | ||||||
|  | </template> | ||||||
|  | 
 | ||||||
|  | <style scoped> | ||||||
|  | 
 | ||||||
|  | </style> | ||||||
|  | @ -1,12 +1,11 @@ | ||||||
| <script setup lang="ts"> | <script setup lang="ts"> | ||||||
| import {ref, watch} from "vue"; |     import {ref, watch} from "vue"; | ||||||
|     import { useI18n } from "vue-i18n"; |     import { useI18n } from "vue-i18n"; | ||||||
|  |     import {AGEITEMS, THEMESITEMS} from "@/utils/constants.ts"; | ||||||
|  |     import BrowseThemes from "@/components/BrowseThemes.vue"; | ||||||
| 
 | 
 | ||||||
|     const { t, locale } = useI18n(); |     const { t, locale } = useI18n(); | ||||||
| 
 | 
 | ||||||
|     const themesItems = ref(["all-themes", "culture", "electricity-and-mechanics", "nature-and-climate", "agriculture", "society", "math", "technology", "algorithms"]); |  | ||||||
| 
 |  | ||||||
|     const ageItems = ref(["all-ages",  "primary-school", "lower-secondary", "upper-secondary", "high-school", "older"]); |  | ||||||
| 
 | 
 | ||||||
|     const selectedTheme = ref(t('choose-theme')); |     const selectedTheme = ref(t('choose-theme')); | ||||||
|     const selectedAge = ref(t('choose-age')); |     const selectedAge = ref(t('choose-age')); | ||||||
|  | @ -22,24 +21,22 @@ import {ref, watch} from "vue"; | ||||||
| 
 | 
 | ||||||
| <template> | <template> | ||||||
|     <div class="main-container"> |     <div class="main-container"> | ||||||
|         <div class="header"> |         <h1 class="title">{{ t("themes") }}</h1> | ||||||
|             <h1>{{ t("themes") }}</h1> |         <v-container class="dropdowns"> | ||||||
|         </div> |  | ||||||
|         <div class="dropdowns"> |  | ||||||
|             <v-select class="v-select" |             <v-select class="v-select" | ||||||
|                 :label="t('choose-theme')" |                 :label="t('choose-theme')" | ||||||
|                       :items="themesItems.map(theme => t(`theme-options.${theme}`))" |                       :items="THEMESITEMS.map(theme => t(`theme-options.${theme}`))" | ||||||
|                       v-model="selectedTheme" |                       v-model="selectedTheme" | ||||||
|                       variant="outlined" |                       variant="outlined" | ||||||
|             ></v-select> |             ></v-select> | ||||||
|             <v-select class="v-select" |             <v-select class="v-select" | ||||||
|                 :label="t('choose-age')" |                 :label="t('choose-age')" | ||||||
|                       :items="ageItems.map(age => t(`age-options.${age}`))" |                       :items="AGEITEMS.map(age => t(`age-options.${age}`))" | ||||||
|                       v-model="selectedAge" |                       v-model="selectedAge" | ||||||
|                     variant="outlined" |                     variant="outlined" | ||||||
|             ></v-select> |             ></v-select> | ||||||
|         </div> |         </v-container> | ||||||
|         <div class="content"></div> |         <BrowseThemes/> | ||||||
|     </div> |     </div> | ||||||
| </template> | </template> | ||||||
| 
 | 
 | ||||||
|  | @ -51,19 +48,22 @@ import {ref, watch} from "vue"; | ||||||
|         flex-direction: column; |         flex-direction: column; | ||||||
|         align-items: flex-start; |         align-items: flex-start; | ||||||
|         justify-content: flex-start; |         justify-content: flex-start; | ||||||
|         padding: 2rem; |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     .header { |     .title { | ||||||
|         width: 60%; |  | ||||||
|         max-width: 50rem; |         max-width: 50rem; | ||||||
|         margin-bottom: 1rem; |         margin-left: 1rem; | ||||||
|  |         margin-top: 1rem; | ||||||
|  |         text-align: center; | ||||||
|  |         display: flex; | ||||||
|  |         justify-content: center; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|     .dropdowns { |     .dropdowns { | ||||||
|         display: flex; |         display: flex; | ||||||
|         justify-content: space-between; |         justify-content: space-between; | ||||||
|         gap: 3rem; |         gap: 5rem; | ||||||
|         width: 80%; |         width: 80%; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -79,5 +79,12 @@ import {ref, watch} from "vue"; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     @media (max-width: 700px) { | ||||||
|  |         .dropdowns { | ||||||
|  |             flex-direction: column; | ||||||
|  |             gap: 1rem; | ||||||
|  |             width: 80%; | ||||||
|  |         } | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
| </style> | </style> | ||||||
|  |  | ||||||
		Reference in a new issue
	
	 Joyelle Ndagijimana
						Joyelle Ndagijimana