53 lines
1.4 KiB
TypeScript
53 lines
1.4 KiB
TypeScript
import { useEffect, useMemo, useState } from "react";
|
|
import { useMainSubNav } from "@/layouts/MainSubNavLayout";
|
|
import type { SubNavItem } from "@/layouts/SubNav";
|
|
import { REPORT_SECTIONS } from "@/features/report/constants/report_sections";
|
|
|
|
export function useReportSubNav() {
|
|
const { setSubNav } = useMainSubNav();
|
|
const [activeId, setActiveId] = useState<string>(REPORT_SECTIONS[0]?.id ?? "");
|
|
|
|
const items: SubNavItem[] = useMemo(
|
|
() =>
|
|
REPORT_SECTIONS.map((s) => ({
|
|
id: s.id,
|
|
label: s.label,
|
|
targetId: s.id,
|
|
})),
|
|
[]
|
|
);
|
|
|
|
useEffect(() => {
|
|
const observer = new IntersectionObserver(
|
|
(entries) => {
|
|
const visible = entries
|
|
.filter((e) => e.isIntersecting)
|
|
.sort((a, b) => a.boundingClientRect.top - b.boundingClientRect.top);
|
|
if (visible.length > 0) {
|
|
setActiveId(visible[0].target.id);
|
|
}
|
|
},
|
|
{ rootMargin: "-100px 0px -60% 0px", threshold: 0 }
|
|
);
|
|
|
|
REPORT_SECTIONS.forEach(({ id: sectionId }) => {
|
|
const el = document.getElementById(sectionId);
|
|
if (el) observer.observe(el);
|
|
});
|
|
|
|
return () => observer.disconnect();
|
|
}, []);
|
|
|
|
useEffect(() => {
|
|
setSubNav({
|
|
items,
|
|
activeId,
|
|
scrollActiveIntoView: true,
|
|
});
|
|
}, [activeId, items, setSubNav]);
|
|
|
|
useEffect(() => {
|
|
return () => setSubNav(null);
|
|
}, [setSubNav]);
|
|
}
|