feat(vocab): synchronize SRS session progress and update related UI elements
This commit is contained in:
@@ -84,7 +84,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="srsDueCount > 0" class="course-srs-plan">
|
||||
<div v-if="srsDailyCount > 0" class="course-srs-plan">
|
||||
<div>
|
||||
<span class="course-srs-plan__eyebrow">{{ $t('socialnetwork.vocab.courses.srsEyebrow') }}</span>
|
||||
<h4>{{ $t('socialnetwork.vocab.courses.srsTitle', { scheduled: srsDailyCount, total: srsDueCount }) }}</h4>
|
||||
@@ -98,7 +98,7 @@
|
||||
<div v-if="todayRecommendedSteps.length > 0" class="course-today-plan">
|
||||
<h4 class="course-today-plan__title">{{ $t('socialnetwork.vocab.courses.courseTodayPlanTitle') }}</h4>
|
||||
<p class="course-today-plan__intro">
|
||||
{{ srsDueCount > 0
|
||||
{{ srsDailyCount > 0
|
||||
? $t('socialnetwork.vocab.courses.courseTodayPlanIntroSrs')
|
||||
: dueReviewLessons.length > 0
|
||||
? $t('socialnetwork.vocab.courses.courseTodayPlanIntro')
|
||||
@@ -354,6 +354,8 @@ import { confirmAction, showApiError, showInfo, showSuccess } from '@/utils/feed
|
||||
import VocabPracticeDialog from '@/dialogues/socialnetwork/VocabPracticeDialog.vue';
|
||||
import { localizeVocabCourseTitle } from '@/utils/vocabCourseTitle.js';
|
||||
|
||||
const SRS_SESSION_STORAGE_VERSION = 2;
|
||||
|
||||
export default {
|
||||
name: 'VocabCourseView',
|
||||
components: { VocabPracticeDialog },
|
||||
@@ -372,6 +374,7 @@ export default {
|
||||
srsDueItems: [],
|
||||
srsDueTotal: 0,
|
||||
srsDailyLimit: 50,
|
||||
srsTodayRemaining: null,
|
||||
srsLoading: false,
|
||||
showAddLessonDialog: false,
|
||||
assistantSettings: null,
|
||||
@@ -422,6 +425,9 @@ export default {
|
||||
return Array.isArray(this.srsDueItems) ? this.srsDueItems.length : 0;
|
||||
},
|
||||
srsDailyCount() {
|
||||
if (Number.isFinite(Number(this.srsTodayRemaining))) {
|
||||
return Math.max(0, Number(this.srsTodayRemaining));
|
||||
}
|
||||
return Math.min(this.srsDueCount, this.srsDailyLimit);
|
||||
},
|
||||
hardVocabCount() {
|
||||
@@ -563,6 +569,29 @@ export default {
|
||||
displayCourseTitle(course) {
|
||||
return localizeVocabCourseTitle(course?.title, this.$i18n?.locale) || '';
|
||||
},
|
||||
getLocalDateKey() {
|
||||
const date = new Date();
|
||||
return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`;
|
||||
},
|
||||
syncSrsSessionProgress() {
|
||||
const key = `yourpart:vocab:srsSession:v${SRS_SESSION_STORAGE_VERSION}:${this.courseId}:${this.getLocalDateKey()}`;
|
||||
try {
|
||||
const session = JSON.parse(localStorage.getItem(key) || 'null');
|
||||
const isCurrentSession = session
|
||||
&& session.version === SRS_SESSION_STORAGE_VERSION
|
||||
&& String(session.courseId) === String(this.courseId)
|
||||
&& session.dateKey === this.getLocalDateKey();
|
||||
if (!isCurrentSession) {
|
||||
this.srsTodayRemaining = null;
|
||||
return;
|
||||
}
|
||||
const total = Math.max(0, Number(session.initialTotalDue) || 0);
|
||||
const done = new Set(Array.isArray(session.doneIds) ? session.doneIds : []).size;
|
||||
this.srsTodayRemaining = Math.max(0, total - done);
|
||||
} catch (_) {
|
||||
this.srsTodayRemaining = null;
|
||||
}
|
||||
},
|
||||
async refreshHardVocabList() {
|
||||
if (!this.courseId) {
|
||||
this.hardVocabList = [];
|
||||
@@ -586,6 +615,12 @@ export default {
|
||||
},
|
||||
handleWindowFocus() {
|
||||
this.refreshHardVocabList();
|
||||
this.syncSrsSessionProgress();
|
||||
},
|
||||
handleSrsSessionChanged(event) {
|
||||
if (String(event?.detail?.courseId || '') === String(this.courseId)) {
|
||||
this.syncSrsSessionProgress();
|
||||
}
|
||||
},
|
||||
handleHardVocabChanged(event) {
|
||||
const detailCourseId = event?.detail?.courseId;
|
||||
@@ -635,6 +670,7 @@ export default {
|
||||
this.srsDailyLimit = 50;
|
||||
} finally {
|
||||
this.srsLoading = false;
|
||||
this.syncSrsSessionProgress();
|
||||
}
|
||||
},
|
||||
async loadChapters() {
|
||||
@@ -1009,10 +1045,13 @@ export default {
|
||||
this.loadAssistantSettings()
|
||||
]);
|
||||
this.refreshHardVocabList();
|
||||
this.syncSrsSessionProgress();
|
||||
window.addEventListener('focus', this.handleWindowFocus);
|
||||
window.addEventListener('yourpart:vocab:srsSession:changed', this.handleSrsSessionChanged);
|
||||
},
|
||||
beforeUnmount() {
|
||||
window.removeEventListener('focus', this.handleWindowFocus);
|
||||
window.removeEventListener('yourpart:vocab:srsSession:changed', this.handleSrsSessionChanged);
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user