feat: manage waitlist and remove group members

- Add group-waitlist module (list/promote/remove entries)
- Remove attendee with optional atomic promotion from waitlist
- Block removal when attendee has payments (attendee_has_payments)
- Waitlist detail modal matching members UI; optimistic add-to-waitlist
- Responsive tweaks for the members/waitlist tabs
This commit is contained in:
Jose Selesan
2026-09-22 17:04:41 -03:00
parent 785d54df7e
commit fc30927b8b
19 changed files with 1417 additions and 103 deletions

View File

@@ -14,11 +14,15 @@ import type {
GroupInviteInfoDto,
GroupList,
GroupWaitlistEntryDto,
GroupWaitlistList,
InviteTokenResult,
JoinGroupViaInvite,
JoinGroupViaInviteResult,
OnboardingStatusDto,
ProblemDetails,
PromoteGroupWaitlistEntryResult,
RemoveAttendeeResult,
RemoveGroupWaitlistEntryResult,
} from '@gruperly/shared'
const API_URL = import.meta.env.VITE_API_URL ?? 'http://localhost:4000'
@@ -122,4 +126,29 @@ export const bulkCreateAttendees = (groupId: string, payload: BulkCreateAttendee
})
export const getGroupAttendees = (groupId: string, page = 1, pageSize = 20) =>
apiFetch<AttendeeList>(`/api/v1/groups/${groupId}/attendees?page=${page}&pageSize=${pageSize}`)
apiFetch<AttendeeList>(`/api/v1/groups/${groupId}/attendees?page=${page}&pageSize=${pageSize}`)
export const getGroupWaitlist = (groupId: string, page = 1, pageSize = 100) =>
apiFetch<GroupWaitlistList>(`/api/v1/groups/${groupId}/waitlist?page=${page}&pageSize=${pageSize}`)
export const promoteGroupWaitlistEntry = (groupId: string, entryId: string) =>
apiFetch<PromoteGroupWaitlistEntryResult>(`/api/v1/groups/${groupId}/waitlist/${entryId}/promote`, {
method: 'POST',
})
export const removeGroupWaitlistEntry = (groupId: string, entryId: string) =>
apiFetch<RemoveGroupWaitlistEntryResult>(`/api/v1/groups/${groupId}/waitlist/${entryId}`, {
method: 'DELETE',
})
export const removeGroupAttendee = (
groupId: string,
attendeeId: string,
options?: { promoteFromWaitlist?: boolean },
) =>
apiFetch<RemoveAttendeeResult>(
`/api/v1/groups/${groupId}/attendees/${attendeeId}${options?.promoteFromWaitlist ? '?promoteFromWaitlist=true' : ''}`,
{
method: 'DELETE',
},
)