feat(community): Post.gameName + GameShareBanner-rendering chain

Adds optional `gameName` column to community_posts so game-share posts
can render with the game-banner above the post-content (Snake/Tetris/
Memory/TTT visual indicator).

- prisma/schema.prisma: CommunityPost.gameName String? @map("game_name")
- migration: ALTER TABLE rebreak.community_posts ADD COLUMN game_name
- db/community.ts: createPost() accepts gameName param
- api/community/post.post.ts: extracts gameName from body
- api/community/posts.get.ts: returns gameName, prefers DB over content-parse

Frontend (already in flight on upgrade/sdk-54): PostCard.tsx renders
GameShareBanner when post.category === 'game_share' && post.gameName.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
chahinebrini 2026-05-09 22:28:07 +02:00
parent fd737f8658
commit a81ba2e54a
5 changed files with 11 additions and 4 deletions

View File

@ -0,0 +1,3 @@
-- Migration: add game_name column to community_posts
-- Generated: 2026-05-09
ALTER TABLE "rebreak"."community_posts" ADD COLUMN "game_name" TEXT;

View File

@ -160,6 +160,7 @@ model CommunityPost {
deletedAt DateTime? @map("deleted_at")
/// Wann der Post zum ersten Mal gemeldet wurde (queue-Sortierung).
reportedAt DateTime? @map("reported_at")
gameName String? @map("game_name")
repostOfId String? @map("repost_of_id") @db.Uuid
challengeId String? @map("challenge_id") @db.Uuid
createdAt DateTime @default(now()) @map("created_at")

View File

@ -14,10 +14,11 @@ export default defineEventHandler(async (event) => {
const user = await requireUser(event);
const body = await readBody(event);
const { category, content, imageUrl } = body as {
const { category, content, imageUrl, gameName } = body as {
category: string;
content: string;
imageUrl?: string;
gameName?: string | null;
};
if (!content?.trim() || !category) {
@ -72,7 +73,7 @@ export default defineEventHandler(async (event) => {
}
}
const data = await createPost(user.id, category, content.trim(), imageUrl);
const data = await createPost(user.id, category, content.trim(), imageUrl, gameName ?? null);
// Punkte vergeben
await awardPoints(user.id, "post_created", { post_id: data.id });

View File

@ -64,9 +64,9 @@ export default defineEventHandler(async (event) => {
: null,
gameName: (p as any).challengeId
? challengeStatuses[(p as any).challengeId]?.gameType ?? null
: p.category === "game_share"
: (p as any).gameName ?? (p.category === "game_share"
? p.content.split("\n")[0] ?? null
: null,
: null),
opponentName: (p as any).challengeId
? challengeStatuses[(p as any).challengeId]?.opponentName ?? null
: null,

View File

@ -256,6 +256,7 @@ export async function createPost(
category: string,
content: string,
imageUrl?: string,
gameName?: string | null,
) {
const db = usePrisma();
return db.communityPost.create({
@ -264,6 +265,7 @@ export async function createPost(
category,
content,
imageUrl: imageUrl || null,
gameName: gameName ?? null,
isAnonymous: false,
isModerated: false,
},