Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | 8x 3x 2x 8x 2x 1x 8x 2x 1x 8x 2x 1x 8x 2x 1x 8x 8x 3x 2x | /**
* Partner Meetings API Client
* Story 8.3: Partner Meeting Coordination — AC1–6, 8
* Story 10.27: iCal RSVP Tracking — AC7, AC8
*
* All endpoints served by partner-coordination-service via API Gateway.
* Path is relative to baseURL (which already includes /api/v1).
*/
import apiClient from '@/services/api/apiClient';
import type { components } from '@/types/generated/partner-meetings-api.types';
// ─── Re-export generated types ───────────────────────────────────────────────
export type PartnerMeetingDTO = components['schemas']['PartnerMeetingDTO'];
export type CreateMeetingRequest = components['schemas']['CreateMeetingRequest'];
export type UpdateMeetingRequest = components['schemas']['UpdateMeetingRequest'];
export type SendInviteResponse = components['schemas']['SendInviteResponse'];
// ─── Story 10.27: RSVP types ─────────────────────────────────────────────────
export interface RsvpDTO {
attendeeEmail: string;
status: 'ACCEPTED' | 'DECLINED' | 'TENTATIVE';
respondedAt: string;
}
export interface RsvpSummary {
accepted: number;
declined: number;
tentative: number;
}
export interface MeetingRsvpListResponse {
meetingId: string;
inviteSentAt: string | null;
rsvps: RsvpDTO[];
summary: RsvpSummary;
}
// ─── API functions ────────────────────────────────────────────────────────────
/**
* List all partner meetings sorted by meeting date descending (ORGANIZER only).
*/
export const getMeetings = async (): Promise<PartnerMeetingDTO[]> => {
const response = await apiClient.get<PartnerMeetingDTO[]>('/partner-meetings');
return response.data;
};
/**
* Create a new partner meeting linked to a BATbern event (ORGANIZER only).
*/
export const createMeeting = async (req: CreateMeetingRequest): Promise<PartnerMeetingDTO> => {
const response = await apiClient.post<PartnerMeetingDTO>('/partner-meetings', req);
return response.data;
};
/**
* Get a single partner meeting (ORGANIZER only).
*/
export const getMeeting = async (meetingId: string): Promise<PartnerMeetingDTO> => {
const response = await apiClient.get<PartnerMeetingDTO>(`/partner-meetings/${meetingId}`);
return response.data;
};
/**
* Update meeting agenda or notes — all fields optional (ORGANIZER only).
*/
export const updateMeeting = async (
meetingId: string,
req: UpdateMeetingRequest
): Promise<PartnerMeetingDTO> => {
const response = await apiClient.patch<PartnerMeetingDTO>(`/partner-meetings/${meetingId}`, req);
return response.data;
};
/**
* Send ICS calendar invite to all partner contacts (ORGANIZER only).
* Returns 202 Accepted immediately — email is dispatched asynchronously (AC8).
*/
export const sendInvite = async (meetingId: string): Promise<SendInviteResponse> => {
const response = await apiClient.post<SendInviteResponse>(
`/partner-meetings/${meetingId}/send-invite`
);
return response.data;
};
/**
* Delete a partner meeting (ORGANIZER only).
* If an invite was already sent, a METHOD:CANCEL ICS is dispatched to all partners/organizers.
*/
export const deleteMeeting = async (meetingId: string): Promise<void> => {
await apiClient.delete(`/partner-meetings/${meetingId}`);
};
/**
* Get RSVP responses for a partner meeting (ORGANIZER only).
* Story 10.27 (AC7).
*/
export const getRsvps = async (meetingId: string): Promise<MeetingRsvpListResponse> => {
const response = await apiClient.get<MeetingRsvpListResponse>(
`/partner-meetings/${meetingId}/rsvps`
);
return response.data;
};
|