components/ListArticles.tsx (66 lines of code) (raw):

"use client"; import { Link } from "lucide-react"; import { useEffect, useState } from "react"; import ReactMarkdown from "react-markdown"; export default function ListArticles({ title, page, folder, }: { title: string; page: string; folder: string; }) { const [contents, setContents] = useState< { id: string; title: string; content: string }[] >([]); const [highlightedSection, setHighlightedSection] = useState<string | null>( null ); const getLink = (section: string) => { navigator.clipboard.writeText( `${window.location.origin}/${page}?section=${section}` ); }; useEffect(() => { const fetchFiles = async () => { try { const response = await fetch(`/api/list_files?folder=${folder}`); const files = await response.json(); const fetchContentPromises = files.map(async (file: string) => { const fileName = file.split(".")[0]; const fileResponse = await fetch(`/${folder}/${file}`); const text = await fileResponse.text(); const [firstLine, ...rest] = text.split("\n"); const title = firstLine.replaceAll("#", ""); // Remove markdown header syntax return { id: fileName, title, content: rest.join("\n") }; }); const allContents = await Promise.all(fetchContentPromises); setContents(allContents); } catch (error) { console.error("Error fetching files or contents:", error); } }; fetchFiles(); }, []); useEffect(() => { const urlParams = new URLSearchParams(window.location.search); const section = urlParams.get("section"); if (section) { setHighlightedSection(section); const element = document.getElementById(section); if (element) { element.scrollIntoView({ behavior: "smooth" }); } } }, [contents]); return ( <div className="p-4 bg-white w-full"> <h1 className="text-2xl font-bold mb-4 p-4">{title}</h1> {contents.map(({ id, title, content }, index) => ( <div key={index} id={id} className={`my-8 p-4 md:w-1/2 ${ highlightedSection === id ? "bg-orange-50 rounded-lg" : "" }`} > <h2 className="text-lg font-semibold mb-2 text-zinc-800 flex items-center gap-2"> {title} <Link size={16} className="text-[#ED6A5E] cursor-pointer hover:size-[18px] transition-all duration-100" onClick={() => { getLink(id); }} /> </h2> <ReactMarkdown className="text-zinc-600 prose prose-zinc text-justify"> {content} </ReactMarkdown> </div> ))} </div> ); }