feat: extend user API with contribution history and verified count

This commit is contained in:
2026-04-26 09:47:38 -05:00
parent 53d0a52c07
commit 8301562613
2 changed files with 111 additions and 1 deletions
+94 -1
View File
@@ -1,7 +1,7 @@
import { Elysia, t } from "elysia"
import { auth } from "@/lib/auth"
import { db } from "@/lib/db/index"
import { user, performanceEntries } from "@/lib/db/schema"
import { user, performanceEntries, games, gameVersions, hardware } from "@/lib/db/schema"
import { eq, sql } from "drizzle-orm"
export const userRoutes = new Elysia({ prefix: "/user" })
@@ -32,6 +32,14 @@ export const userRoutes = new Elysia({ prefix: "/user" })
.from(performanceEntries)
.where(eq(performanceEntries.userId, params.id))
// Count verified entries
const [{ count: verifiedEntries }] = await db
.select({ count: sql<number>`count(*)::int` })
.from(performanceEntries)
.where(
sql`${performanceEntries.userId} = ${params.id} AND ${performanceEntries.verifiedAt} IS NOT NULL`
)
// Reputation = contributions * 10 (simple formula for now)
const reputation = contributions * 10
@@ -39,6 +47,7 @@ export const userRoutes = new Elysia({ prefix: "/user" })
return {
...publicProfile,
contributions,
verifiedEntries,
reputation,
verified: emailVerified,
}
@@ -85,10 +94,20 @@ export const userRoutes = new Elysia({ prefix: "/user" })
.from(performanceEntries)
.where(eq(performanceEntries.userId, session.user.id))
// Count verified entries
const [{ count: verifiedEntries }] = await db
.select({ count: sql<number>`count(*)::int` })
.from(performanceEntries)
.where(
sql`${performanceEntries.userId} = ${session.user.id} AND ${performanceEntries.verifiedAt} IS NOT NULL`
)
return {
...profile,
contributions,
verifiedEntries,
reputation: contributions * 10,
verified: profile.emailVerified,
}
},
)
@@ -111,3 +130,77 @@ export const userRoutes = new Elysia({ prefix: "/user" })
return sessions
},
)
.get(
"/profile/:id/contributions",
async ({ params, query, set }) => {
const [profile] = await db
.select({ id: user.id })
.from(user)
.where(eq(user.id, params.id))
.limit(1)
if (!profile) {
set.status = 404
return { error: "User not found" }
}
const limit = Math.min(Number(query.limit) || 10, 50)
const offset = Number(query.offset) || 0
const entries = await db
.select({
id: performanceEntries.id,
fpsAvg: performanceEntries.fpsAvg,
fpsLow: performanceEntries.fpsLow,
fpsHigh: performanceEntries.fpsHigh,
hardwareSlug: performanceEntries.hardwareSlug,
hardwareName: hardware.name,
fsrVersion: performanceEntries.fsrVersion,
frameGenMethod: performanceEntries.frameGenMethod,
verifiedAt: performanceEntries.verifiedAt,
createdAt: performanceEntries.createdAt,
gameTitle: games.title,
gameId: games.id,
gameHeaderImage: games.headerImage,
})
.from(performanceEntries)
.innerJoin(
gameVersions,
eq(performanceEntries.versionId, gameVersions.id),
)
.innerJoin(games, eq(gameVersions.gameId, games.id))
.innerJoin(
hardware,
eq(performanceEntries.hardwareSlug, hardware.slug),
)
.where(eq(performanceEntries.userId, params.id))
.orderBy(sql`${performanceEntries.createdAt} DESC`)
.limit(limit)
.offset(offset)
const [{ count: total }] = await db
.select({ count: sql<number>`count(*)::int` })
.from(performanceEntries)
.where(eq(performanceEntries.userId, params.id))
return {
data: entries.map((e) => ({
...e,
createdAt: e.createdAt.toISOString(),
verifiedAt: e.verifiedAt?.toISOString() ?? null,
})),
total,
limit,
offset,
}
},
{
params: t.Object({
id: t.String(),
}),
query: t.Object({
limit: t.Optional(t.String()),
offset: t.Optional(t.String()),
}),
},
)