invy/frontend/src/api/api.js

243 lines
7.8 KiB
JavaScript

import axios from 'axios'
const API_BASE_URL = window.ENV?.VITE_API_URL || import.meta.env.VITE_API_URL || 'http://localhost:8000'
const api = axios.create({
baseURL: API_BASE_URL,
headers: {
'Content-Type': 'application/json',
},
withCredentials: true, // Send cookies with every request
})
// Add request interceptor to include user ID header
api.interceptors.request.use((config) => {
const userId = localStorage.getItem('userId')
if (userId) {
config.headers['X-User-ID'] = userId
}
return config
})
// ============================================
// Event API Calls
// ============================================
export const getEvents = async () => {
const response = await api.get('/events')
return response.data
}
export const getEvent = async (eventId) => {
const response = await api.get(`/events/${eventId}`)
return response.data
}
export const createEvent = async (event) => {
const response = await api.post('/events', event)
return response.data
}
export const updateEvent = async (eventId, event) => {
const response = await api.patch(`/events/${eventId}`, event)
return response.data
}
export const deleteEvent = async (eventId) => {
const response = await api.delete(`/events/${eventId}`)
return response.data
}
export const getEventStats = async (eventId) => {
const response = await api.get(`/events/${eventId}/stats`)
return response.data
}
// ============================================
// Event Member API Calls
// ============================================
export const getEventMembers = async (eventId) => {
const response = await api.get(`/events/${eventId}/members`)
return response.data
}
export const inviteEventMember = async (eventId, invite) => {
const response = await api.post(`/events/${eventId}/invite-member`, invite)
return response.data
}
export const updateMemberRole = async (eventId, userId, role) => {
const response = await api.patch(`/events/${eventId}/members/${userId}`, { role })
return response.data
}
export const removeMember = async (eventId, userId) => {
const response = await api.delete(`/events/${eventId}/members/${userId}`)
return response.data
}
// ============================================
// Guest API Calls (Event-Scoped)
// ============================================
export const getGuests = async (eventId, options = {}) => {
const params = new URLSearchParams()
if (options.search) params.append('search', options.search)
if (options.rsvpStatus) params.append('rsvp_status', options.rsvpStatus)
if (options.status) params.append('status', options.status) // Backward compat
if (options.side) params.append('side', options.side)
if (options.owner) params.append('owner', options.owner)
if (options.addedByMe) params.append('added_by_me', 'true')
if (options.skip) params.append('skip', options.skip)
if (options.limit) params.append('limit', options.limit)
const response = await api.get(`/events/${eventId}/guests?${params.toString()}`)
return response.data
}
export const getGuestOwners = async (eventId) => {
const response = await api.get(`/events/${eventId}/guest-owners`)
return response.data
}
export const getGuest = async (eventId, guestId) => {
const response = await api.get(`/events/${eventId}/guests/${guestId}`)
return response.data
}
export const createGuest = async (eventId, guest) => {
const response = await api.post(`/events/${eventId}/guests`, guest)
return response.data
}
export const updateGuest = async (eventId, guestId, guest) => {
const response = await api.patch(`/events/${eventId}/guests/${guestId}`, guest)
return response.data
}
export const deleteGuest = async (eventId, guestId) => {
const response = await api.delete(`/events/${eventId}/guests/${guestId}`)
return response.data
}
export const bulkImportGuests = async (eventId, guests) => {
const response = await api.post(`/events/${eventId}/guests/import`, { guests })
return response.data
}
export const searchGuests = async (eventId, filters = {}) => {
const params = new URLSearchParams()
if (filters.query) params.append('search', filters.query)
if (filters.status) params.append('status', filters.status)
if (filters.side) params.append('side', filters.side)
if (filters.addedByMe) params.append('added_by_me', 'true')
const response = await api.get(`/events/${eventId}/guests?${params.toString()}`)
return response.data
}
// ============================================
// WhatsApp API Calls
// ============================================
export const sendWhatsAppMessage = async (eventId, guestId, message) => {
const response = await api.post(`/events/${eventId}/guests/${guestId}/whatsapp`, message)
return response.data
}
export const broadcastWhatsAppMessage = async (eventId, broadcastRequest) => {
const response = await api.post(`/events/${eventId}/whatsapp/broadcast`, broadcastRequest)
return response.data
}
// ============================================
// Legacy endpoints (for backward compatibility)
// ============================================
export const deleteGuestsBulk = async (guestIds) => {
const response = await api.post('/guests/bulk-delete', guestIds)
return response.data
}
export const undoImport = async (owner) => {
const response = await api.delete(`/guests/undo-import/${encodeURIComponent(owner)}`)
return response.data
}
export const getOwners = async () => {
const response = await api.get('/guests/owners/')
return response.data
}
// ============================================
// Google OAuth & Contacts Import
// ============================================
// Get the Google OAuth authorization URL
export const getGoogleAuthUrl = async (eventId = null) => {
const params = new URLSearchParams()
if (eventId) params.append('event_id', eventId)
const response = await api.get(`/auth/google?${params.toString()}`)
return response.data
}
// Import Google contacts for a specific event
export const importGoogleContactsForEvent = async (eventId, accessToken, owner = 'Google Import') => {
const response = await api.post(`/events/${eventId}/import-google-contacts`, {
access_token: accessToken,
owner: owner
})
return response.data
}
// Legacy: Google Contacts Import (backward compatibility)
export const importGoogleContacts = async (accessToken) => {
const response = await api.post('/import/google', null, {
params: { access_token: accessToken }
})
return response.data
}
// Public endpoints for guest self-service
export const getGuestByPhone = async (phoneNumber) => {
const response = await api.get(`/public/guest/${encodeURIComponent(phoneNumber)}`)
return response.data
}
export const updateGuestByPhone = async (phoneNumber, guestData) => {
const response = await api.put(`/public/guest/${encodeURIComponent(phoneNumber)}`, guestData)
return response.data
}
// Duplicate management
export const getDuplicates = async (eventId, by = 'phone') => {
const response = await api.get(`/events/${eventId}/guests/duplicates?by=${by}`)
return response.data
}
export const mergeGuests = async (eventId, keepId, mergeIds) => {
const response = await api.post(`/events/${eventId}/guests/merge`, {
keep_id: keepId,
merge_ids: mergeIds
})
return response.data
}
// ============================================
// WhatsApp Integration
// ============================================
export const sendWhatsAppInvitationToGuests = async (eventId, guestIds, formData) => {
const response = await api.post(`/events/${eventId}/whatsapp/invite`, {
guest_ids: guestIds
})
return response.data
}
export const sendWhatsAppInvitationToGuest = async (eventId, guestId, phoneOverride = null) => {
const payload = {}
if (phoneOverride) {
payload.phone_override = phoneOverride
}
const response = await api.post(`/events/${eventId}/guests/${guestId}/whatsapp/invite`, payload)
return response.data
}
export default api