@qite/tide-booking-component
Version:
React Booking wizard & Booking product component for Tide
352 lines (312 loc) • 12 kB
text/typescript
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
import { ExcursionSearchParams, ExtendedFlightSearchResponseItem, Filter, FlyInType, SortByType } from '../types';
import {
BookingPackage,
BookingPackageItem,
BookingPriceDetails,
ClientPortalItinerary,
PackagingAccommodationResponse,
PackagingEntry,
PackagingFlightResponse
} from '@qite/tide-client/build/types';
export interface SearchResultsState {
results: BookingPackageItem[];
filteredResults: BookingPackageItem[];
selectedSearchResult: BookingPackageItem | null;
packagingAccoResults: PackagingAccommodationResponse[];
filteredPackagingAccoResults: PackagingAccommodationResponse[];
packagingAccoSearchDetails: PackagingAccommodationResponse[];
selectedPackagingAccoResultCode: string | null;
packagingFlightResults: PackagingFlightResponse[];
filteredPackagingFlightResults: PackagingFlightResponse[];
selectedPackagingFlight: PackagingFlightResponse | null;
selectedOutwardKey: string | null;
selectedReturnKey: string | null;
selectedFlight: ExtendedFlightSearchResponseItem | null;
selectedFlightDetails: ExtendedFlightSearchResponseItem | null;
bookingPackageDetails: BookingPackage | null;
priceDetails: BookingPriceDetails | null;
isLoading: boolean;
flightsLoading: boolean;
selectedSortType: SortByType | null;
selectedFlightSortType: SortByType | null;
filters: Filter[];
initialFilters: Filter[];
flightFilters: Filter[];
initialFlightFilters: Filter[];
activeTab: string | null;
currentPage: number;
transactionId: string | null;
flyInIsOpen: boolean;
flyInType: FlyInType | null;
itinerary: ClientPortalItinerary | null;
editablePackagingEntry: PackagingEntry | null;
excursionSearchParams: ExcursionSearchParams | null;
selectedExcursionSearchResult: PackagingAccommodationResponse | null;
confirmedExcursionsByDay: Record<string, PackagingAccommodationResponse[]>;
bookPackagingEntry: boolean;
currentStep: number;
bookingNumber?: string;
}
const initialState: SearchResultsState = {
results: [],
filteredResults: [],
selectedSearchResult: null,
packagingAccoResults: [],
filteredPackagingAccoResults: [],
packagingAccoSearchDetails: [],
selectedPackagingAccoResultCode: null,
packagingFlightResults: [],
filteredPackagingFlightResults: [],
selectedPackagingFlight: null,
selectedOutwardKey: null,
selectedReturnKey: null,
selectedFlight: null,
selectedFlightDetails: null,
bookingPackageDetails: null,
priceDetails: null,
isLoading: false,
flightsLoading: false,
selectedSortType: null,
selectedFlightSortType: null,
initialFilters: [],
filters: [],
initialFlightFilters: [],
flightFilters: [],
activeTab: 'compact',
currentPage: 1,
transactionId: null,
flyInIsOpen: false,
flyInType: null,
editablePackagingEntry: null,
itinerary: null,
excursionSearchParams: null,
selectedExcursionSearchResult: null,
confirmedExcursionsByDay: {},
bookPackagingEntry: false,
currentStep: 0,
bookingNumber: undefined
};
const searchResultsSlice = createSlice({
name: 'searchResults',
initialState,
reducers: {
setResults(state, action: PayloadAction<BookingPackageItem[]>) {
state.results = action.payload;
},
setFilteredResults(state, action: PayloadAction<BookingPackageItem[]>) {
state.filteredResults = action.payload;
},
setSelectedSearchResult(state, action: PayloadAction<BookingPackageItem | null>) {
state.selectedSearchResult = action.payload;
},
setPackagingAccoResults(state, action: PayloadAction<PackagingAccommodationResponse[]>) {
state.packagingAccoResults = action.payload;
},
setFilteredPackagingAccoResults(state, action: PayloadAction<PackagingAccommodationResponse[]>) {
state.filteredPackagingAccoResults = action.payload;
},
setPackagingAccoSearchDetails(state, action: PayloadAction<PackagingAccommodationResponse[]>) {
state.packagingAccoSearchDetails = action.payload;
},
setSelectedPackagingAccoResult(state, action: PayloadAction<string | null>) {
state.selectedPackagingAccoResultCode = action.payload;
},
setPackagingFlightResults(state, action: PayloadAction<PackagingFlightResponse[]>) {
state.packagingFlightResults = action.payload;
},
setFilteredPackagingFlightResults(state, action: PayloadAction<PackagingFlightResponse[]>) {
state.filteredPackagingFlightResults = action.payload;
},
setSelectedPackagingFlight(state, action: PayloadAction<PackagingFlightResponse | null>) {
state.selectedPackagingFlight = action.payload;
},
setSelectedFlight(state, action: PayloadAction<ExtendedFlightSearchResponseItem | null>) {
state.selectedFlight = action.payload;
},
setSelectedFlightDetails(state, action: PayloadAction<ExtendedFlightSearchResponseItem | null>) {
state.selectedFlightDetails = action.payload;
},
setBookingPackageDetails(state, action: PayloadAction<{ details: BookingPackage }>) {
state.bookingPackageDetails = action.payload.details;
},
selectFlight(state, action: PayloadAction<{ flightOptionId: string; isDeparture: boolean }>) {
if (!state.bookingPackageDetails) return;
const { flightOptionId, isDeparture } = action.payload;
const flightKey = isDeparture ? 'outwardFlights' : 'returnFlights';
state.bookingPackageDetails[flightKey] = state.bookingPackageDetails[flightKey].map((flight) => ({
...flight,
isSelected: flight.flightOptionId === flightOptionId
}));
},
setIsLoading(state, action: PayloadAction<boolean>) {
state.isLoading = action.payload;
},
setFlightsLoading(state, action: PayloadAction<boolean>) {
state.flightsLoading = action.payload;
},
setInitialFilters(state, action: PayloadAction<Filter[]>) {
state.initialFilters = action.payload;
},
setFilters(state, action: PayloadAction<Filter[]>) {
const updatedFilters = action.payload;
updatedFilters.forEach((updatedFilter) => {
const existingIndex = state.filters.findIndex((f) => f.property === updatedFilter.property);
if (existingIndex !== -1) {
state.filters[existingIndex] = updatedFilter;
} else {
state.filters.push(updatedFilter); // Optional: Add new filters if not present
}
});
},
resetFilters(state, action: PayloadAction<Filter[]>) {
state.filters = action.payload;
},
setInitialFlightFilters(state, action: PayloadAction<Filter[]>) {
state.initialFlightFilters = action.payload;
},
setFlightFilters(state, action: PayloadAction<Filter[]>) {
const updatedFilters = action.payload;
updatedFilters.forEach((updatedFilter) => {
const existingIndex = state.flightFilters.findIndex((f) => f.property === updatedFilter.property);
if (existingIndex !== -1) {
state.flightFilters[existingIndex] = updatedFilter;
} else {
state.flightFilters.push(updatedFilter); // Optional: Add new filters if not present
}
});
},
resetFlightFilters(state, action: PayloadAction<Filter[]>) {
state.flightFilters = action.payload;
},
setSortType(state, action: PayloadAction<SortByType | null>) {
state.selectedSortType = action.payload;
},
setFlightSortType(state, action: PayloadAction<SortByType | null>) {
state.selectedFlightSortType = action.payload;
},
setActiveTab(state, action: PayloadAction<string | null>) {
state.activeTab = action.payload;
},
setCurrentPage(state, action: PayloadAction<number>) {
state.currentPage = action.payload;
},
resetSearchState(state) {
state.results = [];
state.isLoading = false;
state.filters = [];
state.selectedSortType = null;
state.activeTab = 'compact';
state.currentPage = 1;
},
setFlyInIsOpen(state, action: PayloadAction<boolean>) {
state.flyInIsOpen = action.payload;
},
setEditablePackagingEntry(state, action: PayloadAction<PackagingEntry | null>) {
state.editablePackagingEntry = action.payload;
},
setTransactionId(state, action: PayloadAction<string | null>) {
state.transactionId = action.payload;
},
setFlyInType(state, action: PayloadAction<FlyInType | null>) {
state.flyInType = action.payload;
},
setPriceDetails(state, action: PayloadAction<BookingPriceDetails | null>) {
state.priceDetails = action.payload;
},
setItinerary(state, action: PayloadAction<ClientPortalItinerary | null>) {
state.itinerary = action.payload;
},
setSelectedOutwardKey: (state, action: PayloadAction<string | null>) => {
state.selectedOutwardKey = action.payload;
},
setSelectedReturnKey: (state, action: PayloadAction<string | null>) => {
state.selectedReturnKey = action.payload;
},
resetFlightSelection: (state) => {
state.selectedOutwardKey = null;
state.selectedReturnKey = null;
},
setExcursionSearchParams(state, action: PayloadAction<ExcursionSearchParams>) {
state.excursionSearchParams = action.payload;
},
setSelectedExcursionSearchResult(state, action: PayloadAction<PackagingAccommodationResponse | null>) {
state.selectedExcursionSearchResult = action.payload;
},
confirmExcursionForDay: (state, action: PayloadAction<{ dayKey: string; excursion: PackagingAccommodationResponse }>) => {
const { dayKey, excursion } = action.payload;
const existingForDay = state.confirmedExcursionsByDay[dayKey] ?? [];
const existingIndex = existingForDay.findIndex((item) => item.code === excursion.code);
if (existingIndex >= 0) {
// replace existing confirmed version of same excursion
existingForDay[existingIndex] = excursion;
} else {
existingForDay.push(excursion);
}
state.confirmedExcursionsByDay[dayKey] = existingForDay;
},
removeConfirmedExcursionForDay: (state, action: PayloadAction<{ dayKey: string; excursionCode: string }>) => {
const { dayKey, excursionCode } = action.payload;
state.confirmedExcursionsByDay[dayKey] = (state.confirmedExcursionsByDay[dayKey] ?? []).filter((item) => item.code !== excursionCode);
},
clearConfirmedExcursionsForDay: (state, action: PayloadAction<{ dayKey: string }>) => {
delete state.confirmedExcursionsByDay[action.payload.dayKey];
},
setBookPackagingEntry(state, action: PayloadAction<boolean>) {
state.bookPackagingEntry = action.payload;
},
setCurrentStep(state, action: PayloadAction<number>) {
state.currentStep = action.payload;
},
setBookingNumber(state, action: PayloadAction<string>) {
state.bookingNumber = action.payload;
}
}
});
export const {
setResults,
setFilteredResults,
setSelectedSearchResult,
setPackagingAccoResults,
setFilteredPackagingAccoResults,
setFilteredPackagingFlightResults,
setPackagingAccoSearchDetails,
setSelectedPackagingAccoResult,
setPackagingFlightResults,
setSelectedPackagingFlight,
setSelectedFlight,
setSelectedFlightDetails,
setBookingPackageDetails,
selectFlight,
setIsLoading,
setFlightsLoading,
setInitialFilters,
setFilters,
resetFilters,
setInitialFlightFilters,
setFlightFilters,
resetFlightFilters,
setSortType,
setFlightSortType,
setActiveTab,
setCurrentPage,
resetSearchState,
setFlyInIsOpen,
setEditablePackagingEntry,
setTransactionId,
setFlyInType,
setPriceDetails,
setItinerary,
setSelectedOutwardKey,
setSelectedReturnKey,
resetFlightSelection,
setExcursionSearchParams,
setSelectedExcursionSearchResult,
confirmExcursionForDay,
removeConfirmedExcursionForDay,
clearConfirmedExcursionsForDay,
setBookPackagingEntry,
setCurrentStep,
setBookingNumber
} = searchResultsSlice.actions;
export default searchResultsSlice.reducer;