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:
@@ -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 = [
|
||||
|
||||
@@ -10,7 +10,8 @@ const DEFAULT_WIDGET_TYPES = [
|
||||
{ label: 'News', endpoint: '/api/news?language=de&category=top', description: 'Nachrichten (newsdata.io), Counter für Pagination', orderId: 3 },
|
||||
{ label: 'Geburtstage', endpoint: '/api/calendar/widget/birthdays', description: 'Nächste Geburtstage von Freunden', orderId: 4 },
|
||||
{ label: 'Nächste Termine', endpoint: '/api/calendar/widget/upcoming', description: 'Anstehende Kalendertermine', orderId: 5 },
|
||||
{ label: 'Kalender', endpoint: '/api/calendar/widget/mini', description: 'Mini-Kalenderansicht', orderId: 6 }
|
||||
{ label: 'Kalender', endpoint: '/api/calendar/widget/mini', description: 'Mini-Kalenderansicht', orderId: 6 },
|
||||
{ label: 'Sprachkurse', endpoint: '/api/vocab/dashboard-widget', description: 'Vokabelkurse, aktuelle Lektion, Sprung zur Lektion', orderId: 7 }
|
||||
];
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user