--- 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 SafeExternalLink from "../SafeExternalLink.astro"; 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; } const { atUri, uri, cid, name, startsAt, endsAt, location, mode = "inperson", description, source, sourceAvatar, showRsvp = false, isLoggedIn = false, rsvpStatus, } = Astro.props; const anchorId = eventAnchorId(atUri); const DEFAULT_DURATION_MS = 2 * 60 * 60 * 1000; const computedEndsAt = endsAt ?? new Date(startsAt.getTime() + DEFAULT_DURATION_MS); const nowMs = Date.now(); const isLive = startsAt.getTime() <= nowMs && nowMs < computedEndsAt.getTime(); const dateKeyFmt = new Intl.DateTimeFormat("en-CA", { year: "numeric", month: "2-digit", day: "2-digit", }); const isToday = !isLive && startsAt.getTime() > nowMs && dateKeyFmt.format(startsAt) === dateKeyFmt.format(new Date(nowMs)); const formattedDate = startsAt.toLocaleDateString("en-US", { weekday: "short", month: "short", day: "numeric", timeZone: "UTC", }); const formattedTime = startsAt.toLocaleTimeString("en-US", { hour: "numeric", minute: "2-digit", 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 { canRsvp ? (
) : showRsvp ? ( ) : isGoing ? ( You're going ) : null }
{ canRsvp && (