feat: allow manual unlocks in learn missions

This commit is contained in:
Remi
2025-09-22 07:38:46 +02:00
committed by itsrubberduck
parent 46ece5e5c0
commit 3c12f6d836
4 changed files with 31 additions and 0 deletions

View File

@@ -15,10 +15,14 @@ export default defineEventHandler(async (event) => {
profile.progress && typeof profile.progress === 'object'
? JSON.parse(JSON.stringify(profile.progress))
: {}
const unlockedModules = Array.isArray(profile.unlockedModules)
? Array.from(new Set((profile.unlockedModules as unknown[]).filter(item => typeof item === 'string').map(item => item.trim())))
: []
return {
xp: typeof profile.xp === 'number' ? profile.xp : 0,
progress,
config,
unlockedModules,
}
})

View File

@@ -8,6 +8,7 @@ interface LearnStateUpdateBody {
xp?: number
progress?: LearnProgress
config?: Partial<LearnConfig>
unlockedModules?: string[]
}
function sanitizeProgress(input: LearnProgress | undefined): LearnProgress | undefined {
@@ -76,6 +77,19 @@ function sanitizeConfig(input: Partial<LearnConfig> | undefined): LearnConfig |
return config
}
function sanitizeUnlockedModules(input: string[] | undefined): string[] | undefined {
if (!Array.isArray(input)) {
return undefined
}
const sanitized = input
.filter(value => typeof value === 'string')
.map(value => value.trim())
.filter(value => value.length > 0)
return Array.from(new Set(sanitized))
}
export default defineEventHandler(async (event) => {
const user = await requireUserSession(event)
const body = await readBody<LearnStateUpdateBody>(event)
@@ -99,6 +113,11 @@ export default defineEventHandler(async (event) => {
profile.config = config
}
const unlockedModules = sanitizeUnlockedModules(body.unlockedModules)
if (unlockedModules !== undefined) {
profile.unlockedModules = unlockedModules
}
await profile.save()
const responseConfig = { ...createDefaultLearnConfig(), ...(profile.config || {}) }
@@ -106,10 +125,14 @@ export default defineEventHandler(async (event) => {
profile.progress && typeof profile.progress === 'object'
? JSON.parse(JSON.stringify(profile.progress))
: {}
const responseUnlockedModules = Array.isArray(profile.unlockedModules)
? Array.from(new Set((profile.unlockedModules as unknown[]).filter(item => typeof item === 'string').map(item => item.trim())))
: []
return {
xp: typeof profile.xp === 'number' ? profile.xp : 0,
progress: responseProgress,
config: responseConfig,
unlockedModules: responseUnlockedModules,
}
})

View File

@@ -6,6 +6,7 @@ export interface LearnProfileDocument extends mongoose.Document {
xp: number
progress: LearnProgress
config: LearnConfig
unlockedModules: string[]
createdAt: Date
updatedAt: Date
}
@@ -15,6 +16,7 @@ const learnProfileSchema = new mongoose.Schema<LearnProfileDocument>(
user: { type: mongoose.Schema.Types.ObjectId, ref: 'User', required: true, unique: true },
xp: { type: Number, default: 0 },
progress: { type: mongoose.Schema.Types.Mixed, default: () => ({}) },
unlockedModules: { type: [String], default: () => [] },
config: {
tts: { type: Boolean, default: false },
radioLevel: { type: Number, default: 4, min: 1, max: 5 },

View File

@@ -17,6 +17,7 @@ export interface LearnState {
xp: number
progress: LearnProgress
config: LearnConfig
unlockedModules: string[]
}
export const LEARN_CONFIG_DEFAULTS: LearnConfig = {
@@ -36,5 +37,6 @@ export function createDefaultLearnState(): LearnState {
xp: 0,
progress: {} as LearnProgress,
config: createDefaultLearnConfig(),
unlockedModules: [],
}
}