@qite/tide-booking-component
Version:
React Booking wizard & Booking product component for Tide
267 lines (227 loc) • 6.28 kB
text/typescript
import {
BookingPackage,
BookingPackageRequestRoom,
FlightSearchResponseItem,
PackageMainRoom,
PackagingEntry,
WebsiteConfigurationSearchConfiguration
} from '@qite/tide-client';
import { ReactNode } from 'react';
export type FlightSelectionMode = 'paired' | 'independent';
export interface SearchResultsConfiguration {
searchConfiguration: WebsiteConfigurationSearchConfiguration;
portalId?: number;
agentId?: number;
// Tide connection
tideConnection: {
host: string;
apiKey: string;
catalogueIds?: number[]; // Optional, used for multiple catalogues
officeId?: number;
};
// Filter settings
showFilters: boolean;
filterIcon?: ReactNode;
filters?: Filter[];
useGlobalApplyFilterButton?: boolean;
onFilterChange?: (filters: Filter[]) => void;
// Search results display
// results: SearchResult[];
// customCards?: ReactNode[];
showTabViews?: boolean;
showFlightResults?: boolean;
showHotelAccommodationResults?: boolean;
showFlightAccommodationResults?: boolean;
showRoundTripResults?: boolean;
showCustomCards?: boolean;
customCardRenderer?: (result: SearchResult) => ReactNode;
showMockup?: boolean;
// Map view
// not supported for now
showMapView?: boolean;
// Pagination
// not supported for now
// pagination?: PaginationConfig;
// State
isLoading?: boolean;
customSpinner?: ReactNode;
cmsHotelData?: any[];
cmsGroupTourData?: any[];
tags?: TideTag[];
languageCode?: string;
destinationImage?: { url: string; alt: string };
onBook?: (result: BookingPackage) => void;
onFlightBook?: (result: ExtendedFlightSearchResponseItem) => void;
packagingEntry?: PackagingEntry | null;
generatePaymentUrl?: boolean;
entryStatus?: number;
customEntryStatusId?: number;
}
export type FilterType = 'checkbox' | 'toggle' | 'slider' | 'star-rating';
export type FilterProperty =
| 'regime'
| 'accommodation'
| 'max-duration'
| 'price'
| 'rating'
| 'theme'
| 'airline'
| 'numberOfStops'
| 'departureRange'
| 'departureAirport'
| 'arrivalAirport'
| 'travelDuration';
export interface FilterOption {
label: string;
value: string | number | string[] | number[];
isChecked: boolean;
}
export interface Filter {
// id: string; // maybe this will become deprecated
label: string;
property: FilterProperty;
type: FilterType;
isFrontendFilter: boolean;
options?: FilterOption[];
useApplyFilterButton?: boolean;
min?: number; // For slider type
max?: number; // For slider type
selectedMin?: number; // For slider type
selectedMax?: number; // For slider type
selectedRating?: number; // For star-rating type
}
export interface PaginationConfig {
totalResults: number;
currentPage: number;
onPaginationChange: (page: number) => void;
}
export type SearchResult = HotelResult | FlightResult | RoundTripResult;
export interface BaseSearchResult {
id?: number;
code: string;
title: string;
image: string;
description?: string;
location?: string;
tags?: Tag[];
price: string | number;
ctaText: string;
stars?: number;
accommodation?: string;
regime?: string;
}
export interface HotelResult extends BaseSearchResult {
type: 'hotel';
days: string;
contents?: string;
}
export interface RoundTripResult extends BaseSearchResult {
type: 'roundTrip';
days: string;
}
export interface FlightResult extends BaseSearchResult {
type: 'flight';
days: string;
outbound: FlightLeg;
return: FlightLeg;
}
export interface FlightLeg {
departureAirport: string;
departureDateTime: Date;
arrivalAirport: string;
arrivalDateTime: Date;
airline: Tag;
duration: string;
stops: number;
luggageIncluded: boolean;
}
export interface Tag {
icon: ReactNode;
label: string;
}
export interface SortingOption {
key: 'price-asc' | 'price-desc' | 'departure-date' | 'duration-asc' | 'duration-desc' | 'rating-asc' | 'rating-desc';
label: string;
icon?: ReactNode;
}
export interface ExtendedFlightSearchResponseItem extends FlightSearchResponseItem {
requestId: number; // Unique identifier for the search request
guid: string; // Unique identifier for the item
}
export interface Sequence {
requestId: number;
sequenceId: number;
}
export interface FilterValue {
name: string;
id: number | string;
lowestPrice: number;
}
export interface Filters {
airlines: FilterValue[];
numberOfStops: FilterValue[];
departureRanges: FilterValue[];
departureAirports: FilterValue[];
arrivalAirports: FilterValue[];
travelTimes: FilterValue[];
prices: FilterValue[];
}
export interface SortByType {
direction: 'asc' | 'desc';
label: string;
icon?: ReactNode;
}
export interface TideTag {
id: number;
name: string;
}
export type SearchSeed = {
fromDate: string;
toDate: string;
country?: number | null;
region?: number | null;
oord?: number | null;
location?: number | null;
hotel?: number | null;
hotelCode?: string | null;
tagId?: number | null;
departureAirport?: string | null;
returnAirport?: string | null;
travelClass?: string | null;
nationality?: string | null;
destinationAirport?: string | null;
rooms: BookingPackageRequestRoom[];
};
export type FlyInType =
| 'flight-outward-results'
| 'flight-return-results'
| 'flight-details'
| 'acco-results'
| 'acco-details'
| 'excursion-results'
| 'excursion-details';
export interface ExcursionSearchParams {
// Core: which day are we searching for
date: string; // ISO string (e.g. "2026-07-01")
// Optional but useful if your API expects a range
fromDate: string; // usually same as date
toDate: string; // usually same as date
// Location context
countryId?: number | null;
regionId?: number | null;
oordId?: number | null;
locationId?: number | null;
locationName?: string;
// Accommodation context (important for availability/pricing)
hotelCode: string;
hotelName: string;
accommodationCode: string | null;
accommodationName: string | null;
// Occupancy (VERY likely needed later)
rooms?: PackageMainRoom[];
// Optional: currency / language (depends on your backend)
currencyCode?: string;
languageCode?: string;
// Optional: traceability/debugging
source?: 'day-by-day-excursions';
}