import api from './axiosInstance.api'; // Types export interface IGeoPoint { type: "Point"; coordinates: [number, number]; // [lng, lat] } export interface IEventParticipant { user: string; joinedAt: Date; joinMethod: 'code' | 'link' | 'qr' | 'manual'; } export interface IEvent { _id: string; title: string; code: string; theme: string; description?: string; organization: { _id: string; username: string; organizationType?: string; }; createdBy: { _id: string; username: string; profilePhoto?: string; }; capacity: number; startDate: string; endDate: string; defaultStartTime: string; // HH:MM format defaultEndTime: string; // HH:MM format type: 'in-person' | 'online' | 'hybrid'; venue?: string; location?: IGeoPoint; geofenceRadius?: number; onlineLink?: string; participants: IEventParticipant[]; waitlist: string[]; status: 'draft' | 'published' | 'ongoing' | 'completed' | 'cancelled'; participantCount?: number; isCapacityFull?: boolean; waitlistCount?: number; totalDays?: number; completedDays?: number; liveDays?: number; createdAt: string; updatedAt: string; } export interface EventFilters { query?: string; theme?: string; organization?: string; type?: 'in-person' | 'online' | 'hybrid'; status?: 'draft' | 'published' | 'ongoing' | 'completed' | 'cancelled' | 'all'; startDate?: string; endDate?: string; page?: number; limit?: number; } export interface PaginationMeta { total: number; page: number; limit: number; totalPages: number; } export interface SearchEventsResponse { events: IEvent[]; pagination: PaginationMeta; } export interface CreateEventData { title: string; theme: string; description?: string; capacity: number; startDate: string; endDate: string; defaultStartTime?: string; // HH:MM format, defaults to "09:00" defaultEndTime?: string; // HH:MM format, defaults to "17:00" type: 'in-person' | 'online' | 'hybrid'; venue?: string; longitude?: number; latitude?: number; geofenceRadius?: number; onlineLink?: string; allowSelfJoin?: boolean; } /** * Search events with filters and pagination */ export const searchEvents = async (filters: EventFilters = {}): Promise => { const params = new URLSearchParams(); if (filters.query) params.append('query', filters.query); if (filters.theme) params.append('theme', filters.theme); if (filters.organization) params.append('organization', filters.organization); if (filters.type) params.append('type', filters.type); if (filters.status && filters.status !== 'all') params.append('status', filters.status); if (filters.startDate) params.append('startDate', filters.startDate); if (filters.endDate) params.append('endDate', filters.endDate); if (filters.page) params.append('page', filters.page.toString()); if (filters.limit) params.append('limit', filters.limit.toString()); const response = await api.get(`/events/search?${params.toString()}`); return response.data; }; /** * Get single event details */ export const getEventDetails = async (eventId: string): Promise => { const response = await api.get(`/events/${eventId}`); return response.data; }; /** * Create new event (trainers, organizations, and admins) */ export const createEvent = async (data: CreateEventData): Promise<{ message: string; event: IEvent }> => { const response = await api.post<{ message: string; event: IEvent }>('/events/create', data); return response.data; }; /** * Update existing event */ export const updateEvent = async (eventId: string, data: Partial): Promise<{ message: string; event: IEvent }> => { const response = await api.put<{ message: string; event: IEvent }>(`/events/${eventId}`, data); return response.data; }; /** * Delete event */ export const deleteEvent = async (eventId: string): Promise<{ message: string }> => { const response = await api.delete<{ message: string }>(`/events/${eventId}`); return response.data; }; /** * Get trainer's own events */ export const getTrainerEvents = async (status?: string): Promise<{ events: IEvent[] }> => { const params = status ? `?status=${status}` : ''; const response = await api.get<{ events: IEvent[] }>(`/events/my-events${params}`); return response.data; }; /** * Get nearby events based on location */ export const getNearbyEvents = async ( longitude: number, latitude: number, maxDistance: number = 50000 ): Promise<{ events: IEvent[] }> => { const response = await api.get<{ events: IEvent[] }>( `/events/nearby?longitude=${longitude}&latitude=${latitude}&maxDistance=${maxDistance}` ); return response.data; }; /** * Join event by code */ export const joinEventByCode = async (code: string): Promise<{ message: string; event: IEvent }> => { const response = await api.post<{ message: string; event: IEvent }>('/events/join/code', { code }); return response.data; }; /** * Join event by link */ export const joinEventByLink = async (eventId: string, token: string): Promise<{ message: string; event: IEvent }> => { const response = await api.post<{ message: string; event: IEvent }>('/events/join/link', { eventId, token }); return response.data; }; /** * Get live/ongoing events (for map display) */ export const getLiveEvents = async (): Promise<{ events: IEvent[] }> => { const response = await api.get<{ events: IEvent[] }>('/events/live'); return response.data; }; /** * Get live training events (events with active training sessions) */ export const getLiveTrainingEvents = async (): Promise<{ events: IEvent[] }> => { const response = await api.get<{ events: IEvent[] }>('/events/live-trainings'); return response.data; }; /** * Get all events (admin view) */ export const getAllEventsForAdmin = async (filters: { status?: string; page?: number; limit?: number } = {}): Promise => { const params = new URLSearchParams(); if (filters.status) params.append('status', filters.status); if (filters.page) params.append('page', filters.page.toString()); if (filters.limit) params.append('limit', filters.limit.toString()); const response = await api.get(`/events/all?${params.toString()}`); return response.data; }; export default { searchEvents, getEventDetails, createEvent, updateEvent, deleteEvent, getTrainerEvents, getNearbyEvents, joinEventByCode, joinEventByLink, getLiveEvents, getLiveTrainingEvents, getAllEventsForAdmin, };