feat: tan stack theme query

This commit is contained in:
Gabriellvl 2025-03-22 00:59:37 +01:00
parent 47a522e443
commit 2b509774b8
6 changed files with 197 additions and 64 deletions

View file

@ -16,12 +16,14 @@
"test:e2e": "playwright test"
},
"dependencies": {
"@tanstack/react-query": "^5.69.0",
"@tanstack/vue-query": "^5.69.0",
"axios": "^1.8.2",
"oidc-client-ts": "^3.1.0",
"vue": "^3.5.13",
"vue-i18n": "^11.1.2",
"vue-router": "^4.5.0",
"vuetify": "^3.7.12",
"oidc-client-ts": "^3.1.0",
"axios": "^1.8.2"
"vuetify": "^3.7.12"
},
"devDependencies": {
"@playwright/test": "^1.50.1",

View file

@ -1,76 +1,52 @@
<script setup lang="ts">
import ThemeCard from "@/components/ThemeCard.vue";
import { ref, onMounted, watch } from "vue";
import { useI18n } from "vue-i18n";
import {AGE_TO_THEMES, THEMESITEMS} from "@/utils/constants.ts";
import {getAllThemes} from "@/controllers/themes.ts";
import {getThemeController} from "@/controllers/controllers.ts";
import ThemeCard from "@/components/ThemeCard.vue";
import { ref, watchEffect, computed } from "vue";
import { useI18n } from "vue-i18n";
import { AGE_TO_THEMES, THEMESITEMS } from "@/utils/constants.ts";
import { useThemeQuery } from "@/queries/themes.ts";
// Receive the selectedTheme and selectedAge from the parent component
const props = defineProps({
selectedTheme: {
type: String,
required: true
},
selectedAge: {
type: String,
required: true
}
});
const props = defineProps({
selectedTheme: { type: String, required: true },
selectedAge: { type: String, required: true }
});
const themeController = getThemeController();
const { locale } = useI18n();
const language = computed(() => locale.value);
const {locale} = useI18n();
const { data: allThemes, isLoading, error } = useThemeQuery(language);
const allCards = ref<Array<{ key: string; title: string; description: string; image: string }>>([]);
const cards = ref<Array<{ key: string; title: string; description: string; image: string }>>([]);
const allCards = ref([]);
const cards = ref([]);
// Fetch all themes based on the current language
async function fetchThemes() {
try {
// Get the current selected language
const language = locale.value;
watchEffect(() => {
const themes = allThemes.value ?? [];
allCards.value = themes;
// Update the cards value with the fetched themes
allCards.value = await themeController.getAll(language);
cards.value = allCards.value;
} catch (error) {
console.error("Error fetching themes:", error);
}
if (props.selectedTheme) {
cards.value = themes.filter((theme) =>
THEMESITEMS[props.selectedTheme]?.includes(theme.key) &&
AGE_TO_THEMES[props.selectedAge]?.includes(theme.key)
);
} else {
cards.value = themes;
}
// Fetch on mount
onMounted(fetchThemes);
// Re-fetch themes when language changes
watch(locale, () => {
fetchThemes();
});
// Watch for selectedTheme change and filter themes
watch(() => props.selectedTheme, (newTheme) => {
if (newTheme) {
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 {
cards.value = allCards.value;
}
});
});
</script>
<template>
<v-container>
<v-row>
<div v-if="isLoading" class="text-center py-10">
<v-progress-circular indeterminate color="primary" />
<p>Loading...</p>
</div>
<div v-else-if="error" class="text-center py-10 text-error">
<v-icon large>mdi-alert-circle</v-icon>
<p>Error loading: {{ error.message }}</p>
</div>
<v-row v-else>
<v-col
v-for="card in cards"
:key="card.key"

View file

@ -10,6 +10,7 @@ import i18n from "./i18n/i18n.ts";
// Components
import App from "./App.vue";
import router from "./router";
import { VueQueryPlugin, QueryClient } from '@tanstack/vue-query';
const app = createApp(App);
@ -24,6 +25,18 @@ const vuetify = createVuetify({
components,
directives,
});
const queryClient = new QueryClient({
defaultOptions: {
queries: {
retry: 1,
refetchOnWindowFocus: false,
},
},
});
app.use(vuetify);
app.use(i18n);
app.use(VueQueryPlugin, { queryClient });
app.mount("#app");

View file

@ -0,0 +1,25 @@
import { useQuery } from '@tanstack/vue-query';
import { getThemeController } from '@/controllers/controllers';
import {type MaybeRefOrGetter, toValue} from "vue";
const themeController = getThemeController();
export const useThemeQuery = (language: MaybeRefOrGetter<string>) => {
return useQuery({
queryKey: ['themes', language],
queryFn: () => {
const lang = toValue(language);
return themeController.getAll(lang);
},
enabled: () => !!toValue(language),
});
};
export const useThemeHruidsQuery = (themeKey: string | null) => {
return useQuery({
queryKey: ['theme-hruids', themeKey],
queryFn: () => themeController.getHruidsByKey(themeKey!),
enabled: !!themeKey,
});
};