104 lines
3.7 KiB
TypeScript
104 lines
3.7 KiB
TypeScript
import { authorizedFetch } from './auth/tokens';
|
|
|
|
type JsonValue = Record<string, any>;
|
|
|
|
async function jsonOrThrow<T>(response: Response, message: string): Promise<T> {
|
|
if (!response.ok) {
|
|
const body = await safeJson(response);
|
|
console.error('[API]', message, response.status, body);
|
|
throw new Error(message);
|
|
}
|
|
return (await response.json()) as T;
|
|
}
|
|
|
|
async function safeJson(response: Response): Promise<JsonValue | null> {
|
|
try {
|
|
return (await response.clone().json()) as JsonValue;
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
export async function getEvents(): Promise<any[]> {
|
|
const response = await authorizedFetch('/api/v1/tenant/events');
|
|
const data = await jsonOrThrow<{ data?: any[] }>(response, 'Failed to load events');
|
|
return data.data ?? [];
|
|
}
|
|
|
|
export async function createEvent(payload: { name: string; slug: string; date?: string; is_active?: boolean }): Promise<number> {
|
|
const response = await authorizedFetch('/api/v1/tenant/events', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify(payload),
|
|
});
|
|
const data = await jsonOrThrow<{ id: number }>(response, 'Failed to create event');
|
|
return data.id;
|
|
}
|
|
|
|
export async function updateEvent(
|
|
id: number,
|
|
payload: Partial<{ name: string; slug: string; date?: string; is_active?: boolean }>
|
|
): Promise<void> {
|
|
const response = await authorizedFetch(`/api/v1/tenant/events/${id}`, {
|
|
method: 'PUT',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify(payload),
|
|
});
|
|
if (!response.ok) {
|
|
await safeJson(response);
|
|
throw new Error('Failed to update event');
|
|
}
|
|
}
|
|
|
|
export async function getEventPhotos(id: number): Promise<any[]> {
|
|
const response = await authorizedFetch(`/api/v1/tenant/events/${id}/photos`);
|
|
const data = await jsonOrThrow<{ data?: any[] }>(response, 'Failed to load photos');
|
|
return data.data ?? [];
|
|
}
|
|
|
|
export async function featurePhoto(id: number): Promise<void> {
|
|
const response = await authorizedFetch(`/api/v1/tenant/photos/${id}/feature`, { method: 'POST' });
|
|
if (!response.ok) {
|
|
await safeJson(response);
|
|
throw new Error('Failed to feature photo');
|
|
}
|
|
}
|
|
|
|
export async function unfeaturePhoto(id: number): Promise<void> {
|
|
const response = await authorizedFetch(`/api/v1/tenant/photos/${id}/unfeature`, { method: 'POST' });
|
|
if (!response.ok) {
|
|
await safeJson(response);
|
|
throw new Error('Failed to unfeature photo');
|
|
}
|
|
}
|
|
|
|
export async function getEvent(id: number): Promise<any> {
|
|
const response = await authorizedFetch(`/api/v1/tenant/events/${id}`);
|
|
return jsonOrThrow<any>(response, 'Failed to load event');
|
|
}
|
|
|
|
export async function toggleEvent(id: number): Promise<boolean> {
|
|
const response = await authorizedFetch(`/api/v1/tenant/events/${id}/toggle`, { method: 'POST' });
|
|
const data = await jsonOrThrow<{ is_active: boolean }>(response, 'Failed to toggle event');
|
|
return !!data.is_active;
|
|
}
|
|
|
|
export async function getEventStats(id: number): Promise<{ total: number; featured: number; likes: number }> {
|
|
const response = await authorizedFetch(`/api/v1/tenant/events/${id}/stats`);
|
|
return jsonOrThrow<{ total: number; featured: number; likes: number }>(response, 'Failed to load stats');
|
|
}
|
|
|
|
export async function createInviteLink(id: number): Promise<string> {
|
|
const response = await authorizedFetch(`/api/v1/tenant/events/${id}/invites`, { method: 'POST' });
|
|
const data = await jsonOrThrow<{ link: string }>(response, 'Failed to create invite');
|
|
return data.link;
|
|
}
|
|
|
|
export async function deletePhoto(id: number): Promise<void> {
|
|
const response = await authorizedFetch(`/api/v1/tenant/photos/${id}`, { method: 'DELETE' });
|
|
if (!response.ok) {
|
|
await safeJson(response);
|
|
throw new Error('Failed to delete photo');
|
|
}
|
|
}
|