Skip to main content

Adding a Tile widget to CSL Hotel Search

The following steps help you with adding a tile to hotel search, or details, results (when using CSL).

csl custom tile
  1. First step - create a tile.

To create a tile you need a tile content (React component), tile title and, optionally, action that will be performed when the user clicks on the tile.

React component, that will be used as tile content:

import * as React from 'react';
import { PublicCslData } from "sabre-ngv-csl/response/interfaces/PublicCslData";

export const testTileComponent = (data: PublicCslData) => <div className={'sdk-csl-custom-tile-content'}>
    Prop Id : {data.propertyId}
</div>;

Action that will be performed when user selects the tile, in this case we open up a React modal:

const action = (data: PublicCslData) => {
    console.log("Public tile data: ", data);
    this.showReactModal(data)
}


private showReactModal(data: PublicCslData): void {

    const modalService : PublicModalsService = getService(PublicModalsService);

    const ngvModalOptions : ReactModalOptions = {
        header: "CSL Tile Custom Popup",
        component: React.createElement(ModalComponent, data, {})
    }

    modalService.showReactModal(ngvModalOptions);
}

And the popup itself:

import * as React from "react";

import { Panel } from "react-bootstrap";
import { PublicCslData } from "sabre-ngv-csl/response/interfaces/PublicCslData";

interface OwnProps extends PublicCslData {

}


export class ModalComponent extends React.Component<OwnProps> {

    constructor(props) {
        super(props);
    }


    render(): JSX.Element {

        return (
            <div className="com-sabre-redapp-example3-web-cls-tile">
                <Panel bsStyle="primary">
                    <Panel.Heading>
                        <Panel.Title componentClass="h3">Data available in CSL tile and CSL tile action</Panel.Title>
                    </Panel.Heading>
                    <Panel.Body>
                        <div>
                            <ul>
                                <li>Property ID: {this.props.propertyId}</li>
                                <li>Hotel Name: {this.props.hotelName}</li>
                                <li>Address Lines: {this.props.address.join(",")}</li>
                                <li>Chain Code: {this.props.chainCode}</li>
                                <li>Legacy Property Id: {this.props.legacyPropertyId}</li>
                                <li>Phone Number: {this.props.phoneNumber}</li>
                                <li>Fax Number: {this.props.faxNumber}</li>
                                <li>Negotiated rate: {this.props.negotiatedRate}</li>
                                <li>Negotiated rate raw data: {this.props.negotiatedRateRaw?"true":"false"}</li>
                                <li>Contractual rate: {this.props.contractualRate}</li>
                                <li>Contractual rate raw data: {this.props.contractualRateRaw?"true":"false"}</li>
                                <li>Photo URL: {this.props.photoUrl}</li>
                                <li>Postal Code: {this.props.postalCode}</li>
                                <li>City Code: {this.props.cityCode}</li>
                                <li>City Name: {this.props.cityName}</li>
                                <li>Country Code: {this.props.countryCode}</li>
                                <li>Country Name: {this.props.countryName}</li>
                                <li>State Code: {this.props.stateCode}</li>
                            </ul>
                        </div>
                    </Panel.Body>
                </Panel>
            </div>
        );
    }
}

Both tile content and action are provided with a set of data related to the selected hotel. Model is the same for both search and details:

export interface PublicCslData {

    propertyId: string,
    address: string[],
    hotelName: string,
    chainCode: string,
    legacyPropertyId: string,
    phoneNumber: string,
    faxNumber: string,
    negotiatedRate: string,
    contractualRate: string,
    photoUrl: string,
    postalCode: string,
    cityCode: string,
    cityName: string,
    countryCode: string,
    countryName: string,
    stateCode: string,
    negotiatedRateRaw: boolean,
    contractualRateRaw: boolean,
    checkIn: moment.Moment,
    checkOut: moment.Moment,
    nights: number,
    guestCount: number
}
  1. Next add above components to the hotel search drawer.

To do it, use the PublicCslService service and call createCslDrawerTile method.

getService(PublicCslService).createCslDrawerTile(testTileComponent, action , "Tile Added By SDK");

The whole Main.ts class where tile is set up:

import { Module } from 'sabre-ngv-core/modules/Module';
import { getService } from './Context';
import { PublicCslService } from 'sabre-ngv-csl/response/service/PublicCslService';
import { testTileComponent } from "./TestTile";
import { ReactModalOptions } from "sabre-ngv-modals/components/PublicReactModal/ReactModalOptions";
import { PublicModalsService } from "sabre-ngv-modals/services/PublicModalService";
import { PublicCslData } from "sabre-ngv-csl/response/interfaces/PublicCslData";
import * as React from 'react';
import {ModalComponent} from "./ModalComponent";

export class Main extends Module {


    init(): void {

        super.init();

        const action = (data: PublicCslData) => {
            console.log("Public tile data: ", data);
            this.showReactModal(data)
        }

        getService(PublicCslService).createCslHotelSearchTile(testTileComponent, action , "Hotel Search Tile Added By SDK");
        getService(PublicCslService).createCslHotelDetailsTile(testTileComponent, action, "Hotel Details Tile Added by SDK");
    }

    private showReactModal(data: PublicCslData): void {

        const modalService : PublicModalsService = getService(PublicModalsService);

        const ngvModalOptions : ReactModalOptions = {
            header: "CSL Tile Custom Popup",
            component: React.createElement(ModalComponent, data, {})
        }

        modalService.showReactModal(ngvModalOptions);
    }

}

Check com.sabre.redapp.example3.web.csl.tile sample for the full source code.