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 | /**
* Q&A Service (Story 7.5 — "The Apéro Continues")
*
* HTTP client for per-session Q&A. GET is public; POST is authenticated (JWT attached by the
* apiClient interceptor); PATCH/DELETE are organizer-only.
*/
import apiClient from '@/services/api/apiClient';
import type { components } from '@/types/generated/event-sessions-api.types';
export type QnaWindowResponse = components['schemas']['QnaWindowResponse'];
export type QnaPostResponse = components['schemas']['QnaPostResponse'];
function base(eventCode: string, sessionSlug: string): string {
return `/events/${encodeURIComponent(eventCode)}/sessions/${encodeURIComponent(sessionSlug)}/qna`;
}
/** Public read of a session's Q&A thread. Throws 404 if no window exists yet. */
export async function getThread(
eventCode: string,
sessionSlug: string
): Promise<QnaWindowResponse> {
// Public, optional read on (public) archive pages: a 401 must not force-logout the visitor —
// the caller renders empty on error. See apiClient's skipAuthRedirect handling.
const response = await apiClient.get<QnaWindowResponse>(base(eventCode, sessionSlug), {
skipAuthRedirect: true,
});
return response.data;
}
/** Post a question (no parent) or an answer (parentPostId set). Authenticated. */
export async function addPost(
eventCode: string,
sessionSlug: string,
body: string,
parentPostId?: string | null
): Promise<QnaPostResponse> {
const response = await apiClient.post<QnaPostResponse>(`${base(eventCode, sessionSlug)}/posts`, {
body,
...(parentPostId ? { parentPostId } : {}),
});
return response.data;
}
/**
* Organizer: extend (new closesAt) or close early (close=true) ALL of the event's Q&A windows
* at once (Story 7.5 rework — event-level control replaces the old per-session PATCH).
*/
export interface AdjustEventQnaResult {
eventCode: string;
windowsAdjusted: number;
status: 'OPEN' | 'FROZEN';
}
export async function adjustEventQna(
eventCode: string,
payload: { open?: boolean; closesAt?: string; close?: boolean }
): Promise<AdjustEventQnaResult> {
const response = await apiClient.patch<AdjustEventQnaResult>(
`/events/${encodeURIComponent(eventCode)}/qna`,
payload
);
return response.data;
}
/** Organizer: take down a post (soft-delete tombstone). */
export async function removePost(
eventCode: string,
sessionSlug: string,
postId: string
): Promise<void> {
await apiClient.delete(`${base(eventCode, sessionSlug)}/posts/${encodeURIComponent(postId)}`);
}
|