diff --git a/frontend/src/screens/events/EventMemberSection.test.tsx b/frontend/src/screens/events/EventMemberSection.test.tsx index f4f3da49..bcebe8c6 100644 --- a/frontend/src/screens/events/EventMemberSection.test.tsx +++ b/frontend/src/screens/events/EventMemberSection.test.tsx @@ -307,6 +307,20 @@ describe('EventMemberSection — rsvp-disabled gates (#666, #667)', () => { }); }); +describe('EventMemberSection — capacity note', () => { + it('shows spots left under "who\'s going" when the event has a capacity', () => { + useAuthStore.setState({ status: 'authed', user: STRANGER, accessToken: 'tok' }); + renderSection({ ...BASE_EVENT, rsvpEnabled: true, maxAttendees: 20, attendingCount: 8 }); + expect(screen.getByText('12/20 spots left')).toBeInTheDocument(); + }); + + it('hides the capacity note when the event has no capacity limit', () => { + useAuthStore.setState({ status: 'authed', user: STRANGER, accessToken: 'tok' }); + renderSection({ ...BASE_EVENT, rsvpEnabled: true, maxAttendees: null, attendingCount: 8 }); + expect(screen.queryByText(/spots left/i)).not.toBeInTheDocument(); + }); +}); + describe('EventMemberSection — invite gating on member rsvp (#688)', () => { const ALL_MEMBERS_EVENT: Event = { ...BASE_EVENT, diff --git a/frontend/src/screens/events/EventMemberSection.tsx b/frontend/src/screens/events/EventMemberSection.tsx index ecbdf0be..a09c3940 100644 --- a/frontend/src/screens/events/EventMemberSection.tsx +++ b/frontend/src/screens/events/EventMemberSection.tsx @@ -4,6 +4,7 @@ import { Link } from 'react-router-dom'; import { useAuthStore } from '@/auth/store'; import { Button } from '@/components/ui/Button'; import type { Event } from '@/models/event'; +import { spotsLeft } from '@/models/event'; import { buildEventLinks } from '@/utils/eventLinks'; import { ensureHttps } from '@/utils/url'; @@ -52,6 +53,7 @@ export function EventMemberSection({ event, token }: Props) { {showRsvp ? ( + {canInvite || isCoHost ? (
@@ -78,6 +80,17 @@ export function EventMemberSection({ event, token }: Props) { ); } +function CapacityNote({ event }: { event: Event }) { + const { maxAttendees } = event; + const left = spotsLeft(event); + if (left === null || maxAttendees === null) return null; + return ( +

+ {left}/{maxAttendees} spots left +

+ ); +} + function ReportEventButton({ eventId }: { eventId: string }) { const [open, setOpen] = useState(false); return (