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 | 9x 3x 2x 9x 3x 2x 9x 9x 3x 9x 3x 9x 2x 1x 9x 3x 9x 3x 2x | /**
* Partner Topics API Client
* Story 8.2: Topic Suggestions & Voting — AC1–6
*
* All endpoints served by partner-coordination-service via API Gateway.
* CRITICAL: Path is relative to baseURL (which already includes /api/v1).
*/
import apiClient from '@/services/api/apiClient';
// ─── Types ───────────────────────────────────────────────────────────────────
export interface TopicDTO {
id: string;
title: string;
description?: string | null;
/** Null for COMMUNITY (attendee) suggestions — Story 7.1. */
suggestedByCompany?: string | null;
voteCount: number;
currentPartnerHasVoted: boolean;
status: 'PROPOSED' | 'SELECTED' | 'DECLINED';
plannedEvent?: string | null;
createdAt: string;
/**
* PARTNER (Story 8.2) or COMMUNITY/attendee (Story 7.1). Backend always sends it;
* optional here so pre-7.1 fixtures/callers still type-check (treated as PARTNER when absent).
*/
source?: 'PARTNER' | 'COMMUNITY';
}
export interface TopicSuggestionRequest {
title: string;
description?: string | null;
/** Organizer-only: submit on behalf of a specific partner company. */
companyName?: string | null;
}
export interface TopicStatusUpdateRequest {
status: 'SELECTED' | 'DECLINED';
plannedEvent?: string | null;
}
// ─── API functions ────────────────────────────────────────────────────────────
/** List all topic suggestions sorted by vote count descending (PARTNER + ORGANIZER). */
export const getTopics = async (): Promise<TopicDTO[]> => {
const response = await apiClient.get<TopicDTO[]>('/partners/topics');
return response.data;
};
/** Submit a new topic suggestion (PARTNER only). */
export const suggestTopic = async (req: TopicSuggestionRequest): Promise<TopicDTO> => {
const response = await apiClient.post<TopicDTO>('/partners/topics', req);
return response.data;
};
/**
* Submit a topic suggestion as a logged-in ATTENDEE ("Topics From the Floor", Story 7.1).
* Flows into the same topic pool tagged source=COMMUNITY. Submit-only — there is no
* attendee read endpoint.
*/
export const suggestTopicAsAttendee = async (req: TopicSuggestionRequest): Promise<TopicDTO> => {
const response = await apiClient.post<TopicDTO>('/attendees/topics', req);
return response.data;
};
/** Cast a vote on a topic — toggle on (PARTNER only). Idempotent. */
export const castVote = async (topicId: string): Promise<void> => {
await apiClient.post(`/partners/topics/${topicId}/vote`);
};
/** Remove a vote from a topic — toggle off (PARTNER only). Idempotent. */
export const removeVote = async (topicId: string): Promise<void> => {
await apiClient.delete(`/partners/topics/${topicId}/vote`);
};
/** Update a topic's title/description — own company's topics only (PARTNER). */
export const updateTopic = async (
topicId: string,
req: TopicSuggestionRequest
): Promise<TopicDTO> => {
const response = await apiClient.patch<TopicDTO>(`/partners/topics/${topicId}`, req);
return response.data;
};
/** Delete a topic — own company's topics only (PARTNER). */
export const deleteTopic = async (topicId: string): Promise<void> => {
await apiClient.delete(`/partners/topics/${topicId}`);
};
/** Update topic status (ORGANIZER only). */
export const updateTopicStatus = async (
topicId: string,
req: TopicStatusUpdateRequest
): Promise<TopicDTO> => {
const response = await apiClient.patch<TopicDTO>(`/partners/topics/${topicId}/status`, req);
return response.data;
};
|