export type AppEvent = { id: number; eventId: string; name: string; description?: string; metadata: Record; type: string; }; export type ContentEventDto = { type: 'IMPRESSION' | 'CONVERSION'; action: 'view' | 'click'; metadata?: Record; logId?: string; }; export type ContentEvent = { id?: number; itemId?: string; contentView?: { id?: number; }; logId?: string; metadata?: Record; action: 'view' | 'click'; type: 'IMPRESSION' | 'CONVERSION'; createdAt?: Date; }; export enum ContentViewStatus { DRAFT = 'draft', PUBLISHED = 'published', ARCHIVED = 'archived', } export type ElementType = | 'text' | 'button' | 'image' | 'icon' | 'divider' | 'input' | 'select' | 'checkbox' | 'radio' | 'submit' | 'textarea'; export type ContentType = 'section' | 'list' | 'form' | 'element'; export enum ListDataSource { STATIC = 'static', API = 'api', DATABASE = 'database', } export enum FormStatus { ACTIVE = 'active', INACTIVE = 'inactive', MAINTENANCE = 'maintenance', } export enum FormSubmissionType { WEBHOOK = 'webhook', FUNCTION = 'function', INTERNAL = 'internal', } export type ClickAction = { actionType?: 'link' | 'navigation' | 'share' | 'props'; actionValue?: string; navigation?: { routeName?: string; params?: Record; type?: 'push' | 'navigate' | 'goBack'; }; shareOption?: { message?: string; url?: string; title?: string; }; }; export type ContentElementStyles = { fontSize?: number; fontStyle?: string; fontFamily?: string; fontWeight?: string; textDecorationLine?: string; textDecorationColor?: string; textAlign?: 'left' | 'center' | 'right' | 'justify'; color?: string; textTransform?: string; lineHeight?: number; backgroundColor?: string; padding?: number; margin?: number; marginBottom?: number; borderRadius?: number; borderWidth?: number; borderColor?: string; width?: number | string; height?: number | string; maxWidth?: number | string; position?: string; boxShadow?: string; boxShadowColor?: string; boxShadowOffset?: string; boxShadowOpacity?: number; boxShadowRadius?: number; flex?: number; flexGrow?: number; flexShrink?: number; flexBasis?: number; flexDirection?: string; flexWrap?: string; gap?: number; opacity?: number; objectFit?: 'cover' | 'contain' | 'stretch' | 'repeat' | 'center'; resizeMode?: 'cover' | 'contain' | 'fill' | 'scale-down' | 'none'; tintColor?: string; customStyles?: Record; }; export interface ContainerStyles { flexDirection: 'row' | 'column' | 'grid'; alignItems: | 'flex-start' | 'center' | 'flex-end' | 'space-between' | 'space-around'; justifyContent?: | 'flex-start' | 'center' | 'flex-end' | 'space-between' | 'space-around' | 'space-evenly'; gap: number; padding: number; borderRadius: number; backgroundColor: string; flexWrap: 'nowrap' | 'wrap' | 'wrap-reverse'; width?: number | string; height?: number | string; flex?: number; } export interface ContentElementProperties { iconPosition?: 'left' | 'right' | 'center'; textContent?: string; // Image properties imageUrl?: string; // Image URL/link imageAltText?: string; // Alt text for accessibility imageWidth?: number; // Image width in pixels imageHeight?: number; // Image height in pixels } export type ElementProperty = { styles: ContentElementStyles; customStyles?: Record; properties: ContentElementProperties; clickAction?: ClickAction; customProps?: Record; backgroundImage?: string; icon?: { name?: string; size?: number; color?: string; strokeWidth?: number; }; }; export type SectionProperty = { styles: ContainerStyles; customStyles?: Record; clickAction?: ClickAction; customProps?: Record; scrollOptions: { scrollType: 'vertical' | 'horizontal'; }; backgroundImage?: string; }; export type ListProperty = { styles: ContainerStyles; customStyles?: Record; dataSource: ListDataSource; data?: Array>; apiEndpoint?: string; maxItems?: number; pagination: boolean; customProps?: Record; }; export type FormProperty = { styles: ContainerStyles; customStyles?: Record; submissionType?: FormSubmissionType; submitUrl?: string | null; submissionSettings?: { // Webhook settings webhookHeaders?: Record; webhookMethod?: 'GET' | 'POST' | 'PUT' | 'PATCH'; webhookTimeout?: number; // Function settings functionName?: string; }; submittedSuccessAction?: { type?: 'alert' | 'in_app_navigate' | 'out_app_navigate'; alertTitle?: string; alertMessage?: string; inAppNavigate?: { routeName?: string; params?: Record; type?: 'push' | 'navigate' | 'goBack'; }; outAppNavigate?: { url?: string; }; }; submittedErrorAction?: { type?: 'alert' | 'in_app_navigate' | 'out_app_navigate'; alertTitle?: string; alertMessage?: string; inAppNavigate?: { routeName?: string; params?: Record; type?: 'push' | 'navigate' | 'goBack'; }; outAppNavigate?: { url?: string; }; }; hideAfterSubmission?: boolean; // Form element properties inputMode?: | 'none' | 'text' | 'email' | 'numeric' | 'decimal' | 'tel' | 'url' | 'search'; placeholder?: string; label?: string; required?: boolean; secureTextEntry?: boolean; defaultValue?: string | number | boolean; minLength?: number; maxLength?: number; min?: number; max?: number; step?: number; pattern?: string; options?: Array<{ value: string; label: string; disabled?: boolean }>; rows?: number; cols?: number; validationRules?: ValidationRulesType[]; labelStyle?: Record; status: FormStatus; isActive: boolean; requiresCaptcha: boolean; customProps?: Record; }; type ValidationRulesType = { ruleType: | 'required' | 'greaterThan' | 'lessThan' | 'minLength' | 'maxLength' | 'min' | 'max' | 'pattern' | 'email' | 'url'; value: unknown; message: string; }; export type ContentView = { id: number; name: string; description?: string; status: ContentViewStatus; metadata?: Record; version?: string; appId: number; createdBy: { id: number; name: string; email: string; }; contents: Array; event: AppEvent; isFullPage: boolean; createdAt: Date; updatedAt: Date; }; // maintain a completely flat structure, no children export type ContentItem = { id?: number | null; // Database-generated ID (for backend relationships) itemId: string; // Frontend uses string IDs (UUIDs) type: ContentType; elementType?: ElementType | null; name: string; parentItemId: string | null; // Frontend uses string parent IDs order: number; data: ElementProperty | SectionProperty | ListProperty | FormProperty; event?: AppEvent; eventId?: number; eventConfig?: { action?: 'view' | 'click' | 'submit'; metadata?: Record; logId?: string; }; contentViewId: number; isVisible: boolean; isScrollable: boolean; }; export type FunctionRegistry = { [functionName: string]: (...args: any[]) => void; }; export type NavigationRegistry = { navigate: (routeName: string, params?: Record) => void; push: (routeName: string, params?: Record) => void; goBack: () => void; }; export type LogAnalytics = (logId: string, event: Record) => void;