My personal site hosted @ https://indexx.dev
at main 2.8 kB view raw
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 fetchProjectData = async () => { 9 try { 10 const res = await fetch( 11 "https://pds.indexx.dev/xrpc/com.atproto.repo.listRecords?repo=did%3Aplc%3Asfjxpxxyvewb2zlxwoz2vduw&collection=dev.indexx.www.project&limit=100&reverse=false", 12 ); 13 if (!res.ok) throw new Error(`HTTP ${res.status}`); 14 15 const data = await res.json(); 16 const projects = data.records.map((record) => record.value); 17 18 setData(projects.map((project) => ({ 19 title: project.name, 20 description: project.description, 21 date: project.dateLabel, 22 href: project.url, 23 note: project.note ?? "", 24 }))); 25 } catch (err) { 26 console.error("Fetch failed:", err); 27 setError(err.message); 28 } 29 }; 30 31 fetchProjectData(); 32 }, []); 33 34 if (error) return <span>Error: {error}</span>; 35 if (!data) return null; 36 37 return ( 38 <section id="projects-pane" data-bs-theme="dark"> 39 <h6 40 className="text-muted text-center" 41 style={{ textTransform: "uppercase", letterSpacing: "5px" }} 42 > 43 My Recent Projects 44 </h6> 45 46 <ul className="list-unstyled"> 47 {data.map((project) => ( 48 <li> 49 <a 50 href={project.href} 51 target="_blank" 52 className="text-reset" 53 > 54 <div 55 className="project-card" 56 style={{ color: "#fff" }} 57 > 58 <small className="text-muted"> 59 {project.date} 60 </small> 61 <h4>{project.title}</h4> 62 {project.description} 63 {project.note && ( 64 <> 65 <br /> 66 <small className="text-muted"> 67 {project.note} 68 </small> 69 </> 70 )} 71 </div> 72 </a> 73 </li> 74 ))} 75 </ul> 76 </section> 77 ); 78}