Interfaz de usuario estilo arcade retro para sistema de votación de personajes. Vote por sus personajes favoritos de Rick & Morty, Pokémon y Superhéroes mientras la IA aprende sus preferencias.
Demo en vivo: https://andresgomez-77.github.io/LikeDislike/
- Diseño retro arcade estilo años 80/90
- Sistema de recomendación IA que aprende tus preferencias
- Totalmente responsive (móvil, tablet, escritorio)
- Animaciones fluidas con Framer Motion
- Estadísticas en tiempo real de votaciones
- 3 fuentes de personajes: Rick & Morty, Pokémon, Superhéroes
- Persistencia local de preferencias
| Tecnología | Versión | Propósito |
|---|---|---|
| React | 18.2.0 | Framework UI |
| TypeScript | 5.0 | Tipado estático |
| Vite | 5.0 | Build tool ultra rápido |
| Material-UI (MUI) | 5.x | Componentes UI |
| Framer Motion | 11.x | Animaciones |
| Axios | 1.x | Cliente HTTP |
| React Router | 6.x | Navegación (opcional) |
Antes de comenzar, asegúrate de tener instalado:
- Node.js >= 14.0.0 (Descargar aquí)
- npm >= 6.0.0 (viene con Node.js)
- Git (Descargar aquí)
Verifica las versiones instaladas:
node --version
npm --version
git --versiongit clone https://github.com/andresgomez-77/LikeDislike.git
cd LikeDislikenpm installEste comando instalará todas las dependencias necesarias:
- React y ReactDOM
- Material-UI y componentes relacionados
- Framer Motion para animaciones
- Axios para peticiones HTTP
- TypeScript y tipos relacionados
- Vite y plugins necesarios
Crea un archivo .env en la raíz del proyecto:
Para desarrollo local:
VITE_API_BASE_URL=http://localhost:8080/apiPara producción:
VITE_API_BASE_URL=https://tu-backend-en-produccion.com/apiNota: Las variables en Vite deben comenzar con
VITE_para ser expuestas al cliente.
Inicia el servidor de desarrollo:
npm run devLa aplicación estará disponible en: http://localhost:5173
Previsualiza el build de producción localmente:
npm run previewVerifica errores de código:
npm run lintLikeDislike/
├── public/
│ └── vite.svg
├── src/
│ ├── components/
│ │ ├── Cards.tsx
│ │ ├── CRTScreen.tsx
│ │ ├── PantallaInicio.tsx
│ │ ├── MenuLateral.tsx
│ │ ├── ModalEstadisticos.tsx
│ │ └── PanelPreferencia.tsx
│ ├── contexts/
│ │ └── ContextoPreferencias.tsx
│ ├── services/
│ │ └── obtenerPersonaje.ts
│ ├── types/
│ │ └── personaje.ts
│ ├── styles/
│ │ └── styles.ts
│ ├── App.tsx
│ ├── main.tsx
│ └── vite-env.d.ts
├── .env
├── .gitignore
├── index.html
├── package.json
├── tsconfig.json
├── vite.config.ts
└── README.md
Animación de encendido de monitor CRT retro.
Características:
- Flash blanco inicial
- Línea horizontal expandiéndose
- Texto "SYSTEM BOOTING..." con efecto typewriter
- Logo con efecto glow pulsante
- Duración total: 3.5 segundos
- Callback
onBootCompleteal finalizar
<CRTScreen onBootComplete={handleBootComplete} />Pantalla de bienvenida interactiva.
Características:
- Texto "PRESS START" parpadeante
- Click/touch para iniciar
- Fondo con estrellas animadas
- Efecto de scanlines retro
- Callback
onStartal hacer click
<PantallaInicio onStart={handleGameStart} />Tarjeta principal de votación de personajes.
Características:
- Imagen del personaje cargada desde API
- Nombre y badge de fuente (Rick & Morty, Pokémon, Superhero)
- Botones circulares 3D de Like/Dislike
- Contadores de votos animados
- Animaciones de entrada/salida con Framer Motion
- Integración con sistema de preferencias IA
Estados:
loading: Cargando personajevoting: Procesando votoidle: Listo para votar
Menú lateral con acceso a estadísticas.
Características:
- Botón flotante hamburguesa (posición adaptativa)
- Móvil: Abajo-izquierda
- Escritorio: Arriba-izquierda
- Drawer deslizable con 4 opciones:
- Personaje más gustado
- Personaje menos gustado
- Último evaluado
- Estado de Pikachu
- Animaciones de entrada con Framer Motion
Modal para visualizar estadísticas detalladas.
Características:
- Móvil: Pantalla completa
- Escritorio: Modal centrado
- Imagen y datos del personaje
- Contadores de likes/dislikes
- Loading state con CircularProgress
- Error handling con mensajes visuales
- Información especial de Pikachu
Panel lateral que muestra preferencias del usuario.
Características:
- Móvil:
- Oculto por defecto
- Botón flotante FAB para mostrar/ocultar
- Pantalla completa al abrirse
- Escritorio:
- Visible siempre
- Posición fija derecha
- Barras de progreso por fuente
- Badge de "IA ACTIVA" cuando se alcanza el umbral
- Indicador de fuente favorita
- Contador de votos totales
- Botón de reiniciar preferencias
El sistema aprende las preferencias del usuario basándose en sus votos.
- Registro de votos: Cada like/dislike se registra por fuente
- Cálculo de preferencia: Se determina la fuente favorita
- Activación de IA: Después de 5 votos, la IA empieza a recomendar
- Persistencia: Se guarda en
localStoragedel navegador
const {
preferences, // Objeto con todas las preferencias
trackLike, // Registra un like
trackDislike, // Registra un dislike
resetPreferences, // Reinicia todas las preferencias
getTotalVotes, // Obtiene total de votos
shouldUseRecommendations // Verifica si usar IA (>= 5 votos)
} = usePreferences();interface PreferenciaUsuario {
FuenteLikes: {
RICK_MORTY: number;
POKEMON: number;
SUPERHERO: number;
};
FuenteDislikes: {
RICK_MORTY: number;
POKEMON: number;
SUPERHERO: number;
};
FuentePreferida: PersonajeFuente | null;
PorcentajePreferencia: number;
}Paleta de colores:
- Cyan neón:
#16DBCC(principal) - Amarillo dorado:
#FFB800(acentos) - Azul oscuro:
#0A0E27(fondo) - Azul medio:
#1B2A4E(tarjetas) - Negro:
#000000(bordes)
Tipografía:
- Fuente principal: "Press Start 2P" (pixel art de Google Fonts)
- Fallback:
monospace
Efectos visuales:
- Bordes negros gruesos (3-4px)
- Sombras tipo 3D (
box-shadow: 4px 4px 0 #000) - Efectos glow con
text-shadow - Scanlines horizontales
- Viñeta en bordes
- Estrellas animadas de fondo
Powered by Framer Motion:
// Entrada de personaje
initial={{ scale: 0, rotate: -180 }}
animate={{ scale: 1, rotate: 0 }}
exit={{ scale: 0, rotate: 180 }}
// Hover en botones
whileHover={{ scale: 1.1 }}
whileTap={{ scale: 0.95 }}breakpoints: {
xs: 0,
sm: 600,
md: 900,
lg: 1200,
xl: 1536,
}| Elemento | Móvil | Escritorio |
|---|---|---|
| Título principal | 1.5rem | 2.5rem |
| Botón menú | 48px | 60px |
| Drawer ancho | 280px | 300px |
| Modal | Pantalla completa | 600px max |
| Panel preferencias | Oculto (FAB) | Visible fijo |
| Botones flotantes | Abajo | Según componente |
http://localhost:8080/api
Obtener personaje aleatorio
GET /api/personaje/aleatorioCon preferencias (IA activa)
GET /api/personaje/aleatorio?source=POKEMONRegistrar voto
POST /api/personaje/votar
Content-Type: application/json
{
"id": 123,
"like": true
}Personaje más gustado
GET /api/estadisticas/mas-gustadoPersonaje menos gustado
GET /api/estadisticas/menos-gustadoÚltimo personaje evaluado
GET /api/estadisticas/ultimo-evaluadoEstado especial de Pikachu
GET /api/estadisticas/pikachu┌─────────────────────────┐
│ 1. CRT Boot Animation │ (3.5 segundos)
│ "SYSTEM BOOTING..." │
└───────────┬─────────────┘
│
▼
┌─────────────────────────┐
│ 2. Press Start Screen │ (espera click)
│ "PRESS START" │
└───────────┬─────────────┘
│
▼
┌─────────────────────────┐
│ 3. Juego Principal │
│ ┌────────────────────┐ │
│ │ Ver personaje │ │
│ │ Votar (👍/👎) │ │
│ │ Ver estadísticas │ │
│ │ Revisar gustos │ │
│ └────────────────────┘ │
│ │ (loop) │
│ └────────────────│
└─────────────────────────┘
Problema: La app no puede conectarse a la API.
Solución:
# Verifica que el backend esté corriendo
# Revisa la URL en .env
VITE_API_BASE_URL=http://localhost:8080/api
# Reinicia el servidor de desarrollo
npm run devProblema: Peticiones bloqueadas por CORS.
Solución:
- Asegúrate que el backend permita tu origen
- En desarrollo local, ambos deben estar en
localhost - Verifica configuración CORS en Spring Boot
Problema: La fuente retro no se aplica.
Solución:
<!-- Verifica en index.html -->
<link href="https://fonts.googleapis.com/css2?family=Press+Start+2P&display=swap" rel="stylesheet">Problema: npm run build genera errores.
Solución:
# Limpia caché y reinstala
rm -rf node_modules package-lock.json
npm install
npm run build¡Las contribuciones son bienvenidas! Sigue estos pasos:
- Fork el repositorio
- Crea una rama para tu feature:
git checkout -b feature/nueva-funcionalidad
- Commit tus cambios:
git commit -m "Add: nueva funcionalidad increíble" - Push a tu rama:
git push origin feature/nueva-funcionalidad
- Abre un Pull Request
© 2026 Andrés Gómez. Todos los derechos reservados.
Este proyecto fue creado con fines educativos y de demostración.
Andrés Gómez
- Portfolio: [En construcción]
- LinkedIn: www.linkedin.com/in/andrés-gómez
- Email: andresgomez-77@hotmail.com
- GitHub: @andresgomez-77