Refactor design of learning contents in circle page

This commit is contained in:
Daniel Egger 2023-09-07 18:24:49 +02:00
parent 853c8746ea
commit e43e351e9d
7 changed files with 118 additions and 122 deletions

View File

@ -1,22 +1,22 @@
<script setup lang="ts">
import type { CheckboxItem } from "@/components/ui/checkbox.types";
import log from "loglevel";
import {
itCheckboxDefaultIconCheckedTailwindClass,
itCheckboxDefaultIconUncheckedTailwindClass,
} from "@/constants";
interface Props {
checkboxItem: CheckboxItem<any>;
disabled?: boolean;
iconCheckedPath?: string;
iconCheckedHoverPath?: string;
iconUncheckedPath?: string;
iconUncheckedHoverPath?: string;
iconCheckedTailwindClass?: string;
iconUncheckedTailwindClass?: string;
}
const props = withDefaults(defineProps<Props>(), {
disabled: false,
iconCheckedPath: "/static/icons/icon-checkbox-checked.svg",
iconCheckedHoverPath: "/static/icons/icon-checkbox-checked-hover.svg",
iconUncheckedPath: "/static/icons/icon-checkbox-unchecked.svg",
iconUncheckedHoverPath: "/static/icons/icon-checkbox-unchecked-hover.svg",
iconCheckedTailwindClass: itCheckboxDefaultIconCheckedTailwindClass,
iconUncheckedTailwindClass: itCheckboxDefaultIconUncheckedTailwindClass,
});
const emit = defineEmits(["toggle"]);
@ -51,8 +51,8 @@ const input = () => {
class="flex h-8 items-center bg-contain bg-no-repeat pl-8 disabled:opacity-50"
:class="
checkboxItem.checked
? `bg-[url(${props.iconCheckedPath})] hover:bg-[url(${props.iconCheckedHoverPath})]`
: `bg-[url(${props.iconUncheckedPath})] hover:bg-[url(${props.iconUncheckedHoverPath})]`
? props.iconCheckedTailwindClass
: props.iconUncheckedTailwindClass
"
tabindex="0"
@keydown.stop="keydown"

View File

@ -3,3 +3,9 @@ import type { CourseCompletionStatus } from "@/types";
export const COMPLETION_SUCCESS: CourseCompletionStatus = "SUCCESS";
export const COMPLETION_FAILURE: CourseCompletionStatus = "FAIL";
export const COMPLETION_UNKNOWN: CourseCompletionStatus = "UNKNOWN";
export const itCheckboxDefaultIconCheckedTailwindClass =
"bg-[url(/static/icons/icon-checkbox-checked.svg)] hover:bg-[url(/static/icons/icon-checkbox-checked-hover.svg)]";
export const itCheckboxDefaultIconUncheckedTailwindClass =
"bg-[url(/static/icons/icon-checkbox-unchecked.svg)] hover:bg-[url(/static/icons/icon-checkbox-unchecked-hover.svg)]";

View File

@ -11,16 +11,12 @@
"Anwesenheit prüfen": "Anwesenheit prüfen",
"Anwesenheitskontrolle Präsenzkurse": "Anwesenheitskontrolle Präsenzkurse",
"Benutzername": "Benutzername",
"Die Anwesenheit wurde definitiv bestätigt": [],
"Ergebnisse anschauen": "Ergebnisse anschauen",
"Ergebnisse anzeigen": "Ergebnisse anzeigen",
"Feedback": "Feedback",
"Feedback anschauen": "Feedback anschauen",
"Feedback: Feedback zum Lehrgang": "Feedback: Feedback zum Lehrgang",
"Freigabetermin Bewertungen:": "Freigabetermin Bewertungen:",
"Hier überprüfst und bestätigst du die Anwesenheit deiner Teilnehmenden": [],
"Ich will die Anwesenheit der untenstehenden Personen definitiv bestätigen": [],
"Keine Auftragsdetails verfügbar": [],
"MS Teams öffnen": "MS Teams öffnen",
"Nächste Termine": "Nächste Termine",
"Passwort": "Passwort",
@ -335,4 +331,4 @@
"x von y Feedbacks abgegeben": "{{x}} von {{y}} Feedbacks abgegeben",
"x von y abgeschlossen": "{{x}} von {{y}} abgeschlossen",
"zufrieden": "zufrieden"
}
}

View File

@ -21,6 +21,7 @@
"Ergebnisse abgegeben": "Résultats remis",
"Gesamtpunktzahl": "Score total",
"Höchstpunktzahl": "Score maximum",
"KompetenzNavi": "NaviCompétence",
"Punkte": "points",
"Zwischenstand": "Point intermédiaire",
"Übersicht": "Aperçu"
@ -310,4 +311,4 @@
"x von y Ergebnisse abgegeben": "{{x}} de {{y}} résultats remis",
"x von y Feedbacks abgegeben": "{{x}} de {{y}} feedbacks remis",
"x von y abgeschlossen": "{{x}} de {{y}} achevée/s"
}
}

View File

@ -21,6 +21,7 @@
"Ergebnisse abgegeben": "Risultati consegnati",
"Gesamtpunktzahl": "Punteggio totale",
"Höchstpunktzahl": "Punteggio massimo",
"KompetenzNavi": "NaviCompetenze",
"Punkte": "punti",
"Zwischenstand": "Punto intermedio",
"Übersicht": "Panoramica"
@ -310,4 +311,4 @@
"x von y Ergebnisse abgegeben": "{{x}} di {{y}} risultati consegnati/o",
"x von y Feedbacks abgegeben": "{{x}} di {{y}} feedback consegnati/o",
"x von y abgeschlossen": "{{x}} di {{y}} completate/a"
}
}

View File

@ -6,12 +6,18 @@ import { useCircleStore } from "@/stores/circle";
import type {
CourseCompletionStatus,
LearningContent,
LearningContentAssignment,
LearningContentEdoniqTest,
LearningContentInterface,
LearningSequence,
} from "@/types";
import { humanizeDuration } from "@/utils/humanizeDuration";
import findLast from "lodash/findLast";
import { computed } from "vue";
import { humanizeDuration } from "../../../utils/humanizeDuration";
import {
itCheckboxDefaultIconCheckedTailwindClass,
itCheckboxDefaultIconUncheckedTailwindClass,
} from "@/constants";
type Props = {
learningSequence: LearningSequence;
@ -97,35 +103,22 @@ function belongsToCompetenceCertificate(lc: LearningContent) {
);
}
function checkboxIconCheckedPath(lc: LearningContent) {
type LearninContentWithCompetenceCertificate =
| LearningContentAssignment
| LearningContentEdoniqTest;
function checkboxIconCheckedTailwindClass(lc: LearningContent) {
if (belongsToCompetenceCertificate(lc)) {
return "/static/icons/icon-lc-competence-certificate-checked.svg";
return "bg-[url(/static/icons/icon-lc-competence-certificate-checked.svg)]";
}
return "/static/icons/icon-checkbox-checked.svg";
return itCheckboxDefaultIconCheckedTailwindClass;
}
function checkboxIconCheckedHoverPath(lc: LearningContent) {
function checkboxIconUncheckedTailwindClass(lc: LearningContent) {
if (belongsToCompetenceCertificate(lc)) {
return "/static/icons/icon-lc-competence-certificate-checked.svg";
return "bg-[url(/static/icons/icon-lc-competence-certificate.svg)]";
}
return "/static/icons/icon-checkbox-checked-hover.svg";
}
function checkboxIconUncheckedPath(lc: LearningContent) {
if (belongsToCompetenceCertificate(lc)) {
return "/static/icons/icon-lc-competence-certificate.svg";
}
return "/static/icons/icon-checkbox-unchecked.svg";
}
function checkboxIconUncheckedHoverPath(lc: LearningContent) {
if (belongsToCompetenceCertificate(lc)) {
return "/static/icons/icon-lc-competence-certificate.svg";
}
return "/static/icons/icon-checkbox-unchecked-hover.svg";
return itCheckboxDefaultIconUncheckedTailwindClass;
}
</script>
@ -163,33 +156,36 @@ function checkboxIconUncheckedHoverPath(lc: LearningContent) {
<li
v-for="learningContent in learningUnit.learningContents"
:key="learningContent.id"
class="flex items-center gap-4 pb-3 lg:pb-6"
>
<div v-if="props.readonly">
<it-icon-check
v-if="learningContent.completion_status === 'SUCCESS'"
class="block h-8 w-8"
></it-icon-check>
<div v-else class="h-8 w-8"></div>
</div>
<ItCheckbox
v-else
:checkbox-item="{
value: learningContent.completion_status,
checked: learningContent.completion_status === 'SUCCESS',
}"
:disabled="!learningContent.can_user_self_toggle_course_completion"
:data-cy="`${learningContent.slug}-checkbox`"
:icon-checked-path="checkboxIconCheckedPath(learningContent)"
:icon-checked-hover-path="checkboxIconCheckedHoverPath(learningContent)"
:icon-unchecked-path="checkboxIconUncheckedPath(learningContent)"
:icon-unchecked-hover-path="
checkboxIconUncheckedHoverPath(learningContent)
"
@toggle="toggleCompleted(learningContent)"
/>
<div class="flex-auto pt-1 sm:pt-0">
<div class="flex items-center gap-4">
<div class="flex items-center gap-4 pb-6">
<div v-if="props.readonly">
<it-icon-check
v-if="learningContent.completion_status === 'SUCCESS'"
class="block h-8 w-8"
></it-icon-check>
<div v-else class="h-8 w-8"></div>
</div>
<ItCheckbox
v-else
:checkbox-item="{
value: learningContent.completion_status,
checked: learningContent.completion_status === 'SUCCESS',
}"
:disabled="!learningContent.can_user_self_toggle_course_completion"
:data-cy="`${learningContent.slug}-checkbox`"
:icon-checked-tailwind-class="
checkboxIconCheckedTailwindClass(learningContent)
"
:icon-unchecked-tailwind-class="
checkboxIconUncheckedTailwindClass(learningContent)
"
@toggle="toggleCompleted(learningContent)"
/>
<div class="flex flex-auto flex-col gap-4 xl:flex-row xl:justify-between">
<div class="xl:order-last">
<LearningContentBadge :learning-content="learningContent" />
</div>
<div>
<div v-if="props.readonly" class="w-full text-left sm:w-auto">
{{ learningContent.title }}
@ -202,52 +198,51 @@ function checkboxIconUncheckedHoverPath(lc: LearningContent) {
>
{{ learningContent.title }}
</button>
<div
v-if="belongsToCompetenceCertificate(learningContent)"
class="text-sm text-gray-800"
>
{{ $t("circlePage.Dieser Inhalt gehört zu x") }}
<br />
<router-link
v-if="learningContent.competence_certificate?.frontend_url"
:to="learningContent.competence_certificate.frontend_url"
class="link"
data-cy="show-results"
>
{{ $t("circlePage.Im KompetenzNavi anschauen") }}
</router-link>
</div>
</div>
<div
class="flex flex-col items-center justify-between gap-4 sm:grow md:flex-row lg:flex-col xl:flex-row"
>
<button
v-if="
learningContent.translation_key ===
continueTranslationKeyTuple[0] && !props.readonly
"
class="btn-blue order-1 sm:order-none"
data-cy="ls-continue-button"
@click.stop="circleStore.openLearningContent(learningContent)"
>
<span
v-if="continueTranslationKeyTuple[1]"
class="whitespace-nowrap"
>
{{ $t("general.start") }}
</span>
<span v-else class="whitespace-nowrap">
{{ $t("general.nextStep") }}
</span>
</button>
<div class="hidden sm:block"></div>
<div class="w-full sm:w-auto">
<LearningContentBadge :learning-content="learningContent" />
</div>
</div>
</div>
</div>
<div
v-if="belongsToCompetenceCertificate(learningContent)"
class="mb-8 ml-16 text-sm text-gray-800"
>
{{
$t("circlePage.Dieser Inhalt gehört zu x", {
x: (learningContent as LearninContentWithCompetenceCertificate)
?.competence_certificate?.title,
})
}}
<br />
<router-link
v-if="(learningContent as LearninContentWithCompetenceCertificate).competence_certificate?.frontend_url"
:to="(learningContent as LearninContentWithCompetenceCertificate).competence_certificate?.frontend_url ?? ''"
class="link"
data-cy="show-results"
>
{{ $t("circlePage.Im KompetenzNavi anschauen") }}
</router-link>
</div>
<div
v-if="
learningContent.translation_key === continueTranslationKeyTuple[0] &&
!props.readonly
"
class="mb-6"
>
<button
class="btn-blue order-1 sm:order-none"
data-cy="ls-continue-button"
@click.stop="circleStore.openLearningContent(learningContent)"
>
<span v-if="continueTranslationKeyTuple[1]" class="whitespace-nowrap">
{{ $t("general.start") }}
</span>
<span v-else class="whitespace-nowrap">
{{ $t("general.nextStep") }}
</span>
</button>
</div>
</li>
</ol>
@ -259,24 +254,21 @@ function checkboxIconUncheckedHoverPath(lc: LearningContent) {
>
<div
v-if="circleStore.calcSelfEvaluationStatus(learningUnit) === 'SUCCESS'"
class="self-evaluation-success flex items-center gap-4 pb-3 lg:pb-6"
class="self-evaluation-success flex items-center gap-4 pb-6"
>
<it-icon-smiley-happy class="h-8 w-8 flex-none" data-cy="success" />
<it-icon-smiley-happy class="mr-4 h-8 w-8 flex-none" data-cy="success" />
<div>{{ $t("selfEvaluation.selfEvaluationYes") }}</div>
</div>
<div
v-else-if="circleStore.calcSelfEvaluationStatus(learningUnit) === 'FAIL'"
class="self-evaluation-fail flex items-center gap-4 pb-3 lg:pb-6"
class="self-evaluation-fail flex items-center gap-4 pb-6"
>
<it-icon-smiley-thinking class="h-8 w-8 flex-none" data-cy="fail" />
<it-icon-smiley-thinking class="mr-4 h-8 w-8 flex-none" data-cy="fail" />
<div>{{ $t("selfEvaluation.selfEvaluationNo") }}</div>
</div>
<div
v-else
class="self-evaluation-unknown flex items-center gap-4 pb-3 lg:pb-6"
>
<it-icon-smiley-neutral class="h-8 w-8 flex-none" data-cy="unknown" />
<div>{{ $t("selfEvaluation.selfEvaluation") }}</div>
<div v-else class="self-evaluation-unknown flex items-center gap-4 pb-6">
<it-icon-smiley-neutral class="mr-4 h-8 w-8 flex-none" data-cy="unknown" />
<div>{{ $t("a.Selbsteinschätzung") }}</div>
</div>
</div>

View File

@ -6,9 +6,9 @@ from vbv_lernwelt.competence.serializers import (
from vbv_lernwelt.core.utils import get_django_content_type
from vbv_lernwelt.course.serializer_helpers import get_course_serializer_class
from vbv_lernwelt.learnpath.models import (
LearningUnit,
LearningContentEdoniqTest,
LearningContentAssignment,
LearningContentEdoniqTest,
LearningUnit,
)