-
Notifications
You must be signed in to change notification settings - Fork 27
feat: Activity Logging System — Track All User Actions with Points #147
Description
What
Add an activity logging system that records every meaningful user action with point values. This is the foundation for analytics, engagement scoring, and retention tracking.
Why
We currently have zero visibility into what users actually do on the platform. We can't answer: how many quests were claimed this week? Who's active? Who's at risk of churning? Activity logs answer all of these.
Schema Addition
Add to `prisma/schema.prisma`:
```prisma
model ActivityLog {
id String @id @default(uuid()) @db.Uuid
userId String @Map("user_id") @db.Uuid
action String // e.g. "quest_apply", "quest_complete", "rank_up"
points Int @default(0)
metadata Json? // { questId, fromRank, toRank, etc. }
createdAt DateTime @default(now()) @Map("created_at") @db.Timestamptz
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@index([userId])
@@index([action])
@@index([createdAt])
@@Map("activity_logs")
}
```
Add `activityLogs ActivityLog[]` relation to User model.
Activity Types & Points
```typescript
// lib/activity-points.ts
export const ACTIVITY_POINTS: Record<string, number> = {
quest_view: 1,
quest_apply: 10,
quest_start: 5,
quest_submit: 20,
quest_complete: 50,
quest_rework: 5,
rank_up: 100,
profile_update: 2,
party_create: 15,
party_join: 10,
streak_milestone: 25,
};
```
Utility: `lib/activity-logger.ts`
```typescript
export async function logActivity(
userId: string,
action: string,
metadata?: Record<string, unknown>,
db?: PrismaClient | Prisma.TransactionClient
) {
const client = db || prisma;
const points = ACTIVITY_POINTS[action] ?? 0;
await client.activityLog.create({
data: { userId, action, points, metadata: metadata ?? undefined },
});
}
```
Where to Call It
Add `logActivity()` calls in these existing files:
- `app/api/quests/assignments/route.ts` POST → `logActivity(userId, 'quest_apply', { questId })`
- `app/api/quests/submissions/route.ts` POST → `logActivity(userId, 'quest_submit', { questId })`
- `lib/xp-utils.ts` after XP grant → `logActivity(userId, 'quest_complete', { questId, xp })`
- `lib/xp-utils.ts` after rank up → `logActivity(userId, 'rank_up', { fromRank, toRank })`
API: `GET /api/admin/activity`
Admin-only endpoint returning:
- Recent activity feed (paginated)
- Daily active users (count distinct userId where createdAt > 24h ago)
- Activity breakdown by type
Acceptance Criteria
- ActivityLog model in schema, migration applied
- `logActivity()` utility created
- Activity logged on quest apply, submit, complete, and rank up
- Admin API returns activity feed + DAU count
- Type-check passes