mirror of
https://github.com/bnair123/MusicAnalyser.git
synced 2026-02-25 19:56:06 +00:00
Rebuild frontend with Tailwind CSS + fix Python 3.14 compatibility
- Upgrade SQLAlchemy 2.0.27→2.0.45, google-genai SDK for Python 3.14 - Replace google-generativeai with google-genai in narrative_service.py - Fix HTTPException handling in main.py (was wrapping as 500) - Rebuild all frontend components with Tailwind CSS v3: - Dashboard, NarrativeSection, StatsGrid, VibeRadar, HeatMap, TopRotation - Custom color palette (background-dark, card-dark, accent-neon, etc.) - Add glass-panel, holographic-badge CSS effects - Docker improvements: - Combined backend container (API + worker in entrypoint.sh) - DATABASE_URL configurable via env var - CI workflow builds both backend and frontend images - Update README with clearer docker-compose instructions
This commit is contained in:
46
frontend/src/components/TopRotation.jsx
Normal file
46
frontend/src/components/TopRotation.jsx
Normal file
@@ -0,0 +1,46 @@
|
||||
import React from 'react';
|
||||
|
||||
const TopRotation = ({ volume }) => {
|
||||
if (!volume || !volume.top_tracks) return null;
|
||||
|
||||
// Use placeholder images since API doesn't return album art in the simple list yet
|
||||
const placeHolderImages = [
|
||||
"https://images.unsplash.com/photo-1619983081563-430f63602796?q=80&w=1000&auto=format&fit=crop",
|
||||
"https://images.unsplash.com/photo-1493225255756-d9584f8606e9?q=80&w=1000&auto=format&fit=crop",
|
||||
"https://images.unsplash.com/photo-1470225620780-dba8ba36b745?q=80&w=1000&auto=format&fit=crop",
|
||||
"https://images.unsplash.com/photo-1511671782779-c97d3d27a1d4?q=80&w=1000&auto=format&fit=crop",
|
||||
"https://images.unsplash.com/photo-1514525253440-b393452e8d26?q=80&w=1000&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 || track[0];
|
||||
const artist = track.artist || track[1];
|
||||
|
||||
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('${placeHolderImages[i % placeHolderImages.length]}')` }}
|
||||
></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>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default TopRotation;
|
||||
Reference in New Issue
Block a user