Commit Graph

7 Commits

Author SHA1 Message Date
Inna 94f9731b2c Google Analytics 4, con interruptor y respetando el consentimiento
Se añade GA4 (gtag.js) con el componente oficial `@next/third-parties`, que es lo
que recomienda el doc de Next 16 y carga el mismo gtag pero tras la hidratación.

DOS interruptores:
1. `NEXT_PUBLIC_GA_ID` en el .env (no versionado). Vacío o sin poner = no se carga
   nada. Documentada en el README.
2. El consentimiento del visitante. El sitio YA tenía un banner con la categoría
   «Analíticas» que se puede rechazar: soltar gtag en el <head> lo habría
   convertido en mentira, y con visitantes en la UE, en un problema legal.

Para lo segundo se expone `useConsent(categoría)` desde CookieConsent, que además
reacciona en caliente: `writeConsent`/`revokeConsent` ya disparaban el evento
`ns:consentchange`, así que la analítica entra en cuanto se acepta y desaparece
si se revoca, sin recargar. Arranca en `false` a propósito: hasta confirmar el
consentimiento no se carga nada.

Verificado en el build: sin consentimiento no hay ni rastro de googletagmanager
en el HTML, y la condición compilada es `id && consent ? <GoogleAnalytics/> : null`.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-15 19:49:00 +00:00
Inna 6f52d325a6 Rebranding: sitios de voto, nota legal, prefijo uw->ns y repo renombrado
Sitios de voto: los 4 apuntaban a las fichas de UltimoWoW en los rankings con
SUS ids (Gtop100 94649, pingUsername 91402, etc.). No era cosmética: cada voto
de nuestros jugadores subía a UltimoWoW en el ranking. Se cambian nombre e ids
por un 236588 de relleno, así el enlace deja de acreditar a otro servidor. Las
fichas reales de NightSpire están por crear; entonces habrá que poner sus ids.

Nota legal: decía "Error 404 es la empresa que representa el servicio", heredado
de ultimowow. Al renombrar la marca pasaba a afirmar que una empresa ajena
representa a NightSpire, lo cual es falso. Se quita la empresa en ES y EN.

Prefijo uw- (de UltimoWoW) -> ns-: 100 identificadores en 11 ficheros (clases
CSS, ids de formulario, eventos y la cookie de consentimiento, que pasa a
ns_cookie_consent; a los usuarios les reaparecerá el aviso una vez). Se comprobó
antes que el CSS del tema no define ninguna clase uw-, así que no rompe estilos.
btn-ns-form y ns-cookie-btn-customize se usan sin estar definidas, pero ya era
así antes del cambio: eran clases muertas.

Repo de Gitea renombrado Inna/NovaWoW -> Inna/NightSpire (era la marca vieja más
visible de /changelogs, que forma la URL de cada commit). Gitea redirige la URL
antigua con 301. Se actualizan el remoto y lib/changelog.ts.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-15 15:28:29 +00:00
Inna 2c78489e4d fix: 47 errores de lint, y uno de ellos era un bug de verdad
Salieron al pasar el lint por todo el proyecto. De 47 a 0 (quedan 15 avisos:
<img> vs <Image /> y el <link> del tema, los dos deliberados).

- Footer y Video (42 de los 47, que en realidad eran 7 enlaces: el plugin repite
  cada uno 6 veces): usaban `<a href="/terms-and-conditions">` SIN el idioma
  delante. No estaba roto de milagro: el middleware lo salvaba mirando la cookie
  NEXT_LOCALE. Pero cada clic se comía un 307 y recargaba la página entera en
  vez de navegar en cliente, y el idioma lo decidía la cookie en vez de la URL
  en la que estás. Ahora van con el `Link` de i18n, que ya existía.
- Turnstile: escribía una ref (`cb.current = onVerify`) DURANTE el render. Es el
  patrón de "callback fresca", pero no está permitido: React puede descartar ese
  render y dejarla mal. Pasa a un efecto.
- ActivateClient y ConfirmClient: ponían el estado de error con setState dentro
  del efecto cuando NO hay hash. Eso se sabe ya al renderizar (es un prop), así
  que se deriva del estado inicial y se ahorra un render.
- BattlepayList: `window.location.href = …` -> `.assign()`, igual que en la
  tienda.
- CookieConsent: aquí el efecto es correcto y la regla no aplica, así que se
  silencia explicando por qué: el consentimiento vive en una cookie del
  navegador, en el servidor no existe, y leerlo al renderizar rompería la
  hidratación (le saldría el banner a quien ya había decidido).

Verificado: desde /es/ el pie enlaza a /es/terms-and-conditions y desde /en/ a
/en/terms-and-conditions; portada, cookies, tienda y mi-cuenta siguen dando 200.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-15 12:03:25 +00:00
Inna 651d8deafc i18n: traducir toda la app (ES + EN) — páginas y componentes con texto hardcodeado
Se externaliza el texto español hardcodeado de ~55 archivos a next-intl y se añaden
traducciones al inglés, con paridad de claves es/en. Nuevos namespaces: History,
CharService, CharServiceB, Points, Legal, UI, Misc (+ altas en Common/Admin).

- Historiales (PD/PV, transacciones, sanciones, seguridad), servicios de personaje
  (transfer, send-gift, quest, restore-*, change-*, customize, level-up, gold, rename),
  PD/pagos (d-points, trade, promo, transfer-dp, rename-guild, DPointsTabs), páginas
  legales (cookies, privacidad, términos, reembolsos, aviso legal, contacto), layout
  (cabecera, footer, cookies, 2FA, descargas, jugadores, recluta) y páginas varias
  (home, reino, ayuda, addons, 2falogin).
- Textos con markup inline via t.rich; interpolación con ICU.
- Componente <NoteLegend/> para la leyenda NOTA/NOTE compartida.
- payLabel/confirmText de los servicios de pago traducidos.
- Verificado: tsc OK, next build OK, todas las claves t() resuelven en es y en,
  todos los t.rich casan etiquetas, páginas 200 en /es/ y /en/ sin claves crudas.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 18:58:54 +00:00
Inna 57e91480d1 web-next: «Personalizar» abre panel granular de cookies (uw-cookie-details)
El botón Personalizar del banner ahora despliega un panel con checkboxes por
categoría (Necesarias fija+desactivada, Analíticas, Marketing) y «Guardar
preferencias», tal como el markup del usuario. Al guardar, escribe la cookie
uw_cookie_consent con la selección granular y sincroniza con Zaraz. Categorías
alineadas a las del panel (Necesarias/Analíticas/Marketing); ConsentStatus y
acceptAll/rejectAll usan las mismas. Estilos del panel en globals.css.

Verificado: Personalizar abre el panel, marcar Analíticas + Guardar deja la
cookie {necessary,analytics:true,marketing:false} y /cookies lo refleja.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-13 12:02:49 +00:00
Inna 4ebe3c34d3 web-next: banner de consentimiento de cookies + estado de la API (Zaraz)
- Banner real `uw-cookie-content` (Rechazar/Personalizar/Aceptar todas) fijo
  abajo y site-wide (montado en el layout, componente CookieBanner). Aparece
  en la primera visita, guarda la decisión en la cookie uw_cookie_consent (1
  año) y se sincroniza con Cloudflare Zaraz si está presente
  (zaraz.consent.setAll / .modal). Estilos en globals.css.
- «Personalizar» abre el modal granular de Zaraz (o /cookies si no hay Zaraz).
- window.UWCookies {showBanner, revokeConsent, acceptAll, rejectAll}.
- Página /cookies: panel «Tu estado de consentimiento» (ConsentStatus) que
  muestra los datos EN VIVO de la API de Zaraz (zaraz.consent.getAll()) por
  propósito; si Zaraz no está, cae a la preferencia guardada por categoría.

Verificado con navegador: el banner aparece, «Aceptar todas» lo oculta y
escribe la cookie, y el panel de /cookies refleja el estado.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-13 11:58:54 +00:00
Inna e289a87d1f web-next: página /cookies (Declaración de Cookies) + consentimiento Zaraz
Crea la ruta de Declaración de Cookies con el markup del tema y las 5 tablas
de cookies (uw-cookie-table, estilizadas en globals.css) + estilos de listas
y botones (btn-uw). Los enlaces internos .php se cablean a las rutas Next
(/privacy-policy, /contact-us).

Sistema de consentimiento = Cloudflare Zaraz (elección del usuario):
components/CookieConsent.tsx expone window.UWCookies.showBanner()
(zaraz.consent.modal=true) y revokeConsent() (zaraz.consent.setAll(false)),
que Cloudflare activa cuando el dominio pasa por su proxy con Zaraz Consent;
degrada con aviso si Zaraz no está presente. El footer ya enlazaba aquí.

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