731 lines
20 KiB
TypeScript
731 lines
20 KiB
TypeScript
import { useCSRFFetch } from "@/fetchHelpers";
|
|
import type { CourseStatisticsType } from "@/gql/graphql";
|
|
import { graphqlClient } from "@/graphql/client";
|
|
import {
|
|
COMPETENCE_NAVI_CERTIFICATE_FOR_USER_QUERY,
|
|
COMPETENCE_NAVI_CERTIFICATE_QUERY,
|
|
COURSE_QUERY,
|
|
COURSE_SESSION_DETAIL_QUERY,
|
|
} from "@/graphql/queries";
|
|
import {
|
|
circleFlatChildren,
|
|
circleFlatLearningContents,
|
|
circleFlatLearningUnits,
|
|
someFinishedInLearningSequence,
|
|
} from "@/services/circle";
|
|
import type {
|
|
DashboardDueDate,
|
|
DashboardPersonRoleType,
|
|
DashboardPersonType,
|
|
} from "@/services/dashboard";
|
|
import {
|
|
courseIdForCourseSlug,
|
|
fetchDashboardDueDates,
|
|
fetchDashboardPersons,
|
|
fetchStatisticData,
|
|
} from "@/services/dashboard";
|
|
import { presignUpload, uploadFile } from "@/services/files";
|
|
import { useCompletionStore } from "@/stores/completion";
|
|
import { useCourseSessionsStore } from "@/stores/courseSessions";
|
|
import { useDashboardStore } from "@/stores/dashboard";
|
|
import { useUserStore } from "@/stores/user";
|
|
import type {
|
|
ActionCompetence,
|
|
CircleType,
|
|
Course,
|
|
CourseCompletion,
|
|
CourseCompletionStatus,
|
|
CourseSession,
|
|
CourseSessionDetail,
|
|
DashboardPersonsPageMode,
|
|
LearningContentWithCompletion,
|
|
LearningMentor,
|
|
LearningPathType,
|
|
LearningUnitPerformanceCriteria,
|
|
PerformanceCriteria,
|
|
} from "@/types";
|
|
import { useQuery } from "@urql/vue";
|
|
import dayjs from "dayjs";
|
|
import { t } from "i18next";
|
|
import orderBy from "lodash/orderBy";
|
|
import log from "loglevel";
|
|
import type { ComputedRef, Ref } from "vue";
|
|
import { computed, onMounted, ref, watchEffect } from "vue";
|
|
|
|
export function useCurrentCourseSession() {
|
|
/**
|
|
* We often need the current course session in our components.
|
|
* With this composable we can get it easily.
|
|
*/
|
|
const store = useCourseSessionsStore();
|
|
|
|
const result: ComputedRef<CourseSession> = computed(
|
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
() => {
|
|
if (!store.currentCourseSession) {
|
|
log.error(
|
|
"currentCourseSession is only defined in pages with :courseSlug in the route"
|
|
);
|
|
throw new Error(
|
|
`currentCourseSession is not defined in the store.
|
|
It is only defined in pages with :courseSlug in the route`
|
|
);
|
|
}
|
|
return store.currentCourseSession;
|
|
}
|
|
);
|
|
return result;
|
|
}
|
|
|
|
export function useCourseSessionDetailQuery(courSessionId?: string) {
|
|
if (!courSessionId) {
|
|
courSessionId = useCurrentCourseSession().value.id;
|
|
}
|
|
const queryResult = useQuery({
|
|
query: COURSE_SESSION_DETAIL_QUERY,
|
|
variables: {
|
|
courseSessionId: courSessionId,
|
|
},
|
|
});
|
|
|
|
const courseSessionDetail = computed(() => {
|
|
return queryResult.data.value?.course_session as CourseSessionDetail | undefined;
|
|
});
|
|
|
|
function findAssignmentByAssignmentId(assignmentId: string) {
|
|
return (courseSessionDetail.value?.assignments ?? []).find((a) => {
|
|
return a.learning_content?.content_assignment?.id === assignmentId;
|
|
});
|
|
}
|
|
|
|
function findAssignment(learningContentId: string) {
|
|
return (courseSessionDetail.value?.assignments ?? []).find((a) => {
|
|
return a.learning_content?.id === learningContentId;
|
|
});
|
|
}
|
|
|
|
function findEdoniqTest(learningContentId: string) {
|
|
return (courseSessionDetail.value?.edoniq_tests ?? []).find((e) => {
|
|
return e.learning_content?.id === learningContentId;
|
|
});
|
|
}
|
|
|
|
function findAttendanceCourse(learningContentId: string) {
|
|
return (courseSessionDetail.value?.attendance_courses ?? []).find((e) => {
|
|
return e.learning_content?.id === learningContentId;
|
|
});
|
|
}
|
|
|
|
function findUser(userId: string) {
|
|
return (courseSessionDetail.value?.users ?? []).find((u) => {
|
|
return u.user_id === userId;
|
|
});
|
|
}
|
|
|
|
function findCurrentUser() {
|
|
const userStore = useUserStore();
|
|
const userId = userStore.id;
|
|
return findUser(userId);
|
|
}
|
|
|
|
function filterMembers() {
|
|
return (courseSessionDetail.value?.users ?? []).filter((u) => {
|
|
return u.role === "MEMBER";
|
|
});
|
|
}
|
|
|
|
function filterCircleExperts(circleSlug: string) {
|
|
return (courseSessionDetail.value?.users ?? []).filter((u) => {
|
|
return u.role === "EXPERT" && u.circles.map((c) => c.slug).includes(circleSlug);
|
|
});
|
|
}
|
|
|
|
const dataLoaded = ref(false);
|
|
|
|
function waitForData() {
|
|
return new Promise((resolve) => {
|
|
watchEffect(() => {
|
|
if (queryResult.data.value) {
|
|
dataLoaded.value = true;
|
|
resolve(queryResult.data.value);
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
return {
|
|
...queryResult,
|
|
courseSessionDetail,
|
|
waitForData,
|
|
findAssignmentByAssignmentId,
|
|
findAssignment,
|
|
findEdoniqTest,
|
|
findAttendanceCourse,
|
|
findUser,
|
|
findCurrentUser,
|
|
filterMembers,
|
|
filterCircleExperts,
|
|
};
|
|
}
|
|
|
|
export function flatCircles(learningPath: LearningPathType) {
|
|
return learningPath.topics.flatMap((t) => t.circles);
|
|
}
|
|
|
|
export function useCourseData(courseSlug: string) {
|
|
const learningPath = ref<LearningPathType | undefined>(undefined);
|
|
const actionCompetences = ref<ActionCompetence[]>([]);
|
|
const course = ref<Course | undefined>(undefined);
|
|
|
|
// urql.useQuery is not meant to be used programmatically, so we use graphqlClient.query instead
|
|
const resultPromise = graphqlClient
|
|
.query(COURSE_QUERY, { slug: `${courseSlug}` })
|
|
.toPromise();
|
|
|
|
resultPromise.then((result) => {
|
|
if (result.error) {
|
|
log.error(result.error);
|
|
}
|
|
|
|
course.value = result.data?.course as unknown as Course;
|
|
actionCompetences.value = result.data?.course
|
|
?.action_competences as ActionCompetence[];
|
|
learningPath.value = result.data?.course?.learning_path as LearningPathType;
|
|
|
|
// attach circle information to learning contents
|
|
if (learningPath.value) {
|
|
flatCircles(learningPath.value).forEach((circle) => {
|
|
circle.learning_sequences.forEach((ls, lsIndex) => {
|
|
const circleData = {
|
|
id: circle.id,
|
|
slug: circle.slug,
|
|
title: circle.title,
|
|
};
|
|
return ls.learning_units.forEach((lu, luIndex) => {
|
|
lu.circle = Object.assign({}, circleData);
|
|
lu.learning_contents.forEach((lc, lcIndex) => {
|
|
lc.circle = Object.assign({}, circleData);
|
|
lc.continueUrl = ls.frontend_url || circle.frontend_url;
|
|
lc.firstInCircle = lcIndex === 0 && luIndex === 0 && lsIndex === 0;
|
|
lc.parentLearningUnit = {
|
|
id: lu.id,
|
|
slug: lu.slug,
|
|
title: lu.title,
|
|
};
|
|
});
|
|
|
|
lu.performance_criteria.forEach((luPc) => {
|
|
luPc.circle = Object.assign({}, circleData);
|
|
const pc = findPerformanceCriterion(luPc.id);
|
|
if (pc) {
|
|
pc.circle = Object.assign({}, circleData);
|
|
}
|
|
});
|
|
});
|
|
});
|
|
});
|
|
}
|
|
});
|
|
|
|
const circles = computed(() => {
|
|
if (learningPath.value) {
|
|
return flatCircles(learningPath.value);
|
|
}
|
|
return undefined;
|
|
});
|
|
|
|
function findCircle(idOrSlug: string) {
|
|
return (circles.value ?? []).find((c) => {
|
|
return c.id === idOrSlug || c.slug.endsWith(idOrSlug);
|
|
});
|
|
}
|
|
|
|
function findPerformanceCriterion(id: string) {
|
|
return (actionCompetences.value ?? [])
|
|
.flatMap((ac) => {
|
|
return ac.performance_criteria;
|
|
})
|
|
.find((pc) => {
|
|
return pc.id === id;
|
|
}) as PerformanceCriteria | undefined;
|
|
}
|
|
|
|
function findLearningContent(
|
|
learningContentIdOrSlug: string,
|
|
circleIdOrSlug?: string
|
|
) {
|
|
let filteredCircles = circles.value ?? [];
|
|
if (circleIdOrSlug) {
|
|
filteredCircles = filteredCircles.filter((c) => {
|
|
return c.id === circleIdOrSlug || c.slug.endsWith(circleIdOrSlug);
|
|
});
|
|
}
|
|
|
|
return filteredCircles
|
|
.flatMap((c) => {
|
|
return circleFlatLearningContents(c);
|
|
})
|
|
.find((lc) => {
|
|
return (
|
|
lc.id === learningContentIdOrSlug || lc.slug.endsWith(learningContentIdOrSlug)
|
|
);
|
|
});
|
|
}
|
|
|
|
function findLearningUnit(learningUnitIdOrSlug: string, circleIdOrSlug?: string) {
|
|
let filteredCircles = circles.value ?? [];
|
|
if (circleIdOrSlug) {
|
|
filteredCircles = filteredCircles.filter((c) => {
|
|
return c.id === circleIdOrSlug || c.slug.endsWith(circleIdOrSlug);
|
|
});
|
|
}
|
|
|
|
return filteredCircles
|
|
.flatMap((c) => {
|
|
return circleFlatLearningUnits(c);
|
|
})
|
|
.find((lu) => {
|
|
return lu.id === learningUnitIdOrSlug || lu.slug.endsWith(learningUnitIdOrSlug);
|
|
});
|
|
}
|
|
|
|
const flatPerformanceCriteria = computed(() => {
|
|
return (actionCompetences.value ?? []).flatMap((ac) => {
|
|
return ac.performance_criteria;
|
|
}) as PerformanceCriteria[];
|
|
});
|
|
|
|
return {
|
|
resultPromise,
|
|
course,
|
|
learningPath,
|
|
actionCompetences,
|
|
circles,
|
|
findCircle,
|
|
findLearningContent,
|
|
findLearningUnit,
|
|
flatPerformanceCriteria,
|
|
};
|
|
}
|
|
|
|
export function useCourseDataWithCompletion(
|
|
courseSlug?: string,
|
|
userId?: string,
|
|
courseSessionId?: string
|
|
) {
|
|
if (!courseSlug) {
|
|
courseSlug = useCurrentCourseSession().value.course.slug;
|
|
}
|
|
if (!userId) {
|
|
userId = useUserStore().id;
|
|
}
|
|
if (!courseSessionId) {
|
|
courseSessionId = useCurrentCourseSession().value.id;
|
|
}
|
|
|
|
const courseResult = useCourseData(courseSlug);
|
|
const completionStore = useCompletionStore();
|
|
const nextLearningContent = ref<LearningContentWithCompletion | undefined>(undefined);
|
|
const loaded = ref(false);
|
|
|
|
function updateCompletionData() {
|
|
if (userId && courseSessionId) {
|
|
return completionStore.loadCourseSessionCompletionData(courseSessionId, userId);
|
|
}
|
|
return Promise.resolve([]);
|
|
}
|
|
|
|
function _parseCompletionData(completionData: CourseCompletion[]) {
|
|
if (courseResult.circles.value) {
|
|
courseResult.circles.value.forEach((circle) => {
|
|
circleFlatChildren(circle).forEach((lc) => {
|
|
const pageIndex = completionData.findIndex((e) => {
|
|
return e.page_id === lc.id;
|
|
});
|
|
if (pageIndex >= 0) {
|
|
lc.completion_status = completionData[pageIndex].completion_status;
|
|
} else {
|
|
lc.completion_status = "UNKNOWN";
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
if (courseResult.actionCompetences.value) {
|
|
courseResult.actionCompetences.value.forEach((ac) => {
|
|
ac.performance_criteria.forEach((pc) => {
|
|
const pageIndex = completionData.findIndex((e) => {
|
|
return e.page_id === pc.id;
|
|
});
|
|
if (pageIndex >= 0) {
|
|
pc.completion_status = completionData[pageIndex].completion_status;
|
|
} else {
|
|
pc.completion_status = "UNKNOWN";
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
calcNextLearningContent(completionData);
|
|
}
|
|
|
|
function calcNextLearningContent(completionData: CourseCompletion[]) {
|
|
const flatLearningContents = (courseResult.circles.value ?? []).flatMap((c) => {
|
|
return circleFlatLearningContents(c);
|
|
});
|
|
const lastCompleted = findLastCompletedLearningContent(completionData);
|
|
if (lastCompleted) {
|
|
const lastCompletedIndex = flatLearningContents.findIndex((lc) => {
|
|
return lc.id === lastCompleted.id;
|
|
});
|
|
if (flatLearningContents[lastCompletedIndex + 1]) {
|
|
nextLearningContent.value = flatLearningContents[lastCompletedIndex + 1];
|
|
} else {
|
|
nextLearningContent.value = undefined;
|
|
}
|
|
} else {
|
|
nextLearningContent.value = flatLearningContents[0];
|
|
}
|
|
}
|
|
|
|
function findLastCompletedLearningContent(completionData: CourseCompletion[]) {
|
|
const latestCompletion = orderBy(completionData ?? [], ["updated_at"], "desc").find(
|
|
(c: CourseCompletion) => {
|
|
return (
|
|
c.completion_status === "SUCCESS" &&
|
|
c.page_type.startsWith("learnpath.LearningContent")
|
|
);
|
|
}
|
|
);
|
|
if (latestCompletion) {
|
|
return courseResult.findLearningContent(latestCompletion.page_id);
|
|
}
|
|
}
|
|
|
|
async function markCompletion(
|
|
page: LearningContentWithCompletion | LearningUnitPerformanceCriteria,
|
|
completion_status: CourseCompletionStatus = "SUCCESS"
|
|
) {
|
|
if (userId && courseSessionId) {
|
|
page.completion_status = completion_status;
|
|
const completionData = await completionStore.markPage(
|
|
page,
|
|
userId,
|
|
courseSessionId
|
|
);
|
|
_parseCompletionData(completionData);
|
|
}
|
|
}
|
|
|
|
async function _start() {
|
|
return Promise.all([courseResult.resultPromise, updateCompletionData()]).then(
|
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
([_queryResults, completionData]) => {
|
|
_parseCompletionData(completionData);
|
|
loaded.value = true;
|
|
}
|
|
);
|
|
}
|
|
|
|
const resultPromise = _start();
|
|
|
|
return {
|
|
...courseResult,
|
|
loaded,
|
|
resultPromise,
|
|
markCompletion,
|
|
nextLearningContent,
|
|
};
|
|
}
|
|
|
|
export function useCourseStatistics() {
|
|
const dashboardStore = useDashboardStore();
|
|
|
|
const statistics = computed(() => {
|
|
return dashboardStore.currentDashBoardData as CourseStatisticsType;
|
|
});
|
|
|
|
const courseSessionName = (courseSessionId: string) => {
|
|
return statistics.value.course_session_properties.sessions.find(
|
|
(session) => session.id === courseSessionId
|
|
)?.name;
|
|
};
|
|
|
|
const circleMeta = (circleId: string) => {
|
|
return statistics.value.course_session_properties.circles.find(
|
|
(circle) => circle.id === circleId
|
|
);
|
|
};
|
|
|
|
return { courseSessionName, circleMeta };
|
|
}
|
|
|
|
export function useFileUpload() {
|
|
const error = ref(false);
|
|
const loading = ref(false);
|
|
const fileInfo = ref({} as { id: string; name: string; url: string });
|
|
|
|
async function upload(e: Event) {
|
|
const { files } = e.target as HTMLInputElement;
|
|
if (!files?.length) return;
|
|
|
|
try {
|
|
error.value = false;
|
|
loading.value = true;
|
|
const file = files[0];
|
|
const presignData = await presignUpload(file);
|
|
await uploadFile(presignData.pre_sign, file);
|
|
fileInfo.value = presignData.file_info;
|
|
} catch (e) {
|
|
console.error(e);
|
|
error.value = true;
|
|
} finally {
|
|
loading.value = false;
|
|
}
|
|
}
|
|
|
|
return { upload, error, loading, fileInfo };
|
|
}
|
|
|
|
export function useMyLearningMentors() {
|
|
const learningMentors = ref<LearningMentor[]>([]);
|
|
const currentCourseSessionId = useCurrentCourseSession().value.id;
|
|
const loading = ref(false);
|
|
|
|
const fetchMentors = async () => {
|
|
loading.value = true;
|
|
const { data } = await useCSRFFetch(
|
|
`/api/mentor/${currentCourseSessionId}/mentors`
|
|
).json();
|
|
learningMentors.value = data.value;
|
|
loading.value = false;
|
|
};
|
|
|
|
onMounted(fetchMentors);
|
|
|
|
return {
|
|
learningMentors,
|
|
loading,
|
|
};
|
|
}
|
|
|
|
export function getVvRoleDisplay(role: DashboardPersonRoleType) {
|
|
switch (role) {
|
|
case "LEARNING_MENTOR":
|
|
return t("a.Lernbegleitung");
|
|
case "LEARNING_MENTEE":
|
|
return t("a.Teilnehmer");
|
|
case "EXPERT":
|
|
return t("a.Experte");
|
|
case "MEMBER":
|
|
return t("a.Teilnehmer");
|
|
case "SUPERVISOR":
|
|
return t("a.Regionenleiter");
|
|
default:
|
|
return role;
|
|
}
|
|
}
|
|
|
|
export function getUkRoleDisplay(role: DashboardPersonRoleType) {
|
|
switch (role) {
|
|
case "LEARNING_MENTOR":
|
|
return t("a.Praxisbildner");
|
|
case "LEARNING_MENTEE":
|
|
return t("a.Teilnehmer");
|
|
case "EXPERT":
|
|
return t("a.Trainer");
|
|
case "MEMBER":
|
|
return t("a.Teilnehmer");
|
|
case "SUPERVISOR":
|
|
return t("a.Regionenleiter");
|
|
default:
|
|
return role;
|
|
}
|
|
}
|
|
|
|
export function useDashboardPersonsDueDates(
|
|
mode: DashboardPersonsPageMode = "default"
|
|
) {
|
|
const dashboardPersons = ref<DashboardPersonType[]>([]);
|
|
const dashboardDueDates = ref<DashboardDueDate[]>([]);
|
|
const loading = ref(false);
|
|
|
|
// due dates from today to future
|
|
const currentDueDates = ref<DashboardDueDate[]>([]);
|
|
|
|
const fetchData = async () => {
|
|
loading.value = true;
|
|
try {
|
|
const [persons, dueDates] = await Promise.all([
|
|
fetchDashboardPersons(mode),
|
|
fetchDashboardDueDates(),
|
|
]);
|
|
dashboardPersons.value = persons;
|
|
|
|
// attach role name to persons
|
|
dashboardPersons.value.forEach((person) => {
|
|
person.course_sessions.forEach((cs) => {
|
|
if (cs.is_uk) {
|
|
cs.my_role_display = getUkRoleDisplay(cs.my_role);
|
|
cs.user_role_display = getUkRoleDisplay(cs.user_role);
|
|
} else if (cs.is_vv) {
|
|
cs.my_role_display = getVvRoleDisplay(cs.my_role);
|
|
cs.user_role_display = getVvRoleDisplay(cs.user_role);
|
|
} else {
|
|
cs.my_role_display = "";
|
|
cs.user_role_display = "";
|
|
}
|
|
});
|
|
});
|
|
|
|
dashboardDueDates.value = dueDates.map((dueDate) => {
|
|
const dateType = t(dueDate.date_type_translation_key);
|
|
const assignmentType = t(dueDate.assignment_type_translation_key);
|
|
dueDate.translatedType = dateType;
|
|
if (assignmentType) {
|
|
dueDate.translatedType += " " + assignmentType;
|
|
}
|
|
return dueDate;
|
|
});
|
|
|
|
currentDueDates.value = dashboardDueDates.value.filter((dueDate) => {
|
|
let refDate = dayjs(dueDate.start);
|
|
if (dueDate.end) {
|
|
refDate = dayjs(dueDate.end);
|
|
}
|
|
|
|
return refDate >= dayjs().startOf("day");
|
|
});
|
|
|
|
// attach `LEARNING_MENTEE` to due dates for `LEARNING_MENTOR` persons
|
|
currentDueDates.value.forEach((dueDate) => {
|
|
if (dueDate.course_session.my_role === "LEARNING_MENTOR") {
|
|
dueDate.persons = dashboardPersons.value.filter((person) => {
|
|
if (
|
|
person.course_sessions
|
|
.map((cs) => cs.id)
|
|
.includes(dueDate.course_session.id)
|
|
) {
|
|
return person.course_sessions.some(
|
|
(cs) => cs.user_role === "LEARNING_MENTEE"
|
|
);
|
|
}
|
|
});
|
|
}
|
|
});
|
|
} catch (error) {
|
|
console.error("Error fetching data:", error);
|
|
} finally {
|
|
loading.value = false;
|
|
}
|
|
};
|
|
|
|
onMounted(fetchData);
|
|
|
|
return {
|
|
dashboardPersons,
|
|
dashboardDueDates,
|
|
currentDueDates,
|
|
loading,
|
|
};
|
|
}
|
|
|
|
export function useCourseCircleProgress(circles: Ref<CircleType[] | undefined>) {
|
|
const inProgressCirclesCount = computed(() => {
|
|
if (circles.value?.length) {
|
|
return circles.value.filter(
|
|
(circle) =>
|
|
circle.learning_sequences.filter((ls) => someFinishedInLearningSequence(ls))
|
|
.length
|
|
).length;
|
|
}
|
|
return 0;
|
|
});
|
|
|
|
const circlesCount = computed(() => {
|
|
return circles.value?.length ?? 0;
|
|
});
|
|
|
|
return { inProgressCirclesCount, circlesCount };
|
|
}
|
|
|
|
export function useCourseStatisticsv2(courseSlug: string) {
|
|
const dashboardStore = useDashboardStore();
|
|
const courseStatistics = ref<CourseStatisticsType | null>(null);
|
|
const loading = ref(false);
|
|
|
|
const fetchData = async () => {
|
|
loading.value = true;
|
|
await dashboardStore.loadDashboardDetails();
|
|
const courseId = courseIdForCourseSlug(
|
|
dashboardStore.dashboardConfigsv2,
|
|
courseSlug
|
|
);
|
|
try {
|
|
if (courseId) {
|
|
courseStatistics.value = await fetchStatisticData(courseId);
|
|
}
|
|
} finally {
|
|
loading.value = false;
|
|
}
|
|
};
|
|
|
|
const courseSessionName = (courseSessionId: string) => {
|
|
return courseStatistics?.value?.course_session_properties?.sessions.find(
|
|
(session) => session.id === courseSessionId
|
|
)?.name;
|
|
};
|
|
|
|
const circleMeta = (circleId: string) => {
|
|
return courseStatistics?.value?.course_session_properties.circles.find(
|
|
(circle) => circle.id === circleId
|
|
);
|
|
};
|
|
|
|
onMounted(fetchData);
|
|
|
|
return {
|
|
courseStatistics,
|
|
loading,
|
|
courseSessionName,
|
|
circleMeta,
|
|
};
|
|
}
|
|
|
|
export function useCertificateQuery(userId: string | undefined, courseSlug: string) {
|
|
const certificatesQuery = (() => {
|
|
const courseSession = useCurrentCourseSession();
|
|
if (userId) {
|
|
return useQuery({
|
|
query: COMPETENCE_NAVI_CERTIFICATE_FOR_USER_QUERY,
|
|
variables: {
|
|
courseSlug: courseSlug,
|
|
courseSessionId: courseSession.value.id,
|
|
userId: userId,
|
|
},
|
|
});
|
|
} else {
|
|
return useQuery({
|
|
query: COMPETENCE_NAVI_CERTIFICATE_QUERY,
|
|
variables: {
|
|
courseSlug: courseSlug,
|
|
courseSessionId: courseSession.value.id,
|
|
},
|
|
});
|
|
}
|
|
})();
|
|
|
|
return { certificatesQuery };
|
|
}
|
|
|
|
export function useEvaluationWithFeedback() {
|
|
const currentCourseSession = useCurrentCourseSession();
|
|
const hasFeedback = computed(
|
|
() =>
|
|
currentCourseSession.value.course.configuration.enable_learning_mentor &&
|
|
currentCourseSession.value.course.configuration.is_vv
|
|
);
|
|
|
|
return { hasFeedback };
|
|
}
|