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:
66
frontend/src/components/NarrativeSection.jsx
Normal file
66
frontend/src/components/NarrativeSection.jsx
Normal file
@@ -0,0 +1,66 @@
|
||||
import React from 'react';
|
||||
import { motion } from 'framer-motion';
|
||||
|
||||
const NarrativeSection = ({ narrative, vibe }) => {
|
||||
if (!narrative) return null;
|
||||
|
||||
const persona = narrative.persona || "THE UNKNOWN LISTENER";
|
||||
const vibeCheck = narrative.vibe_check || "Analyzing auditory aura...";
|
||||
|
||||
// Generate tags based on vibe metrics if available
|
||||
const getTags = () => {
|
||||
if (!vibe) return [];
|
||||
const tags = [];
|
||||
if (vibe.valence > 0.6) tags.push({ text: "HIGH VALENCE", color: "primary" });
|
||||
else if (vibe.valence < 0.4) tags.push({ text: "MELANCHOLIC", color: "accent-purple" });
|
||||
|
||||
if (vibe.energy > 0.6) tags.push({ text: "HIGH ENERGY", color: "accent-neon" });
|
||||
else if (vibe.energy < 0.4) tags.push({ text: "CHILL VIBES", color: "accent-purple" });
|
||||
|
||||
if (vibe.danceability > 0.7) tags.push({ text: "DANCEABLE", color: "primary" });
|
||||
|
||||
return tags.slice(0, 3); // Max 3 tags
|
||||
};
|
||||
|
||||
const tags = getTags();
|
||||
|
||||
// Default tags if none generated
|
||||
if (tags.length === 0) {
|
||||
tags.push({ text: "ECLECTIC", color: "primary" });
|
||||
tags.push({ text: "MYSTERIOUS", color: "accent-purple" });
|
||||
}
|
||||
|
||||
return (
|
||||
<section className="relative rounded-2xl overflow-hidden min-h-[400px] flex items-center justify-center p-8 bg-card-dark border border-[#222f49]">
|
||||
{/* Dynamic Background */}
|
||||
<div className="absolute inset-0 mood-gradient"></div>
|
||||
|
||||
<div className="relative z-10 flex flex-col items-center text-center max-w-2xl gap-6">
|
||||
<motion.div
|
||||
initial={{ scale: 0.9, opacity: 0 }}
|
||||
animate={{ scale: 1, opacity: 1 }}
|
||||
transition={{ duration: 0.5 }}
|
||||
className="holographic-badge px-8 py-4 rounded-full border border-primary/30"
|
||||
>
|
||||
<h1 className="text-3xl md:text-5xl font-black tracking-tight text-white drop-shadow-[0_0_15px_rgba(37,106,244,0.5)] uppercase">
|
||||
{persona}
|
||||
</h1>
|
||||
</motion.div>
|
||||
|
||||
<div className="font-mono text-primary/80 text-lg md:text-xl font-medium tracking-wide">
|
||||
<span className="typing-cursor">{vibeCheck}</span>
|
||||
</div>
|
||||
|
||||
<div className="mt-4 flex gap-3 flex-wrap justify-center">
|
||||
{tags.map((tag, i) => (
|
||||
<span key={i} className={`px-3 py-1 rounded-full text-xs font-bold bg-${tag.color}/20 text-${tag.color} border border-${tag.color}/20`}>
|
||||
{tag.text}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
export default NarrativeSection;
|
||||
Reference in New Issue
Block a user