Implement politics overview feature in FalukantService and update UI

- Added a new method `getPoliticsOverview` in FalukantService to retrieve currently held offices, including office holders and term end dates.
- Enhanced the PoliticsView component to display the term end dates for current offices.
- Updated localization files to include a new message for applying to selected positions.
- Improved the handling of already applied positions in the open politics section, pre-selecting checkboxes accordingly.
This commit is contained in:
Torsten Schulz (local)
2025-11-24 11:50:21 +01:00
parent 3b8736acd7
commit 4510aa3d14
3 changed files with 133 additions and 6 deletions

View File

@@ -2472,7 +2472,112 @@ class FalukantService extends BaseService {
}
async getPoliticsOverview(hashedUserId) {
// Liefert alle aktuell besetzten Ämter im eigenen Gebiet inklusive
// Inhaber und berechnetem Enddatum der Amtszeit.
const user = await getFalukantUserOrFail(hashedUserId);
// Charakter des Users bestimmen (Region ist dort hinterlegt)
const character = await FalukantCharacter.findOne({
where: { userId: user.id },
attributes: ['id', 'regionId']
});
if (!character) {
return [];
}
// Alle relevanten Regionen (Region + Eltern) laden
const relevantRegionIds = await this.getRegionAndParentIds(character.regionId);
// Aktuell besetzte Ämter in diesen Regionen laden
const offices = await PoliticalOffice.findAll({
where: {
regionId: {
[Op.in]: relevantRegionIds
}
},
include: [
{
model: PoliticalOfficeType,
as: 'type',
attributes: ['name', 'termLength']
},
{
model: RegionData,
as: 'region',
attributes: ['name'],
include: [
{
model: RegionType,
as: 'regionType',
attributes: ['labelTr']
}
]
},
{
model: FalukantCharacter,
as: 'holder',
attributes: ['id', 'gender'],
include: [
{
model: FalukantPredefineFirstname,
as: 'definedFirstName',
attributes: ['name']
},
{
model: FalukantPredefineLastname,
as: 'definedLastName',
attributes: ['name']
},
{
model: TitleOfNobility,
as: 'nobleTitle',
attributes: ['labelTr']
}
]
}
],
order: [
[{ model: PoliticalOfficeType, as: 'type' }, 'name', 'ASC'],
[{ model: RegionData, as: 'region' }, 'name', 'ASC']
]
});
return offices.map(office => {
const o = office.get({ plain: true });
// Enddatum der Amtszeit berechnen: Start = createdAt, Dauer = termLength Jahre
let termEnds = null;
if (o.createdAt && o.type && typeof o.type.termLength === 'number') {
const start = new Date(o.createdAt);
if (!Number.isNaN(start.getTime())) {
const end = new Date(start);
end.setFullYear(end.getFullYear() + o.type.termLength);
termEnds = end;
}
}
return {
id: o.id,
officeType: {
name: o.type?.name
},
region: {
name: o.region?.name,
regionType: o.region?.regionType
? { labelTr: o.region.regionType.labelTr }
: undefined
},
character: o.holder
? {
definedFirstName: o.holder.definedFirstName,
definedLastName: o.holder.definedLastName,
nobleTitle: o.holder.nobleTitle,
gender: o.holder.gender
}
: null,
termEnds
};
});
}
async getOpenPolitics(hashedUserId) {
@@ -2696,9 +2801,14 @@ class FalukantService extends BaseService {
endDate: h.endDate
}));
const alreadyApplied = (e.candidates || []).some(
c => c.characterId === characterId
);
return {
...e,
history: matchingHistory
history: matchingHistory,
alreadyApplied
};
});
return result;