'use client' /** * HubSpot Ticket Card — unified visual for hubspot-tickets markers. * * PURE PRESENTATION (no internal nav). The card receives the structured * `` prop bundle via `anchorProps` (composed by the caller from a * runtime hook) and renders the rest from the `HubspotTicketItem` shape * directly. */ import React from 'react' import { ExternalLink } from 'lucide-react' import { StatusBadge } from '../../ui/status-badge' import { COMPACT_CARD_META_ROW, COMPACT_CARD_META_ROW_BOX, COMPACT_CARD_OUTER, COMPACT_CARD_OUTER_STATIC, COMPACT_CARD_SKELETON_OUTER, COMPACT_CARD_TEXT_COL, COMPACT_CARD_TITLE, safeHref, } from '../utils/compact-card-classes' import { formatDateUTC as formatDate } from '../../../utils/format' import type { HubspotTicketItem } from '../types/entities/hubspot-ticket' export interface HubspotTicketCardAnchorProps { href: string target?: '_blank' rel?: 'noopener noreferrer' onClick?: (e: React.MouseEvent) => void } export interface HubspotTicketCardProps { item: HubspotTicketItem variant?: 'row' | 'compact' className?: string anchorProps?: HubspotTicketCardAnchorProps } function formatToken(token: string | null | undefined): string | null { if (!token) return null const lower = token.toLowerCase().replace(/_/g, ' ') return lower.charAt(0).toUpperCase() + lower.slice(1) } type BadgeScheme = 'success' | 'error' | 'warning' | 'cyan' | 'default' function priorityScheme(priority: string | null | undefined): BadgeScheme { const p = (priority || '').toUpperCase() if (p === 'URGENT') return 'error' if (p === 'HIGH') return 'warning' if (p === 'MEDIUM') return 'cyan' return 'default' } function statusScheme(status: string | null | undefined): BadgeScheme { const s = (status || '').toUpperCase() if (s === 'CLOSED') return 'success' if (s === 'OPEN') return 'warning' return 'default' } export function HubspotTicketCard({ item, variant = 'compact', className, anchorProps }: HubspotTicketCardProps) { const statusText = item.statusLabel ?? formatToken(item.status) const priorityText = formatToken(item.priority) const dateText = formatDate(item.dateUpdated, { fallback: '', timezone: 'local' }) if (variant === 'row') { return (
{item.title} {item.preview ? ( {item.preview} ) : null} {statusText ? ( ) : null} {dateText ? ( {dateText} ) : null}
) } const metaParts: React.ReactNode[] = [] if (item.customerCompany) { metaParts.push( {item.customerCompany}, ) } if (dateText) metaParts.push({dateText}) const href = safeHref(item.url) const body = ( <> {item.title} {priorityText ? ( ) : null} {statusText ? ( ) : null} {item.customerEmail ? ( From: {item.customerEmail} ) : null} {item.preview || No description provided.} {metaParts.length > 0 ? ( {metaParts.map((part, i) => ( {i > 0 ? · : null} {part} ))} ) : null} {href ? ( ) : null} ) if (anchorProps) { return (
{body} ) } return href ? ( {body} ) : ( {body} ) } export function HubspotTicketCardSkeleton({ variant = 'compact', className }: { variant?: 'row' | 'compact'; className?: string }) { if (variant === 'row') { return (
) } return ( ) }