feat: füge Fortschrittsanzeige für die Freischaltung von Übungen hinzu
All checks were successful
Deploy to production / deploy (push) Successful in 2m6s

This commit is contained in:
Torsten Schulz (local)
2026-05-27 16:22:13 +02:00
parent 908be3e83b
commit b976532b06

View File

@@ -228,6 +228,22 @@
<div v-if="hasExercises && !canAccessExercises" class="exercise-lock-note">
<strong>{{ $t('socialnetwork.vocab.courses.exerciseLockTitle') }}</strong>
<p>{{ exerciseUnlockHint }}</p>
<div class="exercise-unlock-conditions">
<ul>
<li :class="{ ok: exerciseUnlockProgress.newContentOk }">
<strong>{{ $t('socialnetwork.vocab.courses.trainerProgressNewContentLabel') || 'Neue Inhalte:' }}</strong>
<span>{{ exerciseUnlockProgress.currentNew }} / {{ exerciseUnlockProgress.targetNew }}</span>
</li>
<li :class="{ ok: exerciseUnlockProgress.totalAttemptsOk }">
<strong>{{ $t('socialnetwork.vocab.courses.totalAttemptsLabel') || 'Trainer-Versuche gesamt:' }}</strong>
<span>{{ exerciseUnlockProgress.totalAttempts }} / {{ exerciseUnlockProgress.totalTarget }}</span>
</li>
<li :class="{ ok: exerciseUnlockProgress.successRateOk }">
<strong>{{ $t('socialnetwork.vocab.courses.successRateLabel') || 'Erfolgsrate:' }}</strong>
<span>{{ exerciseUnlockProgress.successRate }}% / {{ exerciseUnlockProgress.requiredRate }}%</span>
</li>
</ul>
</div>
</div>
<div v-if="!vocabTrainerActive" class="vocab-trainer-start">
<template v-if="canStartVocabTrainerPrep">
@@ -1237,6 +1253,25 @@ export default {
exerciseUnlockMinSuccessPercent() {
return EXERCISE_UNLOCK_MIN_SUCCESS_PERCENT;
},
exerciseUnlockProgress() {
const currentNew = Math.max(0, Number(this.vocabTrainerCurrentAttempts) || 0);
const targetNew = Math.max(0, Number(this.trainerNewFocusTarget) || 0);
const totalAttempts = Math.max(0, Number(this.vocabTrainerTotalAttempts) || 0);
const totalTarget = Math.max(0, Number(this.trainerExerciseUnlockAttempts) || 0);
const successRate = totalAttempts > 0 ? Math.round((Number(this.vocabTrainerCorrect) || 0) / totalAttempts * 100) : 0;
const requiredRate = Math.max(0, Number(this.exerciseUnlockMinSuccessPercent) || 0);
return {
currentNew,
targetNew,
totalAttempts,
totalTarget,
successRate,
requiredRate,
newContentOk: currentNew >= targetNew,
totalAttemptsOk: totalAttempts >= totalTarget,
successRateOk: successRate >= requiredRate
};
},
currentReviewShare() {
if (!this.hasPreviousVocab) {
return 0;
@@ -4598,6 +4633,22 @@ export default {
color: var(--color-text-secondary);
}
.exercise-unlock-conditions ul {
list-style: none;
padding: 0;
margin: 8px 0 0 0;
}
.exercise-unlock-conditions li {
display: flex;
justify-content: space-between;
padding: 4px 0;
color: var(--color-text-secondary);
}
.exercise-unlock-conditions li.ok {
color: var(--color-positive, #2a9d2b);
font-weight: 600;
}
.language-assistant-panel {
display: grid;
gap: 14px;