teqo-backup/src/components/shareLink/ShareLinkShareMenu.tsx
Francisco Solla b8051bb7e0 feat(S29): link com destino trocável e página de anúncio da atividade
- shareLink ganha modo (direct|announcement), pool de destinos com "Destino no
  ar" por linha e dados do evento; destination escalar sai via migration com
  backfill lossless (legado vira direct com destino no ar)
- página de anúncio pública portada classe-a-classe, header campaign-site
  extraído (CampaignPageHeader) e ativação/troca sem reload por poll da rota
  /api/share-link/<slug>/live (fail-closed, no-store)
- agenda Google (action=TEMPLATE) + .ics por rota sob o slug; compartilhar o
  link curto (kind event); S19 intacto e 404 uniforme preservado

Related #1268
2026-09-23 11:48:12 -03:00

78 lines
2.8 KiB
TypeScript

'use client'
import { CheckIcon, ChevronDownIcon, CopyIcon, Share2Icon } from 'lucide-react'
import { useState } from 'react'
import { MENU_POPOVER, MENU_ROW, SECONDARY_ACTION } from '@/components/shareLink/menuControls'
import { WhatsAppIcon } from '@/components/socialIcons'
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/Popover'
import { buildContentShareLink, buildContentShareWhatsAppUrl } from '@/lib/contentShare'
import { copyFeedbackLabels, copyFeedbackLiveMessages, useCopyFeedback } from '@/lib/copyFeedback'
import { shareLinkPath } from '@/lib/shareLink'
import { cn } from '@/lib/utils'
type ShareLinkShareMenuProps = {
slug: string
title: string
className?: string
}
/**
* S29 — "Compartilhar" (design cena 04): shares the short link itself (never
* the destination URL) with the activity title — WhatsApp with a pre-filled
* message, or copy to the clipboard with the standard feedback contract. The
* short link keeps working even after the destination is swapped.
*/
export const ShareLinkShareMenu = ({ slug, title, className }: ShareLinkShareMenuProps) => {
const [open, setOpen] = useState(false)
const [origin] = useState(() => (typeof window === 'undefined' ? '' : window.location.origin))
const { feedback, copy } = useCopyFeedback()
const link = buildContentShareLink(shareLinkPath(slug), origin || shareLinkPath(slug))
const whatsAppUrl = buildContentShareWhatsAppUrl('event', title, link)
return (
<Popover open={open} onOpenChange={setOpen}>
<PopoverTrigger asChild>
<button type="button" className={cn(SECONDARY_ACTION, className)}>
<Share2Icon className="size-4" aria-hidden="true" />
Compartilhar
{open ? <ChevronDownIcon className="size-4" aria-hidden="true" /> : null}
</button>
</PopoverTrigger>
<PopoverContent
align="center"
className={MENU_POPOVER}
aria-label="Opções de compartilhamento"
>
<a
href={whatsAppUrl}
target="_blank"
rel="noopener noreferrer"
onClick={() => setOpen(false)}
className={MENU_ROW}
>
<WhatsAppIcon className="size-5 flex-none text-[#25D366]" />
Compartilhar no WhatsApp
</a>
<button
type="button"
onClick={() => {
void copy(link)
}}
className={MENU_ROW}
>
{feedback === 'copied' ? (
<CheckIcon className="size-5 flex-none text-green-600" aria-hidden="true" />
) : (
<CopyIcon className="size-5 flex-none" aria-hidden="true" />
)}
{copyFeedbackLabels[feedback]}
</button>
<span aria-live="polite" className="sr-only">
{copyFeedbackLiveMessages[feedback]}
</span>
</PopoverContent>
</Popover>
)
}