feat(vocab-lesson): implement pagination for vocabulary overview in lesson view
All checks were successful
Deploy to production / deploy (push) Successful in 2m59s
All checks were successful
Deploy to production / deploy (push) Successful in 2m59s
- Added pagination functionality to the vocabulary overview in the VocabLessonView component, allowing users to navigate through vocabulary items more efficiently. - Introduced new localization entries for pagination controls in Cebuano, German, English, Spanish, and French, ensuring a consistent user experience across languages. - Enhanced the UI with buttons for previous and next navigation, improving accessibility and usability of the vocabulary list.
This commit is contained in:
@@ -617,6 +617,9 @@
|
|||||||
"deepenSectionTitle": "Deepen ug review",
|
"deepenSectionTitle": "Deepen ug review",
|
||||||
"assistantSectionTitle": "Deepen uban sa pinulongan katabang",
|
"assistantSectionTitle": "Deepen uban sa pinulongan katabang",
|
||||||
"vocabOverviewToggle": "Show full overview sa terms",
|
"vocabOverviewToggle": "Show full overview sa terms",
|
||||||
|
"vocabOverviewPrev": "Balik",
|
||||||
|
"vocabOverviewNext": "Sunod",
|
||||||
|
"vocabOverviewPager": "{from}–{to} sa {total} · Page {page} sa {pages}",
|
||||||
"vocabTrainerLockedHint": "Palihog confirm two preparation steps under “Preparation sa wala pa ang bokabularyo trainer” una.",
|
"vocabTrainerLockedHint": "Palihog confirm two preparation steps under “Preparation sa wala pa ang bokabularyo trainer” una.",
|
||||||
"exerciseUnlockHintAfterPrep": "Work through ang prepared terms una. Ang tsek sa kapitulo will unlock afterwards.",
|
"exerciseUnlockHintAfterPrep": "Work through ang prepared terms una. Ang tsek sa kapitulo will unlock afterwards.",
|
||||||
"speakingTasks": "Speaking Tasks",
|
"speakingTasks": "Speaking Tasks",
|
||||||
|
|||||||
@@ -586,6 +586,9 @@
|
|||||||
"deepenSectionTitle": "Vertiefen und nachlesen",
|
"deepenSectionTitle": "Vertiefen und nachlesen",
|
||||||
"assistantSectionTitle": "Mit Sprachassistent vertiefen",
|
"assistantSectionTitle": "Mit Sprachassistent vertiefen",
|
||||||
"vocabOverviewToggle": "Gesamtübersicht der Begriffe anzeigen",
|
"vocabOverviewToggle": "Gesamtübersicht der Begriffe anzeigen",
|
||||||
|
"vocabOverviewPrev": "Zurück",
|
||||||
|
"vocabOverviewNext": "Weiter",
|
||||||
|
"vocabOverviewPager": "{from}–{to} von {total} · Seite {page} von {pages}",
|
||||||
"vocabTrainerLockedHint": "Bitte bestätige zuerst zwei Lern-Durchgänge bei „Vorbereitung vor dem Vokabeltrainer“.",
|
"vocabTrainerLockedHint": "Bitte bestätige zuerst zwei Lern-Durchgänge bei „Vorbereitung vor dem Vokabeltrainer“.",
|
||||||
"exerciseUnlockHintAfterPrep": "Arbeite zuerst die vorbereiteten Begriffe durch. Danach wird die Kapitel-Prüfung freigeschaltet.",
|
"exerciseUnlockHintAfterPrep": "Arbeite zuerst die vorbereiteten Begriffe durch. Danach wird die Kapitel-Prüfung freigeschaltet.",
|
||||||
"speakingTasks": "Sprechaufträge",
|
"speakingTasks": "Sprechaufträge",
|
||||||
|
|||||||
@@ -586,6 +586,9 @@
|
|||||||
"deepenSectionTitle": "Deepen and review",
|
"deepenSectionTitle": "Deepen and review",
|
||||||
"assistantSectionTitle": "Deepen with language assistant",
|
"assistantSectionTitle": "Deepen with language assistant",
|
||||||
"vocabOverviewToggle": "Show full overview of terms",
|
"vocabOverviewToggle": "Show full overview of terms",
|
||||||
|
"vocabOverviewPrev": "Previous",
|
||||||
|
"vocabOverviewNext": "Next",
|
||||||
|
"vocabOverviewPager": "{from}–{to} of {total} · Page {page} of {pages}",
|
||||||
"vocabTrainerLockedHint": "Please confirm two preparation steps under “Preparation before the vocabulary trainer” first.",
|
"vocabTrainerLockedHint": "Please confirm two preparation steps under “Preparation before the vocabulary trainer” first.",
|
||||||
"exerciseUnlockHintAfterPrep": "Work through the prepared terms first. The chapter test will unlock afterwards.",
|
"exerciseUnlockHintAfterPrep": "Work through the prepared terms first. The chapter test will unlock afterwards.",
|
||||||
"speakingTasks": "Speaking Tasks",
|
"speakingTasks": "Speaking Tasks",
|
||||||
|
|||||||
@@ -584,6 +584,9 @@
|
|||||||
"deepenSectionTitle": "Profundizar y repasar",
|
"deepenSectionTitle": "Profundizar y repasar",
|
||||||
"assistantSectionTitle": "Profundizar con el asistente de idiomas",
|
"assistantSectionTitle": "Profundizar con el asistente de idiomas",
|
||||||
"vocabOverviewToggle": "Mostrar vista general completa de los términos",
|
"vocabOverviewToggle": "Mostrar vista general completa de los términos",
|
||||||
|
"vocabOverviewPrev": "Anterior",
|
||||||
|
"vocabOverviewNext": "Siguiente",
|
||||||
|
"vocabOverviewPager": "{from}–{to} de {total} · Página {page} de {pages}",
|
||||||
"vocabTrainerLockedHint": "Confirma primero los dos pasos de preparación arriba.",
|
"vocabTrainerLockedHint": "Confirma primero los dos pasos de preparación arriba.",
|
||||||
"exerciseUnlockHintAfterPrep": "Primero recorre los términos preparados. Después se desbloqueará la prueba del capítulo.",
|
"exerciseUnlockHintAfterPrep": "Primero recorre los términos preparados. Después se desbloqueará la prueba del capítulo.",
|
||||||
"speakingTasks": "Tareas orales",
|
"speakingTasks": "Tareas orales",
|
||||||
|
|||||||
@@ -584,6 +584,9 @@
|
|||||||
"deepenSectionTitle": "Approfondissez et lisez",
|
"deepenSectionTitle": "Approfondissez et lisez",
|
||||||
"assistantSectionTitle": "Approfondissez avec l'assistant vocal",
|
"assistantSectionTitle": "Approfondissez avec l'assistant vocal",
|
||||||
"vocabOverviewToggle": "Afficher un aperçu complet des termes",
|
"vocabOverviewToggle": "Afficher un aperçu complet des termes",
|
||||||
|
"vocabOverviewPrev": "Précédent",
|
||||||
|
"vocabOverviewNext": "Suivant",
|
||||||
|
"vocabOverviewPager": "{from}–{to} sur {total} · Page {page} sur {pages}",
|
||||||
"vocabTrainerLockedHint": "Veuillez d'abord confirmer deux séances d'apprentissage dans « Préparation avant l'entraîneur de vocabulaire ».",
|
"vocabTrainerLockedHint": "Veuillez d'abord confirmer deux séances d'apprentissage dans « Préparation avant l'entraîneur de vocabulaire ».",
|
||||||
"exerciseUnlockHintAfterPrep": "Commencez par parcourir les termes préparés. L’examen du chapitre sera alors débloqué.",
|
"exerciseUnlockHintAfterPrep": "Commencez par parcourir les termes préparés. L’examen du chapitre sera alors débloqué.",
|
||||||
"speakingTasks": "Travaux oraux",
|
"speakingTasks": "Travaux oraux",
|
||||||
|
|||||||
@@ -156,12 +156,31 @@
|
|||||||
</summary>
|
</summary>
|
||||||
<p class="vocab-info-text">{{ $t('socialnetwork.vocab.courses.vocabInfoText') }}</p>
|
<p class="vocab-info-text">{{ $t('socialnetwork.vocab.courses.vocabInfoText') }}</p>
|
||||||
<div class="vocab-items">
|
<div class="vocab-items">
|
||||||
<div v-for="(vocab, index) in lessonVocab" :key="index" class="vocab-item">
|
<div v-for="(vocab, index) in paginatedLessonVocab" :key="`v-${vocabOverviewPagerMeta.page}-${index}`" class="vocab-item">
|
||||||
<strong>{{ vocab.learning || '—' }}</strong>
|
<strong>{{ vocab.learning || '—' }}</strong>
|
||||||
<span class="separator">→</span>
|
<span class="separator">→</span>
|
||||||
<span>{{ vocab.reference }}</span>
|
<span>{{ vocab.reference }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div v-if="vocabOverviewTotalPages > 1" class="vocab-items-pager">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="vocab-items-pager__btn"
|
||||||
|
:disabled="vocabOverviewPagerMeta.page <= 1"
|
||||||
|
@click="vocabOverviewGoPrev"
|
||||||
|
>
|
||||||
|
{{ $t('socialnetwork.vocab.courses.vocabOverviewPrev') }}
|
||||||
|
</button>
|
||||||
|
<span class="vocab-items-pager__meta">{{ $t('socialnetwork.vocab.courses.vocabOverviewPager', vocabOverviewPagerMeta) }}</span>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="vocab-items-pager__btn"
|
||||||
|
:disabled="vocabOverviewPagerMeta.page >= vocabOverviewPagerMeta.pages"
|
||||||
|
@click="vocabOverviewGoNext"
|
||||||
|
>
|
||||||
|
{{ $t('socialnetwork.vocab.courses.vocabOverviewNext') }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
<div v-if="visibleGrammarExplanations.length > 0" class="lesson-grammar-impulse didactic-card">
|
<div v-if="visibleGrammarExplanations.length > 0" class="lesson-grammar-impulse didactic-card">
|
||||||
@@ -957,6 +976,8 @@ const LESSON_STATE_VERSION = 1;
|
|||||||
const VOCAB_REPEAT_INTERVALS = [1, 2, 4];
|
const VOCAB_REPEAT_INTERVALS = [1, 2, 4];
|
||||||
/** Mindest-Erfolgsquote im Vokabeltrainer (gesamt), damit die Kapitel-Prüfung freigeschaltet wird. */
|
/** Mindest-Erfolgsquote im Vokabeltrainer (gesamt), damit die Kapitel-Prüfung freigeschaltet wird. */
|
||||||
const EXERCISE_UNLOCK_MIN_SUCCESS_PERCENT = 70;
|
const EXERCISE_UNLOCK_MIN_SUCCESS_PERCENT = 70;
|
||||||
|
/** Max. Zeilen pro Seite in der einklappbaren Vokabel-Gesamtübersicht */
|
||||||
|
const VOCAB_OVERVIEW_PAGE_SIZE = 40;
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'VocabLessonView',
|
name: 'VocabLessonView',
|
||||||
@@ -1046,7 +1067,9 @@ export default {
|
|||||||
lessonStateSaveTimer: null,
|
lessonStateSaveTimer: null,
|
||||||
lessonStateSaveInFlight: false,
|
lessonStateSaveInFlight: false,
|
||||||
pendingLessonStatePayload: null,
|
pendingLessonStatePayload: null,
|
||||||
resettingLessonProgress: false
|
resettingLessonProgress: false,
|
||||||
|
/** Seitennummer (1-basiert) für die Vokabel-Gesamtübersicht */
|
||||||
|
vocabOverviewPage: 1
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@@ -1347,6 +1370,31 @@ export default {
|
|||||||
|
|
||||||
return Array.from(vocabByReference.values());
|
return Array.from(vocabByReference.values());
|
||||||
},
|
},
|
||||||
|
vocabOverviewTotalPages() {
|
||||||
|
const n = this.lessonVocab.length;
|
||||||
|
if (n === 0) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return Math.ceil(n / VOCAB_OVERVIEW_PAGE_SIZE);
|
||||||
|
},
|
||||||
|
paginatedLessonVocab() {
|
||||||
|
const list = this.lessonVocab;
|
||||||
|
const totalPages = this.vocabOverviewTotalPages;
|
||||||
|
const page = Math.min(Math.max(1, this.vocabOverviewPage), totalPages);
|
||||||
|
const start = (page - 1) * VOCAB_OVERVIEW_PAGE_SIZE;
|
||||||
|
return list.slice(start, start + VOCAB_OVERVIEW_PAGE_SIZE);
|
||||||
|
},
|
||||||
|
vocabOverviewPagerMeta() {
|
||||||
|
const n = this.lessonVocab.length;
|
||||||
|
const totalPages = this.vocabOverviewTotalPages;
|
||||||
|
const page = Math.min(Math.max(1, this.vocabOverviewPage), totalPages);
|
||||||
|
if (n === 0) {
|
||||||
|
return { from: 0, to: 0, page: 1, pages: 1, total: 0 };
|
||||||
|
}
|
||||||
|
const from = (page - 1) * VOCAB_OVERVIEW_PAGE_SIZE + 1;
|
||||||
|
const to = Math.min(page * VOCAB_OVERVIEW_PAGE_SIZE, n);
|
||||||
|
return { from, to, page, pages: totalPages, total: n };
|
||||||
|
},
|
||||||
trainableLessonVocab() {
|
trainableLessonVocab() {
|
||||||
return this.lessonVocab.filter((entry) => entry.learning && entry.reference && entry.learning !== entry.reference);
|
return this.lessonVocab.filter((entry) => entry.learning && entry.reference && entry.learning !== entry.reference);
|
||||||
},
|
},
|
||||||
@@ -1598,9 +1646,28 @@ export default {
|
|||||||
this.isNavigatingToNext = false;
|
this.isNavigatingToNext = false;
|
||||||
this.loadLesson();
|
this.loadLesson();
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
lessonVocab: {
|
||||||
|
handler() {
|
||||||
|
const totalPages = this.vocabOverviewTotalPages;
|
||||||
|
if (this.vocabOverviewPage > totalPages) {
|
||||||
|
this.vocabOverviewPage = Math.max(1, totalPages);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
deep: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
vocabOverviewGoPrev() {
|
||||||
|
if (this.vocabOverviewPagerMeta.page > 1) {
|
||||||
|
this.vocabOverviewPage -= 1;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
vocabOverviewGoNext() {
|
||||||
|
if (this.vocabOverviewPagerMeta.page < this.vocabOverviewPagerMeta.pages) {
|
||||||
|
this.vocabOverviewPage += 1;
|
||||||
|
}
|
||||||
|
},
|
||||||
exportPersistedExerciseAnswers() {
|
exportPersistedExerciseAnswers() {
|
||||||
const exportedAnswers = {};
|
const exportedAnswers = {};
|
||||||
this.effectiveExercises.forEach((exercise) => {
|
this.effectiveExercises.forEach((exercise) => {
|
||||||
@@ -2267,6 +2334,7 @@ export default {
|
|||||||
this.exerciseRetryPending = false;
|
this.exerciseRetryPending = false;
|
||||||
this.exerciseRetryPendingSinceAttempts = 0;
|
this.exerciseRetryPendingSinceAttempts = 0;
|
||||||
this.exerciseSequentialIndex = 0;
|
this.exerciseSequentialIndex = 0;
|
||||||
|
this.vocabOverviewPage = 1;
|
||||||
this.exercisePreparationCompleted = false;
|
this.exercisePreparationCompleted = false;
|
||||||
this.lessonPrepStage = 0;
|
this.lessonPrepStage = 0;
|
||||||
this.lessonPrepIndex = 0;
|
this.lessonPrepIndex = 0;
|
||||||
@@ -4548,6 +4616,43 @@ export default {
|
|||||||
margin: 0 10px;
|
margin: 0 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.vocab-items-pager {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 12px 16px;
|
||||||
|
margin-top: 14px;
|
||||||
|
padding-top: 12px;
|
||||||
|
border-top: 1px solid #eadfcf;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vocab-items-pager__btn {
|
||||||
|
padding: 6px 14px;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
border: 1px solid #c9b896;
|
||||||
|
border-radius: 8px;
|
||||||
|
background: #faf8f3;
|
||||||
|
color: #333;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vocab-items-pager__btn:hover:not(:disabled) {
|
||||||
|
background: #f0ebe0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vocab-items-pager__btn:disabled {
|
||||||
|
opacity: 0.45;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vocab-items-pager__meta {
|
||||||
|
font-size: 0.88rem;
|
||||||
|
color: #555;
|
||||||
|
text-align: center;
|
||||||
|
min-width: min(100%, 14rem);
|
||||||
|
}
|
||||||
|
|
||||||
.grammar-explanations {
|
.grammar-explanations {
|
||||||
margin: 20px 0;
|
margin: 20px 0;
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
|
|||||||
Reference in New Issue
Block a user