Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions frontend/src/screens/events/EventMemberSection.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
13 changes: 13 additions & 0 deletions frontend/src/screens/events/EventMemberSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand Down Expand Up @@ -52,6 +53,7 @@ export function EventMemberSection({ event, token }: Props) {
<CostSection event={event} />
{showRsvp ? (
<Card label="who's going">
<CapacityNote event={event} />
<RsvpGuestList event={event} canSeeInvited={canSeeInvited} />
{canInvite || isCoHost ? (
<div className="mt-4 flex flex-col items-stretch gap-2">
Expand All @@ -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 (
<p className="text-muted -mt-2 mb-3 text-xs">
{left}/{maxAttendees} spots left
</p>
);
}

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