'use client' import Link from 'next/link' import { usePathname } from 'next/navigation' import { useState, type FormEvent, type ReactNode } from 'react' import { LogOutIcon } from 'lucide-react' import { logoutCampaign } from '@/app/(campaign)/campanha/actions/auth' import { PeopleNavSavedFilters } from '@/components/campaign/people/PeopleNavSavedFilters' import { CampaignUserAvatar } from '@/components/campaign/shared/CampaignUserAvatar' import { MunicipalityNavSavedFilters } from '@/components/campaign/shell/MunicipalityNavSavedFilters' import { activeCampaignSubItemHref, getCampaignNav, getCampaignSecondaryNav, isCampaignNavActive, MUNICIPALITY_NAV_HREF, PEOPLE_NAV_HREF, type CampaignNavItem, } from '@/components/campaign/shell/nav' import { Button } from '@/components/ui/button' import { Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupContent, SidebarMenu, SidebarMenuButton, SidebarMenuItem, SidebarMenuSub, SidebarMenuSubButton, SidebarMenuSubItem, useSidebar, } from '@/components/ui/Sidebar' import { Spinner } from '@/components/ui/Spinner' import { clearLastActedMunicipality } from '@/lib/campaignLastActedMunicipality' import { isStaffCampaignRole } from '@/lib/campaignRoles' import { cn } from '@/lib/utils' import { clearCampaignPwaCaches } from '@/utilities/campaignPwaClient' import type { CampaignUserShellView } from '@/utilities/campaignUserProfile' import { campaignRoleLabels } from '@/utilities/campaignUserProfile' import { clearMunicipalitySavedFilters } from '@/utilities/municipality/municipalitySavedFilters' import { clearPeopleSavedFilters } from '@/utilities/people/peopleSavedFilters' import { clearRecentVisits } from '@/utilities/recentVisits' export type CampaignSidebarUser = CampaignUserShellView const CampaignSidebarLink = ({ item, isActive, pathname, onNavigate, children, }: { item: CampaignNavItem isActive: boolean pathname: string onNavigate: () => void /** Row affordances below the link — B18's saved-filter sub-list (B124: always on). */ children?: ReactNode }) => { // C174 — only the most specific sibling is active (`/acervo` is a prefix of // `/acervo/cortes`). `isActive=false` on the button so our own active style // (card + ring) is the only one applied. const activeSubHref = item.subItems ? activeCampaignSubItemHref(pathname, item.subItems) : null return ( {item.title} {item.subItems?.length ? ( {item.subItems.map((sub) => { const subActive = activeSubHref === sub.href return ( {sub.title} ) })} ) : null} {children} ) } export const CampaignSidebar = ({ user }: { user: CampaignSidebarUser }) => { const pathname = usePathname() const { isMobile, setOpenMobile } = useSidebar() const [isLoggingOut, setIsLoggingOut] = useState(false) const secondaryNav = getCampaignSecondaryNav(user.role) // C102: on mobile the staff navigates from the bottom bar + "Mais" drawer, // so the nav sheet never mounts for staff — every destination lives below. // The leader keeps it (lockdown, no bottom nav). Desktop rail is untouched. if (isMobile && isStaffCampaignRole(user.role)) return null const closeMobileSidebar = () => { if (isMobile) setOpenMobile(false) } const handleLogout = async (event: FormEvent) => { event.preventDefault() if (isLoggingOut) return setIsLoggingOut(true) clearRecentVisits() clearLastActedMunicipality() clearMunicipalitySavedFilters() clearPeopleSavedFilters() await clearCampaignPwaCaches() // logoutCampaign redirects — no need to reset the pending flag on success. await logoutCampaign() } return ( {getCampaignNav(user.role).map((item) => ( {item.href === MUNICIPALITY_NAV_HREF ? ( ) : null} {item.href === PEOPLE_NAV_HREF ? ( ) : null} ))} {/* Reference, not a destination: pinned to the foot of the nav so it never competes with the places the mesa works every day. */} {secondaryNav.length > 0 ? ( {secondaryNav.map((item) => ( ))} ) : null} {user.name} {campaignRoleLabels[user.role]} {isLoggingOut ? : } ) }