Files
NightSpire/web-next/lib/content-creator.ts
T
Inna 25ced0c2f6 web: la página de creadores de contenido (el menú VIDEOS), que daba 404
SiteHeader enlazaba /content-creators y esa página no existía en Next: el menú
VIDEOS llevaba a un 404. Réplica del partial Django `partials/videos.html`, con
sus clases del tema (cc-box, cc-avatar, cc-name...). Lee el primer registro de
home_contentcreator, igual que la vista de Django.

La descripción es HTML de CKEditor (lo edita un admin), así que se sanea con
`cleanPostHtml`, la misma allowlist que los mensajes del foro. Comprobado
metiendo un <script>alert(1)</script> a propósito: no aparece en el HTML servido.

Dos arreglos sobre el diseño de Django, que copiaba tal cual:

- El título va SIEMPRE. Django lo metía dentro del `if content_creator`, así que
  sin datos la página quedaba con un <p> suelto, sin cabecera ni caja. Ahora sin
  creador sale el título de la sección y el aviso centrado en su box-content.
- Los enlaces de YouTube/Facebook se salían por abajo de la caja. El tema le da a
  `.cc-box` una altura FIJA de 172px contando con el content-box del navegador, y
  el border-box de Tailwind le restaba el padding y el borde: 24px menos de alto
  útil. Es el mismo caso que .item-box en la tienda. Medido: la caja pasa de 172
  a 196px de alto y los enlaces dejan de desbordar.

Verificado con un creador de prueba (borrado después): /es/ y /en/ dan 200, el
título, el avatar, el iframe y los enlaces caen dentro de la caja, y con la tabla
vacía sale el mismo texto que Django.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-15 13:03:32 +00:00

46 lines
1.5 KiB
TypeScript

import type { RowDataPacket } from 'mysql2'
import { db, DB } from './db'
/**
* Creador de contenido destacado (`home_contentcreator`, el menú VIDEOS).
*
* Como en Django, se muestra SOLO el primero: la tabla se maneja desde el admin
* y ahora mismo está vacía, así que la página enseña el aviso de "no hay
* información" igual que hacía Django.
*/
export interface ContentCreator {
title: string
/** HTML de CKEditor. Se sanea antes de pintarlo (ver la página). */
description: string
contentType: string
subtitle: string
youtubeVideoUrl: string | null
avatarImageUrl: string | null
youtubeChannelUrl: string | null
facebookPageUrl: string | null
}
export async function getContentCreator(): Promise<ContentCreator | null> {
try {
const [rows] = await db(DB.default).query<RowDataPacket[]>(
`SELECT title, description, content_type, subtitle, youtube_video_url,
avatar_image_url, youtube_channel_url, facebook_page_url
FROM home_contentcreator ORDER BY id LIMIT 1`,
)
const r = rows[0]
if (!r) return null
return {
title: String(r.title),
description: String(r.description ?? ''),
contentType: String(r.content_type ?? ''),
subtitle: String(r.subtitle ?? ''),
youtubeVideoUrl: r.youtube_video_url ?? null,
avatarImageUrl: r.avatar_image_url ?? null,
youtubeChannelUrl: r.youtube_channel_url ?? null,
facebookPageUrl: r.facebook_page_url ?? null,
}
} catch {
return null
}
}