Simplify Subnavigation and create component to handle external vs
internal links
This commit is contained in:
parent
28027eb96f
commit
6c6bbb9e22
|
|
@ -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>
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue