diff --git a/frontend/src/app/games/[id]/page.tsx b/frontend/src/app/games/[id]/page.tsx index f824bfa..ffdd027 100644 --- a/frontend/src/app/games/[id]/page.tsx +++ b/frontend/src/app/games/[id]/page.tsx @@ -18,6 +18,7 @@ import { AlertDialogHeader, AlertDialogTitle, } from '@/components/ui/alert-dialog'; +import Navbar from '@/components/landing/Navbar'; export default function GameDetailPage() { const params = useParams(); @@ -79,180 +80,278 @@ export default function GameDetailPage() { if (loading) { return ( -
-
-
Cargando juego...
-
+
+
+ +
+
+
+
+
+

+ CARGANDO JUEGO... +

+
+
+
+
); } if (error || !game) { return ( -
-
-
{error || 'Juego no encontrado'}
-
+
+
+ +
+
+
+
+

+ {error || 'JUEGO NO ENCONTRADO'} +

+ +
+
+
+
); } return ( -
-
- {/* Header */} -
-
- -
-

{game.title}

-

{game.slug}

+
+
+ +
+
+
+ {/* Header */} +
+
+ +
+

+ {game.title.toUpperCase()} +

+

{game.slug}

+
+
+
+ + +
-
-
- - -
-
- {/* Game Info */} - - - Información del Juego - Detalles y metadatos - - -
- {formatDate(game.releaseDate) && ( -
- - - Fecha de lanzamiento:{' '} - {formatDate(game.releaseDate)} - + {/* Game Info */} + + + INFORMACIÓN DEL JUEGO + Detalles y metadatos + + +
+ {formatDate(game.releaseDate) && ( +
+ + + FECHA DE LANZAMIENTO:{' '} + {formatDate(game.releaseDate)} + +
+ )} +
+ + FUENTE: {game.source.toUpperCase()} + +
+ {game.genre && ( +
+ + GÉNERO: {game.genre.toUpperCase()} + +
+ )} + {game.platform && ( +
+ + PLATAFORMA: {game.platform.toUpperCase()} + +
+ )} + {game.year && ( +
+ + AÑO: {game.year} + +
+ )} + {game.sourceId && ( +
+ + ID DE FUENTE: {game.sourceId} + +
+ )} + {game.igdbId && ( +
+ + IGDB ID: {game.igdbId} + +
+ )} + {game.rawgId && ( +
+ + RAWG ID: {game.rawgId} + +
+ )} + {game.thegamesdbId && ( +
+ + THEGAMESDB ID: {game.thegamesdbId} + +
+ )}
- )} -
- Fuente: {game.source} -
- {game.genre && ( -
- Género: {game.genre} -
- )} - {game.platform && ( -
- Plataforma: {game.platform} -
- )} - {game.year && ( -
- Año: {game.year} -
- )} - {game.sourceId && ( -
- ID de fuente: {game.sourceId} -
- )} - {game.igdbId && ( -
- IGDB ID: {game.igdbId} -
- )} - {game.rawgId && ( -
- RAWG ID: {game.rawgId} -
- )} - {game.thegamesdbId && ( -
- TheGamesDB ID: {game.thegamesdbId} -
- )} -
- {game.description && ( -
-

Descripción

-

{game.description}

-
+ {game.description && ( +
+

DESCRIPCIÓN

+

+ {game.description} +

+
+ )} + + + + {/* ROM Info (if source = rom) */} + {game.source === 'rom' && ( + + + + INFORMACIÓN DEL ARCHIVO ROM + + Detalles del archivo importado + + +
+ {game.romFilename && ( +
+ + + ARCHIVO:{' '} + {game.romFilename} + +
+ )} + {game.romPath && ( +
+ + + RUTA: {game.romPath} + +
+ )} + {game.romSize && ( +
+ + TAMAÑO: {formatFileSize(game.romSize)} + +
+ )} + {game.romFormat && ( +
+ + FORMATO: {game.romFormat.toUpperCase()} + +
+ )} + {game.romChecksum && ( +
+ + CHECKSUM: {game.romChecksum} + +
+ )} +
+
+
)} - - +
- {/* ROM Info (if source = rom) */} - {game.source === 'rom' && ( - - - Información del Archivo ROM - Detalles del archivo importado - - -
- {game.romFilename && ( -
- - - Archivo: {game.romFilename} - -
- )} - {game.romPath && ( -
- - - Ruta: {game.romPath} - -
- )} - {game.romSize && ( -
- Tamaño: {formatFileSize(game.romSize)} -
- )} - {game.romFormat && ( -
- Formato: {game.romFormat} -
- )} - {game.romChecksum && ( -
- Checksum: {game.romChecksum} -
- )} -
-
-
- )} -
- - {/* Delete Game Confirmation */} - - - - ¿Eliminar juego? - - ¿Estás seguro de que deseas eliminar “{game.title}”? Esta acción no se - puede deshacer. - - - - Cancelar - - Eliminar - - - - + {/* Delete Game Confirmation */} + + + + + ¿ELIMINAR JUEGO? + + + ¿Estás seguro de que deseas eliminar “{game.title}”? Esta acción no se + puede deshacer. + + + + + CANCELAR + + + ELIMINAR + + + + +
+
); } diff --git a/frontend/src/app/games/page.tsx b/frontend/src/app/games/page.tsx index b59184f..031a748 100644 --- a/frontend/src/app/games/page.tsx +++ b/frontend/src/app/games/page.tsx @@ -6,7 +6,6 @@ import { Game, gamesApi } from '@/lib/api'; import { GameTable } from '@/components/games/GameTable'; import { GameDialog } from '@/components/games/GameDialog'; import { GameFilters } from '@/components/games/GameFilters'; -import { ImportSheet } from '@/components/games/ImportSheet'; import { Button } from '@/components/ui/button'; import { PlusIcon, LayoutGridIcon, TableIcon } from 'lucide-react'; import { @@ -19,6 +18,8 @@ import { AlertDialogHeader, AlertDialogTitle, } from '@/components/ui/alert-dialog'; +import Navbar from '@/components/landing/Navbar'; +import { GameCard } from '@/components/games/GameCard'; export default function GamesPage() { const router = useRouter(); @@ -96,124 +97,149 @@ export default function GamesPage() { }; return ( -
-
- {/* Header */} -
-
-

Gestión de Videojuegos

-

- {filteredGames.length} {filteredGames.length === 1 ? 'juego' : 'juegos'} en tu - biblioteca -

-
-
- - -
-
+
+ {/* Starfield background */} +
- {/* Filters */} - setSearchQuery('')} - /> + {/* Navbar */} + - {/* View Mode Toggle */} -
- - -
+ {/* Main Content */} +
+
+
+ {/* Header */} +
+
+

+ GESTIÓN DE VIDEOJUEGOS +

+

+ {filteredGames.length} {filteredGames.length === 1 ? 'JUEGO' : 'JUEGOS'} EN TU + BIBLIOTECA +

+
+
+ +
+
- {/* Content */} - {loading ? ( -
-
Cargando juegos...
-
- ) : viewMode === 'table' ? ( - - ) : ( -
- {filteredGames.map((game) => ( - setSearchQuery('')} + /> + + {/* View Mode Toggle */} +
+ + +
+ + {/* Content */} + {loading ? ( +
+
+
+

+ CARGANDO JUEGOS... +

+
+
+ ) : viewMode === 'table' ? ( + - ))} -
- )} + ) : ( +
+ {filteredGames.map((game) => ( + + ))} +
+ )} - {/* Empty State */} - {!loading && filteredGames.length === 0 && ( -
-

- {searchQuery - ? 'No se encontraron juegos que coincidan con tu búsqueda.' - : 'No hay juegos en tu biblioteca.'} -

- {!searchQuery && ( - + {/* Empty State */} + {!loading && filteredGames.length === 0 && ( +
+

+ {searchQuery + ? 'NO SE ENCONTRARON JUEGOS QUE COINCIDAN CON TU BÚSQUEDA.' + : 'NO HAY JUEGOS EN TU BIBLIOTECA.'} +

+ {!searchQuery && ( + + )} +
)}
- )} -
- {/* Dialog */} - + {/* Dialog */} + - {/* Delete Confirmation */} - - - - ¿Eliminar juego? - - ¿Estás seguro de que deseas eliminar "{gameToDelete?.title}"? Esta acción no se puede - deshacer. - - - - Cancelar - - Eliminar - - - - + {/* Delete Confirmation */} + + + + ¿Eliminar juego? + + ¿Estás seguro de que deseas eliminar “{gameToDelete?.title}”? Esta + acción no se puede deshacer. + + + + Cancelar + + Eliminar + + + + +
+
); } diff --git a/frontend/src/app/globals.css b/frontend/src/app/globals.css index 3db86c9..c82d9f9 100644 --- a/frontend/src/app/globals.css +++ b/frontend/src/app/globals.css @@ -157,6 +157,13 @@ border: 1px solid var(--glass-border); } +.glassmorphic { + background: rgba(15, 15, 15, 0.6); + backdrop-filter: blur(16px); + -webkit-backdrop-filter: blur(16px); + border: 1px solid rgba(255, 255, 255, 0.1); +} + /* Glow effects */ .glow-cyan { box-shadow: 0 0 20px var(--glow-cyan), 0 0 40px rgba(0, 240, 255, 0.2); diff --git a/frontend/src/app/import/page.tsx b/frontend/src/app/import/page.tsx index 56787f4..b64c2a5 100644 --- a/frontend/src/app/import/page.tsx +++ b/frontend/src/app/import/page.tsx @@ -16,6 +16,7 @@ import { ArrowLeftIcon, } from 'lucide-react'; import { useRouter } from 'next/navigation'; +import Navbar from '@/components/landing/Navbar'; export default function ImportPage() { const router = useRouter(); @@ -56,167 +57,188 @@ export default function ImportPage() { }; return ( -
-
- {/* Header */} -
- -
-

Importar Juegos

-

- Importa juegos desde archivos ROM en un directorio local -

-
-
- - {/* Import Form */} - - - Configuración de Importación - - Especifica el directorio que contiene los archivos ROM que deseas importar - - - -
- -
- setDirectory(e.target.value)} - placeholder="/path/to/roms" - disabled={isImporting} - /> - +
+
+ +
+
+
+ {/* Header */} +
+ +
+

+ IMPORTAR JUEGOS +

+

+ Importa juegos desde archivos ROM en un directorio local +

-

- Ruta absoluta del directorio que contiene las ROMs -

-
- setRecursive(checked === true)} - disabled={isImporting} - /> - -
- -
- - -
- - - - {/* Result */} - {result && ( - - - - {result.success ? ( - - ) : ( - - )} - {result.success ? 'Importación Exitosa' : 'Error en la Importación'} - - {result.message} - - -
-
-

ROMs importadas

-

{result.imported}

+ {/* Import Form */} + + + + CONFIGURACIÓN DE IMPORTACIÓN + + + Especifica el directorio que contiene los archivos ROM que deseas importar + + + +
+ +
+ setDirectory(e.target.value)} + placeholder="/path/to/roms" + disabled={isImporting} + /> + +
+

+ Ruta absoluta del directorio que contiene las ROMs +

- {result.errors.length > 0 && ( -
-

Errores encontrados

-
-
    - {result.errors.map((error, index) => ( -
  • - - {error} -
  • - ))} -
+
+ setRecursive(checked === true)} + disabled={isImporting} + /> + +
+ +
+ + +
+ + + + {/* Result */} + {result && ( + + + + {result.success ? ( + + ) : ( + + )} + {result.success ? 'Importación Exitosa' : 'Error en la Importación'} + + {result.message} + + +
+
+

ROMs importadas

+

{result.imported}

+
+ + {result.errors.length > 0 && ( +
+

Errores encontrados

+
+
    + {result.errors.map((error, index) => ( +
  • + + {error} +
  • + ))} +
+
+
+ )} + +
+ + {result.success && ( + + )}
- )} +
+
+ )} -
- - {result.success && ( - - )} -
-
- - - )} - - {/* Info */} - - - Información - - -
    -
  • • El sistema escaneará el directorio especificado en busca de archivos ROM
  • -
  • • Se calcularán los checksums (CRC32, MD5, SHA1) para cada archivo
  • -
  • • Las ROMs se asociarán automáticamente con juegos existentes si coinciden
  • -
  • • Los archivos duplicados se detectarán y omitirán
  • -
  • • La importación puede tardar dependiendo de la cantidad de archivos
  • -
-
-
-
+ {/* Info */} + + + Información + + +
    +
  • + • El sistema escaneará el directorio especificado en busca de archivos ROM +
  • +
  • • Se calcularán los checksums (CRC32, MD5, SHA1) para cada archivo
  • +
  • + • Las ROMs se asociarán automáticamente con juegos existentes si coinciden +
  • +
  • • Los archivos duplicados se detectarán y omitirán
  • +
  • • La importación puede tardar dependiendo de la cantidad de archivos
  • +
+
+
+
+
+
); } diff --git a/frontend/src/app/page.tsx b/frontend/src/app/page.tsx index f11c62e..f970284 100644 --- a/frontend/src/app/page.tsx +++ b/frontend/src/app/page.tsx @@ -10,6 +10,7 @@ import Link from 'next/link'; import { GameCover } from '@/components/landing/GameCover'; import { EmptyState } from '@/components/landing/EmptyState'; import { ArrowRight, Grid3X3 } from 'lucide-react'; +import Navbar from '@/components/landing/Navbar'; export default function Home() { const [games, setGames] = useState([]); @@ -43,43 +44,11 @@ export default function Home() { {/* Starfield background */}
- {/* Header */} -
-
- -
- -
-
-

QUASAR

- - GAME LIBRARY SYSTEM - -
- -
- - - - - v1.0.0 - -
-
-
+ {/* Navbar */} + {/* Main Content */} -
+
{isLoading ? (
diff --git a/frontend/src/app/settings/page.tsx b/frontend/src/app/settings/page.tsx new file mode 100644 index 0000000..45c1d7f --- /dev/null +++ b/frontend/src/app/settings/page.tsx @@ -0,0 +1,103 @@ +'use client'; + +import { useState } from 'react'; +import Navbar from '@/components/landing/Navbar'; +import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; +import { Input } from '@/components/ui/input'; +import { Label } from '@/components/ui/label'; +import { Button } from '@/components/ui/button'; +import { FolderIcon, SaveIcon } from 'lucide-react'; + +export default function SettingsPage() { + const [romPath, setRomPath] = useState(''); + const [saved, setSaved] = useState(false); + + const handleSave = () => { + // Aquí se implementaría la lógica para guardar la configuración + console.log('Guardando path:', romPath); + setSaved(true); + setTimeout(() => setSaved(false), 2000); + }; + + return ( +
+ {/* Starfield background */} +
+ + {/* Navbar */} + + + {/* Main Content */} +
+
+
+ {/* Header */} +
+

+ CONFIGURACIÓN +

+

+ CONFIGURA EL DIRECTORIO DE TUS ROMS +

+
+ + {/* Settings Card */} + + + + + DIRECTORIO DE ROMS + + + ESPECIFICA LA RUTA DEL DIRECTORIO DONDE SE ALMACENAN TUS ARCHIVOS DE JUEGO + + + + {/* Path Input */} +
+ + setRomPath(e.target.value)} + className="mono text-sm bg-black/60 border-white/20 text-white placeholder:text-white/40 focus:border-[var(--neon-purple)] focus:ring-[var(--neon-purple)]/20 transition-all duration-300" + /> +
+ + {/* Save Button */} +
+ +
+ + {/* Info Box */} +
+

+ NOTA: El directorio debe ser + accesible desde el servidor backend. Asegúrate de que la ruta sea correcta y + tenga los permisos necesarios para leer los archivos. +

+
+
+
+
+
+
+
+ ); +} diff --git a/frontend/src/components/landing/Navbar.tsx b/frontend/src/components/landing/Navbar.tsx index 2a31fd5..fdcc1c1 100644 --- a/frontend/src/components/landing/Navbar.tsx +++ b/frontend/src/components/landing/Navbar.tsx @@ -1,60 +1,45 @@ 'use client'; import React, { useState } from 'react'; +import Link from 'next/link'; import { Button } from '@/components/ui/button'; -import { Input } from '@/components/ui/input'; - const Navbar = () => { const [isMenuOpen, setIsMenuOpen] = useState(false); - const [searchQuery, setSearchQuery] = useState(''); const toggleMenu = () => { setIsMenuOpen(!isMenuOpen); }; return ( -