Implement leveling rewards feature with UI and backend support

- Added functionality to manage role rewards based on user levels in the leveling system.
- Updated the LevelingForm component to include fields for defining rewards, including validation for unique levels.
- Enhanced backend logic to handle reward data storage and retrieval, ensuring proper integration with the existing leveling configuration.
- Introduced localization keys for rewards in both English and German, improving user experience.
- Updated dashboard search index to include rewards settings for easier access.
This commit is contained in:
smueller
2026-07-23 12:41:13 +02:00
parent 3af989a83b
commit fba597a6f2
9 changed files with 480 additions and 183 deletions

View File

@@ -269,6 +269,12 @@ export type VerificationConfigDashboardPatch = z.infer<typeof VerificationConfig
export const LevelUpModeDashboardSchema = z.enum(['CHANNEL', 'DM', 'OFF']);
export const LevelRewardDashboardSchema = z.object({
level: z.number().int().min(1).max(10_000),
roleId: SnowflakeSchema
});
export type LevelRewardDashboard = z.infer<typeof LevelRewardDashboardSchema>;
export const LevelingConfigDashboardSchema = z.object({
enabled: z.boolean(),
textXpMin: z.number().int().positive(),
@@ -283,6 +289,7 @@ export const LevelingConfigDashboardSchema = z.object({
levelUpChannelId: OptionalSnowflakeSchema,
levelUpMessage: z.string().max(500).nullable().optional(),
stackRewards: z.boolean(),
rewards: z.array(LevelRewardDashboardSchema).max(100),
cardAccentColor: z.string().regex(/^#[0-9a-fA-F]{6}$/),
cardBackgroundColor: z.string().regex(/^#[0-9a-fA-F]{6}$/)
});
@@ -291,6 +298,18 @@ export type LevelingConfigDashboard = z.infer<typeof LevelingConfigDashboardSche
export const LevelingConfigDashboardPatchSchema = nonEmptyPatch(LevelingConfigDashboardSchema);
export type LevelingConfigDashboardPatch = z.infer<typeof LevelingConfigDashboardPatchSchema>;
/** Returns true when every reward level is unique. */
export function hasUniqueRewardLevels(rewards: LevelRewardDashboard[]): boolean {
const levels = new Set<number>();
for (const reward of rewards) {
if (levels.has(reward.level)) {
return false;
}
levels.add(reward.level);
}
return true;
}
// ---------------------------------------------------------------------------
// Economy
// ---------------------------------------------------------------------------