feat(web-player): rebuild Inicio and Buscar to the design handoff
Applies the handoff's layout and image shapes while keeping the current Musify design system (Inter, colors, tokens) — no font or palette swap. Inicio now stacks distinct shelves instead of repeated square grids: recently played rows, a rail of recently listened albums with an "Álbum" badge, a "Hecho para ti" bento of mixes, a rail of playlists with a trailing dashed "Ver todas" tile, tall "Canciones nuevas" posters with a "Nuevo" badge, a rail of circular top-artist avatars, and a recommended rail. Buscar splits into Álbumes (square cards + badge), Usuarios (a circular-avatar directory) and a flat Canciones list. Top artists and the search user directory are filler data until the backend exposes them. New shared pieces: Rail, CoverBadge, ArtistAvatar, MixBentoTile. The orphaned TrackTile and MixCard are removed.
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
export interface HomeArtist {
|
||||
id: string;
|
||||
name: string;
|
||||
}
|
||||
|
||||
const FILLER_ARTISTS = [
|
||||
'Nova Reyes',
|
||||
'The Paper Lanterns',
|
||||
'Kairo',
|
||||
'Lucía Marés',
|
||||
'Midnight Transit',
|
||||
'Sundown Kids',
|
||||
'Aria Volkov',
|
||||
'El Bosque Rojo',
|
||||
'Halcyon',
|
||||
'Marea Baja'
|
||||
];
|
||||
|
||||
export function pickTopArtists(tracks: { artist?: string | null }[], limit: number): HomeArtist[] {
|
||||
const seen = new Set<string>();
|
||||
const artists: HomeArtist[] = [];
|
||||
|
||||
for (const track of tracks) {
|
||||
for (const name of (track.artist ?? '').split(',').map((part) => part.trim())) {
|
||||
const key = name.toLowerCase();
|
||||
if (!name || seen.has(key)) continue;
|
||||
seen.add(key);
|
||||
artists.push({ id: name, name });
|
||||
if (artists.length >= limit) return artists;
|
||||
}
|
||||
}
|
||||
|
||||
for (const name of FILLER_ARTISTS) {
|
||||
const key = name.toLowerCase();
|
||||
if (seen.has(key)) continue;
|
||||
seen.add(key);
|
||||
artists.push({ id: name, name });
|
||||
if (artists.length >= limit) break;
|
||||
}
|
||||
|
||||
return artists;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
export interface DirectoryUser {
|
||||
id: string;
|
||||
name: string;
|
||||
handle: string;
|
||||
}
|
||||
|
||||
const DIRECTORY: DirectoryUser[] = [
|
||||
{ id: 'u1', name: 'Alex Rivera', handle: 'alexrivera' },
|
||||
{ id: 'u2', name: 'Marina Cordero', handle: 'marinac' },
|
||||
{ id: 'u3', name: 'Diego Fuentes', handle: 'dfuentes' },
|
||||
{ id: 'u4', name: 'Lucía Marés', handle: 'luciamares' },
|
||||
{ id: 'u5', name: 'Noah Bennett', handle: 'noahb' },
|
||||
{ id: 'u6', name: 'Sara Ibáñez', handle: 'saraib' },
|
||||
{ id: 'u7', name: 'Kairo', handle: 'kairo' },
|
||||
{ id: 'u8', name: 'Valentina Ortiz', handle: 'valen' }
|
||||
];
|
||||
|
||||
export function searchUsers(query: string, limit = 12): DirectoryUser[] {
|
||||
const term = query.trim().toLowerCase();
|
||||
if (!term) return [];
|
||||
return DIRECTORY.filter(
|
||||
(user) => user.name.toLowerCase().includes(term) || user.handle.toLowerCase().includes(term)
|
||||
).slice(0, limit);
|
||||
}
|
||||
Reference in New Issue
Block a user