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

@@ -36,6 +36,11 @@ FalukantUser.init({
lastNobilityAdvanceAt: {
type: DataTypes.DATE,
allowNull: true
},
lastPoliticalDailySalaryOn: {
type: DataTypes.DATEONLY,
allowNull: true,
field: 'last_political_daily_salary_on'
}
}, {
sequelize,

View File

@@ -1,7 +1,6 @@
// falukant/predefine/political_office_benefit.js
import { Model, DataTypes } from 'sequelize';
import { sequelize } from '../../../utils/sequelize.js';
import PoliticalOfficeBenefitType from '../type/political_office_benefit_type.js';
class PoliticalOfficeBenefit extends Model {}
@@ -9,31 +8,29 @@ PoliticalOfficeBenefit.init({
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true},
politicalOfficeId: {
autoIncrement: true
},
officeTypeId: {
type: DataTypes.INTEGER,
allowNull: false},
allowNull: false,
field: 'office_type_id'
},
benefitTypeId: {
type: DataTypes.INTEGER,
allowNull: false},
allowNull: false,
field: 'benefit_type_id'
},
value: {
type: DataTypes.JSONB,
allowNull: false}}, {
sequelize,
allowNull: false
}
}, {
sequelize,
modelName: 'PoliticalOfficeBenefit',
tableName: 'political_office_benefit',
schema: 'falukant_predefine',
timestamps: false,
underscored: true});
// Association
PoliticalOfficeBenefit.belongsTo(PoliticalOfficeBenefitType, {
foreignKey: 'benefit_type_id',
as: 'benefitType'
});
PoliticalOfficeBenefitType.hasMany(PoliticalOfficeBenefit, {
foreignKey: 'benefit_type_id',
as: 'benefits'
underscored: true
});
export default PoliticalOfficeBenefit;