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/now-playing",
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}