'use client'; import { useEffect } from 'react'; import { usePathname } from 'next/navigation'; import { type BreadcrumbHint, useBreadcrumbStore } from '@/stores/breadcrumb-store'; /** * Detail pages call this on mount to register their entity hierarchy. * The hint is consumed by `useSmartBack` to label the topbar back * button - the closest parent in `parents` becomes the back target, * so a rep on an interest page sees "Back to Mary Smith" (the client * they drilled in from) instead of the URL-derived "Back to Clients". * * Pass a stable hint object (or memoise the inputs) so the effect * doesn't re-fire every render. * * Example (interest detail page): * useBreadcrumbHint({ * parents: [{ label: 'Mary Smith', href: '/port/clients/abc' }], * current: 'B17', * }); * * The hint clears when the page unmounts so a stale hierarchy doesn't * leak into the next route. * * Naming note: the hook + store kept their `breadcrumb` prefix when * the topbar breadcrumb trail was retired in favor of the contextual * back button. They are now back-context hints, not breadcrumb chain * entries - the names stayed to avoid touching every detail page. */ export function useBreadcrumbHint(hint: BreadcrumbHint | null | undefined): void { const pathname = usePathname(); const setHint = useBreadcrumbStore((s) => s.setHint); const clearHint = useBreadcrumbStore((s) => s.clearHint); const cacheLabel = useBreadcrumbStore((s) => s.cacheLabel); // Stringify for stable equality - caller can pass an object literal // each render without wrecking effect deps. The serialized form is // tiny (handful of strings) so this is cheap. const serialized = hint ? JSON.stringify(hint) : null; useEffect(() => { if (!serialized || !hint) return; setHint(pathname, hint); // Snapshot the display label into the persistent labelCache so the // back button can render "Back to Sarah Doe" after the rep has // drilled away from her detail page (at which point the hint above // has unmounted, but the label is still load-bearing). cacheLabel(pathname, hint.current); return () => { clearHint(pathname); }; // serialized stands in for `hint` value-equality; pathname triggers // re-register if the page navigates without unmounting (rare but // possible on client-side route swaps within the same layout). // eslint-disable-next-line react-hooks/exhaustive-deps }, [serialized, pathname, setHint, clearHint, cacheLabel]); }