Merge branch 'worktree-agent-a53b58a7'
This commit is contained in:
commit
b93c735442
5 changed files with 463 additions and 0 deletions
28
server/api/onboarding/status.get.js
Normal file
28
server/api/onboarding/status.get.js
Normal 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,
|
||||
}
|
||||
})
|
||||
51
server/api/onboarding/track.post.js
Normal file
51
server/api/onboarding/track.post.js
Normal 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 }
|
||||
})
|
||||
|
|
@ -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({
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue