feat(vocab): stabilize daily batch handling in SRS session and improve due item display
All checks were successful
Deploy to production / deploy (push) Successful in 3m8s
All checks were successful
Deploy to production / deploy (push) Successful in 3m8s
This commit is contained in:
@@ -133,7 +133,7 @@
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<button type="button" @click="orderParty()">
|
||||
<button type="button" @click="orderParty()" :disabled="isOrderingParty">
|
||||
{{ $t('falukant.reputation.party.order') }}
|
||||
</button>
|
||||
</div>
|
||||
@@ -224,6 +224,7 @@ export default {
|
||||
selectedNobilityIds: [],
|
||||
servantRatio: 50,
|
||||
relationshipId: null,
|
||||
isOrderingParty: false,
|
||||
weddingCandidates: [],
|
||||
inProgressParties: [],
|
||||
completedParties: [],
|
||||
@@ -317,15 +318,23 @@ export default {
|
||||
this.nobilityTitles = await apiClient.get('/api/falukant/nobility/titels').then(r => r.data)
|
||||
},
|
||||
async orderParty() {
|
||||
await apiClient.post('/api/falukant/party', {
|
||||
partyTypeId: this.newPartyTypeId,
|
||||
musicId: this.musicId,
|
||||
banquetteId: this.banquetteId,
|
||||
nobilityIds: this.selectedNobilityIds.map(n => n.id ?? n),
|
||||
servantRatio: this.servantRatio,
|
||||
relationshipId: this.relationshipId
|
||||
});
|
||||
this.toggleNewPartyView();
|
||||
if (this.isOrderingParty) return;
|
||||
this.isOrderingParty = true;
|
||||
try {
|
||||
await apiClient.post('/api/falukant/party', {
|
||||
partyTypeId: this.newPartyTypeId,
|
||||
musicId: this.musicId,
|
||||
banquetteId: this.banquetteId,
|
||||
nobilityIds: this.selectedNobilityIds.map(n => n.id ?? n),
|
||||
servantRatio: this.servantRatio,
|
||||
relationshipId: this.relationshipId
|
||||
});
|
||||
await this.loadParties();
|
||||
this.relationshipId = null;
|
||||
this.toggleNewPartyView();
|
||||
} finally {
|
||||
this.isOrderingParty = false;
|
||||
}
|
||||
},
|
||||
getPartyDate(createdAt) {
|
||||
// Feste finden 1 Tag nach der Bestellung statt
|
||||
|
||||
@@ -317,11 +317,10 @@
|
||||
<section class="dialog intensive-status-dialog" role="dialog" aria-modal="true" @click.stop>
|
||||
<h3>{{ $t('socialnetwork.vocab.courses.courseFlowIntensiveStatusTitle') }}</h3>
|
||||
<p class="intensive-status-dialog__hint">{{ $t('socialnetwork.vocab.courses.courseFlowIntensiveStatusNoDate') }}</p>
|
||||
<p v-if="srsDailyCount === 0 && srsUpcoming.length === 0">{{ $t('socialnetwork.vocab.courses.courseFlowIntensiveStatusAllDone') }}</p>
|
||||
<p v-if="srsDueCount === 0 && srsUpcoming.length === 0">{{ $t('socialnetwork.vocab.courses.courseFlowIntensiveStatusAllDone') }}</p>
|
||||
<ul v-else class="intensive-status-dialog__list">
|
||||
<li v-if="srsDailyCount > 0" class="intensive-status-dialog__item--due">
|
||||
<span>{{ $t('socialnetwork.vocab.courses.courseFlowIntensiveStatusDue') }}</span>
|
||||
<strong>{{ $t('socialnetwork.vocab.courses.courseFlowIntensiveStatusProgress', { count: srsDailyCount }) }}</strong>
|
||||
<li v-if="srsDueCount > 0" class="intensive-status-dialog__item--due">
|
||||
<span>{{ $t('socialnetwork.vocab.courses.courseFlowIntensiveStatusDue', { remaining: srsDailyCount, quota: srsDailyQuota, total: srsDueCount }) }}</span>
|
||||
</li>
|
||||
<li v-for="entry in srsUpcoming" :key="entry.date">
|
||||
<span>{{ formatSrsDate(entry.date) }}</span>
|
||||
@@ -397,6 +396,7 @@ export default {
|
||||
srsDueTotal: 0,
|
||||
srsDailyLimit: 50,
|
||||
srsTodayRemaining: null,
|
||||
srsTodayQuota: null,
|
||||
srsUpcoming: [],
|
||||
srsLoading: false,
|
||||
showIntensiveStatusDialog: false,
|
||||
@@ -449,9 +449,17 @@ export default {
|
||||
return Array.isArray(this.srsDueItems) ? this.srsDueItems.length : 0;
|
||||
},
|
||||
srsDailyCount() {
|
||||
// Der Server ist die maßgebliche Quelle für fällige Begriffe. Ein alter
|
||||
// localStorage-Sitzungsstand darf eine neue oder erneut fällige
|
||||
// Tageswiederholung nicht unsichtbar machen.
|
||||
// A valid current-day session represents the fixed daily batch. Without
|
||||
// one, the server's due count determines the first batch (max. 50).
|
||||
if (Number.isFinite(Number(this.srsTodayRemaining))) {
|
||||
return Math.max(0, Number(this.srsTodayRemaining));
|
||||
}
|
||||
return Math.min(this.srsDueCount, this.srsDailyLimit);
|
||||
},
|
||||
srsDailyQuota() {
|
||||
if (Number.isFinite(Number(this.srsTodayQuota))) {
|
||||
return Math.max(0, Number(this.srsTodayQuota));
|
||||
}
|
||||
return Math.min(this.srsDueCount, this.srsDailyLimit);
|
||||
},
|
||||
hardVocabCount() {
|
||||
@@ -588,13 +596,18 @@ export default {
|
||||
&& session.dateKey === this.getLocalDateKey();
|
||||
if (!isCurrentSession) {
|
||||
this.srsTodayRemaining = null;
|
||||
this.srsTodayQuota = null;
|
||||
return;
|
||||
}
|
||||
const total = Math.max(0, Number(session.initialTotalDue) || 0);
|
||||
const done = new Set(Array.isArray(session.doneIds) ? session.doneIds : []).size;
|
||||
const initialIds = new Set(Array.isArray(session.initialDueIds) ? session.initialDueIds : []);
|
||||
const done = new Set((Array.isArray(session.doneIds) ? session.doneIds : [])
|
||||
.filter((id) => initialIds.has(id))).size;
|
||||
this.srsTodayRemaining = Math.max(0, total - done);
|
||||
this.srsTodayQuota = total;
|
||||
} catch (_) {
|
||||
this.srsTodayRemaining = null;
|
||||
this.srsTodayQuota = null;
|
||||
}
|
||||
},
|
||||
async refreshHardVocabList() {
|
||||
|
||||
Reference in New Issue
Block a user