/** * api/events.js — Client des endpoints Hub /events (vue staff RSVP). * Miroir de services/targo-hub/lib/events.js. Passe par le proxy /ops/hub * (jeton HUB_SERVICE_TOKEN injecté) → routes /events gatées (PII). * * listEvents() → { events:[{id,name,date_iso,active}] } * listRsvps(eventId) → { event:{...,public_url}, responses:[], count, headcount, matched, unmatched } * deleteRsvp(eventId, key) → { ok } * sendInvite(eventId, body) → envoi d'invitations (GATÉ — non branché pour l'instant) */ import { HUB_URL } from 'src/config/hub' async function hubFetch (path, { method = 'GET', body } = {}) { const opts = { method, headers: { 'Content-Type': 'application/json' } } if (body) opts.body = JSON.stringify(body) const res = await fetch(`${HUB_URL}${path}`, opts) const text = await res.text() let data try { data = text ? JSON.parse(text) : {} } catch { throw new Error(`Réponse invalide de ${path}`) } if (!res.ok) throw new Error(data.error || `HTTP ${res.status}`) return data } export async function listEvents () { return hubFetch('/events') } export async function listRsvps (eventId) { return hubFetch(`/events/${encodeURIComponent(eventId)}/rsvps`) } export async function deleteRsvp (eventId, key) { return hubFetch(`/events/${encodeURIComponent(eventId)}/rsvps/${encodeURIComponent(key)}`, { method: 'DELETE' }) } export async function sendInvite (eventId, body) { return hubFetch(`/events/${encodeURIComponent(eventId)}/send`, { method: 'POST', body }) } export async function previewAudience (eventId, body) { return hubFetch(`/events/${encodeURIComponent(eventId)}/audience`, { method: 'POST', body }) } // Aperçu HTML de l'invitation (gabarit festif OU template éditable). template: undefined=modèle configuré, ''=festif, ''=ce template. export async function getInvitePreview (eventId, { lang = 'fr', template } = {}) { const qs = new URLSearchParams({ lang }) if (template !== undefined) qs.set('template', template) return hubFetch(`/events/${encodeURIComponent(eventId)}/invite-preview?${qs.toString()}`) } // Recherche FLOUE de clients (pg_trgm, typo/accent-tolérante) — réutilise l'endpoint app-wide. export async function searchCustomersFuzzy (q) { return hubFetch(`/collab/customer-search?q=${encodeURIComponent(q)}`) } // Liste principale d'audience (additive, persistée par événement). export async function getAudienceList (eventId) { return hubFetch(`/events/${encodeURIComponent(eventId)}/audience-list`) } export async function audienceListAdd (eventId, body) { return hubFetch(`/events/${encodeURIComponent(eventId)}/audience-list/add`, { method: 'POST', body }) } export async function audienceListRemove (eventId, email) { return hubFetch(`/events/${encodeURIComponent(eventId)}/audience-list/remove`, { method: 'POST', body: { email } }) } export async function audienceListClear (eventId) { return hubFetch(`/events/${encodeURIComponent(eventId)}/audience-list`, { method: 'DELETE' }) } export async function listTemplates () { return hubFetch('/campaigns/templates') } // Config brute éditable d'un événement (pour le formulaire d'édition). export async function getEventConfig (eventId) { return hubFetch(`/events/${encodeURIComponent(eventId)}`) } // Création / édition / suppression d'un événement (config persistée côté hub). export async function createEvent (body) { return hubFetch('/events', { method: 'POST', body }) } export async function updateEvent (eventId, body) { return hubFetch(`/events/${encodeURIComponent(eventId)}`, { method: 'PUT', body }) } export async function deleteEvent (eventId) { return hubFetch(`/events/${encodeURIComponent(eventId)}`, { method: 'DELETE' }) } // Pièces jointes du courriel d'invitation (image/PDF, base64). export async function uploadAttachment (eventId, { filename, mime, data, lang }) { return hubFetch(`/events/${encodeURIComponent(eventId)}/attachments`, { method: 'POST', body: { filename, mime, data, lang } }) } export async function deleteAttachment (eventId, stored) { return hubFetch(`/events/${encodeURIComponent(eventId)}/attachments/${encodeURIComponent(stored)}`, { method: 'DELETE' }) }