wip: summary boxes

This commit is contained in:
Livio Bieri 2023-10-27 16:26:15 +02:00
parent ed4f9714d4
commit 63bcb44fa2
8 changed files with 266 additions and 45 deletions

View File

@ -0,0 +1,43 @@
<script setup lang="ts">
import ItProgress from "@/components/ui/ItProgress.vue";
import { computed } from "vue";
import BaseBox from "@/components/dashboard/BaseBox.vue";
const props = defineProps<{
assignmentsCompleted: number;
avgPassed: number;
}>();
const progress = computed(() => {
return {
SUCCESS: props.avgPassed,
FAIL: 100 - props.avgPassed,
UNKNOWN: 0,
};
});
</script>
<template>
<BaseBox :details-link="'/statistic/assignment'">
<template #title>{{ $t("a.Kompetenznachweis-Elemente") }}</template>
<template #content>
<div class="flex items-center">
<i18next :translation="$t('a.NUMBER Elemente abgeschlossen')">
<template #NUMBER>
<span class="mr-3 text-4xl font-bold">{{ assignmentsCompleted }}</span>
</template>
</i18next>
</div>
<div class="flex items-center">
<i18next :translation="$t('a.{NUMBER} Bestanden')">
<template #NUMBER>
<span class="mr-3 text-4xl font-bold">
{{ Math.round(props.avgPassed) }}%
</span>
</template>
</i18next>
</div>
<ItProgress :status-count="progress"></ItProgress>
</template>
</BaseBox>
</template>

View File

@ -0,0 +1,41 @@
<script setup lang="ts">
import ItProgress from "@/components/ui/ItProgress.vue";
import { computed } from "vue";
import BaseBox from "@/components/dashboard/BaseBox.vue";
const props = defineProps<{
daysCompleted: number;
avgParticipantsPresent: number;
}>();
const progressRecord = computed(() => {
return {
SUCCESS: props.avgParticipantsPresent,
FAIL: 100 - props.avgParticipantsPresent,
UNKNOWN: 0,
};
});
</script>
<template>
<BaseBox :details-link="'/statistic/attendance'">
<template #title>{{ $t("a.Anwesenheit") }}</template>
<template #content>
<div class="flex items-center">
<i18next :translation="$t('a.NUMBER Präsenztage abgeschlossen')">
<template #NUMBER>
<span class="mr-3 text-4xl font-bold">{{ daysCompleted }}</span>
</template>
</i18next>
</div>
<div class="flex items-center">
<i18next :translation="$t('a.NUMBER Teilnehmer anwesend')">
<template #NUMBER>
<span class="mr-3 text-4xl font-bold">{{ avgParticipantsPresent }}%</span>
</template>
</i18next>
</div>
<ItProgress :status-count="progressRecord"></ItProgress>
</template>
</BaseBox>
</template>

View File

@ -0,0 +1,19 @@
<script setup lang="ts">
defineProps<{
detailsLink: string;
}>();
</script>
<template>
<div class="flex flex-col space-y-4 bg-white p-6">
<h4 class="mb-1 font-bold">
<slot name="title"></slot>
</h4>
<slot name="content"></slot>
<router-link class="pt-8 underline" :to="detailsLink">
{{ $t("a.Details anschauen") }}
</router-link>
</div>
</template>
<style scoped></style>

View File

@ -0,0 +1,30 @@
<script setup lang="ts">
import BaseBox from "@/components/dashboard/BaseBox.vue";
defineProps<{
failCount: number;
successCount: number;
}>();
</script>
<template>
<BaseBox :details-link="'/statistic/competence'">
<template #title>{{ $t("a.Selbsteinschätzungen") }}</template>
<template #content>
<div class="flex items-center">
<i18next :translation="$t('a.{NUMBER} Das kann ich')">
<template #NUMBER>
<span class="mr-3 text-4xl font-bold">{{ successCount }}</span>
</template>
</i18next>
</div>
<div class="flex items-center">
<i18next :translation="$t('a.{NUMBER} Das will ich nochmals anschauen')">
<template #NUMBER>
<span class="mr-3 text-4xl font-bold">{{ failCount }}%</span>
</template>
</i18next>
</div>
</template>
</BaseBox>
</template>

View File

@ -0,0 +1,38 @@
<script setup lang="ts">
defineProps<{
participantCount: number;
expertCount: number;
sessionCount: number;
}>();
</script>
<template>
<div class="flex items-center justify-between bg-white p-6">
<div class="flex space-x-6">
<div class="flex items-center space-x-2">
<span class="text-4xl font-bold">
{{ participantCount }}
</span>
<span>{{ $t("a.Teilnehmer") }}</span>
</div>
<div class="flex items-center space-x-2">
<span class="text-4xl font-bold">
{{ expertCount }}
</span>
<span>{{ $t("a.Trainer") }}</span>
</div>
<div class="flex items-center space-x-2">
<span class="text-4xl font-bold">
{{ sessionCount }}
</span>
<span>{{ $t("a.Durchführungen") }}</span>
</div>
</div>
<!-- TODO Figure out where this link should go -->
<router-link class="btn-secondary" to="#">
{{ $t("a.Liste anzeigen") }}
</router-link>
</div>
</template>
<style scoped></style>

View File

@ -0,0 +1,30 @@
<script setup lang="ts">
import BaseBox from "@/components/dashboard/BaseBox.vue";
defineProps<{
feedbackCount: number;
statisfactionMax: number;
statisfactionAvg: number;
}>();
</script>
<template>
<BaseBox :details-link="'/statistic/feedback'">
<template #title>{{ $t("a.Feedback Teilnehmer") }}</template>
<template #content>
<div class="flex items-center">
<i18next :translation="$t('a.{AVG} von {MAX}')">
<template #AVG>
<span class="mr-3 text-4xl font-bold">{{ statisfactionAvg }}</span>
</template>
<template #MAX>{{ statisfactionMax }}</template>
</i18next>
</div>
<div class="flex items-center">
<i18next :translation="$t('a.Total {NUMBER} Antworten')">
<template #NUMBER>{{ feedbackCount }}</template>
</i18next>
</div>
</template>
</BaseBox>
</template>

View File

@ -1,63 +1,65 @@
<script setup lang="ts">
import { useDashboardStore } from "@/stores/dashboard";
import { computed } from "vue";
import ItProgress from "@/components/ui/ItProgress.vue";
import CourseStatistics from "@/components/dashboard/CourseStatistics.vue";
import AttendanceSummaryBox from "@/components/dashboard/AttendanceSummaryBox.vue";
import type { CourseStatisticsType } from "@/gql/graphql";
import AssignmentSummaryBox from "@/components/dashboard/AssignmentSummaryBox.vue";
import FeedbackSummaryBox from "@/components/dashboard/FeedbackSummaryBox.vue";
import CompetenceSummaryBox from "@/components/dashboard/CompetenceSummaryBox.vue";
const dashboardStore = useDashboardStore();
const statistics = computed(() => {
return dashboardStore.currentDashBoardData as CourseStatisticsType;
});
const courseSessionSelectionMetrics = computed(() => {
return statistics.value.course_session_selection_metrics;
});
const attendanceDayPresences = computed(() => {
return statistics.value.attendance_day_presences.summary;
});
const assigmentSummary = computed(() => {
return statistics.value.assignments.summary;
});
const competenceSummary = computed(() => {
return statistics.value.competences.summary;
});
const feebackSummary = computed(() => {
return statistics.value.feedback_responses.summary;
});
</script>
<template>
<div v-if="statistics" class="mb-14 space-y-8">
<div class="flex items-center justify-between bg-white p-6">
<div class="flex space-x-6">
<div class="flex items-center space-x-2">
<span class="text-4xl font-bold">352</span>
<span>Teilnehmer</span>
</div>
<div class="flex items-center space-x-2">
<span class="text-4xl font-bold">25</span>
<span>Trainer</span>
</div>
<div class="flex items-center space-x-2">
<span class="text-4xl font-bold">18</span>
<span>Durchführungen</span>
</div>
</div>
<router-link class="btn-secondary" to="#">
{{ $t("a.Liste anzeigen") }}
</router-link>
</div>
<CourseStatistics
:session-count="courseSessionSelectionMetrics.session_count"
:participant-count="courseSessionSelectionMetrics.participant_count"
:expert-count="courseSessionSelectionMetrics.expert_count"
/>
<div class="grid auto-rows-fr grid-cols-1 gap-8 xl:grid-cols-2">
<div class="flex flex-col space-y-4 bg-white p-6">
<h4 class="mb-1 font-bold">{{ $t("a.Anwesenheit") }}</h4>
<div class="flex items-center">
<i18next :translation="$t('a.NUMBER Präsenztage abgeschlossen')">
<template #NUMBER>
<span class="mr-3 text-4xl font-bold">
{{ statistics.attendance_day_presences.summary.days_completed }}
</span>
</template>
</i18next>
</div>
<div class="flex items-center">
<i18next :translation="$t('a.NUMBER Präsenztage abgeschlossen')">
<template #NUMBER>
<span class="mr-3 text-4xl font-bold">
{{ statistics.attendance_day_presences.summary.days_completed }}
</span>
</template>
</i18next>
</div>
<ItProgress></ItProgress>
<router-link class="pt-8 underline" to="/statistic/attendance">
{{ $t("a.Details anschauen") }}
</router-link>
</div>
<AttendanceSummaryBox
:days-completed="attendanceDayPresences.days_completed"
:avg-participants-present="attendanceDayPresences.participants_present"
/>
<AssignmentSummaryBox
:assignments-completed="assigmentSummary.completed_count"
:avg-passed="assigmentSummary.average_passed"
/>
<FeedbackSummaryBox
:feedback-count="feebackSummary.total_responses"
:statisfaction-max="feebackSummary.satisfaction_max"
:statisfaction-avg="feebackSummary.satisfaction_average"
/>
<CompetenceSummaryBox
:fail-count="competenceSummary.fail_total"
:success-count="competenceSummary.success_total"
/>
</div>
</div>
</template>

View File

@ -184,6 +184,24 @@ const router = createRouter({
component: () =>
import("@/pages/dashboard/statistic/AttendanceDayPresences.vue"),
},
{
path: "assignment",
props: true,
component: () =>
import("@/pages/dashboard/statistic/AttendanceDayPresences.vue"),
},
{
path: "competence",
props: true,
component: () =>
import("@/pages/dashboard/statistic/AttendanceDayPresences.vue"),
},
{
path: "feedback",
props: true,
component: () =>
import("@/pages/dashboard/statistic/AttendanceDayPresences.vue"),
},
],
},
{