import { Check, HelpCircle, X, Loader2 } from 'lucide-react'; import { LoginArea } from '@/components/auth/LoginArea'; import { useCurrentUser } from '@/hooks/useCurrentUser'; import { useToast } from '@/hooks/useToast'; import { useEventRsvps, useRsvp } from '@/hooks/useEventRsvps'; import { eventCoord } from '@/hooks/useEventRsvps'; import { cn } from '@/lib/utils'; import { useTranslation } from '@/contexts/language'; import type { RsvpStatus, SkateEvent } from '@/lib/types'; const OPTIONS: { status: RsvpStatus; label: string; shortLabel: string; icon: typeof Check; activeClass: string; }[] = [ { status: 'accepted', label: 'placesUi.rsvp.going', shortLabel: 'placesUi.rsvp.goingShort', icon: Check, activeClass: 'bg-green-500 border-green-500 text-black', }, { status: 'tentative', label: 'placesUi.rsvp.interested', shortLabel: 'placesUi.rsvp.maybe', icon: HelpCircle, activeClass: 'bg-[#ccff00] border-[#ccff00] text-black', }, { status: 'declined', label: 'placesUi.rsvp.cantMakeIt', shortLabel: 'placesUi.rsvp.cant', icon: X, activeClass: 'bg-red-500/80 border-red-500 text-white', }, ]; /** * NIP-52 RSVP control. A segmented Going / Interested / Can't-make-it toggle * that publishes (or replaces) the user's RSVP. Tapping the active option again * is a no-op. Logged-out users see a login prompt instead. */ export function RsvpButtons({ event, className }: { event: SkateEvent; className?: string }) { const { t } = useTranslation(); const { user } = useCurrentUser(); const { toast } = useToast(); const coord = eventCoord(event); const { myRsvp, myStatus, goingCount, tentativeCount } = useEventRsvps(coord); const { mutateAsync: rsvp, isPending } = useRsvp(); const isHost = user?.pubkey === event.pubkey; if (!user) { return (

{t('placesUi.rsvp.areYouGoing')}{' '} {t('placesUi.rsvp.loginToRsvp')}

); } const handleClick = async (status: RsvpStatus) => { if (status === myStatus || isPending) return; try { await rsvp({ event, status, existingIdentifier: myRsvp?.identifier, }); const msg = status === 'accepted' ? t('placesUi.rsvp.toastGoing') : status === 'tentative' ? t('placesUi.rsvp.toastInterested') : t('placesUi.rsvp.toastNotGoing'); toast({ title: msg }); } catch (err) { toast({ title: t('placesUi.rsvp.toastError'), description: err instanceof Error ? err.message : t('placesUi.rsvp.tryAgain'), variant: 'destructive', }); } }; return (
{isHost && (

{t('placesUi.rsvp.hostNote')}

)}
{OPTIONS.map(({ status, label, shortLabel, icon: Icon, activeClass }) => { const active = myStatus === status; return ( ); })}
{(goingCount > 0 || tentativeCount > 0) && (

{goingCount} {t('placesUi.rsvp.goingCount')} {tentativeCount > 0 && ( <> {' ยท '} {tentativeCount} {t('placesUi.rsvp.interestedCount')} )}

)}
); }