My personal site hosted @ https://indexx.dev
1import { useEffect, useState } from "react"; 2 3export default function NowPlaying() { 4 const [data, setData] = useState(null); 5 const [error, setError] = useState(null); 6 7 useEffect(() => { 8 const fetchNowPlaying = async () => { 9 try { 10 const res = await fetch("/api/now-playing"); 11 if (!res.ok) throw new Error(`HTTP ${res.status}`); 12 13 const json = await res.json(); 14 const status = { 15 song: json.track, 16 artist: json.artist, 17 albumArt: json.cover, 18 createdAt: json.createdAt, 19 link: json.url, 20 nowPlaying: !json.createdAt, 21 }; 22 setData(status); 23 } catch (err) { 24 console.error("Fetch failed:", err); 25 setError(err.message); 26 } 27 }; 28 29 fetchNowPlaying(); 30 }, []); 31 32 if (error) return <span>Error: {error}</span>; 33 if (!data) return null; 34 35 let timeAgo = ""; 36 let oldStatusClasses = ""; 37 38 if (!data.nowPlaying && data.createdAt) { 39 const date = new Date(data.createdAt); 40 const now = new Date(); 41 const diff = now.getTime() - date.getTime(); 42 43 const minutes = Math.floor(diff / 60000); 44 const hours = Math.floor(minutes / 60); 45 const days = Math.floor(hours / 24); 46 47 if (days > 0) timeAgo = `${days} days ago`; 48 else if (hours > 0) timeAgo = `${hours} hours ago`; 49 else if (minutes > 0) timeAgo = `${minutes} minutes ago`; 50 else timeAgo = "just now"; 51 52 oldStatusClasses = days > 3 53 ? "opacity-75 text-decoration-line-through" 54 : ""; 55 } 56 57 return ( 58 <a 59 href={data.link} 60 target="_blank" 61 style={{ 62 position: "fixed", 63 bottom: "20px", 64 left: "20px", 65 display: "flex", 66 alignItems: "center", 67 gap: "12px", 68 padding: "8px", 69 backgroundColor: "#1e1d2d", 70 borderRadius: "8px", 71 boxShadow: "0 2px 6px rgba(0, 0, 0, 0.1)", 72 textDecoration: "none", 73 color: "#000", 74 maxWidth: "400px", 75 transition: "opacity 0.2s", 76 textAlign: "left", 77 }} 78 className={oldStatusClasses} 79 > 80 <img 81 src={data.albumArt} 82 alt={`${data.album} cover`} 83 style={{ 84 width: "64px", 85 height: "64px", 86 borderRadius: "4px", 87 objectFit: "cover", 88 }} 89 /> 90 <div 91 style={{ 92 display: "flex", 93 flexDirection: "column", 94 gap: "2px", 95 }} 96 > 97 <div style={{ fontWeight: "bold" }}>{data.song}</div> 98 <div style={{ fontSize: "0.9em", marginTop: "-5px" }}> 99 {data.artist} 100 </div> 101 <div 102 style={{ 103 fontSize: "0.8em", 104 opacity: 0.7, 105 marginTop: "-5px", 106 }} 107 > 108 {data.nowPlaying 109 ? ( 110 <span style={{ color: "#22c55e" }}> 111 Now Playing 112 </span> 113 ) 114 : timeAgo} 115 </div> 116 </div> 117 </a> 118 ); 119}