"use client"
import { Icons } from "./icons"
import { LABELS } from "@/app/labels"
import { useGetProjectRelatedArticles } from "@/hooks/useGetProjectRelatedArticles"
import { ProjectExtraLinkType } from "@/lib/types"
import { cn } from "@/lib/utils"
import { useEffect, useRef, useState } from "react"
interface Section {
level: number
text: string
id: string
}
interface WikiSideNavigationProps {
className?: string
content?: string
project?: any
}
const SideNavigationItem = ({
text,
id,
activeSection,
onClick,
}: {
text: string
id: string
activeSection: string | null
onClick: () => void
}) => {
return (
)
}
export const WikiSideNavigation = ({
className,
content = "",
project,
}: WikiSideNavigationProps) => {
const [sections, setSections] = useState([])
const [activeSection, setActiveSection] = useState(null)
const observerRef = useRef(null)
const { articles, loading } = useGetProjectRelatedArticles({
projectId: project.id,
})
useEffect(() => {
if (!content) return
const sectionsRegex = /^(#{1,3})\s(.+)/gm
const extractedSections: Section[] = []
let match
while ((match = sectionsRegex.exec(content)) !== null) {
const text = match[2]
if (!extractedSections.some((section) => section.text === text)) {
extractedSections.push({
level: match[1].length,
text,
id: text.toLowerCase().replace(/[^a-z0-9]+/g, "-"),
})
}
}
setSections(extractedSections)
if (extractedSections.length > 0) {
setActiveSection(extractedSections[0].id)
}
}, [content])
// Set up intersection observer
useEffect(() => {
const observerOptions = {
root: null,
rootMargin: "-20% 0px -80% 0px",
threshold: 0,
}
observerRef.current = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
setActiveSection(entry.target.getAttribute("data-section-id"))
}
})
}, observerOptions)
sections.forEach((section) => {
const element = document.querySelector(
`[data-section-id="${section.id}"]`
)
if (element) observerRef.current?.observe(element)
})
return () => {
if (observerRef.current) {
observerRef.current.disconnect()
}
}
}, [sections, loading])
const scrollToSection = (sectionId: string) => {
const element = document.querySelector(`[data-section-id="${sectionId}"]`)
if (element) {
const offset = 80 // Adjust this value based on your header height
const elementPosition = element.getBoundingClientRect().top
const offsetPosition = elementPosition + window.scrollY - offset
window.scrollTo({
top: offsetPosition,
behavior: "smooth",
})
setActiveSection(sectionId)
}
}
const ExtraLinkLabelMapping: Record<
ProjectExtraLinkType,
{
label: string
icon?: any
}
> = {
buildWith: {
label: LABELS.COMMON.BUILD_WITH,
icon: ,
},
play: {
label: LABELS.COMMON.TRY_IT_OUT,
icon: ,
},
research: {
label: LABELS.COMMON.DEEP_DIVE_RESEARCH,
icon: ,
},
learn: {
label: LABELS.COMMON.LEARN_MORE,
},
}
const { extraLinks = {}, team = [], youtubeLinks = [] } = project
const hasRelatedArticles = articles.length > 0 && !loading
const hasTeam = Array.isArray(team) && team.length > 0
const hasYoutubeVideos =
Array.isArray(youtubeLinks) && youtubeLinks.length > 0
if (sections.length === 0 || content.length === 0) return null
return (
)
}