feat(vocab): add dashboard learning summary and related endpoints
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:
Torsten Schulz (local)
2026-04-02 15:06:50 +02:00
parent 77e6f8d3e8
commit 5fcd55be43
28 changed files with 1095 additions and 39 deletions

View File

@@ -20,6 +20,7 @@ import PoliticalOfficeType from "../../models/falukant/type/political_office_typ
import ChurchOfficeType from "../../models/falukant/type/church_office_type.js";
import ChurchOfficeRequirement from "../../models/falukant/predefine/church_office_requirement.js";
import PoliticalOfficeBenefitType from "../../models/falukant/type/political_office_benefit_type.js";
import PoliticalOfficeBenefit from "../../models/falukant/predefine/political_office_benefit.js";
import PoliticalOfficePrerequisite from "../../models/falukant/predefine/political_office_prerequisite.js";
import UndergroundType from "../../models/falukant/type/underground.js";
import WeatherType from "../../models/falukant/type/weather.js";
@@ -51,6 +52,7 @@ export const initializeFalukantTypes = async () => {
await initializePoliticalOfficeBenefitTypes();
await initializePoliticalOfficeTypes();
await initializePoliticalOfficePrerequisites();
await initializePoliticalOfficeBenefits();
await initializeChurchOfficeTypes();
await initializeChurchOfficePrerequisites();
await initializeUndergroundTypes();
@@ -352,6 +354,7 @@ const vehicleTypes = [
const politicalOfficeBenefitTypes = [
{ tr: 'salary' },
{ tr: 'daily_salary' },
{ tr: 'reputation' },
{ tr: 'influence' },
{ tr: 'access_level' },
@@ -1038,6 +1041,62 @@ export const initializePoliticalOfficePrerequisites = async () => {
console.log(`[Falukant] OfficePrereq neu=${created} exist=${existing}${skipped?` skip=${skipped}`:''}`);
};
/** Amtsvorteile für Politik-UI und Tageshonorar (Testsysteme / frische DBs). Produktion alternativ: backend/sql/falukant_political_office_benefits.sql */
export const initializePoliticalOfficeBenefits = async () => {
const taxType = await PoliticalOfficeBenefitType.findOne({ where: { tr: 'tax_exemption' } });
const dailyType = await PoliticalOfficeBenefitType.findOne({ where: { tr: 'daily_salary' } });
if (!dailyType) {
if (falukantDebug) console.warn('[Falukant] daily_salary Benefit-Typ fehlt, überspringe Office-Benefits');
return;
}
const taxByOffice = [
{ officeTr: 'council', regions: ['city'] },
{ officeTr: 'taxman', regions: ['city', 'county'] },
{ officeTr: 'treasurer', regions: ['city', 'county', 'shire'] },
{
officeTr: 'super-state-administrator',
regions: ['city', 'county', 'shire', 'markgrave', 'duchy']
},
{ officeTr: 'chancellor', regions: ['*'] }
];
let taxCreated = 0;
if (taxType) {
for (const { officeTr, regions } of taxByOffice) {
const office = await PoliticalOfficeType.findOne({ where: { name: officeTr } });
if (!office) continue;
const [, wasCreated] = await PoliticalOfficeBenefit.findOrCreate({
where: { officeTypeId: office.id, benefitTypeId: taxType.id },
defaults: {
officeTypeId: office.id,
benefitTypeId: taxType.id,
value: { regions }
}
});
if (wasCreated) taxCreated += 1;
}
}
const allOffices = await PoliticalOfficeType.findAll({ attributes: ['id'] });
let dailyCreated = 0;
for (const office of allOffices) {
const [, wasCreated] = await PoliticalOfficeBenefit.findOrCreate({
where: { officeTypeId: office.id, benefitTypeId: dailyType.id },
defaults: {
officeTypeId: office.id,
benefitTypeId: dailyType.id,
value: { base: 4, perRank: 11 }
}
});
if (wasCreated) dailyCreated += 1;
}
console.log(
`[Falukant] PoliticalOfficeBenefits: Steuer neu=${taxCreated}, Tageslohn neu=${dailyCreated} (gesamt Ämter=${allOffices.length})`
);
};
// — Church Offices —
const churchOffices = [