39948-vm/frontend/docs/types-module.md
2026-07-03 16:11:24 +02:00

35 KiB

Types Module

Overview

The types module provides TypeScript type definitions used throughout the frontend application. These types ensure type safety, enable IDE autocompletion, and document the data structures used across components, hooks, stores, and API interactions.

Location: frontend/src/types/

Statistics:

  • 19 files (~2,110 LOC total)
  • 6 categories: Domain Entities, Runtime/Presentation, Infrastructure, Forms/Filters, Specialized, Module Declarations
  • Central export via index.ts

Architecture Diagram

frontend/src/types/
├── index.ts                # Central re-export (14 LOC)
│
├── Domain Entities
│   ├── entities.ts         # Database entity types (307 LOC)
│   ├── constructor.ts      # Canvas element types (418 LOC)
│   └── permissions.ts      # RBAC permission enum (122 LOC)
│
├── Runtime & Presentation
│   ├── runtime.ts          # Runtime page/project types (92 LOC)
│   ├── presentation.ts     # Navigation/transition types (107 LOC)
│   ├── uiControls.ts       # Global UI-control cascade/settings types
│   └── preload.ts          # Preload infrastructure types (57 LOC)
│
├── Infrastructure
│   ├── offline.ts          # PWA/offline storage types (194 LOC)
│   ├── api.ts              # API request/response types (62 LOC)
│   └── redux.ts            # Redux state types (60 LOC)
│
├── Forms & Filters
│   ├── forms.ts            # Form configuration types (76 LOC)
│   └── filters.ts          # Table filter types (74 LOC)
│
├── Specialized
│   ├── charts.ts           # Chart/dashboard data types (42 LOC)
│   ├── components.ts       # UI component prop types (30 LOC)
│   ├── menu.ts             # Navigation menu types (25 LOC)
│   └── ui.ts               # Generic UI element types (35 LOC)
│
└── Module Declarations
    └── css.d.ts            # CSS module type declarations (10 LOC)

Type Categories

1. Domain Entities (entities.ts)

Core database entity types that mirror backend Sequelize models.

BaseEntity

export interface BaseEntity {
  id: string;
  createdAt?: string;
  updatedAt?: string;
}

User Entity

export interface User extends BaseEntity {
  firstName?: string;
  lastName?: string;
  phoneNumber?: string;
  email: string;
  disabled?: boolean;
  avatar?: ImageFile[];
  app_role?: Role | null;
  custom_permissions?: PermissionEntity[];
  password?: string;
}

Project Entity

export interface Project extends BaseEntity {
  name: string;
  slug?: string;
  description?: string;
  logo_url?: string;
  favicon_url?: string;
  og_image_url?: string;
  design_width?: number;    // Design canvas width (default 1920)
  design_height?: number;   // Design canvas height (default 1080)
  is_deleted?: boolean;
  deleted_at_time?: string | Date | null;
}

Asset Entity

export interface Asset extends BaseEntity {
  project?: Project | string | null;
  name: string;
  asset_type: 'image' | 'video' | 'audio' | 'file';
  type?: 'general' | 'icon' | 'background_image' | 'audio' | 'video'
       | 'transition' | 'logo' | 'favicon' | 'document';
  cdn_url?: string;
  storage_key?: string;
  mime_type?: string;
  size_mb?: number;
  width_px?: number;
  height_px?: number;
  duration_sec?: number;
  checksum?: string;
  is_public?: boolean;
  is_deleted?: boolean;
  deleted_at_time?: string | Date;
}

TourPage Entity

export interface TourPage extends BaseEntity {
  project?: Project | string | null;
  name?: string;
  title?: string;
  slug?: string;
  background_asset?: Asset | string | null;
  audio_asset?: Asset | string | null;
  is_start_page?: boolean;
  sort_order?: number;
  environment?: 'dev' | 'stage' | 'production';
  source_key?: string;
  requires_auth?: boolean;
  ui_schema_json?: string;
  // Background URL fields (direct storage paths)
  background_image_url?: string;
  background_video_url?: string;
  background_audio_url?: string;
  background_loop?: boolean;
  // Background video playback settings
  background_video_autoplay?: boolean;
  background_video_loop?: boolean;
  background_video_muted?: boolean;
  background_video_start_time?: number | null;
  background_video_end_time?: number | null;
  // Background audio playback settings
  background_audio_autoplay?: boolean;
  background_audio_loop?: boolean;
  background_audio_start_time?: number | null;
  background_audio_end_time?: number | null;
  // Design canvas dimensions (copied from project on save)
  design_width?: number | null;
  design_height?: number | null;
}

Complete Entity List

Entity Description
User User accounts with roles and permissions
Role Role definitions with permission sets
PermissionEntity Individual permission records
Project Tour projects with configuration
Asset Media assets (images, videos, audio)
AssetVariant Variant versions (thumbnails, previews)
TourPage Tour pages with backgrounds
PageElement UI elements on pages
PageLink Navigation links between pages
Transition Video transitions
ProjectAudioTrack Background audio tracks
ProjectMembership User-project access
PublishEvent Publishing history
PwaCache PWA cache tracking
PresignedUrlRequest File upload/download requests
AccessLog Audit trail entries
UIElement Generic UI element

Entity Type Map

// Type-safe entity name to type mapping
export type EntityName =
  | 'users' | 'roles' | 'permissions' | 'projects'
  | 'project_memberships' | 'assets' | 'asset_variants'
  | 'tour_pages' | 'project_audio_tracks' | 'publish_events'
  | 'pwa_caches' | 'presigned_url_requests' | 'access_logs'
  | 'element_type_defaults';

export interface EntityTypeMap {
  users: User;
  roles: Role;
  permissions: PermissionEntity;
  projects: Project;
  // ... all entities mapped
}

2. Constructor Types (constructor.ts)

Types for the tour builder (constructor) page and UI elements.

Canvas Element Types

// 11 available element types
export type CanvasElementType =
  | 'navigation_next'  // Forward navigation button
  | 'navigation_prev'  // Back navigation button
  | 'spot'             // Hotspot/clickable area
  | 'description'      // Text description block
  | 'tooltip'          // Hover tooltip
  | 'gallery'          // Image gallery
  | 'carousel'         // Image carousel
  | 'logo'             // Logo element
  | 'video_player'     // Video player
  | 'audio_player'     // Audio player
  | 'popup';           // Popup/modal

CanvasElement Interface

export interface CanvasElement extends BaseCanvasElement {
  type: CanvasElementType;
  label: string;
  xPercent: number;
  yPercent: number;

  // Icon
  iconUrl?: string;

  // Media
  mediaUrl?: string;
  mediaAutoplay?: boolean;
  mediaLoop?: boolean;
  mediaMuted?: boolean;

  // Background
  backgroundImageUrl?: string;
  videoUrl?: string;
  audioUrl?: string;

  // Gallery/Carousel
  galleryCards?: GalleryCard[];
  galleryHeaderImageUrl?: string;
  galleryTitle?: string;
  galleryInfoSpans?: GalleryInfoSpan[];
  galleryColumns?: number;
  galleryTitleFontFamily?: string;
  galleryCardFontFamily?: string;
  carouselSlides?: CarouselSlide[];
  carouselCaptionFontFamily?: string;
  carouselPrevIconUrl?: string;
  carouselNextIconUrl?: string;

  // Gallery Carousel Settings (button icons, positions, dimensions)
  galleryCarouselPrevIconUrl?: string;
  galleryCarouselNextIconUrl?: string;
  galleryCarouselBackIconUrl?: string;
  galleryCarouselBackLabel?: string;
  galleryCarouselPrevX?: number;
  galleryCarouselPrevY?: number;
  galleryCarouselNextX?: number;
  galleryCarouselNextY?: number;
  galleryCarouselBackX?: number;
  galleryCarouselBackY?: number;
  galleryCarouselPrevWidth?: string;
  galleryCarouselPrevHeight?: string;
  galleryCarouselNextWidth?: string;
  galleryCarouselNextHeight?: string;
  galleryCarouselBackWidth?: string;
  galleryCarouselBackHeight?: string;

  // Info Panel trigger/default behavior
  infoPanelTriggerLabel?: string;
  infoPanelTriggerFontFamily?: string;
  infoPanelDisabled?: boolean;
  infoPanelOpenByDefault?: boolean;

  // Tooltip
  tooltipTitle?: string;
  tooltipText?: string;
  tooltipTitleFontFamily?: string;
  tooltipTextFontFamily?: string;

  // Description
  descriptionTitle?: string;
  descriptionText?: string;
  descriptionTitleFontSize?: string;
  descriptionTextFontSize?: string;
  descriptionTitleFontFamily?: string;
  descriptionTextFontFamily?: string;
  descriptionTitleColor?: string;
  descriptionTextColor?: string;
  descriptionBackgroundColor?: string;

  // Navigation
  navLabel?: string;
  navType?: NavigationButtonKind;
  navDisabled?: boolean;
  /** @deprecated Use targetPageSlug instead */
  targetPageId?: string;
  targetPageSlug?: string;
  transitionVideoUrl?: string;
  transitionReverseMode?: 'auto_reverse' | 'separate_video';
  reverseVideoUrl?: string;
  transitionDurationSec?: number;
}
export interface GalleryCard {
  id: string;
  imageUrl: string;
  title: string;
  description: string;
}

export interface GalleryInfoSpan {
  id: string;
  text: string;
}

export interface CarouselSlide {
  id: string;
  imageUrl: string;
  caption: string;
}

Constructor Schema & Asset Types

export interface ConstructorSchema {
  elements?: CanvasElement[];
}

export interface ConstructorAsset {
  id: string;
  name?: string;
  asset_type?: 'image' | 'video' | 'audio' | 'file';
  type?: 'icon' | 'background_image' | 'audio' | 'video'
       | 'transition' | 'logo' | 'favicon' | 'document' | 'general';
  cdn_url?: string | null;
  storage_key?: string | null;
}

export interface AssetOption {
  value: string;
  label: string;
}

Type Guards

// Type guard for canvas element types
export function isCanvasElementType(value: string): value is CanvasElementType {
  return CANVAS_ELEMENT_TYPES.includes(value as CanvasElementType);
}

Element Default Normalization

// Normalize API response to consistent format
export function normalizeElementDefault(
  row: Record<string, unknown>,
): NormalizedElementDefault | null;

// Build lookup map from defaults array
export function buildElementDefaultsMap(
  defaults: NormalizedElementDefault[],
): Partial<Record<CanvasElementType, Partial<CanvasElement>>>;

Page Background State Types

// Video playback settings
export interface PageBackgroundVideoSettings {
  autoplay: boolean;
  loop: boolean;
  muted: boolean;
  startTime: number | null;
  endTime: number | null;
}

// Audio playback settings
export interface PageBackgroundAudioSettings {
  autoplay: boolean;
  loop: boolean;
  startTime: number | null;
  endTime: number | null;
}

// Consolidated background state (replaces 8 useState hooks)
export interface PageBackgroundState {
  imageUrl: string;
  videoUrl: string;
  audioUrl: string;
  videoSettings: PageBackgroundVideoSettings;
  audioSettings: PageBackgroundAudioSettings;
}

// Default constants
export const DEFAULT_VIDEO_SETTINGS: PageBackgroundVideoSettings;
export const DEFAULT_AUDIO_SETTINGS: PageBackgroundAudioSettings;
export const DEFAULT_PAGE_BACKGROUND: PageBackgroundState;

// Factory function
export function createPageBackgroundFromPage(
  page: TourPage | null
): PageBackgroundState;

Editor Panel Props

The constructor types also define grouped props interfaces for the ElementEditorPanel:

Interface Purpose
EditorLayoutProps Panel position and collapse state
EditorStateProps Tabs and title
EditorElementProps Selected element and callbacks
EditorBackgroundProps Background image/video/audio URLs
EditorTransitionProps Transition creation state
EditorDurationNotesProps Duration display notes
EditorAssetOptionsProps Asset dropdown options
EditorNavigationProps Navigation settings
EditorCollectionOpsProps Gallery/carousel operations
EditorMediaUtilsProps Duration utilities

3. Permissions (permissions.ts)

RBAC (Role-Based Access Control) permission definitions.

Permission Enum

export enum Permission {
  // User permissions
  READ_USERS = 'READ_USERS',
  CREATE_USERS = 'CREATE_USERS',
  UPDATE_USERS = 'UPDATE_USERS',
  DELETE_USERS = 'DELETE_USERS',

  // Role permissions
  READ_ROLES = 'READ_ROLES',
  CREATE_ROLES = 'CREATE_ROLES',
  UPDATE_ROLES = 'UPDATE_ROLES',
  DELETE_ROLES = 'DELETE_ROLES',

  // Project permissions
  READ_PROJECTS = 'READ_PROJECTS',
  CREATE_PROJECTS = 'CREATE_PROJECTS',
  UPDATE_PROJECTS = 'UPDATE_PROJECTS',
  DELETE_PROJECTS = 'DELETE_PROJECTS',

  // ... 60+ total permissions covering all entities
}

Permission Helper

// Generate CRUD permissions for any entity
export const getEntityPermissions = (entityName: string) => {
  const uppercased = entityName.toUpperCase();
  return {
    read: `READ_${uppercased}` as PermissionString,
    create: `CREATE_${uppercased}` as PermissionString,
    update: `UPDATE_${uppercased}` as PermissionString,
    delete: `DELETE_${uppercased}` as PermissionString,
  };
};

// Usage
const assetPerms = getEntityPermissions('assets');
// { read: 'READ_ASSETS', create: 'CREATE_ASSETS', ... }

4. Runtime Types (runtime.ts)

Types for runtime presentation playback.

RuntimeProject

export interface RuntimeProject {
  id: string;
  name?: string;
  slug?: string;
  description?: string;
}

RuntimePage

// Extends PreloadPage with display/navigation fields
export interface RuntimePage extends PreloadPage {
  slug?: string;
  name?: string;
  sort_order?: number;
  ui_schema_json?: string;
  environment?: 'dev' | 'stage' | 'production';
  // Background video playback settings
  background_video_autoplay?: boolean;
  background_video_loop?: boolean;
  background_video_muted?: boolean;
  background_video_start_time?: number | null;
  background_video_end_time?: number | null;
  // Background audio playback settings
  background_audio_autoplay?: boolean;
  background_audio_loop?: boolean;
  background_audio_start_time?: number | null;
  background_audio_end_time?: number | null;
  // Design canvas dimensions (copied from project on save)
  design_width?: number | null;
  design_height?: number | null;
}

RuntimeTransition

export interface RuntimeTransition {
  id: string;
  name?: string;
  slug?: string;
  video_url?: string;
  duration_sec?: number;
  supports_reverse?: boolean;
}

TransitionOverlayState

export interface TransitionOverlayState {
  targetPageId: string;
  transitionName: string;
  videoUrl: string;
  isReverse: boolean;
  durationSec?: number;
}

Global UI Control Types (uiControls.ts)

Global UI-control types describe the fullscreen, sound, and offline system buttons and their cascade:

export type SystemUiControlType = 'fullscreen' | 'sound' | 'offline';
export type SystemUiControlAnchor =
  | 'center'
  | 'top-left'
  | 'top-right'
  | 'bottom-left'
  | 'bottom-right';

export interface SystemUiControlSettings {
  enabled?: boolean;
  hidden?: boolean;
  xPercent?: number;
  yPercent?: number;
  anchor?: SystemUiControlAnchor;
  buttonSizePercent?: number;
  iconSizePercent?: number;
  defaultIconUrl?: string;
  activeIconUrl?: string;
  defaultBackgroundColor?: string;
  activeBackgroundColor?: string;
  defaultBorderColor?: string;
  activeBorderColor?: string;
}

Helpers:

  • resolveUiControlsSettings(global, project, page) merges the cascade field-by-field.
  • parseUiControlsSettings(value) normalizes JSON/string input.
  • getSystemControlAnchorBounds(anchor, size, aspectRatio) clamps controls inside the visible canvas.

5. Presentation Types (presentation.ts)

Shared types for RuntimePresentation and constructor.tsx.

Note: Not exported from index.ts, must import directly from @/types/presentation.

Navigation Types

export interface NavigableElement {
  id: string;
  type: string;
  targetPageSlug?: string;
  targetPageId?: string;
  transitionVideoUrl?: string;
  navType?: 'forward' | 'back';
  navDisabled?: boolean;
}

export interface NavigationTarget {
  page: RuntimePage;
  pageId: string;
  transitionVideoUrl?: string;
  isBack: boolean;
}

RuntimeProject (Presentation)

// Duplicate definition for page data loader context
export interface RuntimeProject {
  id: string;
  name?: string;
  slug?: string;
  description?: string;
}

Transition Phase

export type TransitionPhase =
  | 'idle'       // No transition
  | 'preparing'  // Loading video
  | 'playing'    // Forward playback
  | 'reversing'  // Reverse playback
  | 'completed'; // Finished

Background State

export interface BackgroundState {
  imageUrl: string;
  videoUrl: string;
  audioUrl: string;
}

export interface TransitionPreviewState {
  targetPageId: string;
  videoUrl: string;
  storageKey: string;
  isReverse: boolean;
}

Page Data Loader

export interface PageDataLoaderResult {
  project: RuntimeProject | null;
  pages: RuntimePage[];
  isLoading: boolean;
  error: string;
  reload: (preservePageId?: string) => Promise<void>;
}

Runtime API Config

export interface RuntimeApiConfig {
  headers: {
    'X-Runtime-Project-Slug'?: string;
    'X-Runtime-Environment'?: string;
  };
}

Background Transition Options

export interface BackgroundTransitionOptions {
  pendingTransitionComplete: boolean;
  isBackgroundReady: boolean;
  transitionVideoRef: React.RefObject<HTMLVideoElement | null>;
  pageSwitch: {
    clearPreviousBackground: () => void;
    isSwitching: boolean;
    isNewBgReady: boolean;
    previousBgImageUrl: string;
  };
  onCleanup: () => void;
}

6. Preload Types (preload.ts)

Minimal types for asset preloading infrastructure.

PreloadPage

// Simplified page type (subset of TourPage)
export interface PreloadPage {
  id: string;
  background_image_url?: string;
  background_video_url?: string;
  background_audio_url?: string;
}
export interface PreloadPageLink {
  id: string;
  from_pageId?: string;
  to_pageId?: string;
  is_active?: boolean;
  transition?: {
    id: string;
    video_url?: string;
  };
}

PreloadElement

export interface PreloadElement {
  id: string;
  pageId?: string;
  element_type?: string;
  content_json?: string;
}

PreloadAssetInfo

export interface PreloadAssetInfo {
  url: string;
  pageId: string;
  assetType: 'image' | 'video' | 'audio' | 'transition' | 'other';
  priority: number;
}

PreloadNeighborInfo

export interface PreloadNeighborInfo {
  pageId: string;
  distance: number;
}

7. Offline Types (offline.ts)

Types for PWA and offline storage functionality.

Asset Variant & Type

export type AssetVariantType =
  | 'thumbnail' | 'preview' | 'webp'
  | 'mp4_low' | 'mp4_high' | 'original';

export type AssetType = 'image' | 'video' | 'audio' | 'transition' | 'other';

Preload Job

export type PreloadJobStatus =
  | 'queued' | 'downloading' | 'completed' | 'error' | 'paused';

export interface PreloadJob {
  id: string;
  assetId: string;
  url: string;
  filename: string;
  progress: number;
  status: PreloadJobStatus;
  bytesLoaded: number;
  totalBytes: number;
  pageId?: string;
  variantType?: AssetVariantType;
  assetType?: AssetType;
  error?: string;
  addedAt: number;
  startedAt?: number;
  completedAt?: number;
}

Offline Project

export type ProjectOfflineStatus =
  | 'not_downloaded' | 'downloading' | 'downloaded' | 'outdated' | 'error';

export interface OfflineProject {
  id: string;
  slug: string;
  name: string;
  status: ProjectOfflineStatus;
  totalAssets: number;
  downloadedAssets: number;
  totalSizeBytes: number;
  downloadedSizeBytes: number;
  lastSyncedAt?: number;
  version?: string;
}

Offline Asset (IndexedDB)

export interface OfflineAsset {
  id: string;
  projectId: string;
  url: string;
  filename: string;
  variantType: AssetVariantType;
  assetType: AssetType;
  mimeType: string;
  sizeBytes: number;
  blob: Blob;
  downloadedAt: number;
}

Download Queue Item

export interface DownloadQueueItem {
  id: string;
  projectId: string;
  assetId: string;
  url: string;
  filename: string;
  status: PreloadJobStatus;
  priority: number;
  retryCount: number;
  bytesLoaded: number;
  totalBytes: number;
  addedAt: number;
  lastAttemptAt?: number;
  error?: string;
}

Network & Storage Info

export interface NetworkInfo {
  isOnline: boolean;
  effectiveType?: 'slow-2g' | '2g' | '3g' | '4g';
  downlink?: number; // Mbps
  rtt?: number;      // ms
  saveData?: boolean;
}

export interface StorageQuotaInfo {
  usage: number;
  quota: number;
  percentUsed: number;
  available: number;
  canStore: (bytes: number) => boolean;
}

Offline Manifest

export interface OfflineManifest {
  version: string;
  projectId: string;
  projectSlug: string;
  assets: ManifestAsset[];
  totalSizeBytes: number;
  generatedAt: number;
}

export interface ManifestAsset {
  id: string;
  url: string;
  filename: string;
  variantType: AssetVariantType;
  assetType: AssetType;
  mimeType: string;
  sizeBytes: number;
  pageIds: string[];
}

Preload State & Neighbor Graph

export interface PreloadState {
  isActive: boolean;
  currentPageId: string | null;
  queuedAssets: string[];
  loadingAssets: string[];
  completedAssets: string[];
  failedAssets: string[];
  totalProgress: number;
}

export interface NeighborGraph {
  connections: Map<string, Array<{ pageId: string; distance: number }>>;
  getNeighbors: (pageId: string, maxDepth: number) => string[];
  getAssetsForPages: (pageIds: string[]) => string[];
}

Event Payloads

export interface PreloadStartEvent {
  jobId: string;
  assetId: string;
  url: string;
}

export interface PreloadProgressEvent {
  jobId: string;
  progress: number;
  bytesLoaded: number;
  totalBytes: number;
}

export interface PreloadCompleteEvent {
  jobId: string;
  assetId: string;
}

export interface PreloadErrorEvent {
  jobId: string;
  assetId: string;
  error: string;
}

export interface ProjectDownloadProgressEvent {
  projectId: string;
  progress: number;
  downloadedAssets: number;
  totalAssets: number;
  downloadedBytes: number;
  totalBytes: number;
}

export interface ProjectDownloadCompleteEvent {
  projectId: string;
}

8. API Types (api.ts)

Types for API requests and responses.

Paginated Response

export interface PaginatedResponse<T> {
  rows: T[];
  count: number;
}

Fetch Parameters

export interface FetchParams {
  id?: string;
  query?: string;
  limit?: number;
  page?: number;
}

List Query Parameters

export interface ListQueryParams {
  page?: number;
  limit?: number;
  sort?: 'asc' | 'desc';
  field?: string;
  [filterKey: string]: string | number | boolean | undefined;
}

Sort Model & Autocomplete

export interface SortModel {
  field: string;
  sort: 'asc' | 'desc';
}

export interface AutocompleteItem {
  id: string;
  label: string;
}

API Error

export interface ApiError {
  message?: string;
  statusCode?: number;
  errors?: Record<string, { _errors: string[] }>;
}

Mutation Payloads

export interface MutationPayload<T> {
  id?: string;
  data: Partial<T>;
}

export interface DeleteByIdsPayload {
  ids: string[];
}

export interface CsvUploadResponse {
  imported: number;
  errors?: string[];
}

9. Redux Types (redux.ts)

Types for Redux state management.

Notification State

export interface NotificationState {
  showNotification: boolean;
  textNotification: string;
  typeNotification: 'warn' | 'error' | 'success' | 'info' | '';
}

Entity Slice State

export interface EntitySliceState<T> {
  data: T[];
  loading: boolean;
  count: number;
  refetch: boolean;
  notify: NotificationState;
}

Slice Factory Config

export interface EntitySliceConfig {
  name: string;
  endpoint: string;
  singularName?: string; // For notification messages
}

Core State Types

export interface AuthState {
  currentUser: User | null;
  token: string | null;
  isFetching: boolean;
  errorMessage: string | null;
  loadingMessage: string | null;
  notify: NotificationState;
}

export interface StyleState {
  darkMode: boolean;
  bgLayoutColor: string;
  focusRingColor: string;
  corners: string;
  cardsColor: string;
}

export interface MainState {
  isAsideMobileExpanded: boolean;
  isAsideLgActive: boolean;
}

10. Forms Types (forms.ts)

Types for form rendering and validation.

Form Field Types

export type FormFieldType =
  | 'text' | 'email' | 'number' | 'password'
  | 'textarea' | 'richtext'
  | 'select' | 'multiselect'
  | 'date' | 'datetime'
  | 'boolean' | 'switch'
  | 'image' | 'file' | 'enum';

Form Field Config

export interface FormFieldConfig {
  name: string;
  label: string;
  type: FormFieldType;
  required?: boolean;
  placeholder?: string;
  itemRef?: string;      // Entity endpoint for options
  showField?: string;    // Display field from options
  options?: EnumOption[];
  uploadPath?: string;
  fileSchema?: FileSchema;
  min?: number;
  max?: number;
  maxLength?: number;
  className?: string;
}

Form Page Config

export interface FormPageConfig<TFormData> {
  entityName: string;
  entityTitle: string;
  mode: 'create' | 'edit';
  permission: string;
  initialValues: TFormData;
  fields: FormFieldConfig[];
  listPath?: string;
}

11. Filters Types (filters.ts)

Types for table filtering and sorting.

Filter Definition

export type FilterType = 'text' | 'enum' | 'date' | 'number' | 'boolean';

export interface Filter {
  label: string;
  title: string; // Field name to filter by
  type?: FilterType;
  options?: string[]; // For enum filters
  number?: boolean;
  date?: boolean;
}

Active Filter

export interface FilterItem {
  id: string;
  fields: FilterFields;
}

export interface FilterFields {
  selectedField: string;
  filterValue: string;
  filterValueFrom: string;
  filterValueTo: string;
}

Table Configuration

export interface TableColumnConfig {
  field: string;
  headerName: string;
  width?: number;
  minWidth?: number;
  maxWidth?: number;
  flex?: number;
  editable?: boolean;
  sortable?: boolean;
  filterable?: boolean;
  type?: 'string' | 'number' | 'date' | 'dateTime' | 'boolean' | 'singleSelect';
  valueOptions?: string[];
  renderType?: 'link' | 'boolean' | 'date' | 'datetime' | 'image' | 'actions' | 'relation';
  relationField?: string;
}

export interface TableConfig {
  entityName: string;
  columns: TableColumnConfig[];
  filters: Filter[];
  defaultSort?: { field: string; sort: 'asc' | 'desc' };
  perPage?: number;
}

12. Specialized Types

Additional type files for specific features.

Charts Types (charts.ts)

export interface ChartDataPoint {
  label: string;
  value: number;
}

export interface DashboardStats {
  totalProjects: number;
  totalPages: number;
  totalAssets: number;
  recentActivity: ActivityItem[];
}

Components Types (components.ts)

export interface BaseComponentProps {
  className?: string;
  children?: React.ReactNode;
}

export interface DataGridProps<T> {
  rows: T[];
  columns: GridColDef[];
  loading?: boolean;
}

Menu Types (menu.ts)

export interface MenuItem {
  label: string;
  href?: string;
  icon?: string;
  permission?: string;
  children?: MenuItem[];
}

UI Types (ui.ts)

export interface ToastNotification {
  id: string;
  type: 'success' | 'error' | 'info' | 'warning';
  message: string;
  duration?: number;
}

export interface ModalProps {
  isOpen: boolean;
  onClose: () => void;
  title?: string;
}

Type Relationships

┌─────────────────────────────────────────────────────────────┐
│                      entities.ts                            │
│  BaseEntity → User, Project, Asset, TourPage, etc.         │
└─────────────────────────────────────────────────────────────┘
              │
              ├──────────────────────────────┐
              ▼                              ▼
┌─────────────────────────┐    ┌─────────────────────────────┐
│    constructor.ts       │    │       runtime.ts            │
│                         │    │                             │
│ CanvasElement           │    │ RuntimePage extends         │
│ (extends styles/effects)│    │ PreloadPage                 │
└─────────────────────────┘    └─────────────────────────────┘
              │                              │
              ▼                              ▼
┌─────────────────────────┐    ┌─────────────────────────────┐
│   presentation.ts       │    │      preload.ts             │
│                         │    │                             │
│ NavigableElement        │◄───│ PreloadPage                 │
│ NavigationTarget        │    │ PreloadPageLink             │
│ TransitionPhase         │    │ PreloadElement              │
└─────────────────────────┘    └─────────────────────────────┘
                                             │
                                             ▼
                               ┌─────────────────────────────┐
                               │      offline.ts             │
                               │                             │
                               │ OfflineAsset                │
                               │ DownloadQueueItem           │
                               │ PreloadJob                  │
                               └─────────────────────────────┘

Import Patterns

// Import from central index (10 modules re-exported)
// entities, api, redux, forms, filters, permissions,
// offline, preload, runtime, constructor
import type {
  User,
  Project,
  Asset,
  CanvasElement,
  Permission,
  PaginatedResponse,
} from '@/types';

Direct Import (For Specific Modules)

// Import from specific file
import type { CanvasElement, CanvasElementType } from '@/types/constructor';
import type { RuntimePage, RuntimeProject } from '@/types/runtime';
import type { PreloadJob, OfflineAsset } from '@/types/offline';

// Note: presentation.ts is NOT exported from index.ts, must import directly
import type { NavigableElement, TransitionPhase } from '@/types/presentation';

Usage Examples

Entity Types in API Calls

import type { User, PaginatedResponse } from '@/types';

const response = await axios.get<PaginatedResponse<User>>('/api/users');
const users: User[] = response.data.rows;

Canvas Elements in Constructor

import type { CanvasElement, CanvasElementType } from '@/types/constructor';
import { isCanvasElementType } from '@/types/constructor';

const handleAddElement = (type: string) => {
  if (isCanvasElementType(type)) {
    const element: CanvasElement = createDefaultElement(type);
    setElements([...elements, element]);
  }
};

Permissions in Components

import { Permission } from '@/types/permissions';

const canEdit = userPermissions.includes(Permission.UPDATE_PROJECTS);

Redux State Types

import type { EntitySliceState, NotificationState } from '@/types/redux';

interface UsersSliceState extends EntitySliceState<User> {
  // Additional state if needed
}

Offline Storage Types

import type { OfflineAsset, PreloadJobStatus } from '@/types/offline';

const asset: OfflineAsset = {
  id: 'asset-1',
  projectId: 'project-1',
  url: 'https://...',
  filename: 'image.jpg',
  variantType: 'original',
  assetType: 'image',
  mimeType: 'image/jpeg',
  sizeBytes: 1024000,
  blob: imageBlob,
  downloadedAt: Date.now(),
};

Best Practices

1. Use Type Guards

// Use type guards for runtime type checking
if (isCanvasElementType(element.type)) {
  // TypeScript knows type is CanvasElementType
}

2. Prefer Interfaces for Objects

// Good - interfaces are extendable
export interface User extends BaseEntity { ... }

// Use types for unions/primitives
export type CanvasElementType = 'navigation_next' | 'navigation_prev' | ...

3. Use Generic Types

// Generic response types
export interface PaginatedResponse<T> {
  rows: T[];
  count: number;
}

// Usage
const response: PaginatedResponse<Asset>;

4. Document Deprecations

export interface CanvasElement {
  /** @deprecated Use targetPageSlug instead - IDs change when copied */
  targetPageId?: string;
  targetPageSlug?: string;
}

5. Export via Index

// types/index.ts
export * from './entities';
export * from './api';
// ... all modules

// Consumer
import type { User, Asset, Permission } from '@/types';