Nueva entrega de vComics DB con GitHub Copilot (Claude Sonnet 4.6) al mando. Esta vez el salto ha sido especialmente visual y funcional: la app pasa de ser un catálogo de consulta a una herramienta real de gestión personal. Cada usuario puede ahora llevar el registro de sus cómics, gestionar sus colecciones y, si tiene rol de administrador, mantener el catálogo completo desde la propia app.
Y sí, este post también lo ha generado Copilot, con mi supervisión y edición final.
El proyecto
vComics DB es una aplicación web para gestionar colecciones de cómics. Está formada por un frontend en React 18 + Vite y un backend en Spring Boot 3 + Java. Esta entrega construye encima del sistema JWT y del módulo de colecciones introducidos en la iteración anterior, añadiendo la capa de colección personal por usuario, páginas de detalle y un panel de administración.
Código disponible en GitHub:
🖥️ Frontend: github.com/entorno5/front-comics
⚙️ Backend: github.com/entorno5/comics-backend
Nota: Tanto el código como este post han sido generados por GitHub Copilot (Claude Sonnet 4.6) bajo la supervisión del desarrollador. El flujo de trabajo ha sido: indicación → generación → revisión → ajuste → commit. Sin magia negra, con criterio humano encima.
⚙️ Backend Spring Boot — Lo que se ha añadido
👤 Colección personal de cómics por usuario
El cambio más importante del backend en esta iteración. Se ha implementado un módulo completo para que cada usuario autenticado lleve el registro de los cómics que tiene físicamente:
- UserComic — Nuevo modelo de dominio que representa la relación entre un usuario y un cómic,
incluyendo el campo
unitspara registrar cuántas copias tiene. - UserComicRepository — Interfaz del repositorio, con implementación en memoria
(
InMemoryUserComicRepository) para el perfil mock. - UserComicService — Lógica de negocio completa: listar con paginación y búsqueda, obtener un cómic concreto, añadir, actualizar unidades y eliminar.
- MyComicController — Endpoints REST bajo
/api/v1/my/comics:GET /api/v1/my/comics— Lista paginada de cómics del usuario, con filtro por texto.GET /api/v1/my/comics/{id}— Obtener un cómic concreto de mi colección.POST /api/v1/my/comics/{id}— Añadir un cómic a mi colección con el número de unidades.PATCH /api/v1/my/comics/{id}— Actualizar el número de unidades.DELETE /api/v1/my/comics/{id}— Eliminar un cómic de mi colección.
- AddMyComicDTO, UpdateMyComicDTO, UserComicResponseDTO, UserComicPageResponse — DTOs de entrada y salida para el nuevo controlador.
📚 Colecciones personales por usuario
Paralelo al módulo de cómics, se ha añadido la gestión de colecciones propias de cada usuario:
- UserCollectionService — Lógica para listar, crear, actualizar y eliminar colecciones de un usuario concreto.
- MyCollectionController — Endpoints REST bajo
/api/v1/my/collectionspara CRUD completo de colecciones personales. - CreateCollectionDTO — DTO de entrada para crear o editar una colección.
- CollectionPageResponse — Respuesta paginada para el listado de colecciones.
📄 Paginación en el catálogo de colecciones
El CollectionController y el CollectionService se han extendido significativamente para
soportar paginación real (parámetros page, size y q) y devolver los cómics
que pertenecen a cada colección. El ComicService también ha recibido mejoras para soportar filtros
adicionales desde el catálogo.
🔧 Configuración y tests
- application-dev.properties — Nuevo fichero de configuración específico para el perfil de desarrollo, separando valores sensibles del properties principal.
- SecurityRulesTest — Tests de integración que verifican que los endpoints protegidos devuelven
401sin token y200con un token válido. - CollectionServiceTest — Suite de tests unitarios para el servicio de colecciones, que cubre creación, consulta, actualización y borrado.
- ComicServiceTest — Extendido con nuevos casos de prueba para los filtros y la paginación.
🎨 Frontend React — Lo que se ha añadido
📖 Página de detalle de cómic
Nueva página ComicDetail accesible desde cualquier tarjeta del catálogo. Muestra la información
completa del cómic y, si el usuario está autenticado, permite:
- Ver si el cómic ya está en su colección personal.
- Añadirlo con un clic.
- Editar el número de unidades directamente en la página.
- Eliminarlo de su colección.
La carga es paralela: se piden simultáneamente los datos del cómic del catálogo y el estado personal del usuario
para ese cómic, usando Promise.all.
🗂️ Página de detalle de colección
Nueva página CollectionDetail que muestra todos los números (issues) de una colección.
Para cada issue se puede marcar si está en la colección personal del usuario, toggling entre añadir y eliminar
directamente desde la lista. Funciona tanto para colecciones propias como para colecciones publicadas del catálogo
general.
🛡️ Panel de administración
Nueva página Admin, accesible únicamente para usuarios con rol de administrador:
- Interfaz de pestañas para alternar entre el panel de Colecciones y el de Cómics.
- CollectionsPanel — Gestión completa del catálogo de colecciones: listar con scroll infinito, crear, editar y eliminar.
- ComicsPanel — Gestión completa del catálogo de cómics con las mismas operaciones.
- AdminRoute — Componente protector que redirige a home si el usuario no tiene el rol
ADMIN.
🧭 PageNav — Navegación unificada
Se ha creado un componente PageNav que reemplaza las distintas cabeceras que existían, ofreciendo una
navegación consistente en toda la app:
- Acceso a Inicio, Mis cómics, Mis colecciones, Cómics publicados y Colecciones publicadas.
- Si el usuario es administrador, aparece además el enlace a Gestión.
- Botón de logout integrado.
- Toggle de modo oscuro.
- Menú hamburguesa en mobile.
♾️ useInfiniteList — Scroll infinito genérico
Nuevo hook useInfiniteList que abstrae el patrón de scroll infinito sobre cualquier endpoint paginado.
Recibe una función fetchPage(page, size) y gestiona internamente el estado de items, carga, errores,
página actual y la detección del centinela (IntersectionObserver) para disparar la siguiente página.
Lo usan los paneles del admin para cargar colecciones y cómics sin límite aparente.
🔌 Nuevos servicios
- myComicService.js — Consume
/api/v1/my/comics: obtener lista, añadir, actualizar unidades, eliminar y obtener todos los IDs de mi colección. - myCollectionService.js — Consume
/api/v1/my/collections: CRUD completo de colecciones personales. - userService.js — Obtiene el perfil del usuario autenticado.
- apiError.js — Utilidad centralizada para parsear errores de la API y extraer mensajes legibles.
- comicService.js — Extendido con
getComic(id), endpoints filtrados y soporte de paginación. - collectionService.js — Extendido con
getCollection(id)ygetCollectionComics(id)para las páginas de detalle.
🔑 isAdmin en AuthContext
El AuthContext ahora decodifica el JWT y expone el flag isAdmin a toda la aplicación.
Esto permite que PageNav muestre u oculte el enlace de administración y que AdminRoute
proteja la ruta sin necesidad de llamar al backend.
🖼️ Rediseño visual
Aprovechando la iteración, se ha realizado un rediseño visual completo de varios componentes y páginas:
- HeroSection — Completamente reescrita con nueva estructura, tipografía y llamadas a la acción
más claras. Se elimina el antiguo componente
FeatureSection. - ComicCard — Nueva imagen de portada con fallback a
comic-placeholder.svg, más información visible y mejor accesibilidad. - CollectionCard — Rediseñada con más contexto visual.
- Home, Catalog, Collections — CSS Modules revisados para mayor coherencia visual y mejor comportamiento responsive.
- IssueRow — Nuevo componente de fila para listar los números de una colección con botón de toggle de propiedad.
- comic-placeholder.svg — Imagen SVG de relleno para portadas sin imagen.
- utils/comicImage.js — Función que resuelve la URL de portada de un cómic y devuelve el placeholder si no hay imagen disponible.
✅ Tests
Todo el código nuevo tiene cobertura de tests con Vitest + Testing Library. Los tests existentes se han actualizado para adaptarse al rediseño. Tests nuevos:
AdminRoute.test.jsxCollectionsPanel.test.jsxIssueRow.test.jsxPageNav.test.jsxCollections.test.jsxComicDetail.test.jsx
Stack tecnológico
| Frontend | React 18, Vite, CSS Modules, React Router v7 |
| Auth Frontend | JWT decodificado en cliente, isAdmin desde token, AdminRoute |
| Tests Frontend | Vitest, Testing Library |
| Backend | Spring Boot 3, Java, Maven |
| Auth Backend | Spring Security + JWT (HMAC-SHA256), rutas por rol |
| Persistencia | Repositorios en memoria (perfil mock), separación de perfil dev |
| Tests Backend | JUnit 5, Spring Security test slice, Mockito |
| IA utilizada | GitHub Copilot — Claude Sonnet 4.6 (código + este post) |
| Control de versiones | Git + GitHub |
Reflexión final (del humano supervisor)
Esta iteración ha sido la más satisfactoria hasta ahora. La app ha pasado de ser un catálogo de consulta a tener una lógica de usuario real: cada persona puede registrar sus cómics, cuántas copias tiene, y gestionar sus propias colecciones. Y el admin puede mantener el catálogo sin tocar una base de datos.
Lo que más me ha sorprendido esta vez es la consistencia entre capas. Copilot ha generado los DTOs del backend, los servicios del frontend que los consumen y los tests de ambos en el mismo flujo de trabajo, y todo encajaba. Revisé los contratos de la API y los modelos de respuesta, y estaban alineados sin necesidad de corrección manual.
El rediseño visual también ha sido fluido: los componentes tienen mejor aspecto y la navegación es coherente en
toda la app. El componente PageNav unifica algo que antes era inconsistente entre páginas.
Código generado por GitHub Copilot (Claude Sonnet 4.6), revisado y supervisado por mí. Este post también. Ya lo sabéis. 😄
