Implement church career management features

- Added endpoints for church career functionalities including overview, available positions, application submission, and application decision-making.
- Enhanced the FalukantController to handle church-related requests.
- Updated associations and models to support church office types and requirements.
- Integrated new routes in the falukantRouter for church career operations.
- Implemented service methods for managing church applications and checking church career status.
- Updated frontend components to display current positions, available positions, and manage applications with appropriate UI elements and loading states.
- Localized new church-related strings in both English and German.
This commit is contained in:
Torsten Schulz (local)
2026-01-22 16:46:42 +01:00
parent 8e226615eb
commit 4f786cdcc3
13 changed files with 1424 additions and 2 deletions

View File

@@ -16,6 +16,8 @@ import ReputationActionType from "../../models/falukant/type/reputation_action.j
import VehicleType from "../../models/falukant/type/vehicle.js";
import LearnRecipient from "../../models/falukant/type/learn_recipient.js";
import PoliticalOfficeType from "../../models/falukant/type/political_office_type.js";
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 PoliticalOfficePrerequisite from "../../models/falukant/predefine/political_office_prerequisite.js";
import UndergroundType from "../../models/falukant/type/underground.js";
@@ -47,6 +49,8 @@ export const initializeFalukantTypes = async () => {
await initializePoliticalOfficeBenefitTypes();
await initializePoliticalOfficeTypes();
await initializePoliticalOfficePrerequisites();
await initializeChurchOfficeTypes();
await initializeChurchOfficePrerequisites();
await initializeUndergroundTypes();
await initializeVehicleTypes();
await initializeFalukantWeatherTypes();
@@ -1024,6 +1028,119 @@ export const initializePoliticalOfficePrerequisites = async () => {
console.log(`[Falukant] OfficePrereq neu=${created} exist=${existing}${skipped?` skip=${skipped}`:''}`);
};
// — Church Offices —
const churchOffices = [
{ tr: "village-priest", seatsPerRegion: 1, regionType: "city", hierarchyLevel: 1 },
{ tr: "parish-priest", seatsPerRegion: 1, regionType: "city", hierarchyLevel: 2 },
{ tr: "dean", seatsPerRegion: 1, regionType: "county", hierarchyLevel: 3 },
{ tr: "archdeacon", seatsPerRegion: 1, regionType: "shire", hierarchyLevel: 4 },
{ tr: "bishop", seatsPerRegion: 1, regionType: "markgravate", hierarchyLevel: 5 },
{ tr: "archbishop", seatsPerRegion: 1, regionType: "duchy", hierarchyLevel: 6 },
{ tr: "cardinal", seatsPerRegion: 3, regionType: "country", hierarchyLevel: 7 },
{ tr: "pope", seatsPerRegion: 1, regionType: "country", hierarchyLevel: 8 }
];
const churchOfficePrerequisites = [
{
officeTr: "village-priest",
prerequisite: {
prerequisiteOfficeTypeId: null // Einstiegsposition, keine Voraussetzung
}
},
{
officeTr: "parish-priest",
prerequisite: {
prerequisiteOfficeTypeId: "village-priest"
}
},
{
officeTr: "dean",
prerequisite: {
prerequisiteOfficeTypeId: "parish-priest"
}
},
{
officeTr: "archdeacon",
prerequisite: {
prerequisiteOfficeTypeId: "dean"
}
},
{
officeTr: "bishop",
prerequisite: {
prerequisiteOfficeTypeId: "archdeacon"
}
},
{
officeTr: "archbishop",
prerequisite: {
prerequisiteOfficeTypeId: "bishop"
}
},
{
officeTr: "cardinal",
prerequisite: {
prerequisiteOfficeTypeId: "archbishop"
}
},
{
officeTr: "pope",
prerequisite: {
prerequisiteOfficeTypeId: "cardinal"
}
}
];
export const initializeChurchOfficeTypes = async () => {
for (const co of churchOffices) {
await ChurchOfficeType.findOrCreate({
where: { name: co.tr },
defaults: {
seatsPerRegion: co.seatsPerRegion,
regionType: co.regionType,
hierarchyLevel: co.hierarchyLevel
}
});
}
console.log(`[Falukant] ChurchOfficeTypes initialized`);
};
export const initializeChurchOfficePrerequisites = async () => {
let created = 0;
let existing = 0;
let skipped = 0;
for (const prereq of churchOfficePrerequisites) {
const office = await ChurchOfficeType.findOne({ where: { name: prereq.officeTr } });
if (!office) { skipped++; continue; }
let prerequisiteOfficeTypeId = null;
if (prereq.prerequisite.prerequisiteOfficeTypeId) {
const prerequisiteOffice = await ChurchOfficeType.findOne({
where: { name: prereq.prerequisite.prerequisiteOfficeTypeId }
});
if (prerequisiteOffice) {
prerequisiteOfficeTypeId = prerequisiteOffice.id;
}
}
try {
const [record, wasCreated] = await ChurchOfficeRequirement.findOrCreate({
where: { officeTypeId: office.id },
defaults: {
officeTypeId: office.id,
prerequisiteOfficeTypeId: prerequisiteOfficeTypeId
}
});
if (wasCreated) created++; else existing++;
} catch (e) {
if (falukantDebug) console.error('[Falukant] ChurchOfficePrereq Fehler', { officeId: office?.id, error: e.message });
throw e;
}
}
console.log(`[Falukant] ChurchOfficePrereq neu=${created} exist=${existing}${skipped?` skip=${skipped}`:''}`);
};
export const initializeUndergroundTypes = async () => {
for (const underground of undergroundTypes) {
await UndergroundType.findOrCreate({