Repository: kiwicom/mobile
Pull request #976 (2018-08-10 14:06:07)

Hotels: providing new screen to AppRegistry for new design


Patch:
diff --git a/.eslintrc.js b/.eslintrc.js
index b27fe62a..795966ba 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -58,7 +58,8 @@ module.exports = {
               'TouchableHighlight', // Touchable
               'TouchableNativeFeedback', // Touchable
               'TouchableOpacity', // Touchable
-              'Switch' //Switch
+              'Switch', //Switch
+              'Alert' // Alert (localization)
             ],
             message:
               "Please use '@kiwicom/mobile-shared' package instead.",
diff --git a/app/core/src/navigation/stacks/HotelsStack.js b/app/core/src/navigation/stacks/HotelsStack.js
index 1f9491c4..0f216564 100644
--- a/app/core/src/navigation/stacks/HotelsStack.js
+++ b/app/core/src/navigation/stacks/HotelsStack.js
@@ -9,12 +9,14 @@ import {
 import Homepage from '../../screens/hotelsStack/Homepage';
 import HotelsPackageWrapper from '../../screens/hotelsStack/HotelsPackageWrapper';
 import SingleHotelsPackageWrapper from '../../screens/hotelsStack/SingleHotelPackageWrapper';
+import NewHotelsPackageWrapper from '../../screens/hotelsStack/NewHotelsPackageWrapper';
 
 export default StackNavigator(
   {
     Home: withMappedProps(Homepage),
     HotelsPackage: withMappedProps(HotelsPackageWrapper),
     SingleHotelPackage: withMappedProps(SingleHotelsPackageWrapper),
+    NewHotelsPackage: withMappedProps(NewHotelsPackageWrapper),
   },
   {
     initialRouteName: 'Home',
diff --git a/app/core/src/screens/hotelsStack/Homepage.js b/app/core/src/screens/hotelsStack/Homepage.js
index 1673e8f4..0a18124d 100644
--- a/app/core/src/screens/hotelsStack/Homepage.js
+++ b/app/core/src/screens/hotelsStack/Homepage.js
@@ -33,6 +33,15 @@ export default class Homepage extends React.Component<Props> {
 
   goToAllHotelsPage = () => this.props.navigation.navigate('HotelsPackage');
 
+  goToNewHotelsPage = () =>
+    this.props.navigation.navigate('NewHotelsPackage', {
+      cityId: 'aG90ZWxDaXR5Oi0zNzI0OTA=',
+      currency: 'EUR',
+      checkin: DateFormatter(DateUtils().addDays(30)).formatForMachine(),
+      checkout: DateFormatter(DateUtils().addDays(36)).formatForMachine(),
+      roomsConfiguration: [{ adultsCount: 1, children: [] }],
+    });
+
   goToOslo = () => {
     this.props.navigation.navigate('HotelsPackage', {
       coordinates: {
@@ -65,6 +74,12 @@ export default class Homepage extends React.Component<Props> {
   render = () => {
     return (
       <LayoutSingleColumn>
+        <Section>
+          <TextButton
+            title={<Translation passThrough="New hotels" />}
+            onPress={this.goToNewHotelsPage}
+          />
+        </Section>
         <Section>
           <TextButton
             title={<Translation passThrough="Hotels" />}
diff --git a/app/core/src/screens/hotelsStack/NewHotelsPackageWrapper.js b/app/core/src/screens/hotelsStack/NewHotelsPackageWrapper.js
new file mode 100644
index 00000000..3550b8ee
--- /dev/null
+++ b/app/core/src/screens/hotelsStack/NewHotelsPackageWrapper.js
@@ -0,0 +1,51 @@
+// @flow
+
+import * as React from 'react';
+import { NewHotelsStandAlonePackage } from '@kiwicom/react-native-app-hotels';
+import { type NavigationType } from '@kiwicom/mobile-navigation';
+import { type DimensionType } from '@kiwicom/mobile-shared';
+
+import Config from '../../../config/application';
+import type { RoomConfigurationType } from '../../../../hotels/src/HotelsContext';
+
+type Props = {|
+  +navigation: NavigationType,
+  +coordinates: null | {|
+    +latitude: number,
+    +longitude: number,
+  |},
+  +checkin: string,
+  +checkout: string,
+  +dimensions: DimensionType,
+  +cityId: string,
+  +roomsConfiguration: RoomConfigurationType,
+|};
+
+export default class HotelsPackageWrapper extends React.Component<Props> {
+  static navigationOptions = {
+    header: null,
+  };
+
+  goToHomepage = () => this.props.navigation.goBack();
+
+  render = () => {
+    const affiliate = String(Config.affiliate.bookingCom);
+
+    return (
+      <NewHotelsStandAlonePackage
+        bookingComAffiliate={affiliate}
+        language="en"
+        currency="EUR" // Only EUR is now fully supported as PriceFilter can't handle anything but EUR
+        onBackClicked={this.goToHomepage}
+        dataSaverEnabled={false}
+        coordinates={this.props.coordinates}
+        checkin={this.props.checkin}
+        checkout={this.props.checkout}
+        dimensions={this.props.dimensions}
+        cityId={this.props.cityId}
+        roomsConfiguration={this.props.roomsConfiguration}
+        version="rn-development"
+      />
+    );
+  };
+}
diff --git a/app/hotels/index.js b/app/hotels/index.js
index ef5d0b38..10a66b72 100644
--- a/app/hotels/index.js
+++ b/app/hotels/index.js
@@ -4,11 +4,17 @@ import { AppRegistry } from 'react-native';
 
 import HotelsStandalonePackage from './src/appRegistry/HotelsStandalonePackage';
 import SingleHotelStandalonePackage from './src/appRegistry/SingleHotelStandalonePackage';
+import NewHotelsStandAlonePackage from './src/appRegistry/NewHotelsStandalonePackage';
 
 AppRegistry.registerComponent('KiwiHotels', () => HotelsStandalonePackage);
+AppRegistry.registerComponent('NewKiwiHotels', () => HotelsStandalonePackage);
 AppRegistry.registerComponent(
   'SingleHotel',
   () => SingleHotelStandalonePackage,
 );
 
-export { SingleHotelStandalonePackage, HotelsStandalonePackage };
+export {
+  SingleHotelStandalonePackage,
+  HotelsStandalonePackage,
+  NewHotelsStandAlonePackage,
+};
diff --git a/app/hotels/src/HotelsContext.js b/app/hotels/src/HotelsContext.js
index a5262433..da8efc8a 100644
--- a/app/hotels/src/HotelsContext.js
+++ b/app/hotels/src/HotelsContext.js
@@ -4,27 +4,67 @@ import * as React from 'react';
 
 const defaultState = {
   version: '',
+  cityId: null,
+  checkin: null,
+  checkout: null,
+  roomsConfiguration: null,
+  currency: '',
 };
 
 const { Consumer, Provider: ContextProvider } = React.createContext({
   ...defaultState,
 });
 
+export type RoomConfigurationType = {|
+  +adultsCount: number,
+  +children: $ReadOnlyArray<{|
+    +age: number,
+  |}>,
+|};
+
 type Props = {|
   +children: React.Node,
   +version: string,
+  +cityId: ?string,
+  +checkin: ?string,
+  +checkout: ?string,
+  +roomsConfiguration: ?RoomConfigurationType,
+  +currency: string,
 |};
 
 type State = {|
   +version: string,
+  +cityId: string | null,
+  +checkin: Date | null,
+  +checkout: Date | null,
+  +roomsConfiguration: RoomConfigurationType | null,
+  +currency: string,
 |};
 
+const validateDate = (input: string): boolean => {
+  const reg = /^\d{4}-\d{2}-\d{2}$/;
+  return reg.test(input);
+};
+
+export const getAsUtcDate = (input: ?string): Date | null => {
+  if (input == null || !validateDate(input)) {
+    return null;
+  }
+  const [year, month, date] = input.split('-').map(item => parseInt(item));
+  return new Date(Date.UTC(year, month - 1, date));
+};
+
 class Provider extends React.Component<Props, State> {
   constructor(props: Props) {
     super(props);
 
     this.state = {
       version: props.version,
+      cityId: props.cityId || null,
+      checkin: getAsUtcDate(props.checkin),
+      checkout: getAsUtcDate(props.checkout),
+      roomsConfiguration: props.roomsConfiguration || null,
+      currency: props.currency,
     };
   }
   render = () => (
diff --git a/app/hotels/src/allHotels/AllHotels.js b/app/hotels/src/allHotels/AllHotels.js
index 8b185af9..4e2e9815 100644
--- a/app/hotels/src/allHotels/AllHotels.js
+++ b/app/hotels/src/allHotels/AllHotels.js
@@ -103,7 +103,7 @@ export class AllHotels extends React.Component<PropsWithContext> {
             openLocationPicker={this.props.openLocationPicker}
             openGuestsModal={this.props.openGuestsModal}
           />
-          <FilterStripe currency={this.props.currency} />
+          <FilterStripe />
           {canRenderAllHotelsSearch ? (
             <AllHotelsSearch
               coordinates={coordinates}
diff --git a/app/hotels/src/allHotels/NewAllHotels.js b/app/hotels/src/allHotels/NewAllHotels.js
new file mode 100644
index 00000000..154a538e
--- /dev/null
+++ b/app/hotels/src/allHotels/NewAllHotels.js
@@ -0,0 +1,27 @@
+// @flow strict
+
+import * as React from 'react';
+import { ScrollView } from 'react-native';
+import { StyleSheet } from '@kiwicom/mobile-shared';
+
+import FilterStripe from '../filter/FilterStripe';
+import NewAllHotelsSearch from './NewAllHotelsSearch';
+
+export default function NewAllHotels() {
+  return (
+    <ScrollView
+      bounces={false}
+      contentContainerStyle={styles.scrollViewContainer}
+    >
+      <FilterStripe />
+      <NewAllHotelsSearch />
+    </ScrollView>
+  );
+}
+
+const styles = StyleSheet.create({
+  scrollViewContainer: {
+    flexGrow: 1,
+    paddingBottom: 44,
+  },
+});
diff --git a/app/hotels/src/allHotels/NewAllHotelsSearch.js b/app/hotels/src/allHotels/NewAllHotelsSearch.js
new file mode 100644
index 00000000..f590ed36
--- /dev/null
+++ b/app/hotels/src/allHotels/NewAllHotelsSearch.js
@@ -0,0 +1,104 @@
+// @flow
+
+import * as React from 'react';
+import { graphql, PublicApiRenderer } from '@kiwicom/mobile-relay';
+import { DateFormatter } from '@kiwicom/mobile-localization';
+import {
+  withNavigation,
+  type NavigationType,
+} from '@kiwicom/mobile-navigation';
+
+import HotelsFilterContext from '../HotelsFilterContext';
+import {
+  type RoomConfigurationType,
+  withHotelsContext,
+} from '../HotelsContext';
+import AllHotelsSearchList from './AllHotelsSearchList';
+import { sanitizeHotelFacilities } from '../GraphQLSanitizers';
+import type { NewAllHotelsSearchQueryResponse } from './__generated__/NewAllHotelsSearchQuery.graphql';
+
+type Props = {|
+  +navigation: NavigationType,
+  +checkin: Date | null,
+  +checkout: Date | null,
+  +currency: string,
+  +roomsConfiguration: RoomConfigurationType | null,
+  +cityId: string | null,
+|};
+
+class NewAllHotelsSearch extends React.Component<Props> {
+  openSingleHotel = (hotelId: string) => {
+    this.props.navigation.navigate('SingleHotel', {
+      hotelId,
+      checkin: this.props.checkin,
+      checkout: this.props.checkout,
+      roomsConfiguration: this.props.roomsConfiguration,
+    });
+  };
+
+  renderAllHotelsSearchList = (
+    propsFromRenderer: NewAllHotelsSearchQueryResponse,
+  ) => {
+    return (
+      <AllHotelsSearchList
+        data={propsFromRenderer}
+        openSingleHotel={this.openSingleHotel}
+      />
+    );
+  };
+
+  render = () => {
+    const {
+      cityId,
+      checkin,
+      checkout,
+      roomsConfiguration,
+      currency,
+    } = this.props;
+
+    if (checkin === null || checkout === null) {
+      // TODO: Show error
+      return null;
+    }
+    return (
+      <HotelsFilterContext.Consumer>
+        {({ filterParams }) => (
+          <PublicApiRenderer
+            query={graphql`
+              query NewAllHotelsSearchQuery(
+                $search: HotelsSearchInput!
+                $filter: HotelsFilterInput!
+                $options: AvailableHotelOptionsInput
+                $first: Int
+                $after: String
+              ) {
+                ...AllHotelsSearchList_data
+              }
+            `}
+            variables={{
+              search: {
+                cityId,
+                checkin: DateFormatter(checkin).formatForMachine(),
+                checkout: DateFormatter(checkout).formatForMachine(),
+                roomsConfiguration,
+              },
+              filter: {
+                ...filterParams,
+                hotelFacilities: sanitizeHotelFacilities(
+                  filterParams.hotelFacilities,
+                ),
+              },
+              first: 50,
+              options: {
+                currency,
+              },
+            }}
+            render={this.renderAllHotelsSearchList}
+          />
+        )}
+      </HotelsFilterContext.Consumer>
+    );
+  };
+}
+
+export default withNavigation(withHotelsContext(NewAllHotelsSearch));
diff --git a/app/hotels/src/allHotels/__generated__/NewAllHotelsSearchQuery.graphql.js b/app/hotels/src/allHotels/__generated__/NewAllHotelsSearchQuery.graphql.js
new file mode 100644
index 00000000..6910a59a
--- /dev/null
+++ b/app/hotels/src/allHotels/__generated__/NewAllHotelsSearchQuery.graphql.js
@@ -0,0 +1,513 @@
+/**
+ * @flow
+ * @relayHash c3be4a1851529f8ddca18fbef76b8ccc
+ */
+
+/* eslint-disable */
+
+'use strict';
+
+/*::
+import type { ConcreteRequest } from 'relay-runtime';
+type AllHotelsSearchList_data$ref = any;
+export type Currency = "AED" | "AFN" | "ALL" | "AMD" | "ANG" | "AOA" | "ARS" | "AUD" | "AWG" | "AZN" | "BAM" | "BBD" | "BDT" | "BGN" | "BHD" | "BIF" | "BMD" | "BND" | "BOB" | "BRL" | "BSD" | "BTC" | "BTN" | "BWP" | "BYN" | "BYR" | "BZD" | "CAD" | "CDF" | "CHF" | "CLF" | "CLP" | "CNY" | "COP" | "CRC" | "CUC" | "CUP" | "CVE" | "CZK" | "DJF" | "DKK" | "DOP" | "DZD" | "EEK" | "EGP" | "ERN" | "ETB" | "EUR" | "FJD" | "FKP" | "GBP" | "GEL" | "GGP" | "GHS" | "GIP" | "GMD" | "GNF" | "GTQ" | "GYD" | "HKD" | "HNL" | "HRK" | "HTG" | "HUF" | "IDR" | "ILS" | "IMP" | "INR" | "IQD" | "IRR" | "ISK" | "JEP" | "JMD" | "JOD" | "JPY" | "KES" | "KGS" | "KHR" | "KMF" | "KPW" | "KRW" | "KWD" | "KYD" | "KZT" | "LAK" | "LBP" | "LKR" | "LRD" | "LSL" | "LTL" | "LVL" | "LYD" | "MAD" | "MDL" | "MGA" | "MKD" | "MMK" | "MNT" | "MOP" | "MRO" | "MTL" | "MUR" | "MVR" | "MWK" | "MXN" | "MYR" | "MZN" | "NAD" | "NGN" | "NIO" | "NOK" | "NPR" | "NZD" | "OMR" | "PAB" | "PEN" | "PGK" | "PHP" | "PKR" | "PLN" | "PYG" | "QAR" | "QUN" | "RON" | "RSD" | "RUB" | "RWF" | "SAR" | "SBD" | "SCR" | "SDG" | "SEK" | "SGD" | "SHP" | "SLL" | "SOS" | "SRD" | "STD" | "SVC" | "SYP" | "SZL" | "THB" | "TJS" | "TMT" | "TND" | "TOP" | "TRY" | "TTD" | "TWD" | "TZS" | "UAH" | "UGX" | "USD" | "UYU" | "UZS" | "VEF" | "VND" | "VUV" | "WST" | "XAF" | "XAG" | "XAU" | "XCD" | "XDR" | "XOF" | "XPD" | "XPF" | "XPT" | "YER" | "ZAR" | "ZMK" | "ZMW" | "ZWL" | "%future added value";
+export type Language = "ar" | "bg" | "ca" | "cs" | "da" | "de" | "el" | "en" | "engb" | "enus" | "es" | "esar" | "et" | "fi" | "fr" | "he" | "hr" | "hu" | "id" | "is" | "it" | "ja" | "ko" | "lt" | "lv" | "ms" | "nl" | "no" | "pl" | "pt" | "ptbr" | "ptpt" | "ro" | "ru" | "sk" | "sl" | "sr" | "sv" | "th" | "tl" | "tr" | "uk" | "vi" | "zh" | "zhcn" | "zhtw" | "%future added value";
+export type HotelsSearchInput = {
+  latitude?: ?number,
+  longitude?: ?number,
+  cityId?: ?string,
+  checkin: any,
+  checkout: any,
+  language?: ?Language,
+  roomsConfiguration: $ReadOnlyArray<RoomsConfiguration>,
+};
+export type RoomsConfiguration = {
+  adultsCount: number,
+  children?: ?$ReadOnlyArray<?RoomsChildrenConfiguration>,
+};
+export type RoomsChildrenConfiguration = {
+  age?: ?number
+};
+export type HotelsFilterInput = {
+  starsRating?: ?$ReadOnlyArray<?number>,
+  minPrice?: ?number,
+  maxPrice?: ?number,
+  hotelFacilities?: ?HotelFacilitiesInput,
+  minScore?: ?number,
+  freeCancellation?: ?boolean,
+};
+export type HotelFacilitiesInput = {
+  airportShuttle?: ?boolean,
+  familyRooms?: ?boolean,
+  facilitiesForDisabled?: ?boolean,
+  fitnessCenter?: ?boolean,
+  parking?: ?boolean,
+  freeParking?: ?boolean,
+  valetParking?: ?boolean,
+  indoorPool?: ?boolean,
+  petsAllowed?: ?boolean,
+  spa?: ?boolean,
+  wifi?: ?boolean,
+};
+export type AvailableHotelOptionsInput = {
+  currency?: ?Currency
+};
+export type NewAllHotelsSearchQueryVariables = {|
+  search: HotelsSearchInput,
+  filter: HotelsFilterInput,
+  options?: ?AvailableHotelOptionsInput,
+  first?: ?number,
+  after?: ?string,
+|};
+export type NewAllHotelsSearchQueryResponse = {|
+  +$fragmentRefs: AllHotelsSearchList_data$ref
+|};
+*/
+
+
+/*
+query NewAllHotelsSearchQuery(
+  $search: HotelsSearchInput!
+  $filter: HotelsFilterInput!
+  $options: AvailableHotelOptionsInput
+  $first: Int
+  $after: String
+) {
+  ...AllHotelsSearchList_data
+}
+
+fragment AllHotelsSearchList_data on RootQuery {
+  allAvailableHotels(search: $search, filter: $filter, options: $options, first: $first, after: $after) {
+    pageInfo {
+      hasNextPage
+      hasPreviousPage
+      startCursor
+      endCursor
+    }
+    edges {
+      node {
+        id
+        ...AllHotelsSearchRow
+        __typename
+      }
+      cursor
+    }
+    stats {
+      priceMax
+      priceMin
+    }
+    cityName
+  }
+}
+
+fragment AllHotelsSearchRow on HotelAvailability {
+  ...HotelTitle
+  hotel {
+    id
+    mainPhoto {
+      lowResUrl
+      id
+    }
+    ...HotelReviewScore_hotel
+  }
+}
+
+fragment HotelTitle on HotelAvailability {
+  price {
+    amount
+    currency
+  }
+  hotel {
+    ...HotelDistance_hotel
+    name
+    rating {
+      stars
+    }
+    id
+  }
+}
+
+fragment HotelReviewScore_hotel on Hotel {
+  review {
+    score
+  }
+}
+
+fragment HotelDistance_hotel on Hotel {
+  distanceFromCenter
+}
+*/
+
+const node/*: ConcreteRequest*/ = (function(){
+var v0 = [
+  {
+    "kind": "LocalArgument",
+    "name": "search",
+    "type": "HotelsSearchInput!",
+    "defaultValue": null
+  },
+  {
+    "kind": "LocalArgument",
+    "name": "filter",
+    "type": "HotelsFilterInput!",
+    "defaultValue": null
+  },
+  {
+    "kind": "LocalArgument",
+    "name": "options",
+    "type": "AvailableHotelOptionsInput",
+    "defaultValue": null
+  },
+  {
+    "kind": "LocalArgument",
+    "name": "first",
+    "type": "Int",
+    "defaultValue": null
+  },
+  {
+    "kind": "LocalArgument",
+    "name": "after",
+    "type": "String",
+    "defaultValue": null
+  }
+],
+v1 = {
+  "kind": "ScalarField",
+  "alias": null,
+  "name": "id",
+  "args": null,
+  "storageKey": null
+};
+return {
+  "kind": "Request",
+  "operationKind": "query",
+  "name": "NewAllHotelsSearchQuery",
+  "id": null,
+  "text": "query NewAllHotelsSearchQuery(\n  $search: HotelsSearchInput!\n  $filter: HotelsFilterInput!\n  $options: AvailableHotelOptionsInput\n  $first: Int\n  $after: String\n) {\n  ...AllHotelsSearchList_data\n}\n\nfragment AllHotelsSearchList_data on RootQuery {\n  allAvailableHotels(search: $search, filter: $filter, options: $options, first: $first, after: $after) {\n    pageInfo {\n      hasNextPage\n      hasPreviousPage\n      startCursor\n      endCursor\n    }\n    edges {\n      node {\n        id\n        ...AllHotelsSearchRow\n        __typename\n      }\n      cursor\n    }\n    stats {\n      priceMax\n      priceMin\n    }\n    cityName\n  }\n}\n\nfragment AllHotelsSearchRow on HotelAvailability {\n  ...HotelTitle\n  hotel {\n    id\n    mainPhoto {\n      lowResUrl\n      id\n    }\n    ...HotelReviewScore_hotel\n  }\n}\n\nfragment HotelTitle on HotelAvailability {\n  price {\n    amount\n    currency\n  }\n  hotel {\n    ...HotelDistance_hotel\n    name\n    rating {\n      stars\n    }\n    id\n  }\n}\n\nfragment HotelReviewScore_hotel on Hotel {\n  review {\n    score\n  }\n}\n\nfragment HotelDistance_hotel on Hotel {\n  distanceFromCenter\n}\n",
+  "metadata": {},
+  "fragment": {
+    "kind": "Fragment",
+    "name": "NewAllHotelsSearchQuery",
+    "type": "RootQuery",
+    "metadata": null,
+    "argumentDefinitions": v0,
+    "selections": [
+      {
+        "kind": "FragmentSpread",
+        "name": "AllHotelsSearchList_data",
+        "args": null
+      }
+    ]
+  },
+  "operation": {
+    "kind": "Operation",
+    "name": "NewAllHotelsSearchQuery",
+    "argumentDefinitions": v0,
+    "selections": [
+      {
+        "kind": "LinkedField",
+        "alias": null,
+        "name": "allAvailableHotels",
+        "storageKey": null,
+        "args": [
+          {
+            "kind": "Variable",
+            "name": "after",
+            "variableName": "after",
+            "type": "String"
+          },
+          {
+            "kind": "Variable",
+            "name": "filter",
+            "variableName": "filter",
+            "type": "HotelsFilterInput"
+          },
+          {
+            "kind": "Variable",
+            "name": "first",
+            "variableName": "first",
+            "type": "Int"
+          },
+          {
+            "kind": "Variable",
+            "name": "options",
+            "variableName": "options",
+            "type": "AvailableHotelOptionsInput"
+          },
+          {
+            "kind": "Variable",
+            "name": "search",
+            "variableName": "search",
+            "type": "HotelsSearchInput!"
+          }
+        ],
+        "concreteType": "HotelAvailabilityConnection",
+        "plural": false,
+        "selections": [
+          {
+            "kind": "LinkedField",
+            "alias": null,
+            "name": "pageInfo",
+            "storageKey": null,
+            "args": null,
+            "concreteType": "PageInfo",
+            "plural": false,
+            "selections": [
+              {
+                "kind": "ScalarField",
+                "alias": null,
+                "name": "hasNextPage",
+                "args": null,
+                "storageKey": null
+              },
+              {
+                "kind": "ScalarField",
+                "alias": null,
+                "name": "hasPreviousPage",
+                "args": null,
+                "storageKey": null
+              },
+              {
+                "kind": "ScalarField",
+                "alias": null,
+                "name": "startCursor",
+                "args": null,
+                "storageKey": null
+              },
+              {
+                "kind": "ScalarField",
+                "alias": null,
+                "name": "endCursor",
+                "args": null,
+                "storageKey": null
+              }
+            ]
+          },
+          {
+            "kind": "LinkedField",
+            "alias": null,
+            "name": "edges",
+            "storageKey": null,
+            "args": null,
+            "concreteType": "HotelAvailabilityEdge",
+            "plural": true,
+            "selections": [
+              {
+                "kind": "LinkedField",
+                "alias": null,
+                "name": "node",
+                "storageKey": null,
+                "args": null,
+                "concreteType": "HotelAvailability",
+                "plural": false,
+                "selections": [
+                  v1,
+                  {
+                    "kind": "LinkedField",
+                    "alias": null,
+                    "name": "price",
+                    "storageKey": null,
+                    "args": null,
+                    "concreteType": "Price",
+                    "plural": false,
+                    "selections": [
+                      {
+                        "kind": "ScalarField",
+                        "alias": null,
+                        "name": "amount",
+                        "args": null,
+                        "storageKey": null
+                      },
+                      {
+                        "kind": "ScalarField",
+                        "alias": null,
+                        "name": "currency",
+                        "args": null,
+                        "storageKey": null
+                      }
+                    ]
+                  },
+                  {
+                    "kind": "LinkedField",
+                    "alias": null,
+                    "name": "hotel",
+                    "storageKey": null,
+                    "args": null,
+                    "concreteType": "Hotel",
+                    "plural": false,
+                    "selections": [
+                      {
+                        "kind": "ScalarField",
+                        "alias": null,
+                        "name": "distanceFromCenter",
+                        "args": null,
+                        "storageKey": null
+                      },
+                      {
+                        "kind": "ScalarField",
+                        "alias": null,
+                        "name": "name",
+                        "args": null,
+                        "storageKey": null
+                      },
+                      {
+                        "kind": "LinkedField",
+                        "alias": null,
+                        "name": "rating",
+                        "storageKey": null,
+                        "args": null,
+                        "concreteType": "HotelRating",
+                        "plural": false,
+                        "selections": [
+                          {
+                            "kind": "ScalarField",
+                            "alias": null,
+                            "name": "stars",
+                            "args": null,
+                            "storageKey": null
+                          }
+                        ]
+                      },
+                      v1,
+                      {
+                        "kind": "LinkedField",
+                        "alias": null,
+                        "name": "mainPhoto",
+                        "storageKey": null,
+                        "args": null,
+                        "concreteType": "HotelPhoto",
+                        "plural": false,
+                        "selections": [
+                          {
+                            "kind": "ScalarField",
+                            "alias": null,
+                            "name": "lowResUrl",
+                            "args": null,
+                            "storageKey": null
+                          },
+                          v1
+                        ]
+                      },
+                      {
+                        "kind": "LinkedField",
+                        "alias": null,
+                        "name": "review",
+                        "storageKey": null,
+                        "args": null,
+                        "concreteType": "HotelReview",
+                        "plural": false,
+                        "selections": [
+                          {
+                            "kind": "ScalarField",
+                            "alias": null,
+                            "name": "score",
+                            "args": null,
+                            "storageKey": null
+                          }
+                        ]
+                      }
+                    ]
+                  },
+                  {
+                    "kind": "ScalarField",
+                    "alias": null,
+                    "name": "__typename",
+                    "args": null,
+                    "storageKey": null
+                  }
+                ]
+              },
+              {
+                "kind": "ScalarField",
+                "alias": null,
+                "name": "cursor",
+                "args": null,
+                "storageKey": null
+              }
+            ]
+          },
+          {
+            "kind": "LinkedField",
+            "alias": null,
+            "name": "stats",
+            "storageKey": null,
+            "args": null,
+            "concreteType": "HotelAvailabilityStats",
+            "plural": false,
+            "selections": [
+              {
+                "kind": "ScalarField",
+                "alias": null,
+                "name": "priceMax",
+                "args": null,
+                "storageKey": null
+              },
+              {
+                "kind": "ScalarField",
+                "alias": null,
+                "name": "priceMin",
+                "args": null,
+                "storageKey": null
+              }
+            ]
+          },
+          {
+            "kind": "ScalarField",
+            "alias": null,
+            "name": "cityName",
+            "args": null,
+            "storageKey": null
+          }
+        ]
+      },
+      {
+        "kind": "LinkedHandle",
+        "alias": null,
+        "name": "allAvailableHotels",
+        "args": [
+          {
+            "kind": "Variable",
+            "name": "after",
+            "variableName": "after",
+            "type": "String"
+          },
+          {
+            "kind": "Variable",
+            "name": "filter",
+            "variableName": "filter",
+            "type": "HotelsFilterInput"
+          },
+          {
+            "kind": "Variable",
+            "name": "first",
+            "variableName": "first",
+            "type": "Int"
+          },
+          {
+            "kind": "Variable",
+            "name": "options",
+            "variableName": "options",
+            "type": "AvailableHotelOptionsInput"
+          },
+          {
+            "kind": "Variable",
+            "name": "search",
+            "variableName": "search",
+            "type": "HotelsSearchInput!"
+          }
+        ],
+        "handle": "connection",
+        "key": "AllHotels_allAvailableHotels",
+        "filters": [
+          "search",
+          "filter",
+          "options"
+        ]
+      }
+    ]
+  }
+};
+})();
+// prettier-ignore
+(node/*: any*/).hash = '36f2eee87902e7e54f3e59be1cb00aee';
+module.exports = node;
diff --git a/app/hotels/src/appRegistry/HotelsStandalonePackage.js b/app/hotels/src/appRegistry/HotelsStandalonePackage.js
index 886ea155..47997624 100644
--- a/app/hotels/src/appRegistry/HotelsStandalonePackage.js
+++ b/app/hotels/src/appRegistry/HotelsStandalonePackage.js
@@ -49,6 +49,7 @@ class HotelsStandalonePackage extends React.Component<Props> {
         dimensions={this.props.dimensions}
         dataSaverEnabled={this.props.dataSaverEnabled}
         version={this.props.version}
+        currency={this.props.currency}
       >
         {this.renderInnerComponent()}
       </RootComponent>
diff --git a/app/hotels/src/appRegistry/NewHotelsStandalonePackage.js b/app/hotels/src/appRegistry/NewHotelsStandalonePackage.js
new file mode 100644
index 00000000..58903c45
--- /dev/null
+++ b/app/hotels/src/appRegistry/NewHotelsStandalonePackage.js
@@ -0,0 +1,56 @@
+// @flow strict
+
+import * as React from 'react';
+import {
+  WithNativeNavigation,
+  type DimensionType,
+} from '@kiwicom/mobile-shared';
+
+import RootComponent from './RootComponent';
+import NewHotelsStack from '../navigation/NewNavigationStack';
+import type { Coordinates } from '../CoordinatesType';
+import type { RoomConfigurationType } from '../HotelsContext';
+
+type Props = {
+  +bookingComAffiliate: string,
+  +language: string,
+  +currency: string,
+  +dataSaverEnabled: boolean,
+  +coordinates: Coordinates | null,
+  +checkin?: string,
+  +checkout?: string,
+  +onNavigationStateChange: () => void,
+  +onBackClicked: () => void,
+  +dimensions: DimensionType,
+  +version: string,
+  +cityId: string,
+  +checkin: string,
+  +checkout: string,
+  +roomsConfiguration: RoomConfigurationType,
+};
+
+class NewHotelsStandalonePackage extends React.Component<Props> {
+  render = () => (
+    <RootComponent
+      dimensions={this.props.dimensions}
+      dataSaverEnabled={this.props.dataSaverEnabled}
+      version={this.props.version}
+      cityId={this.props.cityId}
+      checkin={this.props.checkin}
+      checkout={this.props.checkout}
+      currency={this.props.currency}
+      roomsConfiguration={this.props.roomsConfiguration}
+    >
+      <NewHotelsStack
+        screenProps={this.props}
+        onBackClicked={this.props.onBackClicked}
+        onNavigationStateChange={this.props.onNavigationStateChange}
+      />
+    </RootComponent>
+  );
+}
+
+export default WithNativeNavigation(
+  NewHotelsStandalonePackage,
+  'NewKiwiHotels',
+);
diff --git a/app/hotels/src/appRegistry/RootComponent.js b/app/hotels/src/appRegistry/RootComponent.js
index bfd73e63..b7d2da2a 100644
--- a/app/hotels/src/appRegistry/RootComponent.js
+++ b/app/hotels/src/appRegistry/RootComponent.js
@@ -10,13 +10,18 @@ import {
 
 import HotelsSearchContext from '../HotelsSearchContext';
 import HotelsFilterContext from '../HotelsFilterContext';
-import HotelsContext from '../HotelsContext';
+import HotelsContext, { type RoomConfigurationType } from '../HotelsContext';
 
 type Props = {|
   +dataSaverEnabled: boolean,
   +children: React.Node,
   +dimensions: DimensionType,
   +version: string,
+  +cityId?: string,
+  +checkin?: string,
+  +checkout?: string,
+  +roomsConfiguration?: RoomConfigurationType,
+  +currency: string,
 |};
 
 export default class RootComponent extends React.Component<Props> {
@@ -25,7 +30,14 @@ export default class RootComponent extends React.Component<Props> {
       <HotelsSearchContext.Provider>
         <HotelsFilterContext.Provider>
           <GeolocationContext.Provider>
-            <HotelsContext.Provider version={this.props.version}>
+            <HotelsContext.Provider
+              version={this.props.version}
+              cityId={this.props.cityId}
+              checkin={this.props.checkin}
+              checkout={this.props.checkout}
+              roomsConfiguration={this.props.roomsConfiguration}
+              currency={this.props.currency}
+            >
               <Dimensions.Provider dimensions={this.props.dimensions}>
                 {this.props.children}
               </Dimensions.Provider>
diff --git a/app/hotels/src/appRegistry/SingleHotelStandalonePackage.js b/app/hotels/src/appRegistry/SingleHotelStandalonePackage.js
index 439a3acb..fc68bc85 100644
--- a/app/hotels/src/appRegistry/SingleHotelStandalonePackage.js
+++ b/app/hotels/src/appRegistry/SingleHotelStandalonePackage.js
@@ -50,6 +50,7 @@ class SingleHotelStandAlonePackage extends React.Component<Props> {
         dimensions={this.props.dimensions}
         dataSaverEnabled={this.props.dataSaverEnabled}
         version={this.props.version}
+        currency={this.props.currency}
       >
         {this.renderInnerComponent()}
       </RootComponent>
diff --git a/app/hotels/src/filter/FilterStripe.js b/app/hotels/src/filter/FilterStripe.js
index 73c799a5..6aca9428 100644
--- a/app/hotels/src/filter/FilterStripe.js
+++ b/app/hotels/src/filter/FilterStripe.js
@@ -4,6 +4,7 @@ import * as React from 'react';
 import { ScrollView, View } from 'react-native';
 import { StyleSheet } from '@kiwicom/mobile-shared';
 
+import HotelsContext from '../HotelsContext';
 import StarsFilter from './stars/StarsFilter';
 import PriceFilter from './price/PriceFilter';
 import FreeCancellationFilter from './freeCancellation/FreeCancellationFilter';
@@ -18,7 +19,7 @@ import HotelsFilterContext from '../HotelsFilterContext';
 import Filters from './Filters';
 
 type PropsWithContext = {|
-  ...Props,
+  +currency: string,
   +activeFilters: ActiveFilters,
   +onChange: OnChangeFilterParams => void,
   +filter: FilterParams,
@@ -104,21 +105,21 @@ const styles = StyleSheet.create({
   },
 });
 
-type Props = {|
-  +currency: string,
-|};
-
-export default function FilterStripeWithContext(props: Props) {
+export default function FilterStripeWithContext() {
   return (
-    <HotelsFilterContext.Consumer>
-      {({ activeFilters, filterParams, actions: { setFilter } }) => (
-        <FilterStripe
-          {...props}
-          onChange={setFilter}
-          filter={filterParams}
-          activeFilters={activeFilters}
-        />
+    <HotelsContext.Consumer>
+      {({ currency }) => (
+        <HotelsFilterContext.Consumer>
+          {({ activeFilters, filterParams, actions: { setFilter } }) => (
+            <FilterStripe
+              currency={currency}
+              onChange={setFilter}
+              filter={filterParams}
+              activeFilters={activeFilters}
+            />
+          )}
+        </HotelsFilterContext.Consumer>
       )}
-    </HotelsFilterContext.Consumer>
+    </HotelsContext.Consumer>
   );
 }
diff --git a/app/hotels/src/map/allHotels/AllHotelsMap.js b/app/hotels/src/map/allHotels/AllHotelsMap.js
index 005d48f8..30f3c6c0 100644
--- a/app/hotels/src/map/allHotels/AllHotelsMap.js
+++ b/app/hotels/src/map/allHotels/AllHotelsMap.js
@@ -106,9 +106,7 @@ class AllHotelsMap extends React.Component<PropsWithContext> {
         onStateChange={this.validateCheckinDate}
       >
         <View style={styles.container}>
-          <AdaptableLayout
-            renderOnNarrow={<FilterStripe currency={currency} />}
-          />
+          <AdaptableLayout renderOnNarrow={<FilterStripe />} />
           {canSearch ? (
             <PublicApiRenderer
               query={graphql`
diff --git a/app/hotels/src/map/allHotels/NewAllHotelsMap.js b/app/hotels/src/map/allHotels/NewAllHotelsMap.js
new file mode 100644
index 00000000..ba145c6b
--- /dev/null
+++ b/app/hotels/src/map/allHotels/NewAllHotelsMap.js
@@ -0,0 +1,110 @@
+// @flow strict
+
+import * as React from 'react';
+import { View } from 'react-native';
+import { graphql, PublicApiRenderer } from '@kiwicom/mobile-relay';
+import { DateFormatter } from '@kiwicom/mobile-localization';
+import { StyleSheet, AdaptableLayout } from '@kiwicom/mobile-shared';
+import type { NavigationType } from '@kiwicom/mobile-navigation';
+
+import FilterStripe from '../../filter/FilterStripe';
+import {
+  withHotelsContext,
+  type RoomConfigurationType,
+} from '../../HotelsContext';
+import HotelsFilterContext from '../../HotelsFilterContext';
+import MapScreen from './MapScreen';
+import { sanitizeHotelFacilities } from '../../GraphQLSanitizers';
+import type { NewAllHotelsMapQueryResponse } from './__generated__/NewAllHotelsMapQuery.graphql';
+
+type Props = {|
+  +cityId: string,
+  +checkin: Date | null,
+  +checkout: Date | null,
+  +currency: string,
+  +roomsConfiguration: RoomConfigurationType,
+  +navigation: NavigationType,
+|};
+
+class NewAllHotelsMap extends React.Component<Props> {
+  openSingleHotel = (hotelId: string) => {
+    this.props.navigation.navigate('SingleHotel', {
+      hotelId,
+      checkin: this.props.checkin,
+      checkout: this.props.checkout,
+      roomsConfiguration: this.props.roomsConfiguration,
+    });
+  };
+
+  renderInnerComponent = (props: NewAllHotelsMapQueryResponse) => (
+    <MapScreen
+      data={props.allAvailableHotels}
+      onOpenSingleHotel={this.openSingleHotel}
+    />
+  );
+
+  render = () => {
+    const {
+      checkin,
+      checkout,
+      cityId,
+      currency,
+      roomsConfiguration,
+    } = this.props;
+    if (checkin === null || checkout === null) {
+      return null;
+    }
+    return (
+      <HotelsFilterContext.Consumer>
+        {({ filterParams }) => (
+          <View style={styles.container}>
+            <AdaptableLayout renderOnNarrow={<FilterStripe />} />
+            <PublicApiRenderer
+              query={graphql`
+                query NewAllHotelsMapQuery(
+                  $search: HotelsSearchInput!
+                  $filter: HotelsFilterInput
+                  $options: AvailableHotelOptionsInput
+                ) {
+                  allAvailableHotels(
+                    search: $search
+                    filter: $filter
+                    options: $options
+                  ) {
+                    ...MapScreen
+                  }
+                }
+              `}
+              variables={{
+                search: {
+                  cityId,
+                  roomsConfiguration,
+                  checkin: DateFormatter(checkin).formatForMachine(),
+                  checkout: DateFormatter(checkout).formatForMachine(),
+                },
+                filter: {
+                  ...filterParams,
+                  hotelFacilities: sanitizeHotelFacilities(
+                    filterParams.hotelFacilities,
+                  ),
+                },
+                options: {
+                  currency,
+                },
+              }}
+              render={this.renderInnerComponent}
+            />
+          </View>
+        )}
+      </HotelsFilterContext.Consumer>
+    );
+  };
+}
+
+const styles = StyleSheet.create({
+  container: {
+    ...StyleSheet.absoluteFillObject,
+  },
+});
+
+export default withHotelsContext(NewAllHotelsMap);
diff --git a/app/hotels/src/map/allHotels/__generated__/NewAllHotelsMapQuery.graphql.js b/app/hotels/src/map/allHotels/__generated__/NewAllHotelsMapQuery.graphql.js
new file mode 100644
index 00000000..52ac6eb4
--- /dev/null
+++ b/app/hotels/src/map/allHotels/__generated__/NewAllHotelsMapQuery.graphql.js
@@ -0,0 +1,434 @@
+/**
+ * @flow
+ * @relayHash 8fe3694629986a106be2b7d3ba9e87d1
+ */
+
+/* eslint-disable */
+
+'use strict';
+
+/*::
+import type { ConcreteRequest } from 'relay-runtime';
+type MapScreen$ref = any;
+export type Currency = "AED" | "AFN" | "ALL" | "AMD" | "ANG" | "AOA" | "ARS" | "AUD" | "AWG" | "AZN" | "BAM" | "BBD" | "BDT" | "BGN" | "BHD" | "BIF" | "BMD" | "BND" | "BOB" | "BRL" | "BSD" | "BTC" | "BTN" | "BWP" | "BYN" | "BYR" | "BZD" | "CAD" | "CDF" | "CHF" | "CLF" | "CLP" | "CNY" | "COP" | "CRC" | "CUC" | "CUP" | "CVE" | "CZK" | "DJF" | "DKK" | "DOP" | "DZD" | "EEK" | "EGP" | "ERN" | "ETB" | "EUR" | "FJD" | "FKP" | "GBP" | "GEL" | "GGP" | "GHS" | "GIP" | "GMD" | "GNF" | "GTQ" | "GYD" | "HKD" | "HNL" | "HRK" | "HTG" | "HUF" | "IDR" | "ILS" | "IMP" | "INR" | "IQD" | "IRR" | "ISK" | "JEP" | "JMD" | "JOD" | "JPY" | "KES" | "KGS" | "KHR" | "KMF" | "KPW" | "KRW" | "KWD" | "KYD" | "KZT" | "LAK" | "LBP" | "LKR" | "LRD" | "LSL" | "LTL" | "LVL" | "LYD" | "MAD" | "MDL" | "MGA" | "MKD" | "MMK" | "MNT" | "MOP" | "MRO" | "MTL" | "MUR" | "MVR" | "MWK" | "MXN" | "MYR" | "MZN" | "NAD" | "NGN" | "NIO" | "NOK" | "NPR" | "NZD" | "OMR" | "PAB" | "PEN" | "PGK" | "PHP" | "PKR" | "PLN" | "PYG" | "QAR" | "QUN" | "RON" | "RSD" | "RUB" | "RWF" | "SAR" | "SBD" | "SCR" | "SDG" | "SEK" | "SGD" | "SHP" | "SLL" | "SOS" | "SRD" | "STD" | "SVC" | "SYP" | "SZL" | "THB" | "TJS" | "TMT" | "TND" | "TOP" | "TRY" | "TTD" | "TWD" | "TZS" | "UAH" | "UGX" | "USD" | "UYU" | "UZS" | "VEF" | "VND" | "VUV" | "WST" | "XAF" | "XAG" | "XAU" | "XCD" | "XDR" | "XOF" | "XPD" | "XPF" | "XPT" | "YER" | "ZAR" | "ZMK" | "ZMW" | "ZWL" | "%future added value";
+export type Language = "ar" | "bg" | "ca" | "cs" | "da" | "de" | "el" | "en" | "engb" | "enus" | "es" | "esar" | "et" | "fi" | "fr" | "he" | "hr" | "hu" | "id" | "is" | "it" | "ja" | "ko" | "lt" | "lv" | "ms" | "nl" | "no" | "pl" | "pt" | "ptbr" | "ptpt" | "ro" | "ru" | "sk" | "sl" | "sr" | "sv" | "th" | "tl" | "tr" | "uk" | "vi" | "zh" | "zhcn" | "zhtw" | "%future added value";
+export type HotelsSearchInput = {
+  latitude?: ?number,
+  longitude?: ?number,
+  cityId?: ?string,
+  checkin: any,
+  checkout: any,
+  language?: ?Language,
+  roomsConfiguration: $ReadOnlyArray<RoomsConfiguration>,
+};
+export type RoomsConfiguration = {
+  adultsCount: number,
+  children?: ?$ReadOnlyArray<?RoomsChildrenConfiguration>,
+};
+export type RoomsChildrenConfiguration = {
+  age?: ?number
+};
+export type HotelsFilterInput = {
+  starsRating?: ?$ReadOnlyArray<?number>,
+  minPrice?: ?number,
+  maxPrice?: ?number,
+  hotelFacilities?: ?HotelFacilitiesInput,
+  minScore?: ?number,
+  freeCancellation?: ?boolean,
+};
+export type HotelFacilitiesInput = {
+  airportShuttle?: ?boolean,
+  familyRooms?: ?boolean,
+  facilitiesForDisabled?: ?boolean,
+  fitnessCenter?: ?boolean,
+  parking?: ?boolean,
+  freeParking?: ?boolean,
+  valetParking?: ?boolean,
+  indoorPool?: ?boolean,
+  petsAllowed?: ?boolean,
+  spa?: ?boolean,
+  wifi?: ?boolean,
+};
+export type AvailableHotelOptionsInput = {
+  currency?: ?Currency
+};
+export type NewAllHotelsMapQueryVariables = {|
+  search: HotelsSearchInput,
+  filter?: ?HotelsFilterInput,
+  options?: ?AvailableHotelOptionsInput,
+|};
+export type NewAllHotelsMapQueryResponse = {|
+  +allAvailableHotels: ?{|
+    +$fragmentRefs: MapScreen$ref
+  |}
+|};
+*/
+
+
+/*
+query NewAllHotelsMapQuery(
+  $search: HotelsSearchInput!
+  $filter: HotelsFilterInput
+  $options: AvailableHotelOptionsInput
+) {
+  allAvailableHotels(search: $search, filter: $filter, options: $options) {
+    ...MapScreen
+  }
+}
+
+fragment MapScreen on HotelAvailabilityConnection {
+  edges {
+    node {
+      id
+    }
+    ...MapView
+    ...HotelSwipeList
+  }
+}
+
+fragment MapView on HotelAvailabilityEdge {
+  node {
+    id
+    price {
+      ...PriceMarker
+    }
+    hotel {
+      coordinates {
+        lat
+        lng
+      }
+      id
+    }
+  }
+}
+
+fragment HotelSwipeList on HotelAvailabilityEdge {
+  node {
+    id
+    ...HotelSwipeItem
+    hotel {
+      address {
+        ...Address_address
+      }
+      id
+    }
+  }
+}
+
+fragment HotelSwipeItem on HotelAvailability {
+  ...HotelDetailPreview_availability
+  hotel {
+    id
+  }
+}
+
+fragment Address_address on Address {
+  street
+  city
+  zip
+}
+
+fragment HotelDetailPreview_availability on HotelAvailability {
+  price {
+    amount
+    currency
+  }
+  hotel {
+    id
+    name
+    mainPhoto {
+      thumbnailUrl
+      id
+    }
+    review {
+      score
+      description
+      count
+    }
+  }
+}
+
+fragment PriceMarker on Price {
+  amount
+  currency
+}
+*/
+
+const node/*: ConcreteRequest*/ = (function(){
+var v0 = [
+  {
+    "kind": "LocalArgument",
+    "name": "search",
+    "type": "HotelsSearchInput!",
+    "defaultValue": null
+  },
+  {
+    "kind": "LocalArgument",
+    "name": "filter",
+    "type": "HotelsFilterInput",
+    "defaultValue": null
+  },
+  {
+    "kind": "LocalArgument",
+    "name": "options",
+    "type": "AvailableHotelOptionsInput",
+    "defaultValue": null
+  }
+],
+v1 = [
+  {
+    "kind": "Variable",
+    "name": "filter",
+    "variableName": "filter",
+    "type": "HotelsFilterInput"
+  },
+  {
+    "kind": "Variable",
+    "name": "options",
+    "variableName": "options",
+    "type": "AvailableHotelOptionsInput"
+  },
+  {
+    "kind": "Variable",
+    "name": "search",
+    "variableName": "search",
+    "type": "HotelsSearchInput!"
+  }
+],
+v2 = {
+  "kind": "ScalarField",
+  "alias": null,
+  "name": "id",
+  "args": null,
+  "storageKey": null
+};
+return {
+  "kind": "Request",
+  "operationKind": "query",
+  "name": "NewAllHotelsMapQuery",
+  "id": null,
+  "text": "query NewAllHotelsMapQuery(\n  $search: HotelsSearchInput!\n  $filter: HotelsFilterInput\n  $options: AvailableHotelOptionsInput\n) {\n  allAvailableHotels(search: $search, filter: $filter, options: $options) {\n    ...MapScreen\n  }\n}\n\nfragment MapScreen on HotelAvailabilityConnection {\n  edges {\n    node {\n      id\n    }\n    ...MapView\n    ...HotelSwipeList\n  }\n}\n\nfragment MapView on HotelAvailabilityEdge {\n  node {\n    id\n    price {\n      ...PriceMarker\n    }\n    hotel {\n      coordinates {\n        lat\n        lng\n      }\n      id\n    }\n  }\n}\n\nfragment HotelSwipeList on HotelAvailabilityEdge {\n  node {\n    id\n    ...HotelSwipeItem\n    hotel {\n      address {\n        ...Address_address\n      }\n      id\n    }\n  }\n}\n\nfragment HotelSwipeItem on HotelAvailability {\n  ...HotelDetailPreview_availability\n  hotel {\n    id\n  }\n}\n\nfragment Address_address on Address {\n  street\n  city\n  zip\n}\n\nfragment HotelDetailPreview_availability on HotelAvailability {\n  price {\n    amount\n    currency\n  }\n  hotel {\n    id\n    name\n    mainPhoto {\n      thumbnailUrl\n      id\n    }\n    review {\n      score\n      description\n      count\n    }\n  }\n}\n\nfragment PriceMarker on Price {\n  amount\n  currency\n}\n",
+  "metadata": {},
+  "fragment": {
+    "kind": "Fragment",
+    "name": "NewAllHotelsMapQuery",
+    "type": "RootQuery",
+    "metadata": null,
+    "argumentDefinitions": v0,
+    "selections": [
+      {
+        "kind": "LinkedField",
+        "alias": null,
+        "name": "allAvailableHotels",
+        "storageKey": null,
+        "args": v1,
+        "concreteType": "HotelAvailabilityConnection",
+        "plural": false,
+        "selections": [
+          {
+            "kind": "FragmentSpread",
+            "name": "MapScreen",
+            "args": null
+          }
+        ]
+      }
+    ]
+  },
+  "operation": {
+    "kind": "Operation",
+    "name": "NewAllHotelsMapQuery",
+    "argumentDefinitions": v0,
+    "selections": [
+      {
+        "kind": "LinkedField",
+        "alias": null,
+        "name": "allAvailableHotels",
+        "storageKey": null,
+        "args": v1,
+        "concreteType": "HotelAvailabilityConnection",
+        "plural": false,
+        "selections": [
+          {
+            "kind": "LinkedField",
+            "alias": null,
+            "name": "edges",
+            "storageKey": null,
+            "args": null,
+            "concreteType": "HotelAvailabilityEdge",
+            "plural": true,
+            "selections": [
+              {
+                "kind": "LinkedField",
+                "alias": null,
+                "name": "node",
+                "storageKey": null,
+                "args": null,
+                "concreteType": "HotelAvailability",
+                "plural": false,
+                "selections": [
+                  v2,
+                  {
+                    "kind": "LinkedField",
+                    "alias": null,
+                    "name": "price",
+                    "storageKey": null,
+                    "args": null,
+                    "concreteType": "Price",
+                    "plural": false,
+                    "selections": [
+                      {
+                        "kind": "ScalarField",
+                        "alias": null,
+                        "name": "amount",
+                        "args": null,
+                        "storageKey": null
+                      },
+                      {
+                        "kind": "ScalarField",
+                        "alias": null,
+                        "name": "currency",
+                        "args": null,
+                        "storageKey": null
+                      }
+                    ]
+                  },
+                  {
+                    "kind": "LinkedField",
+                    "alias": null,
+                    "name": "hotel",
+                    "storageKey": null,
+                    "args": null,
+                    "concreteType": "Hotel",
+                    "plural": false,
+                    "selections": [
+                      {
+                        "kind": "LinkedField",
+                        "alias": null,
+                        "name": "coordinates",
+                        "storageKey": null,
+                        "args": null,
+                        "concreteType": "Coordinates",
+                        "plural": false,
+                        "selections": [
+                          {
+                            "kind": "ScalarField",
+                            "alias": null,
+                            "name": "lat",
+                            "args": null,
+                            "storageKey": null
+                          },
+                          {
+                            "kind": "ScalarField",
+                            "alias": null,
+                            "name": "lng",
+                            "args": null,
+                            "storageKey": null
+                          }
+                        ]
+                      },
+                      v2,
+                      {
+                        "kind": "ScalarField",
+                        "alias": null,
+                        "name": "name",
+                        "args": null,
+                        "storageKey": null
+                      },
+                      {
+                        "kind": "LinkedField",
+                        "alias": null,
+                        "name": "mainPhoto",
+                        "storageKey": null,
+                        "args": null,
+                        "concreteType": "HotelPhoto",
+                        "plural": false,
+                        "selections": [
+                          {
+                            "kind": "ScalarField",
+                            "alias": null,
+                            "name": "thumbnailUrl",
+                            "args": null,
+                            "storageKey": null
+                          },
+                          v2
+                        ]
+                      },
+                      {
+                        "kind": "LinkedField",
+                        "alias": null,
+                        "name": "review",
+                        "storageKey": null,
+                        "args": null,
+                        "concreteType": "HotelReview",
+                        "plural": false,
+                        "selections": [
+                          {
+                            "kind": "ScalarField",
+                            "alias": null,
+                            "name": "score",
+                            "args": null,
+                            "storageKey": null
+                          },
+                          {
+                            "kind": "ScalarField",
+                            "alias": null,
+                            "name": "description",
+                            "args": null,
+                            "storageKey": null
+                          },
+                          {
+                            "kind": "ScalarField",
+                            "alias": null,
+                            "name": "count",
+                            "args": null,
+                            "storageKey": null
+                          }
+                        ]
+                      },
+                      {
+                        "kind": "LinkedField",
+                        "alias": null,
+                        "name": "address",
+                        "storageKey": null,
+                        "args": null,
+                        "concreteType": "Address",
+                        "plural": false,
+                        "selections": [
+                          {
+                            "kind": "ScalarField",
+                            "alias": null,
+                            "name": "street",
+                            "args": null,
+                            "storageKey": null
+                          },
+                          {
+                            "kind": "ScalarField",
+                            "alias": null,
+                            "name": "city",
+                            "args": null,
+                            "storageKey": null
+                          },
+                          {
+                            "kind": "ScalarField",
+                            "alias": null,
+                            "name": "zip",
+                            "args": null,
+                            "storageKey": null
+                          }
+                        ]
+                      }
+                    ]
+                  }
+                ]
+              }
+            ]
+          }
+        ]
+      }
+    ]
+  }
+};
+})();
+// prettier-ignore
+(node/*: any*/).hash = '4100278bc2b770ac3c15545fa38c2cdb';
+module.exports = node;
diff --git a/app/hotels/src/navigation/NewNavigationStack.js b/app/hotels/src/navigation/NewNavigationStack.js
new file mode 100644
index 00000000..d3c6581a
--- /dev/null
+++ b/app/hotels/src/navigation/NewNavigationStack.js
@@ -0,0 +1,37 @@
+// @flow
+
+import {
+  StackNavigator,
+  StackNavigatorOptions,
+  type NavigationType,
+} from '@kiwicom/mobile-navigation';
+import { withMappedNavigationAndConfigProps as withMappedProps } from 'react-navigation-props-mapper';
+
+import SingleHotel from './singleHotel/SingleHotelNavigationScreen';
+import SearchResults from './allHotels/SearchResultsScreen';
+import AllHotelsMap from './allHotelsMap/AllHotelsMapNavigationScreen';
+
+export type NavigationProps = {|
+  navigation: NavigationType,
+  bookingComAffiliate: string,
+  language: string,
+  currency: string,
+|};
+
+export default StackNavigator(
+  {
+    SearchResults: {
+      screen: withMappedProps(SearchResults),
+    },
+    SingleHotel: {
+      screen: withMappedProps(SingleHotel),
+    },
+    AllHotelsMap: {
+      screen: withMappedProps(AllHotelsMap),
+    },
+  },
+  {
+    ...StackNavigatorOptions,
+    initialRouteName: 'SearchResults',
+  },
+);
diff --git a/app/hotels/src/navigation/allHotels/SearchResultsScreen.js b/app/hotels/src/navigation/allHotels/SearchResultsScreen.js
new file mode 100644
index 00000000..7c3a38d6
--- /dev/null
+++ b/app/hotels/src/navigation/allHotels/SearchResultsScreen.js
@@ -0,0 +1,77 @@
+// @flow strict
+
+import * as React from 'react';
+import { View } from 'react-native';
+import { HeaderTitle, type NavigationType } from '@kiwicom/mobile-navigation';
+import { Translation } from '@kiwicom/mobile-localization';
+import {
+  LayoutDoubleColumn,
+  AdaptableLayout,
+  Button,
+  Text,
+  StyleSheet,
+  Color,
+} from '@kiwicom/mobile-shared';
+
+import NewAllHotels from '../../allHotels/NewAllHotels';
+import NewAllHotelsMap from '../../map/allHotels/NewAllHotelsMap';
+import MapHeaderButton from './MapHeaderButton';
+
+type Props = {|
+  +navigation: NavigationType,
+  +onBackClicked: () => void,
+|};
+
+export default class SearchResultsScreen extends React.Component<Props> {
+  static navigationOptions = (props: Props) => {
+    function goToAllHotelsMap() {
+      props.navigation.navigate('AllHotelsMap');
+    }
+
+    return {
+      headerTitle: (
+        <HeaderTitle>
+          <Translation id="hotels.navigation.title.all_hotels" />
+        </HeaderTitle>
+      ),
+      headerRight: (
+        <AdaptableLayout
+          renderOnNarrow={<MapHeaderButton onPress={goToAllHotelsMap} />}
+        />
+      ),
+    };
+  };
+
+  render = () => (
+    <LayoutDoubleColumn
+      menuComponent={
+        <View style={styles.container}>
+          <NewAllHotels />
+          <Button onPress={this.props.onBackClicked} style={styles.button}>
+            <Text style={styles.text}>
+              <Translation id="shared.button.close" />
+            </Text>
+          </Button>
+        </View>
+      }
+      containerComponent={<NewAllHotelsMap />}
+    />
+  );
+}
+
+const styles = StyleSheet.create({
+  container: {
+    flex: 1,
+  },
+  button: {
+    position: 'absolute',
+    bottom: 8,
+    start: 8,
+    end: 8,
+    backgroundColor: Color.inputBackground,
+  },
+  text: {
+    fontWeight: '800',
+    fontSize: 16,
+  },
+});
diff --git a/ios/reactNativeApp/AppDelegate.m b/ios/reactNativeApp/AppDelegate.m
index 4a22338d..4f804fe1 100644
--- a/ios/reactNativeApp/AppDelegate.m
+++ b/ios/reactNativeApp/AppDelegate.m
@@ -31,6 +31,7 @@
   rootViewController.view = rootView;
   self.window.rootViewController = rootViewController;
   [self.window makeKeyAndVisible];
+  [self.window setTintColor:[UIColor colorWithRed: 0 green:169.0/255.0 blue:145.0/255.0 alpha:1]];
   return YES;
 }
 
diff --git a/packages/localization/src/Alert.js b/packages/localization/src/Alert.js
index 59116b8a..2092307c 100644
--- a/packages/localization/src/Alert.js
+++ b/packages/localization/src/Alert.js
@@ -1,6 +1,6 @@
 // @flow
 
-import { Alert as AlertNative } from 'react-native';
+import { Alert as AlertNative } from 'react-native'; // eslint-disable-line no-restricted-imports
 
 import { type TranslationKeys } from './DefaultVocabulary';
 import { type TranslationPromise } from './CancellableTranslation';
diff --git a/packages/navigation/types/Navigation.js b/packages/navigation/types/Navigation.js
index 95791a77..57baaabd 100644
--- a/packages/navigation/types/Navigation.js
+++ b/packages/navigation/types/Navigation.js
@@ -6,6 +6,7 @@ type NavigationStateParameters = Object;
 type CoreStackNavigatorRouteNames =
   | 'Homepage'
   | 'HotelsPackage'
+  | 'NewHotelsPackage'
   | 'SingleHotelPackage'
   | 'MMBPackage';
 


Test patch:
diff --git a/app/hotels/src/__tests__/HotelsContext.test.js b/app/hotels/src/__tests__/HotelsContext.test.js
new file mode 100644
index 00000000..80d4be5d
--- /dev/null
+++ b/app/hotels/src/__tests__/HotelsContext.test.js
@@ -0,0 +1,14 @@
+// @flow strict
+
+import { getAsUtcDate } from '../HotelsContext';
+
+describe('getAsUtcDate', () => {
+  it('should return null for invalid date string', () => {
+    expect(getAsUtcDate('١٨-٠١-٠ذ')).toBe(null);
+    expect(getAsUtcDate('2018-lol-01')).toBe(null);
+  });
+
+  it('should return the utc date for valid dates', () => {
+    expect(getAsUtcDate('2018-01-01')).toEqual(new Date(Date.UTC(2018, 0, 1)));
+  });
+});