Add subpages and subnavigation to cockpit page
This commit is contained in:
parent
bc2dd2ba6e
commit
3f5d837db9
|
|
@ -0,0 +1,112 @@
|
|||
<script setup lang="ts">
|
||||
import SubmissionsOverview from "@/components/cockpit/SubmissionsOverview.vue";
|
||||
import UserStatusCount from "@/components/cockpit/UserStatusCount.vue";
|
||||
import CourseSessionDueDatesList from "@/components/dueDates/CourseSessionDueDatesList.vue";
|
||||
import LearningPathDiagram from "@/components/learningPath/LearningPathDiagram.vue";
|
||||
import ItDropdownSelect from "@/components/ui/ItDropdownSelect.vue";
|
||||
import ItPersonRow from "@/components/ui/ItPersonRow.vue";
|
||||
import { useCourseSessionDetailQuery, useCurrentCourseSession } from "@/composables";
|
||||
import { useExpertCockpitStore } from "@/stores/expertCockpit";
|
||||
import AttendanceOverview from "./AttendanceOverview.vue";
|
||||
|
||||
const expertCockpitStore = useExpertCockpitStore();
|
||||
const courseSession = useCurrentCourseSession();
|
||||
const courseSessionDetailResult = useCourseSessionDetailQuery();
|
||||
|
||||
const props = defineProps<{
|
||||
courseSlug: string;
|
||||
}>();
|
||||
</script>
|
||||
<template>
|
||||
<div v-if="expertCockpitStore.circles?.length">
|
||||
<div v-if="expertCockpitStore.currentCircle" class="container-large">
|
||||
<div class="mb-9 flex flex-col lg:flex-row lg:items-center lg:justify-between">
|
||||
<ItDropdownSelect
|
||||
:model-value="expertCockpitStore.currentCircle"
|
||||
class="mt-4 w-full lg:mt-0 lg:w-96"
|
||||
:items="expertCockpitStore.circles"
|
||||
@update:model-value="expertCockpitStore.setCurrentCourseCircleFromEvent"
|
||||
></ItDropdownSelect>
|
||||
</div>
|
||||
<!-- Status -->
|
||||
<div class="mb-4 gap-4">
|
||||
<AttendanceOverview />
|
||||
</div>
|
||||
|
||||
<div class="mb-4 bg-white p-6">
|
||||
<CourseSessionDueDatesList
|
||||
:course-session-id="courseSession.id"
|
||||
:circle-id="expertCockpitStore.currentCircle.id"
|
||||
:max-count="4"
|
||||
></CourseSessionDueDatesList>
|
||||
</div>
|
||||
<SubmissionsOverview
|
||||
:course-session="courseSession"
|
||||
:selected-circle="expertCockpitStore.currentCircle.id"
|
||||
></SubmissionsOverview>
|
||||
<div class="pt-4">
|
||||
<!-- progress -->
|
||||
<div
|
||||
v-if="courseSessionDetailResult.filterMembers().length > 0"
|
||||
class="bg-white p-6"
|
||||
>
|
||||
<h1 class="heading-3 mb-5">{{ $t("cockpit.progress") }}</h1>
|
||||
<ul>
|
||||
<ItPersonRow
|
||||
v-for="csu in courseSessionDetailResult.filterMembers()"
|
||||
:key="csu.user_id"
|
||||
:name="`${csu.first_name} ${csu.last_name}`"
|
||||
:avatar-url="csu.avatar_url"
|
||||
>
|
||||
<template #center>
|
||||
<div
|
||||
class="mt-2 flex w-full flex-col items-center justify-start lg:mt-0 lg:flex-row"
|
||||
>
|
||||
<LearningPathDiagram
|
||||
:course-session-id="courseSession.id"
|
||||
:course-slug="props.courseSlug"
|
||||
:user-id="csu.user_id"
|
||||
:show-circle-slugs="[expertCockpitStore.currentCircle.slug]"
|
||||
diagram-type="singleSmall"
|
||||
class="mr-4"
|
||||
></LearningPathDiagram>
|
||||
<p class="lg:min-w-[150px]">
|
||||
{{ expertCockpitStore.currentCircle.title }}
|
||||
</p>
|
||||
<UserStatusCount
|
||||
:course-slug="props.courseSlug"
|
||||
:user-id="csu.user_id"
|
||||
></UserStatusCount>
|
||||
</div>
|
||||
</template>
|
||||
<template #link>
|
||||
<router-link
|
||||
:to="{
|
||||
name: 'profileLearningPath',
|
||||
params: { userId: csu.user_id, courseSlug: props.courseSlug },
|
||||
}"
|
||||
class="link w-full lg:text-right"
|
||||
>
|
||||
{{ $t("general.profileLink") }}
|
||||
</router-link>
|
||||
</template>
|
||||
</ItPersonRow>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="container-large mt-4">
|
||||
<!-- No circle selected -->
|
||||
<span class="text-lg text-orange-600">
|
||||
{{ $t("a.Kein Circle verfügbar oder ausgewählt.") }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="container-large mt-4">
|
||||
<span class="text-lg text-orange-600">
|
||||
<!-- No circle at all (should never happen, mostly
|
||||
for us to reduce confusion why the cockpit is just empty...) -->
|
||||
{{ $t("a.Kein Circle verfügbar oder ausgewählt.") }}
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -1,186 +0,0 @@
|
|||
<script setup lang="ts">
|
||||
import LearningPathDiagram from "@/components/learningPath/LearningPathDiagram.vue";
|
||||
import ItPersonRow from "@/components/ui/ItPersonRow.vue";
|
||||
|
||||
import SubmissionsOverview from "@/components/cockpit/SubmissionsOverview.vue";
|
||||
import UserStatusCount from "@/components/cockpit/UserStatusCount.vue";
|
||||
import CourseSessionDueDatesList from "@/components/dueDates/CourseSessionDueDatesList.vue";
|
||||
import ItDropdownSelect from "@/components/ui/ItDropdownSelect.vue";
|
||||
import { useCourseSessionDetailQuery, useCurrentCourseSession } from "@/composables";
|
||||
import { useExpertCockpitPageData } from "@/pages/cockpit/cockpitPage/composables";
|
||||
import { useExpertCockpitStore } from "@/stores/expertCockpit";
|
||||
import log from "loglevel";
|
||||
|
||||
const props = defineProps<{
|
||||
courseSlug: string;
|
||||
}>();
|
||||
|
||||
log.debug("CockpitIndexPage created", props.courseSlug);
|
||||
|
||||
const { loading } = useExpertCockpitPageData(props.courseSlug);
|
||||
|
||||
const expertCockpitStore = useExpertCockpitStore();
|
||||
const courseSession = useCurrentCourseSession();
|
||||
const courseSessionDetailResult = useCourseSessionDetailQuery();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div v-if="!loading" class="bg-gray-200">
|
||||
<div v-if="expertCockpitStore.circles?.length">
|
||||
<div v-if="expertCockpitStore.currentCircle" class="container-large">
|
||||
<div class="mb-9 flex flex-col lg:flex-row lg:items-center lg:justify-between">
|
||||
<h1>Cockpit</h1>
|
||||
<ItDropdownSelect
|
||||
:model-value="expertCockpitStore.currentCircle"
|
||||
class="mt-4 w-full lg:mt-0 lg:w-96"
|
||||
:items="expertCockpitStore.circles"
|
||||
@update:model-value="expertCockpitStore.setCurrentCourseCircleFromEvent"
|
||||
></ItDropdownSelect>
|
||||
</div>
|
||||
<!-- Status -->
|
||||
<div class="mb-4 gap-4 lg:grid lg:grid-cols-3 lg:grid-rows-none">
|
||||
<div class="my-4 flex flex-col justify-between bg-white p-6 lg:my-0">
|
||||
<div>
|
||||
<h3 class="heading-3 mb-4 flex items-center gap-2">
|
||||
{{ $t("Trainerunterlagen") }}
|
||||
</h3>
|
||||
<div class="mb-4">
|
||||
{{ $t("cockpit.trainerFilesText") }}
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<a
|
||||
href="https://vbvbern.sharepoint.com/sites/myVBV-AFA_K-CI"
|
||||
class="btn-secondary min-w-min"
|
||||
target="_blank"
|
||||
>
|
||||
{{ $t("MS Teams öffnen") }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-if="courseSession.course.configuration.enable_circle_documents"
|
||||
class="my-4 flex flex-col justify-between bg-white p-6 lg:my-0"
|
||||
data-cy="circle-documents"
|
||||
>
|
||||
<div>
|
||||
<h3 class="heading-3 mb-4 flex items-center gap-2">
|
||||
{{ $t("a.Unterlagen für Teilnehmenden") }}
|
||||
</h3>
|
||||
<div class="mb-4">
|
||||
{{ $t("a.Stelle deinen Lernenden zusätzliche Inhalte zur Verfügung.") }}
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<router-link
|
||||
:to="`/course/${props.courseSlug}/cockpit/documents`"
|
||||
class="btn-secondary min-w-min"
|
||||
>
|
||||
{{ $t("a.Zum Unterlagen-Upload") }}
|
||||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
<div class="my-4 flex flex-col justify-between bg-white p-6 lg:my-0">
|
||||
<div>
|
||||
<h3 class="heading-3 mb-4 flex items-center gap-2">
|
||||
{{ $t("a.Anwesenheitskontrolle Präsenzkurse") }}
|
||||
</h3>
|
||||
<div class="mb-4">
|
||||
{{
|
||||
$t(
|
||||
"Hier überprüfst und bestätigst du die Anwesenheit deiner Teilnehmenden."
|
||||
)
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<router-link
|
||||
:to="`/course/${props.courseSlug}/cockpit/attendance`"
|
||||
class="btn-secondary min-w-min"
|
||||
>
|
||||
{{ $t("Anwesenheit prüfen") }}
|
||||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-4 bg-white p-6">
|
||||
<CourseSessionDueDatesList
|
||||
:course-session-id="courseSession.id"
|
||||
:circle-id="expertCockpitStore.currentCircle.id"
|
||||
:max-count="4"
|
||||
></CourseSessionDueDatesList>
|
||||
</div>
|
||||
<SubmissionsOverview
|
||||
:course-session="courseSession"
|
||||
:selected-circle="expertCockpitStore.currentCircle.id"
|
||||
></SubmissionsOverview>
|
||||
<div class="pt-4">
|
||||
<!-- progress -->
|
||||
<div
|
||||
v-if="courseSessionDetailResult.filterMembers().length > 0"
|
||||
class="bg-white p-6"
|
||||
>
|
||||
<h1 class="heading-3 mb-5">{{ $t("cockpit.progress") }}</h1>
|
||||
<ul>
|
||||
<ItPersonRow
|
||||
v-for="csu in courseSessionDetailResult.filterMembers()"
|
||||
:key="csu.user_id"
|
||||
:name="`${csu.first_name} ${csu.last_name}`"
|
||||
:avatar-url="csu.avatar_url"
|
||||
>
|
||||
<template #center>
|
||||
<div
|
||||
class="mt-2 flex w-full flex-col items-center justify-start lg:mt-0 lg:flex-row"
|
||||
>
|
||||
<LearningPathDiagram
|
||||
:course-session-id="courseSession.id"
|
||||
:course-slug="props.courseSlug"
|
||||
:user-id="csu.user_id"
|
||||
:show-circle-slugs="[expertCockpitStore.currentCircle.slug]"
|
||||
diagram-type="singleSmall"
|
||||
class="mr-4"
|
||||
></LearningPathDiagram>
|
||||
<p class="lg:min-w-[150px]">
|
||||
{{ expertCockpitStore.currentCircle.title }}
|
||||
</p>
|
||||
<UserStatusCount
|
||||
:course-slug="props.courseSlug"
|
||||
:user-id="csu.user_id"
|
||||
></UserStatusCount>
|
||||
</div>
|
||||
</template>
|
||||
<template #link>
|
||||
<router-link
|
||||
:to="{
|
||||
name: 'profileLearningPath',
|
||||
params: { userId: csu.user_id, courseSlug: props.courseSlug },
|
||||
}"
|
||||
class="link w-full lg:text-right"
|
||||
>
|
||||
{{ $t("general.profileLink") }}
|
||||
</router-link>
|
||||
</template>
|
||||
</ItPersonRow>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="container-large mt-4">
|
||||
<!-- No circle selected -->
|
||||
<span class="text-lg text-orange-600">
|
||||
{{ $t("a.Kein Circle verfügbar oder ausgewählt.") }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="container-large mt-4">
|
||||
<span class="text-lg text-orange-600">
|
||||
<!-- No circle at all (should never happen, mostly
|
||||
for us to reduce confusion why the cockpit is just empty...) -->
|
||||
{{ $t("a.Kein Circle verfügbar oder ausgewählt.") }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
<script setup lang="ts">
|
||||
import SubNavigation from "@/components/header/SubNavigation.vue";
|
||||
import { useExpertCockpitPageData } from "@/pages/cockpit/cockpitPage/composables";
|
||||
import { ATTENDANCE_ROUTE, COCKPIT_ROUTE, DOCUMENTS_ROUTE } from "@/router/names";
|
||||
import { useTranslation } from "i18next-vue";
|
||||
import log from "loglevel";
|
||||
|
||||
const props = defineProps<{
|
||||
courseSlug: string;
|
||||
}>();
|
||||
|
||||
log.debug("CockpitIndexPage created", props.courseSlug);
|
||||
|
||||
const { loading } = useExpertCockpitPageData(props.courseSlug);
|
||||
|
||||
const defaultRoute = {
|
||||
name: COCKPIT_ROUTE,
|
||||
};
|
||||
const attendanceRoute = {
|
||||
name: ATTENDANCE_ROUTE,
|
||||
};
|
||||
const documentsRoute = {
|
||||
name: DOCUMENTS_ROUTE,
|
||||
};
|
||||
|
||||
const { t } = useTranslation();
|
||||
|
||||
const items = [
|
||||
{ id: 1, name: t("a.Übersicht"), route: defaultRoute },
|
||||
{ id: 2, name: t("a.Teilnehmer"), route: attendanceRoute },
|
||||
{ id: 3, name: t("a.Unterlagen"), route: documentsRoute },
|
||||
|
||||
{
|
||||
id: 4,
|
||||
name: "Vorschau Teilnehmer",
|
||||
route: "https://iterativ.ch",
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: "MS Teams",
|
||||
route: "https://vbvbern.sharepoint.com/sites/myVBV-AFA_K-CI",
|
||||
},
|
||||
];
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div v-if="!loading" class="bg-gray-200">
|
||||
<SubNavigation :items="items" />
|
||||
<router-view />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
|
|
@ -56,17 +56,6 @@ const items: SubNavEntry[] = [
|
|||
route: selfEvaluationRoute,
|
||||
},
|
||||
{ id: 3, name: t("a.Handlungskompetenzen"), route: competencesRoute },
|
||||
|
||||
{
|
||||
id: 4,
|
||||
name: "MS Teams",
|
||||
route: "https://iterativ.ch",
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: "Vorschau Teilnehmer",
|
||||
route: "https://iterativ.ch",
|
||||
},
|
||||
];
|
||||
</script>
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue