export type BrandFont = { name: string; source: 'google' | 'custom'; weights: string[]; files: { [weight: string]: string; }; }; export type RecursivePartial = { [P in keyof T]?: T[P] extends (...args: any[]) => any ? T[P] : T[P] extends readonly (infer U)[] ? ReadonlyArray> : T[P] extends (infer U)[] ? RecursivePartial[] : T[P] extends object ? RecursivePartial : T[P]; }; export type BaseBrandKit = { colors: { primary: string; secondary: string; accent: string; background: { base: string; elevated: string; }; neutral: { light: string; mid: string; dark: string; }; status: { success: string; warning: string; error: string; info?: string; }; text: { onPrimary: string; primary: string; secondary: string; tertiary: string; }; }; }; export type TemplateVersion = { version: number; template: { mainView?: Record; cartView?: Record; }; createdAt: string; createdBy?: string; description?: string; }; export type LayoutConfig = { template?: { mainView?: Record; cartView?: Record; }; plugins?: { type: 'REMOTE'; url: string; pluginParams?: Record; }[]; templateHistory?: TemplateVersion[]; currentVersion?: number; }; export type BrandKit = BaseBrandKit & { fonts: { brand: string; heading?: string; body?: string; }; fontFamilies?: { stylesheet: string; }[]; ordering?: { app: { category: 'HORIZONTAL' | 'VERTICAL'; items: 'LIST' | 'GRID'; singleCategory: boolean; brandkitOverride?: RecursivePartial; }; kiosk: { category: 'HORIZONTAL' | 'VERTICAL'; singleCategory: boolean; brandkitOverride?: RecursivePartial; showSubItemAsRadioIfPossible?: boolean; }; }; layout?: { app?: LayoutConfig; kiosk?: LayoutConfig; }; ods?: OdsConfigEntry[]; }; export type OdsConfigEntry = { /** Display name for this config entry, e.g. "Flagship", "Express". */ label?: string; /** Whether this is the default config applied to all unmatched restaurants. */ isDefault: boolean; /** Restaurant IDs this config applies to. Ignored when `isDefault` is true. */ restaurantIds?: string[]; brandkitOverride?: RecursivePartial; layout?: OdsLayoutConfig; display?: OdsDisplayConfig; }; export type BrandkitOverrideBy = 'app' | 'kiosk'; /** * Controls what appears at the bottom of the ODS screen. * * - `feedme` – Default "Powered by FeedMe" footer bar with settings on click. * - `settingsIcon` – No footer bar; a floating settings gear icon appears at * the bottom-right on mouse/touch activity and auto-hides * after ~10 seconds of inactivity. */ export type OdsFooterMode = 'feedme' | 'settingsIcon'; export type OrderGroupingMode = 'type' | 'status'; export type OrderStatusBoardLayout = 'horizontal' | 'vertical'; /** * Pre-built templates for the status board sections (preparing / ready). * * - `default` – Standard ODS StatusOrderSection (current behaviour). * - `bordered-card` – Gold-bordered cards with inline titles, order cards with numbering + platform logos. * - `floating-tab` – Gray-bordered card with a floating tab title, minimal order text grid. * - `centered-pill` – Pill-shaped container with centered gold title + underline, single-column grid. */ export type StatusSectionTemplateName = 'default' | 'bordered-card' | 'floating-tab' | 'centered-pill'; export type OdsLayoutConfig = { /** Background image covering the full screen, behind everything. */ background?: { url: string; /** CSS background-size. default: 'cover' */ size?: string; /** CSS background-position. default: 'center' */ position?: string; } | null; /** * Decorative image panel beside the board. * Reduces available board space by its width. */ sidePanel?: { url: string; /** Which side the panel sits on. default: 'left' */ position: 'left' | 'right'; /** Width as % of full screen. default: 30 */ widthPercent: number; /** CSS object-fit for the image. default: 'cover' */ objectFit?: string; } | null; /** * Board width as % of available space (full screen minus side panel). * default: 100 */ boardWidthPercent?: number; /** * Board alignment when boardWidthPercent < 100. * default: 'left' */ boardAlign?: 'left' | 'right' | 'center'; /** * Footer mode for the ODS screen. * - `feedme` (default): shows "Powered by FeedMe" footer bar. * - `settingsIcon`: hides footer bar, shows a floating settings icon * at bottom-right that auto-hides after ~10s of inactivity. */ footerMode?: OdsFooterMode; }; export type OdsDisplayConfig = { groupBy: OrderGroupingMode; statusLayout: OrderStatusBoardLayout; statusSlidingPeriod: number; currentOrder?: { enabled?: boolean; }; showProgressBar: boolean; /** Number of order-code columns within each status section (preparing / ready). 1, 2, or 3. */ statusColumnCount: number; /** Show delivery platform icon next to order numbers in status board. */ showDeliveryIcons: boolean; /** Show the In Restaurant / Delivery tabs on the order board when groupBy is 'type'. */ showOrderTypeTabs: boolean; /** Show order count, drinks, and food statistics in the preparing section header. */ showOrderCount: boolean; /** Show estimated waiting time in the preparing section header. Default false. */ showEstimatedTime: boolean; /** * Named template for the horizontal status board. * When set to a non-default value, replaces the entire horizontal status * board content with a custom template component. * Only applies when statusLayout is 'horizontal'. * default: 'default' */ statusTemplate?: StatusSectionTemplateName; }; export type ApplyBrandKitOptions = { overrideBy?: BrandkitOverrideBy; }; export type FdoMetadata = { type: 'BUSINESS' | 'RESTAURANT'; country: string; businessId?: string; pwaConfig?: { short_name: string; name: string; background_color: string; theme_color: string; }; brandkit?: BrandKit | null; }; export type NativeCredentials = { bundle_id?: string; android?: { package_name?: string; keystore?: string; key_properties?: string; service_account_json?: string; }; ios?: { bundle_id?: string; distribution_certificate?: string; password?: string; provisioning_profile?: string; provisioning_profile_uuid?: string; app_store_connect_api_key?: string; app_store_connect_api_key_id?: string; app_store_connect_api_private_key?: string; }; };