"use client" import type { MouseEvent, ReactNode } from "react" import { useCallback, useEffect, useMemo, useRef, useState } from "react" import { HoverCard, HoverCardContent, HoverCardTrigger, } from "@/components/ui/hover-card" import { Button } from "@/components/ui/button" import { cn } from "@/lib/utils" import { avatarColor, cleanSenderName, resolveSenderEmail, senderInitial, } from "@/lib/sender-display" import { Calendar, ExternalLink, Mail, MessageSquare, UserPlus, Video, } from "lucide-react" import { useComposeActions } from "@/lib/compose-context" import { useContactsStore } from "@/lib/contacts/contacts-store" import { findContactByEmail, parseDisplayNameToNameParts, } from "@/lib/contacts/find-contact" import { useLongPress } from "@/hooks/use-long-press" import { useCoarsePointer } from "@/hooks/use-touch-nav" const HOVER_OPEN_DELAY_MS = 1000 export interface ContactHoverCardProps { /** Champ expéditeur brut (liste, conversation, etc.) */ displayName: string email?: string children: ReactNode className?: string onTriggerClick?: (e: MouseEvent) => void align?: "start" | "center" | "end" side?: "top" | "right" | "bottom" | "left" } export function ContactHoverCard({ displayName, email: emailOverride, children, className, onTriggerClick, align = "start", side = "bottom", }: ContactHoverCardProps) { const { openComposeWithInitial } = useComposeActions() const contacts = useContactsStore((s) => s.contacts) const openContactDetail = useContactsStore((s) => s.openContactDetail) const openCreateContact = useContactsStore((s) => s.openCreateContact) const [open, setOpen] = useState(false) const coarsePointer = useCoarsePointer() const triggerRef = useRef(null) const contentRef = useRef(null) const allowHoverOpenRef = useRef(false) const name = cleanSenderName(displayName) const email = resolveSenderEmail(displayName, emailOverride) const color = avatarColor(name) const matchedContact = useMemo( () => findContactByEmail(contacts, email), [contacts, email], ) const openContactsPanel = useCallback(() => { setOpen(false) if (matchedContact) { openContactDetail(matchedContact.id) return } const { firstName, lastName } = parseDisplayNameToNameParts(name) openCreateContact({ firstName, lastName, emails: email ? [{ value: email, label: "Domicile" }] : undefined, }) }, [matchedContact, name, email, openContactDetail, openCreateContact]) const openFromLongPress = useCallback(() => { allowHoverOpenRef.current = true setOpen(true) queueMicrotask(() => { allowHoverOpenRef.current = false }) }, []) const longPress = useLongPress(openFromLongPress, { disabled: !coarsePointer, delay: HOVER_OPEN_DELAY_MS, }) const handleOpenChange = useCallback( (next: boolean) => { if (coarsePointer && next && !allowHoverOpenRef.current) return setOpen(next) }, [coarsePointer] ) useEffect(() => { if (!open) return const close = () => setOpen(false) const opts: AddEventListenerOptions = { capture: true, passive: true } window.addEventListener("scroll", close, opts) window.addEventListener("wheel", close, opts) window.addEventListener("touchmove", close, opts) return () => { window.removeEventListener("scroll", close, opts) window.removeEventListener("wheel", close, opts) window.removeEventListener("touchmove", close, opts) } }, [open]) useEffect(() => { if (!open || !coarsePointer) return const onPointerDown = (e: PointerEvent) => { const target = e.target as Node if (triggerRef.current?.contains(target)) return if (contentRef.current?.contains(target)) return setOpen(false) } document.addEventListener("pointerdown", onPointerDown, { capture: true }) return () => document.removeEventListener("pointerdown", onPointerDown, { capture: true }) }, [open, coarsePointer]) return ( { onTriggerClick?.(e) }} onPointerDown={coarsePointer ? longPress.onPointerDown : undefined} onPointerUp={coarsePointer ? longPress.onPointerUp : undefined} onPointerLeave={coarsePointer ? longPress.onPointerLeave : undefined} onPointerCancel={coarsePointer ? longPress.onPointerCancel : undefined} onClickCapture={coarsePointer ? longPress.onClickCapture : undefined} > {children}
{senderInitial(name)}

{name}

{email}

) }