--- import { actions } from "astro:actions"; import EventLocation from "./EventLocation.astro"; import CheckIcon from "./icons/CheckIcon.astro"; import ExternalLinkIcon from "./icons/ExternalLinkIcon.astro"; import { eventAnchorId } from "../../lib/community/happening-now"; import { smokeSignalHref } from "../../lib/community/events"; import { effectiveEndsAt, eventTimingState, } from "../../lib/community/event-time"; import { formatEventTime } from "../../lib/community/event-format"; import SafeExternalLink from "../SafeExternalLink.astro"; import { Image } from "astro:assets"; interface Props { atUri: string; uri: string; cid?: string; name: string; startsAt: Date; endsAt?: Date; location?: string; mode?: "inperson" | "virtual" | "hybrid"; description?: string; source?: string; sourceAvatar?: string; showRsvp?: boolean; isLoggedIn?: boolean; rsvpStatus?: string; unshareShareRecordUri?: string; } const { atUri, uri, cid, name, startsAt, endsAt, location, mode = "inperson", description, source, sourceAvatar, showRsvp = false, isLoggedIn = false, rsvpStatus, unshareShareRecordUri, } = Astro.props; const anchorId = eventAnchorId(atUri); const computedEndsAt = effectiveEndsAt({ startsAt, endsAt }); // We use UTC here so the markup doesn't depend on where this rendered. The viewer's own // timezone is applied in the browser by `applyEventCardTiming`, which also // re-decides what "today" means. const state = eventTimingState({ startsAt, endsAt }, { timeZone: "UTC" }); const isLive = state === "live"; const isToday = state === "today"; const formattedTime = formatEventTime(startsAt, { timeZone: "UTC" }); const sourceLabel = source ? `@${source.replace(/\.bsky\.social$/, "")}` : undefined; const titleSize = name.length <= 45 ? "lg" : name.length <= 70 ? "md" : "sm"; const isGoing = rsvpStatus === "community.lexicon.calendar.rsvp#going"; const isNotGoing = rsvpStatus === "community.lexicon.calendar.rsvp#notgoing"; const hasPositiveRsvp = Boolean(rsvpStatus && !isNotGoing); const nextRsvpStatus = isGoing ? "notgoing" : "going"; const rsvpButtonLabel = isGoing ? "I'm not going" : "I'm going"; const rsvpButtonAriaLabel = isGoing ? `Mark yourself as not going to ${name}` : `Mark yourself as going to ${name}`; const canRsvp = showRsvp && isLoggedIn && Boolean(cid); const eventFallbackHref = smokeSignalHref(atUri); ---
{ sourceLabel && (
{sourceAvatar ? ( ) : (
) }

{name}

{description ?? "No description provided."}

Details { unshareShareRecordUri && (
) } { canRsvp ? (
) : showRsvp ? ( // Logged in but still can't RSVP means we couldn't resolve the event's // canonical cid, so don't tell them to log in — they already are. ) : isGoing ? ( You're going ) : null }
{ canRsvp && (