o2o-clinicad-frontend/src/features/report/hooks/useReportSubNav.ts

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]);
}