Files
NightSpire/web-next/lib/admin-forum.ts
T
Inna 85c5c995ee Admin del foro: gestionar traducción EN de categorías y foros
Los formularios de crear categoría/foro aceptan nombre/descripción en inglés, y
se añade EDICIÓN en línea de categorías (name, name_en, order) y foros (name,
name_en, description, description_en). lib/admin-forum: createCategory/createForum
con EN + updateCategory/updateForum; rutas PUT en category/[id] y forum/[id].
Claves Admin nuevas (nombre/descripción EN). Verificado: listado con EN + update
round-trip; PUT protegido (403 sin admin).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 19:55:54 +00:00

118 lines
3.8 KiB
TypeScript

import type { RowDataPacket, ResultSetHeader } from 'mysql2'
import { db, DB } from './db'
export interface AdminCategory {
id: number
name: string
name_en: string
order: number
}
export interface AdminForum {
id: number
category_id: number
name: string
name_en: string
description: string
description_en: string
order: number
visibility: number
}
/** Categorías con sus foros (incluye ocultos y sin borrar), para el admin. */
export async function listCategoriesWithForums(): Promise<
{ category: AdminCategory; forums: AdminForum[] }[]
> {
const [cats] = await db(DB.web).query<RowDataPacket[]>(
'SELECT id, name, name_en, `order` FROM forum_categories ORDER BY `order`, id',
)
const [forums] = await db(DB.web).query<RowDataPacket[]>(
'SELECT id, category_id, name, name_en, description, description_en, `order`, visibility FROM forums WHERE deleted = 0 ORDER BY `order`, id',
)
return cats.map((c) => ({
category: { id: c.id, name: c.name, name_en: c.name_en || '', order: c.order },
forums: forums
.filter((f) => f.category_id === c.id)
.map((f) => ({
id: f.id,
category_id: f.category_id,
name: f.name,
name_en: f.name_en || '',
description: f.description,
description_en: f.description_en || '',
order: f.order,
visibility: f.visibility,
})),
}))
}
export async function createCategory(name: string, nameEn: string | null, order: number): Promise<number> {
const [res] = await db(DB.web).query<ResultSetHeader>(
'INSERT INTO forum_categories (name, name_en, `order`, created_at) VALUES (?, ?, ?, NOW())',
[name, nameEn || null, order],
)
return res.insertId
}
export async function updateCategory(id: number, name: string, nameEn: string | null, order: number): Promise<void> {
await db(DB.web).query('UPDATE forum_categories SET name = ?, name_en = ?, `order` = ? WHERE id = ?', [
name,
nameEn || null,
order,
id,
])
}
/** Borra una categoría solo si no tiene foros (no borrados). */
export async function deleteCategory(id: number): Promise<boolean> {
const [f] = await db(DB.web).query<RowDataPacket[]>(
'SELECT COUNT(*) AS n FROM forums WHERE category_id = ? AND deleted = 0',
[id],
)
if (Number(f[0]?.n ?? 0) > 0) return false
await db(DB.web).query('DELETE FROM forum_categories WHERE id = ?', [id])
return true
}
export async function createForum(
categoryId: number,
name: string,
nameEn: string | null,
description: string,
descriptionEn: string | null,
order: number,
visibility: number,
): Promise<number> {
const [res] = await db(DB.web).query<ResultSetHeader>(
'INSERT INTO forums (category_id, name, name_en, description, description_en, `order`, type, visibility, deleted, created_at, updated_at) ' +
'VALUES (?, ?, ?, ?, ?, ?, 0, ?, 0, NOW(), NOW())',
[categoryId, name, nameEn || null, description, descriptionEn || null, order, visibility ? 1 : 0],
)
return res.insertId
}
export async function updateForum(
id: number,
name: string,
nameEn: string | null,
description: string,
descriptionEn: string | null,
order: number,
visibility: number,
): Promise<void> {
await db(DB.web).query(
'UPDATE forums SET name = ?, name_en = ?, description = ?, description_en = ?, `order` = ?, visibility = ?, updated_at = NOW() WHERE id = ?',
[name, nameEn || null, description, descriptionEn || null, order, visibility ? 1 : 0, id],
)
}
/** Borrado lógico de un foro (deleted = 1). */
export async function deleteForum(id: number): Promise<void> {
await db(DB.web).query('UPDATE forums SET deleted = 1 WHERE id = ?', [id])
}
/** Cambia la visibilidad de un foro. */
export async function setForumVisibility(id: number, visible: boolean): Promise<void> {
await db(DB.web).query('UPDATE forums SET visibility = ? WHERE id = ?', [visible ? 1 : 0, id])
}