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
2 changes: 1 addition & 1 deletion frontend/e2e/live-updates.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ test('member A comment appears live in member B open event view via SSE', async
await pageB.goto(`/events/${event_id}`);

const rsvpSectionA = pageA.getByLabel('rsvp');
await rsvpSectionA.getByRole('button', { name: "i'm going" }).click();
await rsvpSectionA.getByRole('button', { name: 'rsvp' }).click();
await pageA
.getByRole('dialog', { name: 'rsvp' })
.getByRole('button', { name: 'confirm' })
Expand Down
2 changes: 1 addition & 1 deletion frontend/e2e/rsvp-member.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ test('member rsvps to an event from event detail', async ({ page }) => {
await expect(page.getByRole('heading', { name: event_title })).toBeVisible();

const rsvpSection = page.getByLabel('rsvp');
await rsvpSection.getByRole('button', { name: "i'm going" }).click();
await rsvpSection.getByRole('button', { name: 'rsvp' }).click();

const rsvpDialog = page.getByRole('dialog', { name: 'rsvp' });
await rsvpDialog.getByRole('button', { name: 'confirm' }).click();
Expand Down
15 changes: 0 additions & 15 deletions frontend/src/components/ui/RsvpStatusPicker.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,21 +51,6 @@ describe('RsvpStatusPicker', () => {
expect(screen.getByRole('button', { name: 'join the waitlist' })).toBeInTheDocument();
});

it('renders default-size pills unless prominent is set', () => {
render(<RsvpStatusPicker value={null} onSelect={vi.fn()} />);
const pill = screen.getByRole('button', { name: "i'm going" });
expect(pill).toHaveClass('h-10');
expect(pill).not.toHaveClass('flex-1');
});

it('renders bigger, full-width pills when prominent', () => {
render(<RsvpStatusPicker value={null} onSelect={vi.fn()} prominent />);
const pill = screen.getByRole('button', { name: "i'm going" });
expect(pill).toHaveClass('h-12');
expect(pill).toHaveClass('flex-1');
expect(pill).toHaveClass('text-base');
});

it('filters to only the given statuses', () => {
render(<RsvpStatusPicker value={null} onSelect={vi.fn()} statuses={['attending', 'maybe']} />);
expect(screen.getByRole('button', { name: "i'm going" })).toBeInTheDocument();
Expand Down
13 changes: 2 additions & 11 deletions frontend/src/components/ui/RsvpStatusPicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,9 @@ interface Props {
disabled?: boolean;
labelFor?: (status: RsvpInputStatus, defaultLabel: string) => string;
statuses?: RsvpInputStatus[];
prominent?: boolean;
}

export function RsvpStatusPicker({
value,
onSelect,
disabled = false,
labelFor,
statuses,
prominent = false,
}: Props) {
export function RsvpStatusPicker({ value, onSelect, disabled = false, labelFor, statuses }: Props) {
const options = statuses
? RSVP_STATUS_LABELS.filter((p) => statuses.includes(p.status))
: RSVP_STATUS_LABELS;
Expand All @@ -37,8 +29,7 @@ export function RsvpStatusPicker({
onSelect(p.status);
}}
className={cn(
'inline-flex shrink-0 items-center justify-center rounded-full font-medium transition-colors disabled:cursor-not-allowed',
prominent ? 'h-12 flex-1 px-5 text-base' : 'h-10 px-4 text-sm',
'inline-flex h-10 shrink-0 items-center justify-center rounded-full px-4 text-sm font-medium transition-colors disabled:cursor-not-allowed',
active
? 'bg-brand-600 text-brand-on'
: 'border-border-strong text-foreground-secondary hover:bg-background border',
Expand Down
30 changes: 21 additions & 9 deletions frontend/src/screens/events/RsvpSection.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,29 +67,41 @@ beforeEach(() => {
});

describe('RsvpSection — before RSVPing', () => {
it('opens the RSVP box when a pill is tapped (not yet RSVP’d)', () => {
it('opens the RSVP box when the rsvp button is tapped (not yet RSVP’d)', () => {
renderSection(makeEvent({ myRsvp: null }));

expect(screen.queryByRole('dialog')).not.toBeInTheDocument();
fireEvent.click(screen.getByRole('button', { name: "i'm going" }));
fireEvent.click(screen.getByRole('button', { name: 'rsvp' }));

expect(screen.getByRole('dialog', { name: /RSVP/i })).toBeInTheDocument();
});

it('shows all three pills and no status line when I have not RSVP’d', () => {
it('shows a single rsvp button and no status line when I have not RSVP’d', () => {
renderSection(makeEvent({ myRsvp: null }));

expect(screen.getByRole('button', { name: "i'm going" })).toBeInTheDocument();
expect(screen.getByRole('button', { name: 'maybe' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: "can't go" })).toBeInTheDocument();
expect(screen.getByRole('button', { name: 'rsvp' })).toBeInTheDocument();
expect(screen.queryByRole('button', { name: "i'm going" })).not.toBeInTheDocument();
expect(screen.queryByRole('button', { name: 'maybe' })).not.toBeInTheDocument();
expect(screen.queryByRole('button', { name: "can't go" })).not.toBeInTheDocument();
expect(screen.queryByRole('button', { name: /edit RSVP/i })).not.toBeInTheDocument();
});

it('shows "join the waitlist" instead of "i\'m going" when the event is full', () => {
it('shows "join the waitlist" instead of "rsvp" when the event is full', () => {
renderSection(makeEvent({ maxAttendees: 2, attendingCount: 2, myRsvp: null }));

expect(screen.getByRole('button', { name: 'join the waitlist' })).toBeInTheDocument();
expect(screen.queryByRole('button', { name: "i'm going" })).not.toBeInTheDocument();
expect(screen.queryByRole('button', { name: 'rsvp' })).not.toBeInTheDocument();
});

it('opens the RSVP box defaulted to "going" when the rsvp button is tapped', () => {
renderSection(makeEvent({ myRsvp: null }));

fireEvent.click(screen.getByRole('button', { name: 'rsvp' }));

expect(screen.getByRole('button', { name: "i'm going" })).toHaveAttribute(
'aria-pressed',
'true',
);
});
});

Expand Down Expand Up @@ -271,7 +283,7 @@ describe('RsvpSection — comments in public manage vs member flows', () => {
}),
);

fireEvent.click(screen.getByRole('button', { name: /going/i }));
fireEvent.click(screen.getByRole('button', { name: 'rsvp' }));
expect(screen.getByTestId('rsvp-comment-field')).toBeInTheDocument();
});
});
18 changes: 9 additions & 9 deletions frontend/src/screens/events/RsvpSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { useCancelPublicMyRsvp, useUpdatePublicMyRsvp } from '@/api/publicRsvp';
import { useRemoveRsvp, useSetRsvp } from '@/api/rsvp';
import { useAuthStore } from '@/auth/store';
import { Button } from '@/components/ui/Button';
import { RsvpStatusPicker } from '@/components/ui/RsvpStatusPicker';
import {
type Event,
isRsvpInputStatus,
Expand Down Expand Up @@ -198,15 +197,16 @@ function RsvpControls({
}

return (
<RsvpStatusPicker
value={null}
<button
type="button"
onClick={() => {
onOpenCreate(RsvpStatus.Attending);
}}
disabled={busy}
prominent
onSelect={onOpenCreate}
labelFor={(status, defaultLabel) =>
status === RsvpStatus.Attending && atCapacity ? 'join the waitlist' : defaultLabel
}
/>
className="bg-brand-600 text-brand-on hover:bg-brand-700 mx-auto inline-flex h-12 min-w-28 items-center justify-center rounded-full px-5 text-base font-medium transition-colors disabled:opacity-60"
>
{atCapacity ? 'join the waitlist' : 'rsvp'}
</button>
);
}

Expand Down
Loading