feat: dashboard store
This commit is contained in:
parent
e55cb31e9f
commit
0b25e8f72b
|
|
@ -23,7 +23,7 @@ const documents = {
|
||||||
"\n query courseQuery($slug: String!) {\n course(slug: $slug) {\n id\n title\n slug\n category_name\n action_competences {\n competence_id\n ...CoursePageFields\n performance_criteria {\n competence_id\n learning_unit {\n id\n slug\n evaluate_url\n }\n ...CoursePageFields\n }\n }\n learning_path {\n ...CoursePageFields\n topics {\n is_visible\n ...CoursePageFields\n circles {\n description\n goals\n ...CoursePageFields\n learning_sequences {\n icon\n ...CoursePageFields\n learning_units {\n evaluate_url\n ...CoursePageFields\n performance_criteria {\n ...CoursePageFields\n }\n learning_contents {\n can_user_self_toggle_course_completion\n content_url\n minutes\n description\n ...CoursePageFields\n ... on LearningContentAssignmentObjectType {\n assignment_type\n content_assignment {\n id\n }\n competence_certificate {\n ...CoursePageFields\n }\n }\n ... on LearningContentEdoniqTestObjectType {\n checkbox_text\n has_extended_time_test\n content_assignment {\n id\n }\n competence_certificate {\n ...CoursePageFields\n }\n }\n ... on LearningContentRichTextObjectType {\n text\n }\n }\n }\n }\n }\n }\n }\n }\n }\n": types.CourseQueryDocument,
|
"\n query courseQuery($slug: String!) {\n course(slug: $slug) {\n id\n title\n slug\n category_name\n action_competences {\n competence_id\n ...CoursePageFields\n performance_criteria {\n competence_id\n learning_unit {\n id\n slug\n evaluate_url\n }\n ...CoursePageFields\n }\n }\n learning_path {\n ...CoursePageFields\n topics {\n is_visible\n ...CoursePageFields\n circles {\n description\n goals\n ...CoursePageFields\n learning_sequences {\n icon\n ...CoursePageFields\n learning_units {\n evaluate_url\n ...CoursePageFields\n performance_criteria {\n ...CoursePageFields\n }\n learning_contents {\n can_user_self_toggle_course_completion\n content_url\n minutes\n description\n ...CoursePageFields\n ... on LearningContentAssignmentObjectType {\n assignment_type\n content_assignment {\n id\n }\n competence_certificate {\n ...CoursePageFields\n }\n }\n ... on LearningContentEdoniqTestObjectType {\n checkbox_text\n has_extended_time_test\n content_assignment {\n id\n }\n competence_certificate {\n ...CoursePageFields\n }\n }\n ... on LearningContentRichTextObjectType {\n text\n }\n }\n }\n }\n }\n }\n }\n }\n }\n": types.CourseQueryDocument,
|
||||||
"\n query dashboardConfig {\n dashboard_config {\n id\n slug\n name\n dashboard_type\n }\n }\n": types.DashboardConfigDocument,
|
"\n query dashboardConfig {\n dashboard_config {\n id\n slug\n name\n dashboard_type\n }\n }\n": types.DashboardConfigDocument,
|
||||||
"\n query dashboardProgress($courseId: ID!) {\n course_progress(course_id: $courseId) {\n _id\n course_id\n session_to_continue_id\n competence {\n _id\n total_count\n success_count\n fail_count\n }\n assignment {\n _id\n total_count\n points_max_count\n points_achieved_count\n }\n }\n }\n": types.DashboardProgressDocument,
|
"\n query dashboardProgress($courseId: ID!) {\n course_progress(course_id: $courseId) {\n _id\n course_id\n session_to_continue_id\n competence {\n _id\n total_count\n success_count\n fail_count\n }\n assignment {\n _id\n total_count\n points_max_count\n points_achieved_count\n }\n }\n }\n": types.DashboardProgressDocument,
|
||||||
"\n query courseStatistics($course_id: ID!) {\n course_statistics(course_id: $course_id) {\n _id\n course_id\n course_title\n course_slug\n course_session_properties {\n _id\n sessions {\n _id\n session_id\n session_title\n }\n generations\n circles {\n _id\n circle_id\n circle_title\n experts\n }\n }\n course_session_selection_ids\n course_session_selection_metrics {\n _id\n session_count\n participant_count\n expert_count\n }\n attendance_day_presences {\n _id\n records {\n _id\n course_session_id\n generation\n circle_id\n due_date\n participants_present\n participants_total\n details_url\n }\n summary {\n _id\n days_completed\n participants_present\n }\n }\n feedback_responses {\n _id\n records {\n _id\n course_session_id\n generation\n circle_id\n satisfaction_average\n satisfaction_max\n details_url\n }\n summary {\n _id\n satisfaction_average\n satisfaction_max\n total_responses\n }\n }\n assignments {\n _id\n summary {\n _id\n completed_count\n average_passed\n }\n records {\n _id\n course_session_id\n course_session_assignment_id\n circle_id\n generation\n assignment_title\n assignment_type_translation_key\n details_url\n deadline\n metrics {\n _id\n passed_count\n failed_count\n unranked_count\n ranking_completed\n average_passed\n }\n }\n }\n competences {\n _id\n summary {\n _id\n success_total\n fail_total\n }\n performances {\n _id\n course_session_id\n generation\n circle_id\n success_count\n fail_count\n details_url\n }\n }\n }\n }\n": types.CourseStatisticsDocument,
|
"\n query courseStatistics($courseId: ID!) {\n course_statistics(course_id: $courseId) {\n _id\n course_id\n course_title\n course_slug\n course_session_properties {\n _id\n sessions {\n _id\n session_id\n session_title\n }\n generations\n circles {\n _id\n circle_id\n circle_title\n experts\n }\n }\n course_session_selection_ids\n course_session_selection_metrics {\n _id\n session_count\n participant_count\n expert_count\n }\n attendance_day_presences {\n _id\n records {\n _id\n course_session_id\n generation\n circle_id\n due_date\n participants_present\n participants_total\n details_url\n }\n summary {\n _id\n days_completed\n participants_present\n }\n }\n feedback_responses {\n _id\n records {\n _id\n course_session_id\n generation\n circle_id\n satisfaction_average\n satisfaction_max\n details_url\n }\n summary {\n _id\n satisfaction_average\n satisfaction_max\n total_responses\n }\n }\n assignments {\n _id\n summary {\n _id\n completed_count\n average_passed\n }\n records {\n _id\n course_session_id\n course_session_assignment_id\n circle_id\n generation\n assignment_title\n assignment_type_translation_key\n details_url\n deadline\n metrics {\n _id\n passed_count\n failed_count\n unranked_count\n ranking_completed\n average_passed\n }\n }\n }\n competences {\n _id\n summary {\n _id\n success_total\n fail_total\n }\n performances {\n _id\n course_session_id\n generation\n circle_id\n success_count\n fail_count\n details_url\n }\n }\n }\n }\n": types.CourseStatisticsDocument,
|
||||||
"\n mutation SendFeedbackMutation(\n $courseSessionId: ID!\n $learningContentId: ID!\n $data: GenericScalar!\n $submitted: Boolean\n ) {\n send_feedback(\n course_session_id: $courseSessionId\n learning_content_page_id: $learningContentId\n data: $data\n submitted: $submitted\n ) {\n feedback_response {\n id\n data\n submitted\n }\n errors {\n field\n messages\n }\n }\n }\n": types.SendFeedbackMutationDocument,
|
"\n mutation SendFeedbackMutation(\n $courseSessionId: ID!\n $learningContentId: ID!\n $data: GenericScalar!\n $submitted: Boolean\n ) {\n send_feedback(\n course_session_id: $courseSessionId\n learning_content_page_id: $learningContentId\n data: $data\n submitted: $submitted\n ) {\n feedback_response {\n id\n data\n submitted\n }\n errors {\n field\n messages\n }\n }\n }\n": types.SendFeedbackMutationDocument,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -84,7 +84,7 @@ export function graphql(source: "\n query dashboardProgress($courseId: ID!) {\n
|
||||||
/**
|
/**
|
||||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||||
*/
|
*/
|
||||||
export function graphql(source: "\n query courseStatistics($course_id: ID!) {\n course_statistics(course_id: $course_id) {\n _id\n course_id\n course_title\n course_slug\n course_session_properties {\n _id\n sessions {\n _id\n session_id\n session_title\n }\n generations\n circles {\n _id\n circle_id\n circle_title\n experts\n }\n }\n course_session_selection_ids\n course_session_selection_metrics {\n _id\n session_count\n participant_count\n expert_count\n }\n attendance_day_presences {\n _id\n records {\n _id\n course_session_id\n generation\n circle_id\n due_date\n participants_present\n participants_total\n details_url\n }\n summary {\n _id\n days_completed\n participants_present\n }\n }\n feedback_responses {\n _id\n records {\n _id\n course_session_id\n generation\n circle_id\n satisfaction_average\n satisfaction_max\n details_url\n }\n summary {\n _id\n satisfaction_average\n satisfaction_max\n total_responses\n }\n }\n assignments {\n _id\n summary {\n _id\n completed_count\n average_passed\n }\n records {\n _id\n course_session_id\n course_session_assignment_id\n circle_id\n generation\n assignment_title\n assignment_type_translation_key\n details_url\n deadline\n metrics {\n _id\n passed_count\n failed_count\n unranked_count\n ranking_completed\n average_passed\n }\n }\n }\n competences {\n _id\n summary {\n _id\n success_total\n fail_total\n }\n performances {\n _id\n course_session_id\n generation\n circle_id\n success_count\n fail_count\n details_url\n }\n }\n }\n }\n"): (typeof documents)["\n query courseStatistics($course_id: ID!) {\n course_statistics(course_id: $course_id) {\n _id\n course_id\n course_title\n course_slug\n course_session_properties {\n _id\n sessions {\n _id\n session_id\n session_title\n }\n generations\n circles {\n _id\n circle_id\n circle_title\n experts\n }\n }\n course_session_selection_ids\n course_session_selection_metrics {\n _id\n session_count\n participant_count\n expert_count\n }\n attendance_day_presences {\n _id\n records {\n _id\n course_session_id\n generation\n circle_id\n due_date\n participants_present\n participants_total\n details_url\n }\n summary {\n _id\n days_completed\n participants_present\n }\n }\n feedback_responses {\n _id\n records {\n _id\n course_session_id\n generation\n circle_id\n satisfaction_average\n satisfaction_max\n details_url\n }\n summary {\n _id\n satisfaction_average\n satisfaction_max\n total_responses\n }\n }\n assignments {\n _id\n summary {\n _id\n completed_count\n average_passed\n }\n records {\n _id\n course_session_id\n course_session_assignment_id\n circle_id\n generation\n assignment_title\n assignment_type_translation_key\n details_url\n deadline\n metrics {\n _id\n passed_count\n failed_count\n unranked_count\n ranking_completed\n average_passed\n }\n }\n }\n competences {\n _id\n summary {\n _id\n success_total\n fail_total\n }\n performances {\n _id\n course_session_id\n generation\n circle_id\n success_count\n fail_count\n details_url\n }\n }\n }\n }\n"];
|
export function graphql(source: "\n query courseStatistics($courseId: ID!) {\n course_statistics(course_id: $courseId) {\n _id\n course_id\n course_title\n course_slug\n course_session_properties {\n _id\n sessions {\n _id\n session_id\n session_title\n }\n generations\n circles {\n _id\n circle_id\n circle_title\n experts\n }\n }\n course_session_selection_ids\n course_session_selection_metrics {\n _id\n session_count\n participant_count\n expert_count\n }\n attendance_day_presences {\n _id\n records {\n _id\n course_session_id\n generation\n circle_id\n due_date\n participants_present\n participants_total\n details_url\n }\n summary {\n _id\n days_completed\n participants_present\n }\n }\n feedback_responses {\n _id\n records {\n _id\n course_session_id\n generation\n circle_id\n satisfaction_average\n satisfaction_max\n details_url\n }\n summary {\n _id\n satisfaction_average\n satisfaction_max\n total_responses\n }\n }\n assignments {\n _id\n summary {\n _id\n completed_count\n average_passed\n }\n records {\n _id\n course_session_id\n course_session_assignment_id\n circle_id\n generation\n assignment_title\n assignment_type_translation_key\n details_url\n deadline\n metrics {\n _id\n passed_count\n failed_count\n unranked_count\n ranking_completed\n average_passed\n }\n }\n }\n competences {\n _id\n summary {\n _id\n success_total\n fail_total\n }\n performances {\n _id\n course_session_id\n generation\n circle_id\n success_count\n fail_count\n details_url\n }\n }\n }\n }\n"): (typeof documents)["\n query courseStatistics($courseId: ID!) {\n course_statistics(course_id: $courseId) {\n _id\n course_id\n course_title\n course_slug\n course_session_properties {\n _id\n sessions {\n _id\n session_id\n session_title\n }\n generations\n circles {\n _id\n circle_id\n circle_title\n experts\n }\n }\n course_session_selection_ids\n course_session_selection_metrics {\n _id\n session_count\n participant_count\n expert_count\n }\n attendance_day_presences {\n _id\n records {\n _id\n course_session_id\n generation\n circle_id\n due_date\n participants_present\n participants_total\n details_url\n }\n summary {\n _id\n days_completed\n participants_present\n }\n }\n feedback_responses {\n _id\n records {\n _id\n course_session_id\n generation\n circle_id\n satisfaction_average\n satisfaction_max\n details_url\n }\n summary {\n _id\n satisfaction_average\n satisfaction_max\n total_responses\n }\n }\n assignments {\n _id\n summary {\n _id\n completed_count\n average_passed\n }\n records {\n _id\n course_session_id\n course_session_assignment_id\n circle_id\n generation\n assignment_title\n assignment_type_translation_key\n details_url\n deadline\n metrics {\n _id\n passed_count\n failed_count\n unranked_count\n ranking_completed\n average_passed\n }\n }\n }\n competences {\n _id\n summary {\n _id\n success_total\n fail_total\n }\n performances {\n _id\n course_session_id\n generation\n circle_id\n success_count\n fail_count\n details_url\n }\n }\n }\n }\n"];
|
||||||
/**
|
/**
|
||||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -303,8 +303,8 @@ export const DASHBOARD_COURSE_SESSION_PROGRESS = graphql(`
|
||||||
`);
|
`);
|
||||||
|
|
||||||
export const DASHBOARD_COURSE_STATISTICS = graphql(`
|
export const DASHBOARD_COURSE_STATISTICS = graphql(`
|
||||||
query courseStatistics($course_id: ID!) {
|
query courseStatistics($courseId: ID!) {
|
||||||
course_statistics(course_id: $course_id) {
|
course_statistics(course_id: $courseId) {
|
||||||
_id
|
_id
|
||||||
course_id
|
course_id
|
||||||
course_title
|
course_title
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ const boards: Record<DashboardType, DashboardPage> = {
|
||||||
STATISTICS_DASHBOARD: { main: StatisticPage, aside: SimpleDates },
|
STATISTICS_DASHBOARD: { main: StatisticPage, aside: SimpleDates },
|
||||||
};
|
};
|
||||||
|
|
||||||
onMounted(dashboardStore.loadDashboardConfig);
|
onMounted(dashboardStore.loadDashboardDetails);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
@ -35,7 +35,7 @@ onMounted(dashboardStore.loadDashboardConfig);
|
||||||
:model-value="dashboardStore.currentDashboardConfig"
|
:model-value="dashboardStore.currentDashboardConfig"
|
||||||
class="mt-4 w-full lg:mt-0 lg:w-96"
|
class="mt-4 w-full lg:mt-0 lg:w-96"
|
||||||
:items="dashboardStore.dashboardConfigs"
|
:items="dashboardStore.dashboardConfigs"
|
||||||
@update:model-value="dashboardStore.setCurrentDashboardConfig"
|
@update:model-value="dashboardStore.switchAndLoadDashboardConfig"
|
||||||
></ItDropdownSelect>
|
></ItDropdownSelect>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,26 +1,22 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useDashboardStore } from "@/stores/dashboard";
|
import { useDashboardStore } from "@/stores/dashboard";
|
||||||
import { useQuery } from "@urql/vue";
|
|
||||||
import { computed } from "vue";
|
import { computed } from "vue";
|
||||||
import LearningPathDiagram from "@/components/learningPath/LearningPathDiagram.vue";
|
import LearningPathDiagram from "@/components/learningPath/LearningPathDiagram.vue";
|
||||||
import ItProgress from "@/components/ui/ItProgress.vue";
|
import ItProgress from "@/components/ui/ItProgress.vue";
|
||||||
import { DASHBOARD_COURSE_SESSION_PROGRESS } from "@/graphql/queries";
|
|
||||||
import { getLearningPathUrl } from "@/utils/utils";
|
import { getLearningPathUrl } from "@/utils/utils";
|
||||||
import type {
|
import type {
|
||||||
|
CourseProgressType,
|
||||||
ProgressDashboardAssignmentType,
|
ProgressDashboardAssignmentType,
|
||||||
ProgressDashboardCompetenceType,
|
ProgressDashboardCompetenceType,
|
||||||
} from "@/gql/graphql";
|
} from "@/gql/graphql";
|
||||||
|
|
||||||
const dashboardStore = useDashboardStore();
|
const dashboardStore = useDashboardStore();
|
||||||
|
|
||||||
const courseId = computed(() => dashboardStore.currentDashboardConfig?.id);
|
|
||||||
const courseSlug = computed(() => dashboardStore.currentDashboardConfig?.slug);
|
const courseSlug = computed(() => dashboardStore.currentDashboardConfig?.slug);
|
||||||
const courseName = computed(() => dashboardStore.currentDashboardConfig?.name);
|
const courseName = computed(() => dashboardStore.currentDashboardConfig?.name);
|
||||||
|
|
||||||
const { data: progress } = useQuery({
|
const courseSessionProgress = computed(() => {
|
||||||
query: DASHBOARD_COURSE_SESSION_PROGRESS,
|
return dashboardStore.currentDashBoardData as CourseProgressType;
|
||||||
// @ts-ignore
|
|
||||||
variables: { courseId },
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const DEFAULT_ASSIGNMENT = {
|
const DEFAULT_ASSIGNMENT = {
|
||||||
|
|
@ -32,13 +28,13 @@ const DEFAULT_COMPETENCE = { total_count: 0, success_count: 0, fail_count: 0 };
|
||||||
|
|
||||||
const assignment = computed<ProgressDashboardAssignmentType>(
|
const assignment = computed<ProgressDashboardAssignmentType>(
|
||||||
() =>
|
() =>
|
||||||
(progress.value?.course_progress?.assignment as ProgressDashboardAssignmentType) ??
|
(courseSessionProgress.value?.assignment as ProgressDashboardAssignmentType) ??
|
||||||
DEFAULT_ASSIGNMENT
|
DEFAULT_ASSIGNMENT
|
||||||
);
|
);
|
||||||
|
|
||||||
const competence = computed<ProgressDashboardCompetenceType>(
|
const competence = computed<ProgressDashboardCompetenceType>(
|
||||||
() =>
|
() =>
|
||||||
(progress.value?.course_progress?.competence as ProgressDashboardCompetenceType) ??
|
(courseSessionProgress.value?.competence as ProgressDashboardCompetenceType) ??
|
||||||
DEFAULT_COMPETENCE
|
DEFAULT_COMPETENCE
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -49,26 +45,26 @@ const assignment_progress = computed(() => ({
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const competenceCertificateUrl = computed(() => {
|
const competenceCertificateUrl = computed(() => {
|
||||||
return `/course/${courseSlug.value}/competence/certificates?courseSessionId=${progress.value?.course_progress?.session_to_continue_id}`;
|
return `/course/${courseSlug.value}/competence/certificates?courseSessionId=${courseSessionProgress.value?.session_to_continue_id}`;
|
||||||
});
|
});
|
||||||
|
|
||||||
const competenceCriteriaUrl = computed(() => {
|
const competenceCriteriaUrl = computed(() => {
|
||||||
return `/course/${courseSlug.value}/competence/criteria?courseSessionId=${progress.value?.course_progress?.session_to_continue_id}`;
|
return `/course/${courseSlug.value}/competence/criteria?courseSessionId=${courseSessionProgress.value?.session_to_continue_id}`;
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
v-if="progress?.course_progress && dashboardStore.currentDashboardConfig"
|
v-if="courseSessionProgress && dashboardStore.currentDashboardConfig"
|
||||||
class="mb-14 space-y-8"
|
class="mb-14 space-y-8"
|
||||||
>
|
>
|
||||||
<div class="flex flex-col space-y-7 bg-white p-6">
|
<div class="flex flex-col space-y-7 bg-white p-6">
|
||||||
<h3>{{ courseName }}</h3>
|
<h3>{{ courseName }}</h3>
|
||||||
<LearningPathDiagram
|
<LearningPathDiagram
|
||||||
v-if="progress.course_progress.session_to_continue_id && courseSlug"
|
v-if="courseSessionProgress.session_to_continue_id && courseSlug"
|
||||||
:key="courseSlug"
|
:key="courseSlug"
|
||||||
:course-slug="courseSlug"
|
:course-slug="courseSlug"
|
||||||
:course-session-id="progress.course_progress.session_to_continue_id"
|
:course-session-id="courseSessionProgress.session_to_continue_id"
|
||||||
diagram-type="horizontal"
|
diagram-type="horizontal"
|
||||||
></LearningPathDiagram>
|
></LearningPathDiagram>
|
||||||
<div>
|
<div>
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,18 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useDashboardStore } from "@/stores/dashboard";
|
import { useDashboardStore } from "@/stores/dashboard";
|
||||||
import { onMounted } from "vue";
|
import { computed } from "vue";
|
||||||
import ItProgress from "@/components/ui/ItProgress.vue";
|
import ItProgress from "@/components/ui/ItProgress.vue";
|
||||||
|
import type { CourseStatisticsType } from "@/gql/graphql";
|
||||||
|
|
||||||
const dashboardStore = useDashboardStore();
|
const dashboardStore = useDashboardStore();
|
||||||
|
|
||||||
onMounted(dashboardStore.loadDashboardStatistics);
|
const statistics = computed(() => {
|
||||||
|
return dashboardStore.currentDashBoardData as CourseStatisticsType;
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div v-if="dashboardStore.currentCourseStatistics" class="mb-14 space-y-8">
|
<div v-if="statistics" class="mb-14 space-y-8">
|
||||||
<div class="flex items-center justify-between bg-white p-6">
|
<div class="flex items-center justify-between bg-white p-6">
|
||||||
<div class="flex space-x-6">
|
<div class="flex space-x-6">
|
||||||
<div class="flex items-center space-x-2">
|
<div class="flex items-center space-x-2">
|
||||||
|
|
@ -36,10 +39,7 @@ onMounted(dashboardStore.loadDashboardStatistics);
|
||||||
<i18next :translation="$t('a.NUMBER Präsenztage abgeschlossen')">
|
<i18next :translation="$t('a.NUMBER Präsenztage abgeschlossen')">
|
||||||
<template #NUMBER>
|
<template #NUMBER>
|
||||||
<span class="mr-3 text-4xl font-bold">
|
<span class="mr-3 text-4xl font-bold">
|
||||||
{{
|
{{ statistics.attendance_day_presences.summary.days_completed }}
|
||||||
dashboardStore.currentCourseStatistics.attendance_day_presences
|
|
||||||
.summary.days_completed
|
|
||||||
}}
|
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</i18next>
|
</i18next>
|
||||||
|
|
@ -48,15 +48,18 @@ onMounted(dashboardStore.loadDashboardStatistics);
|
||||||
<i18next :translation="$t('a.NUMBER Präsenztage abgeschlossen')">
|
<i18next :translation="$t('a.NUMBER Präsenztage abgeschlossen')">
|
||||||
<template #NUMBER>
|
<template #NUMBER>
|
||||||
<span class="mr-3 text-4xl font-bold">
|
<span class="mr-3 text-4xl font-bold">
|
||||||
{{
|
{{ statistics.attendance_day_presences.summary.days_completed }}
|
||||||
dashboardStore.currentCourseStatistics.attendance_day_presences
|
|
||||||
.summary.days_completed
|
|
||||||
}}
|
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</i18next>
|
</i18next>
|
||||||
</div>
|
</div>
|
||||||
<ItProgress></ItProgress>
|
<ItProgress></ItProgress>
|
||||||
|
<router-link
|
||||||
|
class="pt-8 underline"
|
||||||
|
:to="`/statistic/${dashboardStore?.currentDashboardConfig?.slug}/attendance`"
|
||||||
|
>
|
||||||
|
{{ $t("a.Details anschauen") }}
|
||||||
|
</router-link>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { useDashboardStore } from "@/stores/dashboard";
|
||||||
|
import ItDropdownSelect from "@/components/ui/ItDropdownSelect.vue";
|
||||||
|
|
||||||
|
const dashboardStore = useDashboardStore();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<main>
|
||||||
|
<div class="mb-10 flex items-center justify-between">
|
||||||
|
<h3>Anwesenheit</h3>
|
||||||
|
<ItDropdownSelect
|
||||||
|
:model-value="dashboardStore.currentDashboardConfig"
|
||||||
|
class="mt-4 w-full lg:mt-0 lg:w-96"
|
||||||
|
:items="dashboardStore.dashboardConfigs"
|
||||||
|
@update:model-value="dashboardStore.switchAndLoadDashboardConfig"
|
||||||
|
></ItDropdownSelect>
|
||||||
|
</div>
|
||||||
|
<div class="bg-white">Stats</div>
|
||||||
|
</main>
|
||||||
|
</template>
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { useDashboardStore } from "@/stores/dashboard";
|
||||||
|
import { onMounted } from "vue";
|
||||||
|
|
||||||
|
const dashboardStore = useDashboardStore();
|
||||||
|
onMounted(dashboardStore.loadDashboardDetails);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="bg-gray-200">
|
||||||
|
<div class="container-large flex flex-col space-y-8">
|
||||||
|
<router-link class="btn-text inline-flex items-center pl-0" to="/">
|
||||||
|
<it-icon-arrow-left />
|
||||||
|
<span>{{ $t("general.back") }}</span>
|
||||||
|
</router-link>
|
||||||
|
<router-view></router-view>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
@ -173,6 +173,19 @@ const router = createRouter({
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "/statistic/:courseSlug",
|
||||||
|
props: true,
|
||||||
|
component: () => import("@/pages/dashboard/statistic/StatisticParentPage.vue"),
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: "attendance",
|
||||||
|
props: true,
|
||||||
|
component: () =>
|
||||||
|
import("@/pages/dashboard/statistic/AttendanceDayPresences.vue"),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: "/shop",
|
path: "/shop",
|
||||||
component: () => import("@/pages/ShopPage.vue"),
|
component: () => import("@/pages/ShopPage.vue"),
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
import { graphqlClient } from "@/graphql/client";
|
||||||
|
import {
|
||||||
|
DASHBOARD_CONFIG,
|
||||||
|
DASHBOARD_COURSE_SESSION_PROGRESS,
|
||||||
|
DASHBOARD_COURSE_STATISTICS,
|
||||||
|
} from "@/graphql/queries";
|
||||||
|
|
||||||
|
import type {
|
||||||
|
CourseProgressType,
|
||||||
|
CourseStatisticsType,
|
||||||
|
DashboardConfigType,
|
||||||
|
} from "@/gql/graphql";
|
||||||
|
|
||||||
|
export const fetchStatisticData = async (
|
||||||
|
courseId: string
|
||||||
|
): Promise<CourseStatisticsType | null> => {
|
||||||
|
try {
|
||||||
|
const res = await graphqlClient.query(DASHBOARD_COURSE_STATISTICS, { courseId });
|
||||||
|
return res.data?.course_statistics || null;
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Error fetching statistics for course ID: ${courseId}`, error);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const fetchProgressData = async (
|
||||||
|
courseId: string
|
||||||
|
): Promise<CourseProgressType | null> => {
|
||||||
|
try {
|
||||||
|
const res = await graphqlClient.query(DASHBOARD_COURSE_SESSION_PROGRESS, {
|
||||||
|
courseId,
|
||||||
|
});
|
||||||
|
return res.data?.course_progress || null;
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Error fetching progress for course ID: ${courseId}`, error);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
export const fetchDashboardConfig = async (): Promise<DashboardConfigType[] | null> => {
|
||||||
|
try {
|
||||||
|
const res = await graphqlClient.query(DASHBOARD_CONFIG, {});
|
||||||
|
return res.data?.dashboard_config || null;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error fetching dashboard config:", error);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -1,6 +1,14 @@
|
||||||
import type { CourseStatisticsType, DashboardConfigType } from "@/gql/graphql";
|
import type {
|
||||||
import { graphqlClient } from "@/graphql/client";
|
CourseProgressType,
|
||||||
import { DASHBOARD_CONFIG, DASHBOARD_COURSE_STATISTICS } from "@/graphql/queries";
|
CourseStatisticsType,
|
||||||
|
DashboardConfigType,
|
||||||
|
DashboardType,
|
||||||
|
} from "@/gql/graphql";
|
||||||
|
import {
|
||||||
|
fetchDashboardConfig,
|
||||||
|
fetchProgressData,
|
||||||
|
fetchStatisticData,
|
||||||
|
} from "@/services/dashboard";
|
||||||
import { defineStore } from "pinia";
|
import { defineStore } from "pinia";
|
||||||
import type { Ref } from "vue";
|
import type { Ref } from "vue";
|
||||||
import { ref } from "vue";
|
import { ref } from "vue";
|
||||||
|
|
@ -8,59 +16,62 @@ import { ref } from "vue";
|
||||||
export const useDashboardStore = defineStore("dashboard", () => {
|
export const useDashboardStore = defineStore("dashboard", () => {
|
||||||
const dashboardConfigs: Ref<DashboardConfigType[]> = ref([]);
|
const dashboardConfigs: Ref<DashboardConfigType[]> = ref([]);
|
||||||
const currentDashboardConfig: Ref<DashboardConfigType | undefined> = ref();
|
const currentDashboardConfig: Ref<DashboardConfigType | undefined> = ref();
|
||||||
const courseStatisticsCache: Record<string, CourseStatisticsType | null> = {};
|
const dashBoardDataCache: Record<
|
||||||
const currentCourseStatistics: Ref<CourseStatisticsType | null> = ref(null);
|
string,
|
||||||
|
CourseStatisticsType | CourseProgressType | null
|
||||||
|
> = {};
|
||||||
|
const currentDashBoardData: Ref<CourseStatisticsType | CourseProgressType | null> =
|
||||||
|
ref(null);
|
||||||
|
|
||||||
const setCurrentDashboardConfig = async (config: DashboardConfigType) => {
|
const loadDashboardData = async (type: DashboardType, id: string) => {
|
||||||
currentDashboardConfig.value = config;
|
let data;
|
||||||
if (config.dashboard_type === "STATISTICS_DASHBOARD") {
|
switch (type) {
|
||||||
await loadDashboardStatistics();
|
case "STATISTICS_DASHBOARD":
|
||||||
|
data = await fetchStatisticData(id);
|
||||||
|
break;
|
||||||
|
case "PROGRESS_DASHBOARD":
|
||||||
|
data = await fetchProgressData(id);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
dashBoardDataCache[id] = data;
|
||||||
|
currentDashBoardData.value = data;
|
||||||
|
};
|
||||||
|
|
||||||
|
const switchAndLoadDashboardConfig = async (config: DashboardConfigType) => {
|
||||||
|
currentDashboardConfig.value = config;
|
||||||
|
await loadDashboardDetails();
|
||||||
};
|
};
|
||||||
|
|
||||||
const loadDashboardConfig = async () => {
|
const loadDashboardConfig = async () => {
|
||||||
const res = await graphqlClient.query(DASHBOARD_CONFIG, {});
|
if (dashboardConfigs.value.length > 0) return;
|
||||||
if (res.data) {
|
const configData = await fetchDashboardConfig();
|
||||||
dashboardConfigs.value = res.data.dashboard_config;
|
if (configData) {
|
||||||
currentDashboardConfig.value = res.data.dashboard_config[0];
|
dashboardConfigs.value = configData;
|
||||||
} else {
|
await switchAndLoadDashboardConfig(configData[0]);
|
||||||
console.warn("No dashboard config found");
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const loadDashboardStatistics = async () => {
|
const loadDashboardDetails = async () => {
|
||||||
if (!currentDashboardConfig.value) {
|
if (!currentDashboardConfig.value) {
|
||||||
currentCourseStatistics.value = null;
|
await loadDashboardConfig();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const { id, dashboard_type } = currentDashboardConfig.value;
|
||||||
const courseId = currentDashboardConfig.value.id;
|
if (dashBoardDataCache[id]) {
|
||||||
|
currentDashBoardData.value = dashBoardDataCache[id];
|
||||||
if (courseStatisticsCache[courseId]) {
|
|
||||||
currentCourseStatistics.value = courseStatisticsCache[courseId];
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
await loadDashboardData(dashboard_type, id);
|
||||||
const res = await graphqlClient.query(DASHBOARD_COURSE_STATISTICS, {
|
|
||||||
course_id: courseId,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (res.data && res.data.course_statistics) {
|
|
||||||
courseStatisticsCache[courseId] = res.data.course_statistics;
|
|
||||||
currentCourseStatistics.value = res.data.course_statistics;
|
|
||||||
} else {
|
|
||||||
console.warn(`No course statistics found for course ID: ${courseId}`);
|
|
||||||
courseStatisticsCache[courseId] = null;
|
|
||||||
currentCourseStatistics.value = null;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
dashboardConfigs,
|
dashboardConfigs,
|
||||||
currentDashboardConfig,
|
currentDashboardConfig,
|
||||||
setCurrentDashboardConfig,
|
switchAndLoadDashboardConfig,
|
||||||
loadDashboardConfig,
|
loadDashboardConfig,
|
||||||
loadDashboardStatistics,
|
loadDashboardDetails,
|
||||||
currentCourseStatistics,
|
currentDashBoardData,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -211,7 +211,9 @@ class CourseSessionObjectType(DjangoObjectType):
|
||||||
return CourseSessionEdoniqTest.objects.filter(course_session=self)
|
return CourseSessionEdoniqTest.objects.filter(course_session=self)
|
||||||
|
|
||||||
def resolve_users(self, info):
|
def resolve_users(self, info):
|
||||||
csu = list(CourseSessionUser.objects.filter(course_session_id=self.id).distinct())
|
csu = list(
|
||||||
|
CourseSessionUser.objects.filter(course_session_id=self.id).distinct()
|
||||||
|
)
|
||||||
|
|
||||||
# TODO remove or fix this
|
# TODO remove or fix this
|
||||||
# HACK: This is an ugly hack to pretend supervisor is a course session expert
|
# HACK: This is an ugly hack to pretend supervisor is a course session expert
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue