diff --git a/lib/politicalStatements.ts b/lib/politicalStatements.ts index 29e99b9..15127e2 100644 --- a/lib/politicalStatements.ts +++ b/lib/politicalStatements.ts @@ -1,99 +1,94 @@ -import { promises as fs } from 'fs'; -import path from 'path'; +import { PrismaClient, PoliticalStatement as PrismaPoliticalStatement } from '@prisma/client'; + +const prisma = new PrismaClient(); export type PoliticalStatement = { id: number; + locale: string; text: string; - active?: boolean; - source?: string; + active: boolean; + source?: string | null; }; -function getFilePath(locale: string): string { - const safeLocale = ['de', 'en'].includes(locale) ? locale : 'en'; - return path.join(process.cwd(), 'data', `political-statements.${safeLocale}.json`); -} - -async function readStatementsFile(locale: string): Promise { - const filePath = getFilePath(locale); - try { - const raw = await fs.readFile(filePath, 'utf-8'); - const data = JSON.parse(raw); - if (Array.isArray(data)) { - return data; - } - return []; - } catch (err: any) { - if (err.code === 'ENOENT') { - // File does not exist yet - return []; - } - console.error('[politicalStatements] Failed to read file', filePath, err); - return []; - } -} - -async function writeStatementsFile(locale: string, statements: PoliticalStatement[]): Promise { - const filePath = getFilePath(locale); - const dir = path.dirname(filePath); - try { - await fs.mkdir(dir, { recursive: true }); - await fs.writeFile(filePath, JSON.stringify(statements, null, 2), 'utf-8'); - } catch (err) { - console.error('[politicalStatements] Failed to write file', filePath, err); - throw err; - } +function mapFromPrisma(stmt: PrismaPoliticalStatement): PoliticalStatement { + return { + id: stmt.id, + locale: stmt.locale, + text: stmt.text, + active: stmt.active, + source: stmt.source, + }; } export async function getRandomActiveStatement(locale: string): Promise { - const statements = await readStatementsFile(locale); - const active = statements.filter((s) => s.active !== false); - if (active.length === 0) { + const safeLocale = ['de', 'en'].includes(locale) ? locale : 'en'; + const all = await prisma.politicalStatement.findMany({ + where: { + locale: safeLocale, + active: true, + }, + }); + + if (all.length === 0) { return null; } - const index = Math.floor(Math.random() * active.length); - return active[index] ?? null; + + const index = Math.floor(Math.random() * all.length); + return mapFromPrisma(all[index]); } export async function getAllStatements(locale: string): Promise { - return readStatementsFile(locale); + const safeLocale = ['de', 'en'].includes(locale) ? locale : 'en'; + const all = await prisma.politicalStatement.findMany({ + where: { locale: safeLocale }, + orderBy: { id: 'asc' }, + }); + return all.map(mapFromPrisma); } -export async function createStatement(locale: string, input: Omit): Promise { - const statements = await readStatementsFile(locale); - const nextId = statements.length > 0 ? Math.max(...statements.map((s) => s.id)) + 1 : 1; - const newStatement: PoliticalStatement = { - id: nextId, - active: true, - ...input, - }; - statements.push(newStatement); - await writeStatementsFile(locale, statements); - return newStatement; +export async function createStatement(locale: string, input: Omit): Promise { + const safeLocale = ['de', 'en'].includes(locale) ? locale : 'en'; + const created = await prisma.politicalStatement.create({ + data: { + locale: safeLocale, + text: input.text, + active: input.active ?? true, + source: input.source ?? null, + }, + }); + return mapFromPrisma(created); } -export async function updateStatement(locale: string, id: number, input: Partial>): Promise { - const statements = await readStatementsFile(locale); - const index = statements.findIndex((s) => s.id === id); - if (index === -1) return null; +export async function updateStatement(locale: string, id: number, input: Partial>): Promise { + const safeLocale = ['de', 'en'].includes(locale) ? locale : 'en'; - const updated: PoliticalStatement = { - ...statements[index], - ...input, - id, - }; - statements[index] = updated; - await writeStatementsFile(locale, statements); - return updated; + // Optional: sicherstellen, dass das Statement zu dieser Locale gehört + const existing = await prisma.politicalStatement.findUnique({ where: { id } }); + if (!existing || existing.locale !== safeLocale) { + return null; + } + + const updated = await prisma.politicalStatement.update({ + where: { id }, + data: { + text: input.text ?? existing.text, + active: input.active ?? existing.active, + source: input.source !== undefined ? input.source : existing.source, + }, + }); + + return mapFromPrisma(updated); } export async function deleteStatement(locale: string, id: number): Promise { - const statements = await readStatementsFile(locale); - const filtered = statements.filter((s) => s.id !== id); - if (filtered.length === statements.length) { + const safeLocale = ['de', 'en'].includes(locale) ? locale : 'en'; + + const existing = await prisma.politicalStatement.findUnique({ where: { id } }); + if (!existing || existing.locale !== safeLocale) { return false; } - await writeStatementsFile(locale, filtered); + + await prisma.politicalStatement.delete({ where: { id } }); return true; } - diff --git a/prisma/migrations/20251202131410_add_political_statements/migration.sql b/prisma/migrations/20251202131410_add_political_statements/migration.sql new file mode 100644 index 0000000..5986498 --- /dev/null +++ b/prisma/migrations/20251202131410_add_political_statements/migration.sql @@ -0,0 +1,13 @@ +-- CreateTable +CREATE TABLE "PoliticalStatement" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "locale" TEXT NOT NULL, + "text" TEXT NOT NULL, + "active" BOOLEAN NOT NULL DEFAULT true, + "source" TEXT, + "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" DATETIME NOT NULL +); + +-- CreateIndex +CREATE INDEX "PoliticalStatement_locale_active_idx" ON "PoliticalStatement"("locale", "active"); diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 015a219..26f2268 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -101,3 +101,15 @@ model PlayerState { @@unique([identifier, genreKey]) @@index([identifier]) } + +model PoliticalStatement { + id Int @id @default(autoincrement()) + locale String + text String + active Boolean @default(true) + source String? + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + @@index([locale, active]) +}