Merge branch 'worktree-agent-a53b58a7'

This commit is contained in:
Jennie Robinson Faber 2026-04-09 22:33:41 +01:00
commit b93c735442
5 changed files with 463 additions and 0 deletions

View file

@ -0,0 +1,28 @@
import { requireAuth } from '../../utils/auth.js'
export default defineEventHandler(async (event) => {
const member = await requireAuth(event)
const hasProfileTags =
member.craftTags.length > 0 &&
(member.communityEcology?.topics || []).length > 0
const hasVisitedEvent = !!member.onboarding?.eventPageVisited
const topics = member.communityEcology?.topics || []
const hasEngagedEcology =
!!member.onboarding?.ecologyPageVisited &&
topics.some((t) => ['help', 'interested', 'seeking'].includes(t.state))
const hasClickedWiki = !!member.onboarding?.wikiClicked
return {
goals: {
hasProfileTags,
hasVisitedEvent,
hasEngagedEcology,
hasClickedWiki,
},
completedAt: member.onboarding?.completedAt || null,
}
})

View file

@ -0,0 +1,51 @@
import { requireAuth } from '../../utils/auth.js'
import { validateBody } from '../../utils/validateBody.js'
import { onboardingTrackSchema } from '../../utils/schemas.js'
import Member from '../../models/member.js'
import { logActivity } from '../../utils/activityLog.js'
export default defineEventHandler(async (event) => {
const member = await requireAuth(event)
const { goal } = await validateBody(event, onboardingTrackSchema)
// Already graduated — no-op
if (member.onboarding?.completedAt) {
return { success: true }
}
// Idempotent — already tracked
if (member.onboarding?.[goal]) {
return { success: true }
}
// Set the boolean
await Member.findByIdAndUpdate(member._id, {
$set: { [`onboarding.${goal}`]: true },
})
// Log the individual goal completion
await logActivity(member._id, 'member_onboarding_goal_completed', { goal }, { visibility: 'admin' })
// Graduation check — atomic so concurrent requests can't double-graduate
const graduated = await Member.findOneAndUpdate(
{
_id: member._id,
'onboarding.completedAt': null,
'onboarding.eventPageVisited': true,
'onboarding.ecologyPageVisited': true,
'onboarding.wikiClicked': true,
'craftTags.0': { $exists: true },
'communityEcology.topics': {
$elemMatch: { state: { $in: ['help', 'interested', 'seeking'] } },
},
},
{ $set: { 'onboarding.completedAt': new Date() } },
{ new: true }
)
if (graduated) {
await logActivity(member._id, 'member_onboarding_completed', {}, { visibility: 'admin' })
}
return { success: true, graduated: !!graduated }
})

View file

@ -364,6 +364,12 @@ export const inviteAcceptSchema = z.object({
token: z.string().min(1)
})
// --- Onboarding schemas ---
export const onboardingTrackSchema = z.object({
goal: z.enum(['eventPageVisited', 'ecologyPageVisited', 'wikiClicked'])
})
// --- Tag schemas ---
export const tagSuggestionSchema = z.object({