Changelogs

fix: /expired-link, el botón descuadrado y el mensaje que no se veía

15 de julio de 2026 a las 13:14

adevopg · 57dd48e

Dos cosas, y la segunda dejaba la página sin contenido: - El botón "Solicitar nuevo cambio de correo" salía de 250x100 pegado a la derecha. `.back-to-account` es el botón de la CABECERA de una caja (250px de ancho, line-height 50, float right); suelto en el CUERPO el float lo pega a un lado, y el texto no cabe en 250px, se parte en dos líneas y cada una se lleva sus 50px. Se le deja el aspecto del tema pero ajustado a su texto: pasa a 336x50 y centrado. - El mensaje rojo ("el enlace ha expirado") NO SE VEÍA: el tema deja `.alert-message` con display:none porque es el hueco que rellena y revela el JS, y aquí el aviso es estático. Se pone display:block a mano, igual que hacen todos los formularios del proyecto. Comprobado que al original le pasa lo mismo: su página de enlace caducado enseña el título y el botón, y la explicación queda invisible. Medido en el navegador: botón 336x50, centrado, sin desbordar, y el mensaje visible.




web: páginas de enlace caducado y mantenimiento (las que faltaban vs Django)

15 de julio de 2026 a las 13:07

adevopg · c4f9515

Réplica de los partials `expired_link.html` y `maintenance.html`, con las clases del tema. Con esto web-next ya tiene todo lo que tiene Django: las demás rutas que faltaban eran los *-success/*-cancel por servicio, que aquí sustituye el /service-success unificado, y novawow-realm/players, que los sirve la ruta dinámica [realm]. Dos erratas del original que NO se copian: - "Enlace Expirado" enseñaba un «No hay códigos de promoción disponibles» que es de otra página. - Su botón "Solicitar nuevo cambio de correo" enlazaba a `expired-link`, o sea a sí misma. Aquí va a /change-email, que es lo que pretendía. Verificado: /es/ y /en/ de las dos dan 200 (Django también), la imagen de mantenimiento carga y cabe (437x371, sin desbordar), y el botón apunta a /es/change-email.




web: la página de creadores de contenido (el menú VIDEOS), que daba 404

15 de julio de 2026 a las 13:03

adevopg · 25ced0c

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.




send-gift: rediseño al original — es la tienda, pero regalando

15 de julio de 2026 a las 12:45

adevopg · 67faa1a

El original lo dice en su propio texto ("los objetos disponibles son los mismos de la tienda") y lo confirma su JS, que usa #store-list y .store-add-button: el regalo NO tiene catálogo propio, es la tienda con el correo a otro personaje. Nosotros teníamos una tabla aparte (home_item) con 8 objetos y precios en euros. Ahora send-gift monta StoreBrowser en modo `gift`: mismo catálogo (3068 ítems, PD/PV), mismo carrito con cantidades y las cuatro formas de pago. Antes NO tenía Stripe: solo SumUp, PD y PV. Dos pasos, como el original: primero #char-select-div (personaje de origen, destino, confirmación y token) y solo al pulsar "Mostrar Regalos" aparece el catálogo. Se borran SendGiftForm, /api/gift/checkout y lib/gift (ya no los usa nadie); la tabla home_item se queda en la BD, sin usar. Tres cosas que el usuario pidió y que estaban mal: - El formulario va con `noValidate`: los avisos los damos nosotros en rojo (#show-gif-response), no el navegador. - "Mostrar Regalos" ahora valida contra el SERVIDOR (que el personaje de origen sea tuyo, que el destino exista y que el token sea correcto). Antes elegías objetos para descubrir al final que el destino no existía. - BUG REAL: el nombre del destino distinguía mayúsculas. `characters.name` es `utf8mb4_bin`, así que "innakh" NO encontraba a "Innakh" (comprobado: 0 resultados; con COLLATE, 1). `findCharacterByName` busca sin distinguir y devuelve el nombre CANÓNICO, que es el que va al comando SOAP. La validación vive en lib/gift-check y la usan las dos rutas: /api/gift/check (el botón) y /api/gift/send, que revalida porque el cliente puede saltarse el paso 1. También se quita del texto "El pago se realiza mediante SumUp": el original no lo dice y además ya era falso con cuatro formas de pago. Verificado: innakh / INNAKH / InNaKh resuelven a "Innakh"; token malo y destino inexistente salen en rojo sin pasar al catálogo. Con 500 PD de saldo de prueba, 2 copias de un ítem de 200 pasan el cobro (deliveryFailed por el worldserver caído, con su reembolso) y 3 dan insufficientPd: el servidor cobra por copias. Datos de prueba borrados.




fix: 47 errores de lint, y uno de ellos era un bug de verdad

15 de julio de 2026 a las 12:03

adevopg · 2c78489

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.





SÍGUENOS EN