mirror of
https://github.com/bnair123/MusicAnalyser.git
synced 2026-02-25 11:46:07 +00:00
Major changes: - Add skip tracking: poll currently-playing every 15s, detect skips (<30s listened) - Add listening-log and sessions API endpoints - Fix ReccoBeats client to extract spotify_id from href response - Compress heatmap from 24 hours to 6 x 4-hour blocks - Add OpenAI support in narrative service (use max_completion_tokens for new models) - Add ListeningLog component with timeline and list views - Update all frontend components to use real data (album art, play counts) - Add docker-compose external network (dockernet) support - Add comprehensive documentation (API, DATA_MODEL, ARCHITECTURE, FRONTEND) - Add unit tests for ingest and API endpoints
42 lines
2.1 KiB
JavaScript
42 lines
2.1 KiB
JavaScript
import React from 'react';
|
|
|
|
const TopRotation = ({ volume }) => {
|
|
if (!volume || !volume.top_tracks) return null;
|
|
|
|
const fallbackImage = "https://images.unsplash.com/photo-1619983081563-430f63602796?q=80&w=200&auto=format&fit=crop";
|
|
|
|
return (
|
|
<div className="bg-card-dark border border-[#222f49] rounded-xl p-6 overflow-hidden">
|
|
<div className="flex items-center justify-between mb-4">
|
|
<h3 className="text-xl font-bold text-white">Top Rotation</h3>
|
|
<div className="flex gap-2">
|
|
<span className="size-2 rounded-full bg-primary"></span>
|
|
<span className="size-2 rounded-full bg-slate-600"></span>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="flex gap-4 overflow-x-auto no-scrollbar pb-2">
|
|
{volume.top_tracks.slice(0, 5).map((track, i) => {
|
|
const name = track.name || "Unknown";
|
|
const artist = track.artist || "Unknown";
|
|
const image = track.image || fallbackImage;
|
|
|
|
return (
|
|
<div key={i} className={`min-w-[140px] flex flex-col gap-2 group cursor-pointer ${i === 0 ? 'min-w-[180px]' : 'opacity-80 hover:opacity-100 transition-opacity pt-4'}`}>
|
|
<div
|
|
className={`w-full aspect-square rounded-lg bg-cover bg-center ${i === 0 ? 'shadow-lg shadow-black/50 transition-transform group-hover:scale-105' : ''}`}
|
|
style={{ backgroundImage: `url('${image}')` }}
|
|
></div>
|
|
<p className={`text-white font-medium truncate ${i === 0 ? 'font-bold' : 'text-sm'}`}>{name}</p>
|
|
<p className="text-xs text-slate-400 truncate">{artist}</p>
|
|
<p className="text-xs text-primary">{track.count} plays</p>
|
|
</div>
|
|
);
|
|
})}
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default TopRotation;
|