368 lines
11 KiB
Vue
368 lines
11 KiB
Vue
<script setup lang="ts">
|
|
import LoadingSpinner from "@/components/ui/LoadingSpinner.vue";
|
|
import log from "loglevel";
|
|
import { useDashboardPersons } from "@/composables";
|
|
import ItDropdownSelect from "@/components/ui/ItDropdownSelect.vue";
|
|
import { computed, ref, watch } from "vue";
|
|
import { useTranslation } from "i18next-vue";
|
|
import _ from "lodash";
|
|
import type { DashboardPersonCourseSessionType } from "@/services/dashboard";
|
|
import { useRouteQuery } from "@vueuse/router";
|
|
|
|
log.debug("DashboardPersonsPage created");
|
|
|
|
const UNFILTERED = Number.MAX_SAFE_INTEGER.toString();
|
|
|
|
type MenuItem = {
|
|
id: string;
|
|
name: string;
|
|
};
|
|
|
|
const { t } = useTranslation();
|
|
|
|
const { loading, dashboardPersons } = useDashboardPersons();
|
|
|
|
const courses = computed(() => {
|
|
return [
|
|
{
|
|
id: UNFILTERED,
|
|
name: `${t("Lehrgang")}: ${t("a.Alle")}`,
|
|
},
|
|
..._(dashboardPersons.value)
|
|
.flatMap((person) => person.course_sessions)
|
|
.map((cs) => {
|
|
return { name: cs.course_title, id: cs.course_id };
|
|
})
|
|
.uniqBy("id")
|
|
.orderBy("name")
|
|
.value(),
|
|
];
|
|
});
|
|
const selectedCourse = ref<MenuItem>(courses.value[0]);
|
|
const selectedCourseRouteQuery = useRouteQuery("course", UNFILTERED, {
|
|
mode: "replace",
|
|
});
|
|
|
|
watch(selectedCourse, () => {
|
|
selectedCourseRouteQuery.value = selectedCourse.value.id;
|
|
});
|
|
watch(courses, () => {
|
|
if (selectedCourseRouteQuery.value !== UNFILTERED) {
|
|
selectedCourse.value =
|
|
courses.value.find((course) => course.id === selectedCourseRouteQuery.value) ||
|
|
courses.value[0];
|
|
}
|
|
});
|
|
|
|
const regions = computed(() => {
|
|
let values = _(dashboardPersons.value)
|
|
.flatMap((person) => person.course_sessions)
|
|
.map((cs) => {
|
|
return Object.assign({}, cs, { name: cs.region, id: cs.region });
|
|
})
|
|
.filter((cs) => !!cs.region)
|
|
.uniqBy("id")
|
|
.orderBy("name")
|
|
.value();
|
|
|
|
// filter by selected course
|
|
if (selectedCourse.value.id !== UNFILTERED) {
|
|
values = values.filter((cs) => cs.course_id === selectedCourse.value.id);
|
|
}
|
|
|
|
return [
|
|
{
|
|
id: UNFILTERED,
|
|
name: `${t("Region")}: ${t("a.Alle")}`,
|
|
},
|
|
...values,
|
|
];
|
|
});
|
|
const selectedRegion = ref<MenuItem>(regions.value[0]);
|
|
|
|
const courseSessions = computed(() => {
|
|
let values = _(dashboardPersons.value)
|
|
.flatMap((person) => person.course_sessions)
|
|
.map((cs) => {
|
|
return Object.assign({}, cs, { name: cs.session_title, id: cs.id });
|
|
})
|
|
.uniqBy("id")
|
|
.orderBy("name")
|
|
.value();
|
|
|
|
// filter by selected course
|
|
if (selectedCourse.value.id !== UNFILTERED) {
|
|
values = values.filter((cs) => cs.course_id === selectedCourse.value.id);
|
|
}
|
|
// filter by selected region
|
|
if (selectedRegion.value.id !== UNFILTERED) {
|
|
values = values.filter((cs) => cs.region === selectedRegion.value.id);
|
|
}
|
|
|
|
return [
|
|
{
|
|
id: UNFILTERED,
|
|
name: `${t("Durchführung")}: ${t("a.Alle")}`,
|
|
},
|
|
...values,
|
|
];
|
|
});
|
|
const selectedSession = ref<MenuItem>(courseSessions.value[0]);
|
|
|
|
const generations = computed(() => {
|
|
const values = _(dashboardPersons.value)
|
|
.flatMap((person) => person.course_sessions)
|
|
.map((cs) => {
|
|
return Object.assign({}, cs, { name: cs.generation, id: cs.generation });
|
|
})
|
|
.filter((cs) => !!cs.generation)
|
|
.uniqBy("id")
|
|
.orderBy("name")
|
|
.value();
|
|
|
|
return [
|
|
{
|
|
id: UNFILTERED,
|
|
name: `${t("Generation")}: ${t("a.Alle")}`,
|
|
},
|
|
...values,
|
|
];
|
|
});
|
|
const selectedGeneration = ref<MenuItem>(generations.value[0]);
|
|
|
|
const roles = computed(() => {
|
|
const values = _(dashboardPersons.value)
|
|
.flatMap((person) => person.course_sessions)
|
|
.map((cs) => {
|
|
return Object.assign({}, cs, {
|
|
name: cs.user_role_display,
|
|
id: cs.user_role_display,
|
|
});
|
|
})
|
|
.uniqBy("id")
|
|
.orderBy("name")
|
|
.value();
|
|
|
|
return [
|
|
{
|
|
id: "",
|
|
name: `${t("Rolle")}: ${t("a.Alle")}`,
|
|
},
|
|
...values,
|
|
];
|
|
});
|
|
const selectedRole = ref<MenuItem>(roles.value[0]);
|
|
|
|
const filteredPersons = computed(() => {
|
|
return _.orderBy(
|
|
dashboardPersons.value
|
|
.filter((person) => {
|
|
if (selectedCourse.value.id === UNFILTERED) {
|
|
return true;
|
|
}
|
|
return person.course_sessions.some(
|
|
(cs) => cs.course_id === selectedCourse.value.id
|
|
);
|
|
})
|
|
.filter((person) => {
|
|
if (selectedSession.value.id === UNFILTERED) {
|
|
return true;
|
|
}
|
|
return person.course_sessions.some((cs) => cs.id === selectedSession.value.id);
|
|
})
|
|
.filter((person) => {
|
|
if (selectedRegion.value.id === UNFILTERED) {
|
|
return true;
|
|
}
|
|
return person.course_sessions.some(
|
|
(cs) => cs.region === selectedRegion.value.id
|
|
);
|
|
})
|
|
.filter((person) => {
|
|
if (selectedGeneration.value.id === UNFILTERED) {
|
|
return true;
|
|
}
|
|
return person.course_sessions.some(
|
|
(cs) => cs.generation === selectedGeneration.value.id
|
|
);
|
|
})
|
|
.filter((person) => {
|
|
if (selectedRole.value.id === "") {
|
|
return true;
|
|
}
|
|
return person.course_sessions.some(
|
|
(cs) => cs.user_role_display === selectedRole.value.id
|
|
);
|
|
}),
|
|
["last_name", "first_name"]
|
|
);
|
|
});
|
|
|
|
const filtersVisible = computed(() => {
|
|
return (
|
|
courses.value.length > 2 ||
|
|
courseSessions.value.length > 2 ||
|
|
regions.value.length > 2 ||
|
|
generations.value.length > 2 ||
|
|
roles.value.length > 2
|
|
);
|
|
});
|
|
|
|
function personRoleDisplayValue(personCourseSession: DashboardPersonCourseSessionType) {
|
|
if (
|
|
["SUPERVISOR", "EXPERT", "LEARNING_MENTOR"].includes(personCourseSession.user_role)
|
|
) {
|
|
return personCourseSession.user_role_display;
|
|
}
|
|
|
|
return "";
|
|
}
|
|
|
|
watch(selectedCourse, () => {
|
|
selectedRegion.value = regions.value[0];
|
|
});
|
|
|
|
watch(selectedRegion, () => {
|
|
selectedSession.value = courseSessions.value[0];
|
|
selectedGeneration.value = generations.value[0];
|
|
selectedRole.value = roles.value[0];
|
|
});
|
|
</script>
|
|
|
|
<template>
|
|
<div>
|
|
<div v-if="loading" class="m-8 flex justify-center">
|
|
<LoadingSpinner />
|
|
</div>
|
|
<div v-else class="bg-gray-200">
|
|
<div class="container-large">
|
|
<router-link
|
|
:to="`/`"
|
|
class="btn-text inline-flex items-center p-0"
|
|
data-cy="back-to-learning-path-button"
|
|
>
|
|
<it-icon-arrow-left class="-ml-1 mr-1 h-5 w-5"></it-icon-arrow-left>
|
|
<span class="inline">{{ $t("general.back") }}</span>
|
|
</router-link>
|
|
<h2 class="my-4">{{ $t("a.Personen") }}</h2>
|
|
<div class="bg-white px-4 py-2">
|
|
<section
|
|
v-if="filtersVisible"
|
|
class="flex flex-col space-x-0 border-b bg-white lg:flex-row lg:space-x-3"
|
|
>
|
|
<ItDropdownSelect
|
|
v-if="courses.length > 2"
|
|
v-model="selectedCourse"
|
|
data-cy="select-course"
|
|
:items="courses"
|
|
borderless
|
|
></ItDropdownSelect>
|
|
|
|
<ItDropdownSelect
|
|
v-if="regions.length > 2"
|
|
v-model="selectedRegion"
|
|
data-cy="select-region"
|
|
:items="regions"
|
|
borderless
|
|
></ItDropdownSelect>
|
|
|
|
<ItDropdownSelect
|
|
v-if="courseSessions.length > 2"
|
|
v-model="selectedSession"
|
|
data-cy="select-course"
|
|
:items="courseSessions"
|
|
borderless
|
|
></ItDropdownSelect>
|
|
|
|
<ItDropdownSelect
|
|
v-if="generations.length > 2"
|
|
v-model="selectedGeneration"
|
|
data-cy="select-generation"
|
|
:items="generations"
|
|
borderless
|
|
></ItDropdownSelect>
|
|
|
|
<ItDropdownSelect
|
|
v-if="roles.length > 2"
|
|
v-model="selectedRole"
|
|
data-cy="select-role"
|
|
:items="roles"
|
|
borderless
|
|
></ItDropdownSelect>
|
|
</section>
|
|
<div
|
|
v-for="person in filteredPersons"
|
|
:key="person.user_id"
|
|
data-cy="person"
|
|
class="flex flex-col justify-between gap-4 border-b p-2 last:border-b-0 md:flex-row md:items-center md:justify-between md:gap-16"
|
|
>
|
|
<div class="w-full flex-auto md:w-1/3">
|
|
<div class="flex items-center space-x-2">
|
|
<img
|
|
class="inline-block h-11 w-11 rounded-full"
|
|
:src="
|
|
person.avatar_url_small ||
|
|
'/static/avatars/myvbv-default-avatar.png'
|
|
"
|
|
:alt="`${person.first_name} ${person.last_name}`"
|
|
/>
|
|
<div>
|
|
<div class="text-bold">
|
|
{{ person.first_name }}
|
|
{{ person.last_name }}
|
|
</div>
|
|
<div class="text-gray-900">{{ person.email }}</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="w-full flex-auto items-start md:w-2/3">
|
|
<div
|
|
v-for="cs in person.course_sessions"
|
|
:key="cs.id"
|
|
class="w-full border-b pb-2 pt-2 first:pt-0 last:border-b-0 last:pb-0"
|
|
>
|
|
<div class="flex flex-col md:flex-row md:items-center">
|
|
<div class="md:w-1/2">
|
|
<div class="text-gray-900">{{ cs.course_title }}</div>
|
|
<div v-if="cs.is_uk">{{ cs.session_title }}</div>
|
|
</div>
|
|
<div class="md:w-1/4">
|
|
<!-- <div>{{ cs.user_role }}</div>-->
|
|
<!-- <div>my role: {{ cs.my_role }}</div>-->
|
|
{{ personRoleDisplayValue(cs) }}
|
|
</div>
|
|
<div class="md:w-1/4 md:text-right">
|
|
<div
|
|
v-if="
|
|
(['SUPERVISOR', 'EXPERT'].includes(cs.my_role) &&
|
|
cs.user_role === 'MEMBER') ||
|
|
(cs.my_role === 'LEARNING_MENTOR' &&
|
|
cs.user_role === 'LEARNING_MENTEE')
|
|
"
|
|
>
|
|
<router-link
|
|
:to="{
|
|
name: 'profileLearningPath',
|
|
params: {
|
|
userId: person.user_id,
|
|
courseSlug: cs.course_slug,
|
|
},
|
|
query: { courseSessionId: cs.id },
|
|
}"
|
|
class="link w-full lg:text-right"
|
|
>
|
|
{{ $t("a.Profil anzeigen") }}
|
|
</router-link>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|