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 id="now-playing"
62 href={data.link}
63 target="_blank"
64 className={oldStatusClasses}
65 >
66 <img
67 src={data.albumArt}
68 alt={`${data.album} cover`}
69 />
70 <div
71 style={{
72 display: "flex",
73 flexDirection: "column",
74 gap: "2px",
75 width: "100%",
76 }}
77 >
78 <div style={{ fontWeight: "bold" }}>{data.song}</div>
79 <div style={{ fontSize: "0.9em", marginTop: "-5px" }}>
80 {data.artist}
81 </div>
82 <div
83 style={{
84 fontSize: "0.8em",
85 opacity: 0.7,
86 marginTop: "-5px",
87 }}
88 >
89 {data.nowPlaying
90 ? (
91 <span style={{ color: "#22c55e" }}>
92 ▶ Now Playing
93 </span>
94 )
95 : timeAgo}
96 </div>
97 </div>
98 </a>
99 );
100}