mirror of
https://github.com/fsolla/teqo.git
synced 2026-11-15 10:43:07 +00:00
- 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
61 lines
1.6 KiB
TypeScript
61 lines
1.6 KiB
TypeScript
import { formatBahiaEventDateLabel } from '@/lib/campaignTime'
|
|
|
|
/**
|
|
* S29 — pure view model of the public announcement page. The server read
|
|
* resolves the OG image and hands the client a serializable shape; the labels
|
|
* (Bahia date, trimmed location) are computed here, client-safe, with no
|
|
* Payload import.
|
|
*/
|
|
|
|
type ShareLinkAnnouncementMedia = {
|
|
alt?: string | null
|
|
}
|
|
|
|
export type ShareLinkAnnouncementSource = {
|
|
slug: string
|
|
title: string
|
|
description: string
|
|
image?: ShareLinkAnnouncementMedia | number | null
|
|
startsAt?: string | null
|
|
endsAt?: string | null
|
|
location?: string | null
|
|
}
|
|
|
|
export type ShareLinkAnnouncementView = {
|
|
slug: string
|
|
title: string
|
|
description: string
|
|
imageUrl: string | null
|
|
imageAlt: string
|
|
eventLabel: string | null
|
|
location: string | null
|
|
startsAt: string | null
|
|
endsAt: string | null
|
|
}
|
|
|
|
const isMedia = (
|
|
value: ShareLinkAnnouncementSource['image'],
|
|
): value is ShareLinkAnnouncementMedia => typeof value === 'object' && value !== null
|
|
|
|
export const buildShareLinkAnnouncementView = ({
|
|
link,
|
|
imageUrl,
|
|
}: {
|
|
link: ShareLinkAnnouncementSource
|
|
imageUrl: string | null
|
|
}): ShareLinkAnnouncementView => {
|
|
const mediaAlt = isMedia(link.image) ? link.image.alt?.trim() : null
|
|
const location = link.location?.trim()
|
|
|
|
return {
|
|
slug: link.slug,
|
|
title: link.title,
|
|
description: link.description,
|
|
imageUrl,
|
|
imageAlt: mediaAlt || link.title,
|
|
eventLabel: link.startsAt ? formatBahiaEventDateLabel(link.startsAt) || null : null,
|
|
location: location || null,
|
|
startsAt: link.startsAt ?? null,
|
|
endsAt: link.endsAt ?? null,
|
|
}
|
|
}
|