Se aborda junto con esta parte la tarea 5 diferida desde P5: se
elimina el envoltorio TrackTarget de tracks.ts y sus 8 accesores
(targetId/targetTitle/targetArtist/targetOwnerUserId/targetExplicit/
targetListensCount/isTargetCurrent/queueItemForTarget/
targetForQueueItem). Explorar, Inicio, Mezcla, menus.svelte.ts y
mixes.ts pasan a usar los objetos de pista directamente, con
toQueueItem/trackFromQueueItem (nuevo, en player.svelte.ts) como
únicos conversores. TypeScript reveló en el proceso que el campo
isExplicit no existe en el schema real de /tracks: el badge
"explicit" de Explorar ya era un no-op antes del refactor (siempre
undefined ?? false); se retira el binding en vez de fingir soporte
que nunca existió.
Explorar: GENRE_INFO/genreTiles se extraen a src/lib/genres.ts; la
lógica de búsqueda (showGroup/capped/matchPlaylists/searchCounts/
searchChips/findTopResult) se extrae a src/lib/search.ts como
funciones puras parametrizadas por sfilter/query en vez de cerrar
sobre el estado del componente. "Mejor resultado" unifica el botón/
enlace duplicado con <svelte:element>. Decisión tomada sin bloquear:
no se colapsan los 4 bloques de grupo (Canciones/Álbumes/Usuarios/
Playlists) en un único {#each groups} — cada grupo tiene snippets,
menú contextual y props de ListRow genuinamente distintos, y una
configuración genérica habría añadido más indirección de la que
elimina.
Inicio: usa Page en vez de page-x a mano; las 3 estadísticas pasan a
{#each}; los fondos de hero/spotlight (style= con variables CSS) se
convierten en las utilities hero-surface/spotlight-surface, y
gap-11.5 se sustituye por el token --spacing-section (2.875rem) vía
gap-section.
Verificado con npm run check (0 errores) y npm run build. /explore
sin sesión redirige a /login porque +layout.server.ts exige
allowAnonymousListening desde el backend (inalcanzable sin Docker en
esta sesión) — comportamiento preexistente, no una regresión. Sin QA
visual autenticada; smoke test de /login sin errores de consola.
25 lines
1.3 KiB
TypeScript
25 lines
1.3 KiB
TypeScript
// No hay sistema de tags/géneros todavía: esta lista es un placeholder de
|
|
// cliente y cada tile enlaza a una búsqueda normal por ese término.
|
|
export const GENRE_INFO: Record<string, { label: string; tagline: string }> = {
|
|
pop: { label: 'Pop', tagline: 'Éxitos que suenan en todas partes' },
|
|
rock: { label: 'Rock', tagline: 'Guitarras, actitud y ruido' },
|
|
reggaeton: { label: 'Reggaetón', tagline: 'El ritmo que no para' },
|
|
'lo-fi': { label: 'Lo-fi', tagline: 'Para concentrarte o relajarte' },
|
|
indie: { label: 'Indie', tagline: 'Voces fuera del radar' },
|
|
salsa: { label: 'Salsa', tagline: 'Para mover el cuerpo' },
|
|
'k-pop': { label: 'K-pop', tagline: 'Coreografías pegajosas' },
|
|
electrónica: { label: 'Electrónica', tagline: 'Beats para perderte' },
|
|
jazz: { label: 'Jazz', tagline: 'Improvisación y elegancia' },
|
|
baladas: { label: 'Baladas', tagline: 'Para sentir con calma' },
|
|
trap: { label: 'Trap', tagline: 'Autotune y bajos pesados' },
|
|
cumbia: { label: 'Cumbia', tagline: 'El sabor de siempre' },
|
|
'hip hop': { label: 'Hip hop', tagline: 'Rimas con actitud' },
|
|
'música clásica': { label: 'Clásica', tagline: 'Siglos de composición' }
|
|
};
|
|
|
|
export const genreTiles = Object.entries(GENRE_INFO).map(([query, info], i, all) => ({
|
|
query,
|
|
hue: Math.round((i * 360) / all.length),
|
|
...info
|
|
}));
|