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