feat: thema's filteren op categorie en leeftijd werkt
This commit is contained in:
parent
d4e0dc2703
commit
54a2cf0800
3 changed files with 120 additions and 61 deletions
|
@ -2,10 +2,19 @@
|
||||||
import ThemeCard from "@/components/ThemeCard.vue";
|
import ThemeCard from "@/components/ThemeCard.vue";
|
||||||
import { ref, onMounted, watch } from "vue";
|
import { ref, onMounted, watch } from "vue";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
import {THEMESITEMS} from "@/utils/constants.ts";
|
import {AGE_TO_THEMES, THEMESITEMS} from "@/utils/constants.ts";
|
||||||
|
|
||||||
// Receive the selectedTheme from the parent component
|
// Receive the selectedTheme from the parent component
|
||||||
const props = defineProps<{ selectedTheme: string }>();
|
const props = defineProps({
|
||||||
|
selectedTheme: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
selectedAge: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
const {locale} = useI18n();
|
const {locale} = useI18n();
|
||||||
|
|
||||||
|
@ -38,8 +47,17 @@
|
||||||
|
|
||||||
// Watch for selectedTheme change and filter themes
|
// Watch for selectedTheme change and filter themes
|
||||||
watch(() => props.selectedTheme, (newTheme) => {
|
watch(() => props.selectedTheme, (newTheme) => {
|
||||||
if (newTheme && newTheme !== "all") {
|
if (newTheme) {
|
||||||
cards.value = allCards.value.filter(theme => THEMESITEMS[newTheme].includes(theme.key));
|
cards.value = allCards.value.filter(theme => THEMESITEMS[newTheme].includes(theme.key) && AGE_TO_THEMES[props.selectedAge]?.includes(theme.key));
|
||||||
|
} else {
|
||||||
|
cards.value = allCards.value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Watch for selectedAge change and filter themes
|
||||||
|
watch(() => props.selectedAge, (newAge) => {
|
||||||
|
if (newAge) {
|
||||||
|
cards.value = allCards.value.filter(theme => THEMESITEMS[props.selectedTheme].includes(theme.key) && AGE_TO_THEMES[newAge]?.includes(theme.key));
|
||||||
} else {
|
} else {
|
||||||
cards.value = allCards.value;
|
cards.value = allCards.value;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,12 +16,22 @@ export const THEMESITEMS: Record<string, string[]> = {
|
||||||
"algorithms": ["math_with_python", "python_programming", "stem", "algorithms", "basics_ai"],
|
"algorithms": ["math_with_python", "python_programming", "stem", "algorithms", "basics_ai"],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export const AGEITEMS = [
|
export const AGEITEMS = [
|
||||||
"all",
|
"all", "primary-school", "lower-secondary", "upper-secondary", "high-school", "older"
|
||||||
"primary-school",
|
|
||||||
"lower-secondary",
|
|
||||||
"upper-secondary",
|
|
||||||
"high-school",
|
|
||||||
"older",
|
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export const AGE_TO_THEMES: Record<string, string[]> = {
|
||||||
|
"all": THEMES_KEYS,
|
||||||
|
"primary-school": ["wegostem", "computational_thinking", "physical_computing"],
|
||||||
|
"lower-secondary": ["socialrobot", "art", "wegostem", "computational_thinking", "physical_computing"],
|
||||||
|
"upper-secondary": ["kiks", "art", "socialrobot", "agriculture",
|
||||||
|
"computational_thinking", "math_with_python", "python_programming",
|
||||||
|
"stem", "care", "chatbot", "algorithms", "basics_ai"],
|
||||||
|
"high-school": [
|
||||||
|
"kiks", "art", "agriculture", "computational_thinking", "math_with_python", "python_programming",
|
||||||
|
"stem", "care", "chatbot", "algorithms", "basics_ai"
|
||||||
|
],
|
||||||
|
"older": [
|
||||||
|
"kiks", "computational_thinking", "algorithms", "basics_ai"
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
|
@ -1,19 +1,49 @@
|
||||||
<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 { THEMESITEMS, AGEITEMS } from "@/utils/constants.ts";
|
import {THEMESITEMS, AGE_TO_THEMES} from "@/utils/constants.ts";
|
||||||
import BrowseThemes from "@/components/BrowseThemes.vue";
|
import BrowseThemes from "@/components/BrowseThemes.vue";
|
||||||
|
|
||||||
const { t, locale } = useI18n();
|
const {t, locale} = useI18n();
|
||||||
|
|
||||||
const selectedThemeKey = ref<string | null>(null);
|
const selectedThemeKey = ref<string>('all');
|
||||||
const selectedAgeKey = ref<string | null>(null);
|
const selectedAgeKey = ref<string>('all');
|
||||||
|
|
||||||
|
const allThemes = ref(Object.keys(THEMESITEMS));
|
||||||
|
const availableThemes = ref([...allThemes.value]);
|
||||||
|
|
||||||
|
const allAges = ref(Object.keys(AGE_TO_THEMES));
|
||||||
|
const availableAges = ref([...allAges.value]);
|
||||||
|
|
||||||
// Reset selection when language changes
|
// Reset selection when language changes
|
||||||
watch(locale, () => {
|
watch(locale, () => {
|
||||||
selectedThemeKey.value = null;
|
selectedThemeKey.value = 'all';
|
||||||
selectedAgeKey.value = null;
|
selectedAgeKey.value = 'all';
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
watch(selectedThemeKey, () => {
|
||||||
|
if (selectedThemeKey.value === "all") {
|
||||||
|
availableAges.value = [...allAges.value]; // Reset to all ages
|
||||||
|
} else {
|
||||||
|
const themes = THEMESITEMS[selectedThemeKey.value];
|
||||||
|
availableAges.value = allAges.value.filter(age =>
|
||||||
|
AGE_TO_THEMES[age]?.some(theme => themes.includes(theme))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
watch(selectedAgeKey, () => {
|
||||||
|
if (selectedAgeKey.value === "all") {
|
||||||
|
availableThemes.value = [...allThemes.value]; // Reset to all themes
|
||||||
|
} else {
|
||||||
|
const themes = AGE_TO_THEMES[selectedAgeKey.value];
|
||||||
|
availableThemes.value = allThemes.value.filter(theme =>
|
||||||
|
THEMESITEMS[theme]?.some(theme => themes.includes(theme))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -22,7 +52,7 @@
|
||||||
<v-container class="dropdowns">
|
<v-container class="dropdowns">
|
||||||
<v-select class="v-select"
|
<v-select class="v-select"
|
||||||
:label="t('choose-theme')"
|
:label="t('choose-theme')"
|
||||||
:items="Object.keys(THEMESITEMS).map(theme => ({ title: t(`theme-options.${theme}`), value: theme }))"
|
:items="availableThemes.map(theme => ({ title: t(`theme-options.${theme}`), value: theme }))"
|
||||||
v-model="selectedThemeKey"
|
v-model="selectedThemeKey"
|
||||||
item-title="title"
|
item-title="title"
|
||||||
item-value="value"
|
item-value="value"
|
||||||
|
@ -33,7 +63,7 @@
|
||||||
<v-select
|
<v-select
|
||||||
class="v-select"
|
class="v-select"
|
||||||
:label="t('choose-age')"
|
:label="t('choose-age')"
|
||||||
:items="AGEITEMS.map(age => ({ key: age, label: t(`age-options.${age}`), value: age }))"
|
:items="availableAges.map(age => ({ key: age, label: t(`age-options.${age}`), value: age }))"
|
||||||
v-model="selectedAgeKey"
|
v-model="selectedAgeKey"
|
||||||
item-title="label"
|
item-title="label"
|
||||||
item-value="key"
|
item-value="key"
|
||||||
|
@ -41,55 +71,56 @@
|
||||||
></v-select>
|
></v-select>
|
||||||
</v-container>
|
</v-container>
|
||||||
|
|
||||||
<BrowseThemes :selectedTheme="selectedThemeKey ?? ''" />
|
<BrowseThemes :selectedTheme="selectedThemeKey ?? ''" :selectedAge="selectedAgeKey ?? ''"/>
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
.main-container {
|
||||||
|
min-height: 100vh;
|
||||||
|
min-width: 100vw;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
justify-content: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
max-width: 50rem;
|
||||||
|
margin-left: 1rem;
|
||||||
|
margin-top: 1rem;
|
||||||
|
text-align: center;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.dropdowns {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 5rem;
|
||||||
|
width: 80%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v-select {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
.main-container {
|
.main-container {
|
||||||
min-height: 100vh;
|
padding: 1rem;
|
||||||
min-width: 100vw;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: flex-start;
|
|
||||||
justify-content: flex-start;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.title {
|
@media (max-width: 700px) {
|
||||||
max-width: 50rem;
|
|
||||||
margin-left: 1rem;
|
|
||||||
margin-top: 1rem;
|
|
||||||
text-align: center;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.dropdowns {
|
.dropdowns {
|
||||||
display: flex;
|
flex-direction: column;
|
||||||
justify-content: space-between;
|
gap: 1rem;
|
||||||
gap: 5rem;
|
|
||||||
width: 80%;
|
width: 80%;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
.v-select {
|
|
||||||
flex: 1;
|
|
||||||
min-width: 100px;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@media (max-width: 768px) {
|
|
||||||
.main-container {
|
|
||||||
padding: 1rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 700px) {
|
|
||||||
.dropdowns {
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 1rem;
|
|
||||||
width: 80%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue