import { useEffect, useLayoutEffect, useRef, useState } from 'react' import { createPortal } from 'react-dom' import { Building2, Eraser, ExternalLink, FileText, Globe, MoreHorizontal, Trash2, UserRound, Users, } from 'lucide-react' import { fitFixedPopover } from '../utils/fitFixedPopover' import styles from './BusinessActionsOverflowMenu.module.css' type PopoverPosition = { top: number left: number } interface BusinessActionsOverflowMenuProps { businessName: string /** Primary apex domain host when set — enables website / dashboard links. */ host?: string | null onAiPrompts: () => void onAllUsers: () => void onWipeData: () => void onRemove: () => void } function apexHost(host: string) { return host.trim().replace(/^www\./i, '') } function siteProtocol(host: string) { return /\.local$/i.test(host) ? 'http:' : 'https:' } function siteUrl(host: string) { return `${siteProtocol(host)}//${host}` } function openHost(host: string) { window.open(siteUrl(host), '_blank', 'noopener,noreferrer') } export function BusinessActionsOverflowMenu({ businessName, host, onAiPrompts, onAllUsers, onWipeData, onRemove, }: BusinessActionsOverflowMenuProps) { const [open, setOpen] = useState(false) const [popoverPos, setPopoverPos] = useState(null) const wrapRef = useRef(null) const popoverRef = useRef(null) const triggerRef = useRef(null) const apex = host?.trim() ? apexHost(host) : null const linkItems = apex ? ([ { key: 'website', label: 'Open website', detail: apex, icon: Globe, onClick: () => openHost(apex), }, { key: 'business', label: 'Business dashboard', detail: `business.${apex}`, icon: Building2, onClick: () => openHost(`business.${apex}`), }, { key: 'customer', label: 'Customer dashboard', detail: `customer.${apex}`, icon: UserRound, onClick: () => openHost(`customer.${apex}`), }, ] as const) : [] function updatePopoverPosition() { const rect = triggerRef.current?.getBoundingClientRect() if (!rect) return const size = popoverRef.current ? { width: popoverRef.current.offsetWidth, height: popoverRef.current.offsetHeight } : { width: 220, height: linkItems.length ? 280 : 160 } setPopoverPos(fitFixedPopover(rect, size, 'end')) } function toggleOpen() { if (open) { setOpen(false) return } updatePopoverPosition() setOpen(true) } useLayoutEffect(() => { if (!open) return updatePopoverPosition() }, [open]) useEffect(() => { if (!open) return function handleClickOutside(e: MouseEvent) { const target = e.target as Node if (wrapRef.current?.contains(target)) return if (popoverRef.current?.contains(target)) return setOpen(false) } function handleEscape(e: KeyboardEvent) { if (e.key === 'Escape') setOpen(false) } function handleReposition() { updatePopoverPosition() } document.addEventListener('mousedown', handleClickOutside) document.addEventListener('keydown', handleEscape) window.addEventListener('resize', handleReposition) window.addEventListener('scroll', handleReposition, true) return () => { document.removeEventListener('mousedown', handleClickOutside) document.removeEventListener('keydown', handleEscape) window.removeEventListener('resize', handleReposition) window.removeEventListener('scroll', handleReposition, true) } }, [open]) return (
{open && popoverPos && createPortal(
{linkItems.map(({ key, label, detail, icon: Icon, onClick }) => ( ))} {linkItems.length > 0 &&
}
, document.body, )}
) }