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:
@@ -93,6 +93,10 @@ import PoliticalOfficeRequirement from './falukant/predefine/political_office_pr
|
||||
import PoliticalOfficePrerequisite from './falukant/predefine/political_office_prerequisite.js';
|
||||
import PoliticalOfficeHistory from './falukant/log/political_office_history.js';
|
||||
import ElectionHistory from './falukant/log/election_history.js';
|
||||
import ChurchOfficeType from './falukant/type/church_office_type.js';
|
||||
import ChurchOfficeRequirement from './falukant/predefine/church_office_requirement.js';
|
||||
import ChurchOffice from './falukant/data/church_office.js';
|
||||
import ChurchApplication from './falukant/data/church_application.js';
|
||||
import Underground from './falukant/data/underground.js';
|
||||
import UndergroundType from './falukant/type/underground.js';
|
||||
import VehicleType from './falukant/type/vehicle.js';
|
||||
@@ -866,6 +870,86 @@ export default function setupAssociations() {
|
||||
}
|
||||
);
|
||||
|
||||
// — Church Offices —
|
||||
|
||||
// Requirements for church office
|
||||
ChurchOfficeRequirement.belongsTo(ChurchOfficeType, {
|
||||
foreignKey: 'officeTypeId',
|
||||
as: 'officeType'
|
||||
});
|
||||
ChurchOfficeType.hasMany(ChurchOfficeRequirement, {
|
||||
foreignKey: 'officeTypeId',
|
||||
as: 'requirements'
|
||||
});
|
||||
|
||||
// Prerequisite office type
|
||||
ChurchOfficeRequirement.belongsTo(ChurchOfficeType, {
|
||||
foreignKey: 'prerequisiteOfficeTypeId',
|
||||
as: 'prerequisiteOfficeType'
|
||||
});
|
||||
|
||||
// Actual church office holdings
|
||||
ChurchOffice.belongsTo(ChurchOfficeType, {
|
||||
foreignKey: 'officeTypeId',
|
||||
as: 'type'
|
||||
});
|
||||
ChurchOfficeType.hasMany(ChurchOffice, {
|
||||
foreignKey: 'officeTypeId',
|
||||
as: 'offices'
|
||||
});
|
||||
|
||||
ChurchOffice.belongsTo(FalukantCharacter, {
|
||||
foreignKey: 'characterId',
|
||||
as: 'holder'
|
||||
});
|
||||
FalukantCharacter.hasOne(ChurchOffice, {
|
||||
foreignKey: 'characterId',
|
||||
as: 'heldChurchOffice'
|
||||
});
|
||||
|
||||
// Supervisor relationship
|
||||
ChurchOffice.belongsTo(FalukantCharacter, {
|
||||
foreignKey: 'supervisorId',
|
||||
as: 'supervisor'
|
||||
});
|
||||
|
||||
// Applications for church office
|
||||
ChurchApplication.belongsTo(ChurchOfficeType, {
|
||||
foreignKey: 'officeTypeId',
|
||||
as: 'officeType'
|
||||
});
|
||||
ChurchOfficeType.hasMany(ChurchApplication, {
|
||||
foreignKey: 'officeTypeId',
|
||||
as: 'applications'
|
||||
});
|
||||
|
||||
ChurchApplication.belongsTo(FalukantCharacter, {
|
||||
foreignKey: 'characterId',
|
||||
as: 'applicant'
|
||||
});
|
||||
FalukantCharacter.hasMany(ChurchApplication, {
|
||||
foreignKey: 'characterId',
|
||||
as: 'churchApplications'
|
||||
});
|
||||
|
||||
ChurchApplication.belongsTo(FalukantCharacter, {
|
||||
foreignKey: 'supervisorId',
|
||||
as: 'supervisor'
|
||||
});
|
||||
FalukantCharacter.hasMany(ChurchApplication, {
|
||||
foreignKey: 'supervisorId',
|
||||
as: 'supervisedApplications'
|
||||
});
|
||||
|
||||
ChurchApplication.belongsTo(RegionData, {
|
||||
foreignKey: 'regionId',
|
||||
as: 'region'
|
||||
});
|
||||
RegionData.hasMany(ChurchApplication, {
|
||||
foreignKey: 'regionId',
|
||||
as: 'churchApplications'
|
||||
});
|
||||
|
||||
Underground.belongsTo(UndergroundType, {
|
||||
foreignKey: 'undergroundTypeId',
|
||||
as: 'undergroundType'
|
||||
|
||||
47
backend/models/falukant/data/church_application.js
Normal file
47
backend/models/falukant/data/church_application.js
Normal file
@@ -0,0 +1,47 @@
|
||||
import { Model, DataTypes } from 'sequelize';
|
||||
import { sequelize } from '../../../utils/sequelize.js';
|
||||
|
||||
class ChurchApplication extends Model {}
|
||||
|
||||
ChurchApplication.init({
|
||||
id: {
|
||||
type: DataTypes.INTEGER,
|
||||
primaryKey: true,
|
||||
autoIncrement: true
|
||||
},
|
||||
officeTypeId: {
|
||||
type: DataTypes.INTEGER,
|
||||
allowNull: false
|
||||
},
|
||||
characterId: {
|
||||
type: DataTypes.INTEGER,
|
||||
allowNull: false
|
||||
},
|
||||
regionId: {
|
||||
type: DataTypes.INTEGER,
|
||||
allowNull: false
|
||||
},
|
||||
supervisorId: {
|
||||
type: DataTypes.INTEGER,
|
||||
allowNull: false,
|
||||
comment: 'ID des Vorgesetzten, der über die Bewerbung entscheidet'
|
||||
},
|
||||
status: {
|
||||
type: DataTypes.ENUM('pending', 'approved', 'rejected'),
|
||||
allowNull: false,
|
||||
defaultValue: 'pending'
|
||||
},
|
||||
decisionDate: {
|
||||
type: DataTypes.DATE,
|
||||
allowNull: true
|
||||
}
|
||||
}, {
|
||||
sequelize,
|
||||
modelName: 'ChurchApplication',
|
||||
tableName: 'church_application',
|
||||
schema: 'falukant_data',
|
||||
timestamps: true,
|
||||
underscored: true
|
||||
});
|
||||
|
||||
export default ChurchApplication;
|
||||
38
backend/models/falukant/data/church_office.js
Normal file
38
backend/models/falukant/data/church_office.js
Normal file
@@ -0,0 +1,38 @@
|
||||
import { Model, DataTypes } from 'sequelize';
|
||||
import { sequelize } from '../../../utils/sequelize.js';
|
||||
|
||||
class ChurchOffice extends Model {}
|
||||
|
||||
ChurchOffice.init({
|
||||
id: {
|
||||
type: DataTypes.INTEGER,
|
||||
primaryKey: true,
|
||||
autoIncrement: true
|
||||
},
|
||||
officeTypeId: {
|
||||
type: DataTypes.INTEGER,
|
||||
allowNull: false
|
||||
},
|
||||
characterId: {
|
||||
type: DataTypes.INTEGER,
|
||||
allowNull: false
|
||||
},
|
||||
regionId: {
|
||||
type: DataTypes.INTEGER,
|
||||
allowNull: false
|
||||
},
|
||||
supervisorId: {
|
||||
type: DataTypes.INTEGER,
|
||||
allowNull: true,
|
||||
comment: 'ID des Vorgesetzten (höhere Position in der Hierarchie)'
|
||||
}
|
||||
}, {
|
||||
sequelize,
|
||||
modelName: 'ChurchOffice',
|
||||
tableName: 'church_office',
|
||||
schema: 'falukant_data',
|
||||
timestamps: true,
|
||||
underscored: true
|
||||
});
|
||||
|
||||
export default ChurchOffice;
|
||||
@@ -0,0 +1,35 @@
|
||||
import { Model, DataTypes } from 'sequelize';
|
||||
import { sequelize } from '../../../utils/sequelize.js';
|
||||
|
||||
class ChurchOfficeRequirement extends Model {}
|
||||
|
||||
ChurchOfficeRequirement.init({
|
||||
id: {
|
||||
type: DataTypes.INTEGER,
|
||||
primaryKey: true,
|
||||
autoIncrement: true
|
||||
},
|
||||
officeTypeId: {
|
||||
type: DataTypes.INTEGER,
|
||||
allowNull: false
|
||||
},
|
||||
prerequisiteOfficeTypeId: {
|
||||
type: DataTypes.INTEGER,
|
||||
allowNull: true,
|
||||
comment: 'Erforderliche niedrigere Position in der Hierarchie'
|
||||
},
|
||||
minTitleLevel: {
|
||||
type: DataTypes.INTEGER,
|
||||
allowNull: true,
|
||||
comment: 'Mindest-Titel-Level (optional)'
|
||||
}
|
||||
}, {
|
||||
sequelize,
|
||||
modelName: 'ChurchOfficeRequirement',
|
||||
tableName: 'church_office_requirement',
|
||||
schema: 'falukant_predefine',
|
||||
timestamps: false,
|
||||
underscored: true
|
||||
});
|
||||
|
||||
export default ChurchOfficeRequirement;
|
||||
38
backend/models/falukant/type/church_office_type.js
Normal file
38
backend/models/falukant/type/church_office_type.js
Normal file
@@ -0,0 +1,38 @@
|
||||
import { Model, DataTypes } from 'sequelize';
|
||||
import { sequelize } from '../../../utils/sequelize.js';
|
||||
|
||||
class ChurchOfficeType extends Model {}
|
||||
|
||||
ChurchOfficeType.init({
|
||||
id: {
|
||||
type: DataTypes.INTEGER,
|
||||
primaryKey: true,
|
||||
autoIncrement: true
|
||||
},
|
||||
name: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false
|
||||
},
|
||||
seatsPerRegion: {
|
||||
type: DataTypes.INTEGER,
|
||||
allowNull: false
|
||||
},
|
||||
regionType: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false
|
||||
},
|
||||
hierarchyLevel: {
|
||||
type: DataTypes.INTEGER,
|
||||
allowNull: false,
|
||||
comment: 'Höhere Zahl = höhere Position in der Hierarchie'
|
||||
}
|
||||
}, {
|
||||
sequelize,
|
||||
modelName: 'ChurchOfficeType',
|
||||
tableName: 'church_office_type',
|
||||
schema: 'falukant_type',
|
||||
timestamps: false,
|
||||
underscored: true
|
||||
});
|
||||
|
||||
export default ChurchOfficeType;
|
||||
@@ -113,6 +113,12 @@ import Vote from './falukant/data/vote.js';
|
||||
import ElectionResult from './falukant/data/election_result.js';
|
||||
import PoliticalOfficeHistory from './falukant/log/political_office_history.js';
|
||||
import ElectionHistory from './falukant/log/election_history.js';
|
||||
|
||||
// — Kirchliche Ämter (Church) —
|
||||
import ChurchOfficeType from './falukant/type/church_office_type.js';
|
||||
import ChurchOfficeRequirement from './falukant/predefine/church_office_requirement.js';
|
||||
import ChurchOffice from './falukant/data/church_office.js';
|
||||
import ChurchApplication from './falukant/data/church_application.js';
|
||||
import UndergroundType from './falukant/type/underground.js';
|
||||
import Underground from './falukant/data/underground.js';
|
||||
import VehicleType from './falukant/type/vehicle.js';
|
||||
@@ -242,6 +248,10 @@ const models = {
|
||||
ElectionResult,
|
||||
PoliticalOfficeHistory,
|
||||
ElectionHistory,
|
||||
ChurchOfficeType,
|
||||
ChurchOfficeRequirement,
|
||||
ChurchOffice,
|
||||
ChurchApplication,
|
||||
UndergroundType,
|
||||
Underground,
|
||||
WeatherType,
|
||||
|
||||
Reference in New Issue
Block a user