Spaces:
Sleeping
Sleeping
| import { useState } from "react"; | |
| import Recorder from "./components/Recorder"; | |
| import EmotionBars from "./components/EmotionBars"; | |
| import History from "./components/History"; | |
| const EMOTION_EMOJIS = { | |
| neutral: "π", | |
| happy: "π", | |
| sad: "π’", | |
| angry: "π ", | |
| }; | |
| export default function App() { | |
| const [result, setResult] = useState(null); // { emotion, probs } | |
| const [history, setHistory] = useState([]); // [{ emotion, timestamp }] | |
| const handleResult = (data) => { | |
| setResult(data); | |
| setHistory((prev) => [ | |
| ...prev, | |
| { | |
| emotion: data.emotion, | |
| timestamp: new Date().toLocaleTimeString(), | |
| }, | |
| ]); | |
| }; | |
| return ( | |
| <div style={styles.page}> | |
| <div style={styles.card}> | |
| {/* Header */} | |
| <div style={styles.header}> | |
| <h1 style={styles.title}>π€ Speech Emotion Recognition</h1> | |
| <p style={styles.subtitle}> | |
| Record your voice and detect the emotion in real time | |
| </p> | |
| </div> | |
| {/* Current result */} | |
| {result && ( | |
| <div style={styles.resultBox}> | |
| <span style={styles.resultEmoji}> | |
| {EMOTION_EMOJIS[result.emotion] || "π€"} | |
| </span> | |
| <span style={styles.resultEmotion}>{result.emotion}</span> | |
| </div> | |
| )} | |
| {/* Recorder β mic button + waveform */} | |
| <Recorder onResult={handleResult} /> | |
| {/* Probability bars */} | |
| <EmotionBars probs={result?.probs} /> | |
| {/* Divider */} | |
| <hr style={styles.divider} /> | |
| {/* Session history */} | |
| <History history={history} /> | |
| </div> | |
| </div> | |
| ); | |
| } | |
| const styles = { | |
| page: { | |
| minHeight: "100vh", | |
| backgroundColor: "#0f172a", | |
| display: "flex", | |
| alignItems: "center", | |
| justifyContent: "center", | |
| padding: "24px", | |
| fontFamily: "'Segoe UI', sans-serif", | |
| }, | |
| card: { | |
| backgroundColor: "#1e293b", | |
| borderRadius: "20px", | |
| padding: "36px", | |
| width: "100%", | |
| maxWidth: "480px", | |
| boxShadow: "0 20px 60px rgba(0,0,0,0.5)", | |
| }, | |
| header: { | |
| textAlign: "center", | |
| marginBottom: "28px", | |
| }, | |
| title: { | |
| color: "#f1f5f9", | |
| fontSize: "22px", | |
| margin: "0 0 6px 0", | |
| }, | |
| subtitle: { | |
| color: "#64748b", | |
| fontSize: "14px", | |
| margin: 0, | |
| }, | |
| resultBox: { | |
| display: "flex", | |
| alignItems: "center", | |
| justifyContent: "center", | |
| gap: "10px", | |
| backgroundColor: "#0f172a", | |
| borderRadius: "12px", | |
| padding: "14px", | |
| marginBottom: "20px", | |
| }, | |
| resultEmoji: { | |
| fontSize: "32px", | |
| }, | |
| resultEmotion: { | |
| fontSize: "24px", | |
| fontWeight: 700, | |
| textTransform: "capitalize", | |
| color: "#6366f1", | |
| }, | |
| divider: { | |
| border: "none", | |
| borderTop: "1px solid #334155", | |
| margin: "24px 0", | |
| }, | |
| }; |