feat(vocab): add dashboard learning summary and related endpoints
All checks were successful
Deploy to production / deploy (push) Successful in 2m52s
All checks were successful
Deploy to production / deploy (push) Successful in 2m52s
- Introduced `getDashboardLearningSummary` method in `VocabService` to provide a compact overview of enrolled courses and current lessons for users. - Updated `vocabController` to include a new route for the dashboard widget, allowing users to access their learning summary. - Enhanced `vocabRouter` to route requests for the new dashboard widget endpoint. - Added localization support for the new dashboard features across multiple languages, improving user engagement and accessibility. - Updated UI components to integrate the new dashboard widget, ensuring a seamless user experience.
This commit is contained in:
@@ -25,9 +25,11 @@
|
||||
</span>
|
||||
<span>
|
||||
{{ $t('falukant.politics.current.benefit') }}:
|
||||
<template v-if="pos.benefit && pos.benefit.length">
|
||||
<span v-if="pos.benefit.includes('*')">{{ $t('falukant.politics.current.benefit_all') }}</span>
|
||||
<span v-else>{{ pos.benefit.join(', ') }}</span>
|
||||
<template v-if="politicsBenefitItems(pos).length">
|
||||
<template v-for="(b, i) in politicsBenefitItems(pos)" :key="i">
|
||||
<span>{{ formatPoliticsBenefitItem(b) }}</span>
|
||||
<span v-if="i < politicsBenefitItems(pos).length - 1">, </span>
|
||||
</template>
|
||||
</template>
|
||||
<template v-else>—</template>
|
||||
</span>
|
||||
@@ -178,6 +180,49 @@ export default {
|
||||
this.loadCurrentPositions();
|
||||
},
|
||||
methods: {
|
||||
politicsBenefitItems(pos) {
|
||||
const raw = pos?.benefit;
|
||||
if (!Array.isArray(raw) || !raw.length) {
|
||||
return [];
|
||||
}
|
||||
if (raw.every((x) => typeof x === 'string') && raw.includes('*')) {
|
||||
return [this.$t('falukant.politics.current.benefit_all')];
|
||||
}
|
||||
return raw;
|
||||
},
|
||||
|
||||
formatPoliticsRegionLevel(key) {
|
||||
const k = String(key || '');
|
||||
const path = `falukant.politics.regionLevels.${k}`;
|
||||
const t = this.$t(path);
|
||||
return t !== path ? t : k;
|
||||
},
|
||||
|
||||
formatPoliticsBenefitItem(b) {
|
||||
if (b == null) {
|
||||
return '';
|
||||
}
|
||||
if (typeof b === 'string') {
|
||||
return b;
|
||||
}
|
||||
if (typeof b === 'object' && b.tr) {
|
||||
if (b.tr === 'tax_exemption' && b.params?.all) {
|
||||
return this.$t('falukant.politics.benefits.tax_exemption_all');
|
||||
}
|
||||
if (b.tr === 'tax_exemption' && Array.isArray(b.params?.regions)) {
|
||||
const labels = b.params.regions.map((r) => this.formatPoliticsRegionLevel(r)).join(', ');
|
||||
return this.$t('falukant.politics.benefits.tax_exemption', { regions: labels });
|
||||
}
|
||||
if (b.tr === 'daily_salary') {
|
||||
return this.$t('falukant.politics.benefits.daily_salary', { amount: b.params?.amount ?? '—' });
|
||||
}
|
||||
if (b.tr === 'generic_benefit') {
|
||||
return this.$t('falukant.politics.benefits.generic', { code: b.params?.code || '' });
|
||||
}
|
||||
}
|
||||
return String(b);
|
||||
},
|
||||
|
||||
onTabChange(tab) {
|
||||
if (tab === 'current') {
|
||||
this.loadCurrentPositions();
|
||||
|
||||
@@ -192,7 +192,8 @@ export default {
|
||||
'/api/news': 'home.dashboard.widgetLabels.news',
|
||||
'/api/calendar/widget/birthdays': 'home.dashboard.widgetLabels.birthdays',
|
||||
'/api/calendar/widget/upcoming': 'home.dashboard.widgetLabels.upcoming',
|
||||
'/api/calendar/widget/mini': 'home.dashboard.widgetLabels.calendar'
|
||||
'/api/calendar/widget/mini': 'home.dashboard.widgetLabels.calendar',
|
||||
'/api/vocab/dashboard-widget': 'home.dashboard.widgetLabels.vocabCourses'
|
||||
}[endpoint];
|
||||
return key ? this.$t(key) : fallbackLabel;
|
||||
},
|
||||
@@ -211,7 +212,8 @@ export default {
|
||||
'News',
|
||||
'Geburtstage',
|
||||
'Nächste Termine',
|
||||
'Kalender'
|
||||
'Kalender',
|
||||
'Sprachkurse'
|
||||
];
|
||||
return {
|
||||
...widget,
|
||||
|
||||
Reference in New Issue
Block a user