Implement lover relationship management features: Add endpoints for creating, acknowledging, and managing lover relationships in the FalukantController. Enhance backend models with RelationshipState for tracking relationship statuses. Update frontend components to display and manage lover details, including marriage satisfaction and household tension. Improve localization for new features in multiple languages.

This commit is contained in:
Torsten Schulz (local)
2026-03-20 11:37:46 +01:00
parent c7d33525ff
commit 2977b152a2
29 changed files with 4551 additions and 86 deletions

View File

@@ -68,6 +68,7 @@ import PromotionalGiftCharacterTrait from './falukant/predefine/promotional_gift
import PromotionalGiftMood from './falukant/predefine/promotional_gift_mood.js';
import RelationshipType from './falukant/type/relationship.js';
import Relationship from './falukant/data/relationship.js';
import RelationshipState from './falukant/data/relationship_state.js';
import PromotionalGiftLog from './falukant/log/promotional_gift.js';
import HouseType from './falukant/type/house.js';
import BuyableHouse from './falukant/data/buyable_house.js';
@@ -460,6 +461,8 @@ export default function setupAssociations() {
Relationship.belongsTo(FalukantCharacter, { foreignKey: 'character2Id', as: 'character2', });
FalukantCharacter.hasMany(Relationship, { foreignKey: 'character1Id', as: 'relationshipsAsCharacter1', });
FalukantCharacter.hasMany(Relationship, { foreignKey: 'character2Id', as: 'relationshipsAsCharacter2', });
Relationship.hasOne(RelationshipState, { foreignKey: 'relationshipId', as: 'state' });
RelationshipState.belongsTo(Relationship, { foreignKey: 'relationshipId', as: 'relationship' });
PromotionalGiftLog.belongsTo(PromotionalGift, { foreignKey: 'giftId', as: 'gift' });
PromotionalGift.hasMany(PromotionalGiftLog, { foreignKey: 'giftId', as: 'logs' });
@@ -1095,4 +1098,3 @@ export default function setupAssociations() {
CalendarEvent.belongsTo(User, { foreignKey: 'userId', as: 'user' });
User.hasMany(CalendarEvent, { foreignKey: 'userId', as: 'calendarEvents' });
}

View File

@@ -27,7 +27,25 @@ ChildRelation.init(
isHeir: {
type: DataTypes.BOOLEAN,
allowNull: true,
default: false}
default: false},
legitimacy: {
type: DataTypes.STRING,
allowNull: false,
defaultValue: 'legitimate',
validate: {
isIn: [['legitimate', 'acknowledged_bastard', 'hidden_bastard']]
}},
birthContext: {
type: DataTypes.STRING,
allowNull: false,
defaultValue: 'marriage',
validate: {
isIn: [['marriage', 'lover']]
}},
publicKnown: {
type: DataTypes.BOOLEAN,
allowNull: false,
defaultValue: false}
},
{
sequelize,

View File

@@ -0,0 +1,141 @@
import { Model, DataTypes } from 'sequelize';
import { sequelize } from '../../../utils/sequelize.js';
class RelationshipState extends Model {}
RelationshipState.init(
{
relationshipId: {
type: DataTypes.INTEGER,
allowNull: false,
unique: true,
},
marriageSatisfaction: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: 55,
validate: {
min: 0,
max: 100,
},
},
marriagePublicStability: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: 55,
validate: {
min: 0,
max: 100,
},
},
loverRole: {
type: DataTypes.STRING,
allowNull: true,
validate: {
isIn: [[null, 'secret_affair', 'lover', 'mistress_or_favorite'].filter(Boolean)],
},
},
affection: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: 50,
validate: {
min: 0,
max: 100,
},
},
visibility: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: 15,
validate: {
min: 0,
max: 100,
},
},
discretion: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: 50,
validate: {
min: 0,
max: 100,
},
},
maintenanceLevel: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: 50,
validate: {
min: 0,
max: 100,
},
},
statusFit: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: 0,
validate: {
min: -2,
max: 2,
},
},
monthlyBaseCost: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: 0,
validate: {
min: 0,
},
},
monthsUnderfunded: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: 0,
validate: {
min: 0,
},
},
active: {
type: DataTypes.BOOLEAN,
allowNull: false,
defaultValue: true,
},
acknowledged: {
type: DataTypes.BOOLEAN,
allowNull: false,
defaultValue: false,
},
exclusiveFlag: {
type: DataTypes.BOOLEAN,
allowNull: false,
defaultValue: false,
},
lastMonthlyProcessedAt: {
type: DataTypes.DATE,
allowNull: true,
},
lastDailyProcessedAt: {
type: DataTypes.DATE,
allowNull: true,
},
notesJson: {
type: DataTypes.JSONB,
allowNull: true,
},
flagsJson: {
type: DataTypes.JSONB,
allowNull: true,
},
},
{
sequelize,
modelName: 'RelationshipState',
tableName: 'relationship_state',
schema: 'falukant_data',
timestamps: true,
underscored: true,
}
);
export default RelationshipState;

View File

@@ -67,6 +67,7 @@ import Notification from './falukant/log/notification.js';
import MarriageProposal from './falukant/data/marriage_proposal.js';
import RelationshipType from './falukant/type/relationship.js';
import Relationship from './falukant/data/relationship.js';
import RelationshipState from './falukant/data/relationship_state.js';
import CharacterTrait from './falukant/type/character_trait.js';
import FalukantCharacterTrait from './falukant/data/falukant_character_trait.js';
import Mood from './falukant/type/mood.js';
@@ -219,6 +220,7 @@ const models = {
MarriageProposal,
RelationshipType,
Relationship,
RelationshipState,
CharacterTrait,
FalukantCharacterTrait,
Mood,