feat: add customizable event types with admin management
Implements GitHub issue #139 - allows users to create and manage custom event types beyond the default presets (wedding, birthday, corporate, other). Backend: - Add event_types table migration with default system types - Create eventTypeService for CRUD operations with legacy fallback - Add adminEventTypes routes with full REST API - Update event validation to use dynamic event types - Update slug generation to use custom slug_prefix Frontend: - Add EventTypesPage with full CRUD admin interface - Add eventTypes.service.ts API client - Update CreateEventPage to fetch types dynamically - Add Event Types navigation in admin sidebar - Add i18n translations (EN/DE) Backward compatible: existing galleries continue to work, legacy types accepted even if database is empty via fallback mechanisms.
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
/**
|
||||
* Event Types Service
|
||||
* API client for event type management
|
||||
*/
|
||||
|
||||
import { api } from '../config/api';
|
||||
|
||||
export interface EventType {
|
||||
id: number;
|
||||
name: string;
|
||||
slug_prefix: string;
|
||||
emoji: string;
|
||||
theme_preset: string;
|
||||
theme_config: string | null;
|
||||
display_order: number;
|
||||
is_system: boolean;
|
||||
is_active: boolean;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
}
|
||||
|
||||
export interface CreateEventTypeData {
|
||||
name: string;
|
||||
slug_prefix: string;
|
||||
emoji?: string;
|
||||
theme_preset?: string;
|
||||
theme_config?: Record<string, unknown>;
|
||||
display_order?: number;
|
||||
}
|
||||
|
||||
export interface UpdateEventTypeData {
|
||||
name?: string;
|
||||
slug_prefix?: string;
|
||||
emoji?: string;
|
||||
theme_preset?: string;
|
||||
theme_config?: Record<string, unknown>;
|
||||
display_order?: number;
|
||||
is_active?: boolean;
|
||||
}
|
||||
|
||||
export const eventTypesService = {
|
||||
/**
|
||||
* Get all event types (for admin management)
|
||||
*/
|
||||
async getEventTypes(includeInactive = false): Promise<EventType[]> {
|
||||
const response = await api.get<{ eventTypes: EventType[] }>('/admin/event-types', {
|
||||
params: { includeInactive: includeInactive.toString() }
|
||||
});
|
||||
return response.data.eventTypes;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get only active event types (for dropdowns/selection)
|
||||
*/
|
||||
async getActiveEventTypes(): Promise<EventType[]> {
|
||||
const response = await api.get<{ eventTypes: EventType[] }>('/admin/event-types/active');
|
||||
return response.data.eventTypes;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get a single event type by ID
|
||||
*/
|
||||
async getEventType(id: number): Promise<EventType> {
|
||||
const response = await api.get<EventType>(`/admin/event-types/${id}`);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* Create a new event type
|
||||
*/
|
||||
async createEventType(data: CreateEventTypeData): Promise<EventType> {
|
||||
const response = await api.post<EventType>('/admin/event-types', data);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* Update an event type
|
||||
*/
|
||||
async updateEventType(id: number, data: UpdateEventTypeData): Promise<EventType> {
|
||||
const response = await api.put<EventType>(`/admin/event-types/${id}`, data);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* Delete an event type
|
||||
*/
|
||||
async deleteEventType(id: number): Promise<void> {
|
||||
await api.delete(`/admin/event-types/${id}`);
|
||||
},
|
||||
|
||||
/**
|
||||
* Reorder event types
|
||||
*/
|
||||
async reorderEventTypes(orderedIds: number[]): Promise<EventType[]> {
|
||||
const response = await api.post<{ eventTypes: EventType[] }>('/admin/event-types/reorder', {
|
||||
orderedIds
|
||||
});
|
||||
return response.data.eventTypes;
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user