first commit
This commit is contained in:
435
src/features/event/api/eventService.ts
Normal file
435
src/features/event/api/eventService.ts
Normal file
@@ -0,0 +1,435 @@
|
||||
import { getWebhookUrl } from '@/lib/config';
|
||||
|
||||
export interface Event {
|
||||
id?: string | number;
|
||||
user_id?: number;
|
||||
name?: string;
|
||||
title?: string; // neuer Titel-Name vom Timeline-Endpoint
|
||||
description?: string;
|
||||
location?: string;
|
||||
url?: string;
|
||||
image?: string;
|
||||
manager_name?: string;
|
||||
manager_email?: string;
|
||||
guests?: any;
|
||||
begin_date?: string; // ISO date string (YYYY-MM-DD)
|
||||
end_date?: string; // ISO date string (YYYY-MM-DD)
|
||||
eventDate?: string; // ISO date string (YYYY-MM-DD) vom Timeline-Endpoint (camelCase)
|
||||
event_date?: string; // ISO date string (YYYY-MM-DD) direkt aus SQL-Query
|
||||
status?: 'PENDING' | 'ON_AIR'; // aggregierter Status für Timeline
|
||||
overall_status?: 'PENDING' | 'ON_AIR'; // Alias-Name aus SQL-Query
|
||||
creation_date?: number;
|
||||
last_update?: number;
|
||||
}
|
||||
|
||||
// Payload-Struktur für den neuen Event-Endpunkt
|
||||
interface CreateEventPayload {
|
||||
title: string;
|
||||
description?: string;
|
||||
eventDate: string; // YYYY-MM-DD
|
||||
promotionStartDate?: string; // YYYY-MM-DD
|
||||
coverMediaUrl?: string;
|
||||
ticketUrl?: string;
|
||||
admissionTimes?: string;
|
||||
ticketPrice?: string;
|
||||
promotionSlots: Array<{
|
||||
slotIndex: number;
|
||||
slotType: 'EVENT_MAIN' | 'ARTIST';
|
||||
promoDate: string; // YYYY-MM-DD
|
||||
artistName?: string;
|
||||
artistInstagram?: string;
|
||||
}>;
|
||||
}
|
||||
|
||||
export interface EventDetail extends CreateEventPayload {
|
||||
id: string | number;
|
||||
}
|
||||
|
||||
export const createEvent = async (payload: CreateEventPayload): Promise<any> => {
|
||||
try {
|
||||
const { apiFetch } = await import('@/utils/apiFetch');
|
||||
const response = await apiFetch(`${getWebhookUrl()}/events/new`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(payload),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
|
||||
const result = await response.json();
|
||||
return result;
|
||||
} catch (error) {
|
||||
console.error('Error creating event manually:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
export interface ArtistCollabUpdateByOpPayload {
|
||||
eventId: string | number;
|
||||
slotId?: string | number;
|
||||
slotIndex?: number;
|
||||
artistDescription?: string;
|
||||
artistInstagram?: string;
|
||||
artistFacebook?: string;
|
||||
artistLinkedin?: string;
|
||||
artistTiktok?: string;
|
||||
artistYoutube?: string;
|
||||
}
|
||||
|
||||
export const updateArtistCollabDataByOp = async (
|
||||
payload: ArtistCollabUpdateByOpPayload
|
||||
): Promise<{ success: boolean; message?: string }> => {
|
||||
try {
|
||||
const { apiFetch } = await import('@/utils/apiFetch');
|
||||
const response = await apiFetch(`${getWebhookUrl()}/events/update_artist_data_byop`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(payload),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
|
||||
const raw = await response.json();
|
||||
const data = Array.isArray(raw) ? raw[0] ?? {} : raw ?? {};
|
||||
|
||||
return {
|
||||
success: data.success !== false,
|
||||
message: data.message,
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('Error updating artist collab data by op:', error);
|
||||
return { success: false, message: error instanceof Error ? error.message : 'Unknown error' };
|
||||
}
|
||||
};
|
||||
|
||||
export const getEventInfoFromUrl = async (url: string): Promise<any> => {
|
||||
try {
|
||||
const { apiFetch } = await import('@/utils/apiFetch');
|
||||
const response = await apiFetch(`${getWebhookUrl()}/events/getinfofromurl`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({ url }),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
return data;
|
||||
} catch (error) {
|
||||
console.error('Error getting event info from URL:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
export const fetchCurrentEvents = async (apiFetch: Function): Promise<Event[]> => {
|
||||
|
||||
const webhookUrl = `${getWebhookUrl()}/events/get_current`;
|
||||
|
||||
try {
|
||||
const response = await apiFetch(webhookUrl, {
|
||||
method: 'GET',
|
||||
headers: { 'Content-Type': 'application/json' }
|
||||
});
|
||||
|
||||
if (!response.ok) throw new Error('Failed to fetch events');
|
||||
|
||||
const raw = await response.json();
|
||||
|
||||
// n8n kann die Liste ggf. als String-JSON zurückgeben
|
||||
const data =
|
||||
typeof raw === 'string'
|
||||
? (() => {
|
||||
try {
|
||||
return JSON.parse(raw);
|
||||
} catch {
|
||||
return raw;
|
||||
}
|
||||
})()
|
||||
: raw;
|
||||
|
||||
return Array.isArray(data) ? data : data ? [data] : [];
|
||||
} catch (error) {
|
||||
console.error('Error fetching events:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
export interface ArtistCollabUpdatePayload {
|
||||
token: string;
|
||||
slotId?: string | number;
|
||||
eventId?: string | number;
|
||||
artistDescription?: string;
|
||||
artistInstagram?: string;
|
||||
artistFacebook?: string;
|
||||
artistLinkedin?: string;
|
||||
artistTiktok?: string;
|
||||
artistYoutube?: string;
|
||||
}
|
||||
|
||||
export const updateArtistCollabData = async (
|
||||
payload: ArtistCollabUpdatePayload
|
||||
): Promise<{ success: boolean; message?: string }> => {
|
||||
try {
|
||||
const { apiFetch } = await import('@/utils/apiFetch');
|
||||
const response = await apiFetch(`${getWebhookUrl()}/events/update_artist_data`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(payload),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
|
||||
const raw = await response.json();
|
||||
const data = Array.isArray(raw) ? raw[0] ?? {} : raw ?? {};
|
||||
|
||||
return {
|
||||
success: data.success !== false,
|
||||
message: data.message,
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('Error updating artist collab data:', error);
|
||||
return { success: false, message: error instanceof Error ? error.message : 'Unknown error' };
|
||||
}
|
||||
};
|
||||
|
||||
export const fetchEventById = async (
|
||||
apiFetch: Function,
|
||||
id: string | number
|
||||
): Promise<EventDetail> => {
|
||||
const webhookUrl = `${getWebhookUrl()}/events/getbyid?id=${id}`;
|
||||
|
||||
const response = await apiFetch(webhookUrl, {
|
||||
method: 'GET',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
});
|
||||
|
||||
if (!response.ok) throw new Error('Failed to fetch event');
|
||||
|
||||
const raw = await response.json();
|
||||
|
||||
// n8n kann entweder ein Objekt, ein Array mit einem Objekt
|
||||
// oder einen JSON-String zurückgeben – hier alles abfangen.
|
||||
const data =
|
||||
typeof raw === 'string'
|
||||
? (() => {
|
||||
try {
|
||||
return JSON.parse(raw);
|
||||
} catch {
|
||||
return raw;
|
||||
}
|
||||
})()
|
||||
: raw;
|
||||
|
||||
if (Array.isArray(data)) {
|
||||
return (data[0] || {}) as EventDetail;
|
||||
}
|
||||
|
||||
return data as EventDetail;
|
||||
};
|
||||
|
||||
export const updateEvent = async (
|
||||
id: string | number,
|
||||
payload: CreateEventPayload
|
||||
): Promise<any> => {
|
||||
try {
|
||||
const { apiFetch } = await import('@/utils/apiFetch');
|
||||
const response = await apiFetch(`${getWebhookUrl()}/events/update`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({ id, ...payload }),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
|
||||
const result = await response.json();
|
||||
return result;
|
||||
} catch (error) {
|
||||
console.error('Error updating event:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
export const fetchEvents = async (apiFetch: Function): Promise<Event[]> => {
|
||||
const webhookUrl = `${getWebhookUrl()}/events`;
|
||||
|
||||
try {
|
||||
const response = await apiFetch(webhookUrl, {
|
||||
method: 'GET',
|
||||
headers: { 'Content-Type': 'application/json' }
|
||||
});
|
||||
|
||||
if (!response.ok) throw new Error('Failed to fetch events');
|
||||
|
||||
const data = await response.json();
|
||||
return Array.isArray(data) ? data : data ? [data] : [];
|
||||
} catch (error) {
|
||||
console.error('Error fetching events:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
export const createEventFromUrl = async (url: string): Promise<any> => {
|
||||
try {
|
||||
const { apiFetch } = await import('@/utils/apiFetch');
|
||||
const response = await apiFetch(`${getWebhookUrl()}/event/new_fromurl`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
url,
|
||||
command: 'eventmodus_extract_from_url'
|
||||
}),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
return data.message_from_ai || data;
|
||||
} catch (error) {
|
||||
console.error('Error creating event from URL:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
// Helper function to format dates to YYYY-MM-DD
|
||||
export const formatDateForInput = (dateString: string): string => {
|
||||
if (!dateString) return '';
|
||||
const date = new Date(dateString);
|
||||
return date.toISOString().split('T')[0];
|
||||
};
|
||||
|
||||
export interface CollabLinkResponse {
|
||||
token: string;
|
||||
url?: string;
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
export const generateCollabLink = async (
|
||||
eventId: string | number,
|
||||
slotIndex: number,
|
||||
artistName?: string,
|
||||
artistInstagram?: string
|
||||
): Promise<CollabLinkResponse> => {
|
||||
try {
|
||||
const { apiFetch } = await import('@/utils/apiFetch');
|
||||
const response = await apiFetch(`${getWebhookUrl()}/events/generate_collab_link`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({ eventId, slotIndex, artistName, artistInstagram }),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
|
||||
const data = (await response.json()) as CollabLinkResponse;
|
||||
return data;
|
||||
} catch (error) {
|
||||
console.error('Error generating collaboration link:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
export interface CollabMediaItem {
|
||||
id: string;
|
||||
url: string;
|
||||
type?: string;
|
||||
}
|
||||
|
||||
export interface CollabInfo {
|
||||
eventTitle: string;
|
||||
promoDate?: string;
|
||||
artistName?: string;
|
||||
artistDescription?: string;
|
||||
artistMediaUrl?: string;
|
||||
artistInstagram?: string;
|
||||
slotId?: string | number;
|
||||
eventId?: string | number;
|
||||
media?: CollabMediaItem[];
|
||||
}
|
||||
|
||||
export const fetchArtistSlotByToken = async (token: string): Promise<CollabInfo | null> => {
|
||||
try {
|
||||
const { apiFetch } = await import('@/utils/apiFetch');
|
||||
const response = await apiFetch(`${getWebhookUrl()}/events/slots/getartistsslot`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({ token }),
|
||||
});
|
||||
|
||||
if (response.status === 401 || response.status === 403 || response.status === 404) {
|
||||
// Token ungültig, abgelaufen oder Slot nicht gefunden
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
|
||||
const raw = await response.json();
|
||||
|
||||
const data: any = (() => {
|
||||
if (!raw) return null;
|
||||
if (Array.isArray(raw)) return raw[0] ?? null;
|
||||
if (typeof raw === 'string') {
|
||||
try {
|
||||
const parsed = JSON.parse(raw);
|
||||
return Array.isArray(parsed) ? parsed[0] ?? null : parsed;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return raw as any;
|
||||
})();
|
||||
|
||||
if (!data) return null;
|
||||
|
||||
return {
|
||||
eventTitle: data.eventTitle ?? data.event_title ?? data.title ?? '',
|
||||
promoDate: data.promoDate ?? data.promo_date,
|
||||
artistName: data.artistName ?? data.artist_name,
|
||||
artistDescription: data.artistDescription ?? data.artist_description,
|
||||
artistMediaUrl: data.artistMediaUrl ?? data.artist_media_url,
|
||||
artistInstagram: data.artistInstagram ?? data.artist_instagram,
|
||||
slotId: data.id ?? data.slot_id,
|
||||
eventId: data.event_id ?? data.eventId,
|
||||
media: Array.isArray(data.media)
|
||||
? data.media.map((m: any) => ({
|
||||
id: String(m.id),
|
||||
url: m.url || m.file_url,
|
||||
type: m.type || m.file_type,
|
||||
}))
|
||||
: [],
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('Error fetching artist slot by token:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user