| import React from 'react'; |
| import { BrowserRouter as Router, Routes, Route, Navigate, Link } from 'react-router-dom'; |
| import Hero from './components/Hero'; |
| import SingleAnalysis from './components/SingleAnalysis'; |
| import BatchAnalysis from './components/BatchAnalysis'; |
|
|
| const App: React.FC = () => { |
| const [isPlaying, setIsPlaying] = React.useState(false); |
| const audioRef = React.useRef<HTMLAudioElement>(null); |
|
|
| React.useEffect(() => { |
| const audio = audioRef.current; |
| if (!audio) return; |
|
|
| audio.volume = 0.5; |
|
|
| |
| const playPromise = audio.play(); |
| if (playPromise !== undefined) { |
| playPromise |
| .then(() => setIsPlaying(true)) |
| .catch((error) => { |
| console.log("Autoplay blocked. Waiting for user interaction.", error); |
| setIsPlaying(false); |
| }); |
| } |
|
|
| |
| |
| const handleUserInteraction = () => { |
| if (audio.paused) { |
| audio.play() |
| .then(() => { |
| setIsPlaying(true); |
| |
| document.removeEventListener('click', handleUserInteraction); |
| }) |
| .catch(e => console.error("Play failed even after interaction:", e)); |
| } |
| }; |
|
|
| document.addEventListener('click', handleUserInteraction); |
|
|
| return () => { |
| document.removeEventListener('click', handleUserInteraction); |
| }; |
| }, []); |
|
|
| const toggleAudio = () => { |
| if (audioRef.current) { |
| if (isPlaying) { |
| audioRef.current.pause(); |
| } else { |
| audioRef.current.play(); |
| } |
| setIsPlaying(!isPlaying); |
| } |
| }; |
|
|
| return ( |
| <Router> |
| <div className="text-white selection:bg-cyan-500/30 selection:text-cyan-200"> |
| {/* Global Nav / Logo - Fixed and High Z-Index */} |
| <div className="fixed top-0 left-0 w-full p-6 z-50 pointer-events-none flex justify-between items-start"> |
| <Link to="/" className="inline-flex items-center gap-3 px-4 py-2 rounded-full bg-slate-900/80 backdrop-blur-md border border-white/10 shadow-lg pointer-events-auto hover:border-cyan-500/50 transition-all cursor-pointer group"> |
| {/* Logo Icon */} |
| <div className="w-8 h-8 rounded-full flex items-center justify-center overflow-hidden bg-white/5"> |
| <img src="/static/logo.png" alt="Logo" className="w-full h-full object-cover" /> |
| </div> |
| <span className="font-bold tracking-widest text-lg text-white group-hover:text-cyan-400 transition-colors">Samsung Prism Prototype</span> |
| </Link> |
| |
| {/* Audio Toggle */} |
| <div className="relative"> |
| {!isPlaying && ( |
| <div className="absolute right-14 top-1/2 -translate-y-1/2 z-50 flex items-center"> |
| {/* Gradient Border Container */} |
| <div className="relative p-[2px] rounded-full bg-gradient-to-r from-cyan-400 via-purple-500 to-pink-500 animate-pulse shadow-[0_0_15px_rgba(34,211,238,0.5)]"> |
| {/* Inner Glass Content */} |
| <div className="bg-slate-950/90 backdrop-blur-sm rounded-full px-5 py-2.5 flex items-center gap-2"> |
| <span className="text-xs font-bold !text-white whitespace-nowrap" style={{ color: '#ffffff', mixBlendMode: 'normal' }}> |
| ✨ Don't miss the magic! 🎧 |
| </span> |
| </div> |
| {/* Arrow pointing to button */} |
| <div className="absolute top-1/2 -right-1.5 -translate-y-1/2 w-3 h-3 bg-gradient-to-r from-purple-500 to-pink-500 rotate-45 transform origin-center -z-10" /> |
| </div> |
| </div> |
| )} |
| <button |
| onClick={toggleAudio} |
| className={`pointer-events-auto w-10 h-10 rounded-full bg-slate-900/80 backdrop-blur-md border border-white/10 flex items-center justify-center hover:bg-white/10 transition-all group ${!isPlaying ? 'animate-pulse ring-2 ring-cyan-500/50' : ''}`} |
| title={isPlaying ? "Mute Background Music" : "Play Background Music"} |
| > |
| {isPlaying ? ( |
| <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="w-5 h-5 text-cyan-400 group-hover:scale-110 transition-transform"> |
| <path strokeLinecap="round" strokeLinejoin="round" d="M19.114 5.636a9 9 0 010 12.728M16.463 8.288a5.25 5.25 0 010 7.424M6.75 8.25l4.72-4.72a.75.75 0 011.28.53v15.88a.75.75 0 01-1.28.53l-4.72-4.72H4.51c-.88 0-1.704-.507-1.938-1.354A9.01 9.01 0 012.25 12c0-.83.426-1.643 1.087-2.146.24-.184.459-.387.653-.611H6.75z" /> |
| </svg> |
| ) : ( |
| <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="w-5 h-5 text-slate-400 group-hover:text-white transition-colors"> |
| <path strokeLinecap="round" strokeLinejoin="round" d="M17.25 9.75L19.5 12m0 0l2.25 2.25M19.5 12l2.25-2.25M19.5 12l-2.25 2.25m-10.5-6l4.72-4.72a.75.75 0 011.28.53v15.88a.75.75 0 01-1.28.53l-4.72-4.72H4.51c-.88 0-1.704-.507-1.938-1.354A9.01 9.01 0 012.25 12c0-.83.426-1.643 1.087-2.146.24-.184.459-.387.653-.611H6.75z" /> |
| </svg> |
| )} |
| </button> |
| </div> |
| </div> |
| |
| <audio |
| ref={audioRef} |
| src="/static/background.mp3" |
| loop |
| onError={(e) => console.error("Audio failed to load:", e)} |
| /> |
| |
| <main className="animate-fade-in"> |
| <Routes> |
| <Route path="/" element={<Hero />} /> |
| <Route path="/single" element={<SingleAnalysis />} /> |
| <Route path="/batch" element={<BatchAnalysis />} /> |
| <Route path="*" element={<Navigate to="/" replace />} /> |
| </Routes> |
| </main> |
| </div> |
| </Router> |
| ); |
| }; |
|
|
| export default App; |