vbv/client/src/pages/learningPath/learningPathPage/LearningPathPage.vue

148 lines
4.6 KiB
Vue

<script setup lang="ts">
import DueDatesShortList from "@/components/dueDates/DueDatesShortList.vue";
import LearningPathListView from "@/pages/learningPath/learningPathPage/LearningPathListView.vue";
import LearningPathPathView from "@/pages/learningPath/learningPathPage/LearningPathPathView.vue";
import CircleProgress from "@/pages/learningPath/learningPathPage/LearningPathProgress.vue";
import LearningPathTopics from "@/pages/learningPath/learningPathPage/LearningPathTopics.vue";
import type { ViewType } from "@/pages/learningPath/learningPathPage/LearningPathViewSwitch.vue";
import LearningPathViewSwitch from "@/pages/learningPath/learningPathPage/LearningPathViewSwitch.vue";
import { useLearningPathStore } from "@/stores/learningPath";
import { useUserStore } from "@/stores/user";
import { breakpointsTailwind, useBreakpoints } from "@vueuse/core";
import * as log from "loglevel";
import { computed, onMounted, ref } from "vue";
const props = defineProps<{
courseSlug: string;
}>();
const breakpoints = useBreakpoints(breakpointsTailwind);
const learningPathStore = useLearningPathStore();
const userStore = useUserStore();
// Layout state
const useMobileLayout = breakpoints.smaller("sm");
const selectedView = ref<ViewType>(
(window.localStorage.getItem("learningPathView") as ViewType) || "path"
);
onMounted(async () => {
log.debug("LearningPathPage mounted");
try {
await learningPathStore.loadLearningPath(props.courseSlug + "-lp");
} catch (error) {
log.error(error);
}
});
const learningPath = computed(() => {
if (userStore.loggedIn && learningPathStore.state.learningPaths.size > 0) {
const learningPathKey = `${props.courseSlug}-lp-${userStore.id}`;
return learningPathStore.state.learningPaths.get(learningPathKey);
}
return undefined;
});
const circlesCount = computed(() => {
if (learningPath.value) {
return learningPath.value.circles.length;
}
return 0;
});
const inProgressCirclesCount = computed(() => {
if (learningPath.value) {
return learningPath.value.circles.filter(
(circle) =>
circle.learningSequences.filter((ls) =>
circle.someFinishedInLearningSequence(ls.translation_key)
).length
).length;
}
return 0;
});
const changeViewType = (viewType: ViewType) => {
selectedView.value = viewType;
window.localStorage.setItem("learningPathView", viewType);
};
</script>
<template>
<div class="flex flex-col">
<!-- Top -->
<div class="flex flex-row justify-between space-x-8 bg-gray-200 p-6 sm:p-12">
<!-- Left -->
<div class="flex w-1/2 flex-col justify-between">
<div>
<p class="font-bold">
{{ $t("learningPathPage.welcomeBack") }}
</p>
<h2 data-cy="learning-path-title">
{{ learningPath?.title }}
</h2>
</div>
<CircleProgress
:all-count="circlesCount"
:in-progress-count="inProgressCirclesCount"
></CircleProgress>
</div>
<!-- Right -->
<div v-if="!useMobileLayout" class="flex-grow">
<div class="text-bold pb-3">
{{ $t("learningPathPage.nextDueDates") }}
</div>
<DueDatesShortList :max-count="2" :show-top-border="true"></DueDatesShortList>
</div>
</div>
<!-- Bottom -->
<div class="bg-white">
<div class="flex flex-col justify-between px-6 sm:flex-row sm:px-12">
<!-- Topics -->
<div
v-if="selectedView == 'path'"
class="order-2 pb-8 sm:order-1 sm:pb-0 sm:pt-4"
>
<LearningPathTopics :topics="learningPath?.topics ?? []"></LearningPathTopics>
</div>
<div v-else class="flex-grow"></div>
<!-- View switch -->
<LearningPathViewSwitch
class="order-1 py-8 sm:order-2 sm:py-0 sm:pt-4"
:initial-view="selectedView"
@select-view="changeViewType($event)"
></LearningPathViewSwitch>
</div>
<!-- Path view -->
<div v-if="selectedView == 'path'" class="flex flex-col" data-cy="lp-path-view">
<LearningPathPathView
:learning-path="learningPath"
:use-mobile-layout="useMobileLayout"
></LearningPathPathView>
</div>
<!-- List view -->
<div
v-if="selectedView == 'list'"
class="flex flex-col pl-6 sm:pl-24"
data-cy="lp-list-view"
>
<LearningPathListView :learning-path="learningPath"></LearningPathListView>
</div>
<div
v-if="useMobileLayout"
class="p-6"
:class="useMobileLayout ? 'bg-gray-200' : ''"
>
<!--<LearningPathAppointmentsMock></LearningPathAppointmentsMock>-->
</div>
</div>
</div>
</template>