Files
gamegroup2/frontend/src/api/points.ts
T
congsh c5d3ac01ca feat: phase 2 - polls, memories, notifications, stats v0.1.0
- Group polls with option/rollcall modes, edit by creator, auto-settle
- Multimedia memories with upload, preview, inline video playback
- In-app notifications for poll/team/group events
- Points system and group stats dashboard
- Group detail tabs with icons (activity/polls/memories/stats)
- Fix: nginx file upload size, static cache blocking API, timezone, auto-cancel

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-18 18:19:46 +08:00

93 lines
2.5 KiB
TypeScript

import { pb } from './pocketbase'
import type { PointLog, PointAction } from '@/types'
const POINT_MAP: Record<PointAction, number> = {
vote: 1,
team: 2,
memory: 1
}
export async function awardPoints(action: PointAction, relatedId: string): Promise<void> {
const user = pb.authStore.model
if (!user) return
const existing = await pb.collection('point_logs').getList(1, 1, {
filter: `user="${user.id}" && action="${action}" && relatedId="${relatedId}"`,
$autoCancel: false
})
if (existing.items.length > 0) return
const points = POINT_MAP[action]
try {
await pb.collection('point_logs').create({
user: user.id,
action,
points,
relatedId
})
} catch (error: any) {
if (error?.response?.data?.user || error?.message?.includes('unique')) {
return
}
throw error
}
const currentUser = await pb.collection('users').getOne(user.id)
await pb.collection('users').update(user.id, {
points: ((currentUser as any).points || 0) + points
})
}
export async function deductPoints(action: PointAction, relatedId: string): Promise<void> {
const user = pb.authStore.model
if (!user) return
const existing = await pb.collection('point_logs').getList(1, 1, {
filter: `user="${user.id}" && action="${action}" && relatedId="${relatedId}"`,
$autoCancel: false
})
if (existing.items.length === 0) return
const log = existing.items[0]
try {
await pb.collection('point_logs').delete(log.id)
} catch (error: any) {
if (error?.status !== 404) {
throw error
}
}
const pointsToDeduct = POINT_MAP[action]
const currentUser = await pb.collection('users').getOne(user.id)
const currentPoints = (currentUser as any).points || 0
const newPoints = Math.max(0, currentPoints - pointsToDeduct)
await pb.collection('users').update(user.id, {
points: newPoints
})
}
export async function getUserPointLogs(userId: string): Promise<PointLog[]> {
const result = await pb.collection('point_logs').getList(1, 100, {
filter: `user="${userId}"`,
sort: '-created',
$autoCancel: false
})
return result.items as unknown as PointLog[]
}
export async function getGroupMemberRanking(groupId: string, limit = 20) {
const group = await pb.collection('groups').getOne(groupId, {
expand: 'members',
$autoCancel: false
}) as any
const members: any[] = group.expand?.members || []
return members
.map((m: any) => ({ userId: m.id, points: m.points || 0, name: m.name || m.username }))
.sort((a: any, b: any) => b.points - a.points)
.slice(0, limit)
}