feat(frontend): Navigatie voor leerpad geïmplementeerd.

This commit is contained in:
Gerald Schmittinger 2025-03-23 19:20:56 +01:00
parent 3c3fddb7d0
commit 07340de2e3
13 changed files with 216 additions and 54 deletions

View file

@ -37,7 +37,7 @@
</script>
<template>
<main>
<v-app-bar>
<nav class="menu">
<div class="left">
<ul>
@ -133,7 +133,7 @@
</li>
</div>
</nav>
</main>
</v-app-bar>
</template>
<style scoped>
@ -188,4 +188,8 @@
nav a.router-link-active {
font-weight: bold;
}
nav {
width: 100%;
}
</style>

View file

@ -1,39 +1,51 @@
<script setup lang="ts" generic="T">
import {RemoteResource} from "@/services/api-client/remote-resource.ts";
import {computed} from "vue";
import {type ErrorState, RemoteResource, type RemoteResourceState} from "@/services/api-client/remote-resource.ts";
import {computed, onMounted, reactive, ref, type UnwrapNestedRefs, watch} from "vue";
import {useI18n} from "vue-i18n";
const props = defineProps<{
resource: RemoteResource<T>
resource: RemoteResource<T> | (UnwrapNestedRefs<RemoteResource<T>> & {})
}>()
const resource = reactive(props.resource as RemoteResource<T>);
const { t } = useI18n();
const isLoading = computed(() => props.resource.state.type === 'loading');
const isError = computed(() => props.resource.state.type === 'error');
const isLoading = computed(() => resource.state.type === 'loading');
const isError = computed(() => resource.state.type === 'error');
// `data` will be correctly inferred as `T`
const data = computed(() => props.resource.data);
const data = computed(() => resource.data);
const error = computed(() => props.resource.state.type === "error" ? props.resource.state : null);
const error = computed(() => resource.state.type === "error" ? resource.state as ErrorState : null);
const errorMessage = computed(() =>
error.value?.message ? error.value.message : JSON.stringify(error.value?.error)
);
watch(data, (newValue, _) => {
if (!newValue && resource.state.type !== "loading") {
(resource as RemoteResource<T>).startRequestInBackground();
}
}, {immediate: true});
</script>
<template>
<div v-if="isLoading">
<div class="loading-div" v-if="isLoading">
<v-progress-circular indeterminate></v-progress-circular>
</div>
<div v-if="isError">
<v-empty-state
icon="mdi-alert-circle-outline"
text="errorMessage"
:title=t("error_title")
:text="errorMessage"
:title="t('error_title')"
></v-empty-state>
</div>
<slot v-if="data" :data="data!"></slot>
</template>
<style scoped>
.loading-div {
text-align: center;
margin: 10px;
}
</style>