Simplify Subnavigation and create component to handle external vs

internal links
This commit is contained in:
Ramon Wenger 2024-10-24 17:03:08 +02:00
parent 28027eb96f
commit 6c6bbb9e22
2 changed files with 97 additions and 80 deletions

View File

@ -0,0 +1,35 @@
<script setup lang="ts">
import { computed } from "vue";
import { RouterLink } from "vue-router";
// https://router.vuejs.org/guide/advanced/extending-router-link
defineOptions({
inheritAttrs: false,
});
const props = defineProps({
// @ts-expect-error the example above mentions needing @ts-ignore
...RouterLink.props,
});
const isExternalLink = computed(() => {
return typeof props.to === "string" && props.to.startsWith("https");
});
</script>
<template>
<a v-if="isExternalLink" v-bind="$attrs" :href="to" target="_blank">
<slot />
<it-icon-external-link />
</a>
<router-link v-else v-slot="{ isActive, href, navigate }" v-bind="$props" custom>
<a
v-bind="$attrs"
:class="isActive ? activeClass : ''"
:href="href"
@click="navigate"
>
<slot />
</a>
</router-link>
</template>

View File

@ -1,4 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import SubNavItem from "@/components/header/SubNavItem.vue";
import { useCurrentCourseSession, useEvaluationWithFeedback } from "@/composables"; import { useCurrentCourseSession, useEvaluationWithFeedback } from "@/composables";
import { import {
CERTIFICATES_ROUTE, CERTIFICATES_ROUTE,
@ -7,29 +8,16 @@ import {
SELF_EVALUATION_ROUTE, SELF_EVALUATION_ROUTE,
} from "@/router/names"; } from "@/router/names";
import { Listbox, ListboxButton, ListboxOption, ListboxOptions } from "@headlessui/vue"; import { Listbox, ListboxButton, ListboxOption, ListboxOptions } from "@headlessui/vue";
import { useTranslation } from "i18next-vue";
import * as log from "loglevel"; import * as log from "loglevel";
import { onMounted } from "vue"; import { computed, onMounted } from "vue";
import { useRoute } from "vue-router"; import { useRouter } from "vue-router";
log.debug("CompetenceParentPage created"); log.debug("CompetenceParentPage created");
const route = useRoute(); const router = useRouter();
function routeInOverview() { const { t } = useTranslation();
return route.path.endsWith("/competence");
}
function routeInCompetenceCertificate() {
return route.path.includes("/certificate");
}
function routeInActionCompetences() {
return route.path.endsWith("/competences");
}
function routeInSelfEvaluationAndFeedback() {
return route.path.endsWith("/self-evaluation-and-feedback");
}
const currentCourseSession = useCurrentCourseSession(); const currentCourseSession = useCurrentCourseSession();
const hasEvaluationFeedback = useEvaluationWithFeedback().hasFeedback; const hasEvaluationFeedback = useEvaluationWithFeedback().hasFeedback;
@ -38,13 +26,6 @@ onMounted(async () => {
log.debug("CompetenceParentPage mounted"); log.debug("CompetenceParentPage mounted");
}); });
const items = [
{ id: 0, name: "Übersicht" },
{ id: 1, name: "Teilnehmer" },
{ id: 2, name: "Unterlagen" },
{ id: 3, name: "MS Teams", iconName: "it-icon-external-link" },
{ id: 4, name: "Vorschau Teilnehmer", iconName: "it-icon-external-link" },
];
const competenceRoute = { const competenceRoute = {
name: COMPETENCE_ROUTE, name: COMPETENCE_ROUTE,
}; };
@ -57,6 +38,48 @@ const selfEvaluationRoute = {
const competencesRoute = { const competencesRoute = {
name: COMPETENCES_ROUTE, name: COMPETENCES_ROUTE,
}; };
const isCurrentRoute = (route: { name: string } | string) => {
return typeof route !== "string" && route?.name === router.currentRoute.value.name;
};
const items = [
{ id: 0, name: t("a.Übersicht"), route: competenceRoute },
...(currentCourseSession.value.course.configuration.enable_competence_certificates
? [
{
id: 1,
name: t("a.Kompetenznachweise"),
route: certificatesRoute,
},
]
: []),
{
id: 2,
name: hasEvaluationFeedback.value
? t("a.Selbst- und Fremdeinschätzungen")
: t("a.Selbsteinschätzungen"),
route: selfEvaluationRoute,
},
{ id: 3, name: t("a.Handlungskompetenzen"), route: competencesRoute },
{
id: 3,
name: "MS Teams",
iconName: "it-icon-external-link",
route: "https://iterativ.ch",
},
{
id: 3,
name: "Vorschau Teilnehmer",
iconName: "it-icon-external-link",
route: "https://iterativ.ch",
},
// { id: 4, name: "Vorschau Teilnehmer", iconName: "it-icon-external-link" },
];
const currentRouteName = computed(() => {
return items.find((item) => isCurrentRoute(item.route))?.name || "";
});
</script> </script>
<template> <template>
@ -67,7 +90,7 @@ const competencesRoute = {
<ListboxButton <ListboxButton
class="relative flex w-full cursor-default flex-row items-center border bg-white py-3 pl-5 pr-10 text-left" class="relative flex w-full cursor-default flex-row items-center border bg-white py-3 pl-5 pr-10 text-left"
> >
Übersicht {{ currentRouteName }}
<span <span
class="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2" class="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2"
> >
@ -77,69 +100,28 @@ const competencesRoute = {
<ListboxOptions <ListboxOptions
class="absolute top-14 flex w-full cursor-default flex-col rounded-xl border-0 bg-white text-left shadow-lg" class="absolute top-14 flex w-full cursor-default flex-col rounded-xl border-0 bg-white text-left shadow-lg"
> >
<ListboxOption <ListboxOption v-for="item in items" :key="item.id">
v-for="item in items" <SubNavItem
:key="item.id" class="flex w-full items-center gap-2 border-b py-3 pl-5 pr-10 last:border-b-0"
as="router-link" :to="item.route"
class="flex w-full items-center gap-2 border-b py-3 pl-5 pr-10 last:border-b-0" >
>
<router-link to="/">
{{ item.name }} {{ item.name }}
</router-link> </SubNavItem>
<component :is="item.iconName" v-if="item.iconName"></component>
</ListboxOption> </ListboxOption>
</ListboxOptions> </ListboxOptions>
</div> </div>
</Listbox> </Listbox>
<ul class="hidden flex-col lg:flex lg:flex-row"> <ul class="hidden flex-col gap-12 lg:flex lg:flex-row">
<li <li
v-for="item in items"
:key="item.id"
class="border-t-2 border-t-transparent" class="border-t-2 border-t-transparent"
:class="{ 'border-b-2 border-b-blue-900': routeInOverview() }" :class="{ 'border-b-2 border-b-blue-900': isCurrentRoute(item.route) }"
> >
<router-link :to="competenceRoute" class="block py-3"> <SubNavItem :to="item.route" class="block py-3">
{{ $t("a.Übersicht") }} {{ item.name }}
</router-link> </SubNavItem>
</li> </li>
<li
v-if="
currentCourseSession.course.configuration.enable_competence_certificates
"
class="border-t-2 border-t-transparent lg:ml-12"
:class="{ 'border-b-2 border-b-blue-900': routeInCompetenceCertificate() }"
>
<router-link :to="certificatesRoute" class="block py-3">
{{ $t("a.Kompetenznachweise") }}
</router-link>
</li>
<li
class="border-t-2 border-t-transparent lg:ml-12"
:class="{
'border-b-2 border-b-blue-900': routeInSelfEvaluationAndFeedback(),
}"
>
<router-link
:to="selfEvaluationRoute"
class="block py-3"
data-cy="self-evaluation-and-feedback-navigation-link"
>
{{
hasEvaluationFeedback
? $t("a.Selbst- und Fremdeinschätzungen")
: $t("a.Selbsteinschätzungen")
}}
</router-link>
</li>
<li
class="border-t-2 border-t-transparent lg:ml-12"
:class="{ 'border-b-2 border-b-blue-900': routeInActionCompetences() }"
>
<router-link :to="competencesRoute" class="block py-3">
{{ $t("a.Handlungskompetenzen") }}
</router-link>
</li>
<!-- Add similar logic for other `li` items as you expand the list -->
<li class="ml-6 inline-block lg:ml-12"></li>
</ul> </ul>
</nav> </nav>
<main> <main>