feat(vocab): add lesson and completed lesson vocab pool endpoints
All checks were successful
Deploy to production / deploy (push) Successful in 3m5s

- Implemented new endpoints in VocabController for retrieving vocab pools based on lessons and completed lessons.
- Updated vocabRouter to include routes for accessing lesson vocab pools and completed lesson vocab pools.
- Enhanced VocabService with methods to extract vocab from exercises and lesson didactics, improving vocabulary retrieval for users.
- Modified VocabPracticeDialog and VocabCourseView components to support new vocab pool functionalities, enhancing user experience in vocabulary practice.
This commit is contained in:
Torsten Schulz (local)
2026-03-31 11:59:48 +02:00
parent 01293b0102
commit 3187a6e7b0
5 changed files with 313 additions and 9 deletions

View File

@@ -110,7 +110,7 @@ export default {
components: { DialogWidget },
data() {
return {
openParams: null, // { languageId, chapterId }
openParams: null, // { languageId, chapterId, lessonId, courseId }
onClose: null,
loading: false,
allVocabs: false,
@@ -168,12 +168,12 @@ export default {
},
},
methods: {
open({ languageId, chapterId, onClose = null }) {
open({ languageId, chapterId, lessonId, courseId, onClose = null }) {
if (this.autoAdvanceTimer) {
clearTimeout(this.autoAdvanceTimer);
this.autoAdvanceTimer = null;
}
this.openParams = { languageId, chapterId };
this.openParams = { languageId, chapterId, lessonId, courseId };
this.onClose = typeof onClose === 'function' ? onClose : null;
this.allVocabs = false;
this.simpleMode = false;
@@ -231,7 +231,7 @@ export default {
},
resetQuestion() {
this.current = null;
this.direction = Math.random() < 0.5 ? 'L2R' : 'R2L';
this.direction = this.openParams?.lessonId ? 'L2R' : (Math.random() < 0.5 ? 'L2R' : 'R2L');
this.acceptableAnswers = [];
this.choiceOptions = [];
this.typedAnswer = '';
@@ -272,7 +272,19 @@ export default {
this.loading = true;
try {
let res;
if (this.allVocabs) {
if (this.openParams.lessonId) {
if (this.allVocabs && this.openParams.courseId) {
res = await apiClient.get(`/api/vocab/courses/${this.openParams.courseId}/completed-lesson-vocabs`, {
params: {
untilLessonId: this.openParams.lessonId
}
});
this.pool = res.data?.vocabs || [];
} else {
res = await apiClient.get(`/api/vocab/lessons/${this.openParams.lessonId}/vocab-pool`);
this.pool = res.data?.vocabs || [];
}
} else if (this.allVocabs) {
res = await apiClient.get(`/api/vocab/languages/${this.openParams.languageId}/vocabs`);
this.pool = res.data?.vocabs || [];
} else {
@@ -530,5 +542,3 @@ export default {
font-weight: bold;
}
</style>

View File

@@ -88,6 +88,13 @@
>
{{ getLessonProgress(lesson.id)?.completed ? $t('socialnetwork.vocab.courses.review') : $t('socialnetwork.vocab.courses.start') }}
</button>
<button
v-if="getLessonProgress(lesson.id)?.completed"
@click="openLessonPractice(lesson)"
class="btn-edit"
>
Im Trainer üben
</button>
<button v-if="isOwner" @click="editLesson(lesson.id)" class="btn-edit">{{ $t('socialnetwork.vocab.courses.edit') }}</button>
<button v-if="isOwner" @click="deleteLesson(lesson.id)" class="btn-delete">{{ $t('general.delete') }}</button>
</div>
@@ -99,6 +106,8 @@
</div>
</div>
<VocabPracticeDialog ref="practiceDialog" />
<!-- Add Lesson Dialog -->
<div v-if="showAddLessonDialog" class="dialog-overlay" @click="showAddLessonDialog = false">
<div class="dialog" @click.stop>
@@ -138,9 +147,11 @@
import { mapGetters } from 'vuex';
import apiClient from '@/utils/axios.js';
import { confirmAction, showApiError, showInfo, showSuccess } from '@/utils/feedback.js';
import VocabPracticeDialog from '@/dialogues/socialnetwork/VocabPracticeDialog.vue';
export default {
name: 'VocabCourseView',
components: { VocabPracticeDialog },
props: {
courseId: {
type: String,
@@ -325,6 +336,12 @@ export default {
openLesson(lessonId) {
this.$router.push(`/socialnetwork/vocab/courses/${this.courseId}/lessons/${lessonId}`);
},
openLessonPractice(lesson) {
this.$refs.practiceDialog?.open?.({
courseId: this.courseId,
lessonId: lesson.id
});
},
openLessonAssistant(lessonId) {
this.$router.push(`/socialnetwork/vocab/courses/${this.courseId}/lessons/${lessonId}?assistant=1`);
},