"use client"; import React from "react"; import Link from "next/link"; import { useAuth } from "@/components/auth/authContext"; import { getBranches } from "@/lib/frontend/apiClient"; import { branchPath, searchPath } from "@/lib/frontend/routes"; import { isValidBranchParam } from "@/lib/frontend/params"; import { buildNextUrlForBranchSwitch, readRouteBranchFromPathname, safeReadLocalStorageBranch, safeWriteLocalStorageBranch, } from "@/lib/frontend/quickNav/branchSwitch"; import { Button } from "@/components/ui/button"; import { DropdownMenu, DropdownMenuContent, DropdownMenuLabel, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; const STORAGE_KEY_LAST_BRANCH = "rhl_last_branch"; const BRANCH_LIST_STATE = Object.freeze({ IDLE: "idle", LOADING: "loading", READY: "ready", ERROR: "error", }); export default function QuickNav() { const { status, user } = useAuth(); const isAuthenticated = status === "authenticated" && user; const isAdminDev = isAuthenticated && (user.role === "admin" || user.role === "dev"); const isBranchUser = isAuthenticated && user.role === "branch"; const [selectedBranch, setSelectedBranch] = React.useState(null); const [branchList, setBranchList] = React.useState({ status: BRANCH_LIST_STATE.IDLE, branches: null, }); React.useEffect(() => { if (!isAuthenticated) return; if (isBranchUser) { const own = user.branchId; setSelectedBranch(own && isValidBranchParam(own) ? own : null); return; } const fromRoute = readRouteBranchFromPathname(window.location.pathname); const fromStorage = safeReadLocalStorageBranch(STORAGE_KEY_LAST_BRANCH); const initial = fromRoute || fromStorage || null; if (initial) setSelectedBranch(initial); }, [isAuthenticated, isBranchUser, user?.branchId]); React.useEffect(() => { // B.4 fix: // - Fetch the branch list once for admin/dev users (or when the user changes), // not on every selectedBranch change. if (!isAdminDev) return; let cancelled = false; setBranchList({ status: BRANCH_LIST_STATE.LOADING, branches: null }); (async () => { try { const res = await getBranches(); if (cancelled) return; const branches = Array.isArray(res?.branches) ? res.branches : []; setBranchList({ status: BRANCH_LIST_STATE.READY, branches }); } catch (err) { if (cancelled) return; console.error("[QuickNav] getBranches failed:", err); setBranchList({ status: BRANCH_LIST_STATE.ERROR, branches: null }); } })(); return () => { cancelled = true; }; }, [isAdminDev, user?.userId]); React.useEffect(() => { // After we have the branch list, ensure selectedBranch is valid and known. // This effect does NOT trigger any refetches (only local state). if (!isAdminDev) return; if (branchList.status !== BRANCH_LIST_STATE.READY) return; const branches = Array.isArray(branchList.branches) ? branchList.branches : []; if (branches.length === 0) return; // If no selection yet (or selection is no longer in the list), choose a stable default. if (!selectedBranch || !branches.includes(selectedBranch)) { const next = branches[0]; setSelectedBranch(next); safeWriteLocalStorageBranch(STORAGE_KEY_LAST_BRANCH, next); } }, [isAdminDev, branchList.status, branchList.branches, selectedBranch]); React.useEffect(() => { if (!isAdminDev) return; if (!selectedBranch) return; safeWriteLocalStorageBranch(STORAGE_KEY_LAST_BRANCH, selectedBranch); }, [isAdminDev, selectedBranch]); if (!isAuthenticated) return null; const effectiveBranch = isBranchUser ? user.branchId : selectedBranch; const canNavigate = Boolean( effectiveBranch && isValidBranchParam(effectiveBranch) ); function navigateToBranchKeepingContext(nextBranch) { if (typeof window === "undefined") return; if (!isValidBranchParam(nextBranch)) return; const nextUrl = buildNextUrlForBranchSwitch({ pathname: window.location.pathname || "/", search: window.location.search || "", nextBranch, }); if (!nextUrl) return; window.location.assign(nextUrl); } return (