# Frontend de Quasar 🎮
## Visión general
El frontend de Quasar es una Single Page Application (SPA) moderna construida con React + Vite, utilizando shadcn/ui para componentes UI y Tailwind CSS para estilos. La aplicación está diseñada con una estética de modo oscuro sofisticada, priorizando la accesibilidad, la responsividad y un excelente rendimiento.
### Stack tecnológico
| Categoría | Tecnología | Versión | Propósito |
| -------------- | --------------- | -------- | ---------------------------------- |
| Framework | React | ^18.3.0 | Framework base |
| Build tool | Vite | ^5.0.0 | Build tool y dev server |
| Lenguaje | TypeScript | ^5.3.0 | Type safety |
| Estado | TanStack Query | ^5.0.0 | Gestión de estado y cache de datos |
| Routing | TanStack Router | ^1.0.0 | Routing con carga de datos |
| Formularios | TanStack Form | ^0.0.0 | Manejo de formularios |
| Validación | Zod | ^3.0.0 | Validación de esquemas |
| Componentes UI | shadcn/ui | latest | Componentes UI reutilizables |
| Estilos | Tailwind CSS | ^3.4.0 | Framework de estilos |
| Iconos | lucide-react | ^0.300.0 | Iconos |
| HTTP | axios | latest | Cliente HTTP |
| Fechas | date-fns | latest | Manipulación de fechas |
| Utils | clsx | ^2.0.0 | Utilidad de clases condicionales |
| Utils | tailwind-merge | ^2.0.0 | Fusión de clases Tailwind |
## Arquitectura del sistema
### Diagrama de arquitectura
```mermaid
graph TB
subgraph Browser
UI[Componentes UI]
Router[TanStack Router]
Query[TanStack Query]
Forms[TanStack Form + Zod]
end
subgraph Services
API[API Client]
Auth[Auth Service]
end
UI --> Router
UI --> Query
UI --> Forms
Router --> Query
Query --> API
Forms --> Query
API --> Backend[Backend API]
style UI fill:#1e293b
style Router fill:#334155
style Query fill:#334155
style Forms fill:#334155
style API fill:#475569
style Backend fill:#64748b
```
### Estructura de carpetas
```
frontend/
├── src/
│ ├── components/
│ │ ├── ui/ # Componentes shadcn/ui
│ │ ├── layout/ # Componentes de layout
│ │ ├── games/ # Componentes específicos de juegos
│ │ ├── roms/ # Componentes específicos de ROMs
│ │ ├── shared/ # Componentes compartidos
│ │ └── ... # Otros componentes específicos
│ ├── pages/ # Páginas de la aplicación
│ │ ├── DashboardPage.tsx
│ │ ├── GamesPage.tsx
│ │ ├── GameDetailPage.tsx
│ │ ├── GamesNewPage.tsx
│ │ ├── ImportPage.tsx
│ │ ├── PlatformsPage.tsx
│ │ ├── TagsPage.tsx
│ │ ├── SettingsPage.tsx
│ │ └── ExportPage.tsx
│ ├── api/ # Servicios de API y tipos
│ │ ├── client.ts # Cliente HTTP base
│ │ ├── games.ts # Servicios de juegos
│ │ ├── platforms.ts # Servicios de plataformas
│ │ ├── tags.ts # Servicios de etiquetas
│ │ ├── import.ts # Servicios de importación
│ │ ├── settings.ts # Servicios de configuración
│ │ └── types.ts # Tipos de API
│ ├── query/ # Configuración de TanStack Query
│ │ └── client.tsx # Cliente de Query
│ ├── form/ # Configuración de TanStack Form
│ │ └── config.tsx # Configuración de Form + Zod
│ ├── router/ # Configuración de TanStack Router
│ │ └── router.tsx # Configuración del router
│ ├── types/ # Definiciones TypeScript
│ │ └── index.ts # Tipos globales
│ ├── hooks/ # Custom hooks
│ ├── lib/ # Utilidades y configuraciones
│ │ ├── utils.ts # Utilidades generales
│ │ └── ... # Otras utilidades
│ ├── styles/ # Estilos globales
│ │ └── globals.css # CSS global con variables
│ └── layout/ # Componentes de layout
│ ├── Header.tsx # Header principal
│ ├── Sidebar.tsx # Sidebar de navegación
│ └── Layout.tsx # Layout principal
├── public/ # Assets estáticos
├── index.html # HTML entry point
├── package.json # Dependencias y scripts
├── tsconfig.json # Configuración TypeScript
├── vite.config.ts # Configuración Vite
├── tailwind.config.ts # Configuración Tailwind
└── postcss.config.js # Configuración PostCSS
```
## Sistema de diseño
### Principios de diseño
1. **Modo oscuro por defecto**: La aplicación está diseñada para funcionar principalmente en modo oscuro
2. **Alto contraste**: Asegurar legibilidad excelente en todos los contextos
3. **Consistencia**: Componentes y patrones consistentes en toda la aplicación
4. **Accesibilidad**: Cumplimiento con WCAG AA
5. **Performance**: Componentes optimizados para rendimiento
6. **Responsividad**: Mobile-first con breakpoints claros
### Paleta de colores (Modo oscuro)
#### Colores semánticos
```css
/* Primary - Violet (Acción principal) */
--primary-50: #f5f3ff;
--primary-100: #ede9fe;
--primary-200: #ddd6fe;
--primary-300: #c4b5fd;
--primary-400: #a78bfa;
--primary-500: #8b5cf6;
--primary-600: #7c3aed; /* Color principal */
--primary-700: #6d28d9;
--primary-800: #5b21b6;
--primary-900: #4c1d95;
--primary-950: #2e1065;
/* Secondary - Slate (Acciones secundarias) */
--secondary-50: #f8fafc;
--secondary-100: #f1f5f9;
--secondary-200: #e2e8f0;
--secondary-300: #cbd5e1;
--secondary-400: #94a3b8;
--secondary-500: #64748b;
--secondary-600: #475569;
--secondary-700: #334155;
--secondary-800: #1e293b;
--secondary-900: #0f172a;
--secondary-950: #020617;
/* Success - Emerald (Estados positivos) */
--success-50: #ecfdf5;
--success-100: #d1fae5;
--success-200: #a7f3d0;
--success-300: #6ee7b7;
--success-400: #34d399;
--success-500: #10b981;
--success-600: #059669;
--success-700: #047857;
--success-800: #065f46;
--success-900: #064e3b;
--success-950: #022c22;
/* Warning - Amber (Estados de advertencia) */
--warning-50: #fffbeb;
--warning-100: #fef3c7;
--warning-200: #fde68a;
--warning-300: #fcd34d;
--warning-400: #fbbf24;
--warning-500: #f59e0b;
--warning-600: #d97706;
--warning-700: #b45309;
--warning-800: #92400e;
--warning-900: #78350f;
--warning-950: #451a03;
/* Error - Red (Estados de error) */
--error-50: #fef2f2;
--error-100: #fee2e2;
--error-200: #fecaca;
--error-300: #fca5a5;
--error-400: #f87171;
--error-500: #ef4444;
--error-600: #dc2626;
--error-700: #b91c1c;
--error-800: #991b1b;
--error-900: #7f1d1d;
--error-950: #450a0a;
/* Info - Sky (Información) */
--info-50: #f0f9ff;
--info-100: #e0f2fe;
--info-200: #bae6fd;
--info-300: #7dd3fc;
--info-400: #38bdf8;
--info-500: #0ea5e9;
--info-600: #0284c7;
--info-700: #0369a1;
--info-800: #075985;
--info-900: #0c4a6e;
--info-950: #082f49;
```
#### Uso de colores
| Propósito | Color | Hex |
| -------------- | ---------- | ------- |
| Background | Slate-950 | #020617 |
| Card | Slate-950 | #020617 |
| Card hover | Slate-900 | #0f172a |
| Border | Slate-800 | #1e293b |
| Primary action | Violet-600 | #7c3aed |
| Primary hover | Violet-700 | #6d28d9 |
| Text primary | Slate-50 | #f8fafc |
| Text secondary | Slate-400 | #94a3b8 |
| Text muted | Slate-500 | #64748b |
### Tipografía
#### Font family
```css
font-family:
'Inter',
system-ui,
-apple-system,
sans-serif;
```
#### Escala de tamaños
| Token | Tamaño | Line-height | Uso |
| --------- | ------ | ----------- | ------------------------- |
| text-xs | 12px | 16px | Labels pequeños, captions |
| text-sm | 14px | 20px | Texto secundario |
| text-base | 16px | 24px | Texto de cuerpo |
| text-lg | 18px | 28px | Texto de cuerpo grande |
| text-xl | 20px | 28px | Subtítulos |
| text-2xl | 24px | 32px | Títulos pequeños |
| text-3xl | 30px | 40px | Títulos medianos |
| text-4xl | 36px | 44px | Títulos grandes |
| text-5xl | 48px | 56px | Display |
#### Font weights
| Token | Weight | Uso |
| ------------- | ------ | ---------------- |
| font-normal | 400 | Texto de cuerpo |
| font-medium | 500 | Texto de énfasis |
| font-semibold | 600 | Subtítulos |
| font-bold | 700 | Títulos |
### Espaciado
#### Escala de espaciado (base 4px)
| Token | Valor | Uso |
| ---------- | ----- | ---------------------------- |
| p-0, m-0 | 0px | Sin espaciado |
| p-1, m-1 | 4px | Micro espaciado |
| p-2, m-2 | 8px | Espaciado pequeño |
| p-3, m-3 | 12px | Espaciado medio-pequeño |
| p-4, m-4 | 16px | Espaciado medio |
| p-5, m-5 | 20px | Espaciado medio-grande |
| p-6, m-6 | 24px | Espaciado grande |
| p-8, m-8 | 32px | Espaciado extra grande |
| p-10, m-10 | 40px | Espaciado extra extra grande |
| p-12, m-12 | 48px | Espaciado masivo |
## Rutas de la aplicación
### Diagrama de rutas
```mermaid
graph LR
A[/] --> B[Dashboard]
C[/games] --> D[Lista de juegos]
E[/games/:id] --> F[Detalle de juego]
G[/games/new] --> H[Crear juego]
I[/import] --> J[Importar ROMs]
K[/platforms] --> L[Gestión de plataformas]
M[/tags] --> N[Gestión de etiquetas]
O[/settings] --> P[Configuración]
Q[/export] --> R[Exportar/Importar]
style A fill:#7c3aed
style C fill:#7c3aed
style E fill:#7c3aed
style G fill:#7c3aed
style I fill:#7c3aed
style K fill:#7c3aed
style M fill:#7c3aed
style O fill:#7c3aed
style Q fill:#7c3aed
```
### Descripción de rutas
| Ruta | Componente | Descripción |
| ------------ | -------------- | ------------------------------------------------------- |
| `/` | Dashboard | Vista general con estadísticas y juegos recientes |
| `/games` | GamesPage | Lista paginada de juegos con filtros y búsqueda |
| `/games/:id` | GameDetailPage | Vista detallada de un juego con metadata, ROMs, compras |
| `/games/new` | GamesNewPage | Formulario para crear un nuevo juego |
| `/import` | ImportPage | Interfaz para escanear e importar ROMs locales |
| `/platforms` | PlatformsPage | Gestión de plataformas |
| `/tags` | TagsPage | Gestión de etiquetas |
| `/settings` | SettingsPage | Configuración de la aplicación |
| `/export` | ExportPage | Exportar/importar colección |
## Componentes UI (shadcn/ui)
### Componentes base
| Componente | Uso principal |
| ------------ | ---------------------------------- |
| Button | Acciones principales y secundarias |
| Card | Contenedores de contenido |
| Input | Entradas de texto |
| Select | Selección de opciones |
| Dialog | Modales y diálogos |
| Table | Tablas de datos |
| Badge | Etiquetas y estados |
| Avatar | Avatares de usuario |
| DropdownMenu | Menús desplegables |
| Tabs | Navegación por pestañas |
| Form | Formularios |
| Separator | Separadores visuales |
| ScrollArea | Áreas con scroll |
| Tooltip | Información contextual |
| Skeleton | Estados de carga |
| AlertDialog | Confirmaciones |
| Toast | Notificaciones |
### Variantes y tamaños
#### Button
**Variantes:**
- `default`: Acción principal (violet)
- `destructive`: Acción destructiva (rojo)
- `outline`: Acción secundaria con borde
- `secondary`: Acción secundaria (slate)
- `ghost`: Acción sutil sin borde
- `link`: Estilo de enlace
**Tamaños:**
- `sm`: 32px de altura
- `default`: 40px de altura
- `lg`: 48px de altura
- `icon`: 32px x 32px (cuadrado)
#### Card
```tsx
Comienza añadiendo tu primer elemento.