My personal site hosted @ https://indexx.dev
1import { useEffect, useState } from "react";
2
3export default function Tealfm() {
4 const [data, setData] = useState(null);
5 const [error, setError] = useState(null);
6
7 useEffect(() => {
8 const fetchTealfmData = async () => {
9 try {
10 const res = await fetch(
11 "https://pds.indexx.dev/xrpc/com.atproto.repo.listRecords?repo=did%3Aplc%3Asfjxpxxyvewb2zlxwoz2vduw&collection=fm.teal.alpha.feed.play&limit=1&reverse=false",
12 );
13 if (!res.ok) throw new Error(`HTTP ${res.status}`);
14
15 const data = await res.json();
16 const latest = data.records[0].value;
17
18 const status = {
19 song: latest.trackName,
20 artist: latest.artists.map((artist) => artist.artistName)
21 .join(", "),
22 albumArt:
23 `https://coverartarchive.org/release/${latest.releaseMbId}/front-500`,
24 createdAt: latest.playedTime,
25 link: latest.originUrl ?? "",
26 };
27 setData(status);
28 } catch (err) {
29 console.error("Fetch failed:", err);
30 setError(err.message);
31 }
32 };
33
34 fetchTealfmData();
35 }, []);
36
37 if (error) return <span>Error: {error}</span>;
38 if (!data) return null;
39
40 let timeAgo = "";
41 let oldStatusClasses = "";
42
43 const date = new Date(data.createdAt);
44 const now = new Date();
45 const diff = now.getTime() - date.getTime();
46
47 const minutes = Math.floor(diff / 60000);
48 const hours = Math.floor(minutes / 60);
49 const days = Math.floor(hours / 24);
50
51 if (days > 0) timeAgo = `${days} days ago`;
52 else if (hours > 0) timeAgo = `${hours} hours ago`;
53 else if (minutes > 0) timeAgo = `${minutes} minutes ago`;
54 else timeAgo = "just now";
55
56 oldStatusClasses = days > 3
57 ? "opacity-75 text-decoration-line-through"
58 : "";
59
60 return (
61 <a
62 id="now-playing"
63 href={data.link}
64 target="_blank"
65 className={oldStatusClasses}
66 >
67 <img
68 src={data.albumArt}
69 alt={`${data.album} cover`}
70 />
71 <div
72 style={{
73 display: "flex",
74 flexDirection: "column",
75 gap: "2px",
76 width: "100%",
77 }}
78 >
79 <div style={{ fontWeight: "bold" }}>{data.song}</div>
80 <div style={{ fontSize: "0.9em", marginTop: "-5px" }}>
81 {data.artist}
82 </div>
83 <div
84 style={{
85 fontSize: "0.8em",
86 opacity: 0.7,
87 marginTop: "-5px",
88 }}
89 >
90 {timeAgo}
91 </div>
92 </div>
93 </a>
94 );
95}