iceholidays-frontend 0.4.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/stylesheets/iceholidays/frontend/actiontext.scss +119 -0
  3. data/app/assets/stylesheets/iceholidays/frontend/application.sass.scss +968 -355
  4. data/app/assets/stylesheets/iceholidays/frontend/common.scss +159 -74
  5. data/app/assets/stylesheets/iceholidays/frontend/layout.scss +218 -125
  6. data/app/assets/stylesheets/iceholidays/frontend/utils/_antd_overrides.scss +22 -7
  7. data/app/assets/stylesheets/iceholidays/frontend/utils/_variables.scss +2 -1
  8. data/app/assets/stylesheets/iceholidays/frontend/widgets/filter_pills.scss +19 -12
  9. data/app/assets/stylesheets/iceholidays/frontend/widgets/search_bar.scss +4 -0
  10. data/app/controllers/iceholidays/frontend/posts_controller.rb +14 -0
  11. data/app/javascript/api-services/agents-api.service.ts +33 -0
  12. data/app/javascript/api-services/locations-api.service.ts +23 -1
  13. data/app/javascript/api-services/series-api.service.ts +48 -28
  14. data/app/javascript/interfaces/agent.interface.ts +11 -0
  15. data/app/javascript/interfaces/country.interface.ts +4 -3
  16. data/app/javascript/interfaces/itinerary.interface.ts +101 -8
  17. data/app/javascript/react/App.tsx +1 -1
  18. data/app/javascript/react/components/Destinations.tsx +30 -20
  19. data/app/javascript/react/components/PriceDetails.tsx +146 -0
  20. data/app/javascript/react/components/shared/ContactAgentsForm.tsx +44 -0
  21. data/app/javascript/react/components/shared/Headline.tsx +2 -1
  22. data/app/javascript/react/components/shared/LocationDropdown.tsx +34 -0
  23. data/app/javascript/react/components/shared/{Postcard.tsx → LocationPostcards.tsx} +22 -1
  24. data/app/javascript/react/layouts/MainFooter.tsx +64 -39
  25. data/app/javascript/react/layouts/MainHeader.tsx +68 -30
  26. data/app/javascript/react/pages/AboutUsPage.tsx +8 -8
  27. data/app/javascript/react/pages/BlogPage.tsx +6 -4
  28. data/app/javascript/react/pages/ContactAgentsPage.tsx +174 -5
  29. data/app/javascript/react/pages/ContactUsPage.tsx +5 -5
  30. data/app/javascript/react/pages/CountriesPage.tsx +3 -8
  31. data/app/javascript/react/pages/Homepage.tsx +23 -13
  32. data/app/javascript/react/pages/ListingPage.tsx +197 -145
  33. data/app/javascript/react/pages/ShowPage.tsx +275 -265
  34. data/app/javascript/react/widgets/FilterPills.tsx +83 -49
  35. data/app/javascript/react/widgets/SearchBarWidget.tsx +24 -8
  36. data/app/views/iceholidays/frontend/posts/index.html.erb +9 -0
  37. data/app/views/iceholidays/frontend/posts/show.html.erb +2 -0
  38. data/config/routes.rb +2 -1
  39. data/lib/iceholidays/frontend/version.rb +1 -1
  40. data/public/iceholidays-assets/application.css +1209 -437
  41. data/public/iceholidays-assets/application.js +91 -104
  42. data/public/iceholidays-assets/application.js.map +4 -4
  43. data/public/iceholidays-assets/images/TSTRibbon.png +0 -0
  44. data/public/iceholidays-assets/images/about-us_logo_mobile.png +0 -0
  45. data/public/iceholidays-assets/images/destinations_logo.png +0 -0
  46. data/public/iceholidays-assets/images/footer-bg_mobile.png +0 -0
  47. data/public/iceholidays-assets/images/logo_mobile.png +0 -0
  48. metadata +19 -27
  49. data/public/iceholidays-assets/images/8D7N.png +0 -0
  50. data/public/iceholidays-assets/images/Frame71.png +0 -0
  51. data/public/iceholidays-assets/images/africa.png +0 -0
  52. data/public/iceholidays-assets/images/banner1.png +0 -0
  53. data/public/iceholidays-assets/images/banner2.png +0 -0
  54. data/public/iceholidays-assets/images/china.png +0 -0
  55. data/public/iceholidays-assets/images/china2.png +0 -0
  56. data/public/iceholidays-assets/images/chongqing.png +0 -0
  57. data/public/iceholidays-assets/images/guangzhou.png +0 -0
  58. data/public/iceholidays-assets/images/guilin.png +0 -0
  59. data/public/iceholidays-assets/images/harbin.png +0 -0
  60. data/public/iceholidays-assets/images/hongkong.png +0 -0
  61. data/public/iceholidays-assets/images/inner_mongolia.png +0 -0
  62. data/public/iceholidays-assets/images/jiangxi.png +0 -0
  63. data/public/iceholidays-assets/images/kenya.png +0 -0
  64. data/public/iceholidays-assets/images/kenya2.png +0 -0
  65. data/public/iceholidays-assets/images/kunming.png +0 -0
  66. data/public/iceholidays-assets/images/slikroad.png +0 -0
  67. data/public/iceholidays-assets/images/southafrica.png +0 -0
  68. data/public/iceholidays-assets/images/tanzania.png +0 -0
  69. data/public/iceholidays-assets/images/tour1.png +0 -0
  70. data/public/iceholidays-assets/images/uganda.png +0 -0
  71. /data/public/iceholidays-assets/images/{Group_71.png → about-us_logo.png} +0 -0
  72. /data/public/iceholidays-assets/images/{logo_container.png → logo.png} +0 -0
@@ -93,15 +93,30 @@ a{
93
93
  color: $primary-color;
94
94
  }
95
95
 
96
- .ant-select-outlined:not(.ant-select-disabled):not(.ant-select-customize-input):not(.ant-pagination-size-changer):hover .ant-select-selector{
97
- border-color: $primary-color;
96
+ .ant-select-dropdown .ant-select-item-option-active:not(.ant-select-item-option-disabled),
97
+ .ant-select-dropdown .ant-select-item-option-selected:not(.ant-select-item-option-disabled){
98
+ background-color: transparent;
99
+ color: $primary-color;
98
100
  }
99
101
 
100
- .ant-select-item-option-selected:not(.ant-select-item-option-disabled):has(.country-filter_option){
101
- color: $primary-color !important;
102
- background-color: #FFFFFF;
102
+ .ant-select-dropdown .ant-select-item{
103
+ color: #00000080;
103
104
  }
104
105
 
105
- .ant-select-item-option:not(.ant-select-item-option-selected):has(.country-filter_option){
106
- color: #00000080;
106
+ .ant-menu-light{
107
+ &.ant-menu-horizontal{
108
+
109
+ &>.ant-menu-item:hover,
110
+ &>.ant-menu-item-selected,
111
+ &>.ant-menu-item-active{
112
+
113
+ &::after{
114
+ display: none;
115
+ }
116
+ }
117
+ }
118
+
119
+ .ant-menu-item-selected{
120
+ background-color: transparent;
121
+ }
107
122
  }
@@ -1,3 +1,4 @@
1
1
  $font-default: Poppins, san-serif;
2
2
  $primary-color: #DCB062;
3
- $secondary-color: #F9E298;
3
+ $supportive-color: #5B4713;
4
+ $secondary-color: #F9E298;
@@ -17,22 +17,17 @@
17
17
  color: #836848;
18
18
  cursor: pointer;
19
19
  text-align: center;
20
- min-width: 150px;
21
20
 
22
- // &.year{
23
- // min-width: 90px;
24
- // }
25
-
26
- // &.month{
27
- // min-width: 150px;
28
- // }
21
+ &.default-filter{
22
+ background: #F9E298;
23
+ }
29
24
 
30
25
  span{
31
26
  font-family: $font-default;
32
- font-size: 18px;
33
- font-weight: 400;
34
- line-height: 27px;
35
- letter-spacing: 0.05em;
27
+ font-weight: 500;
28
+ font-size: 14px;
29
+ line-height: 21px;
30
+ letter-spacing: 2%;
36
31
  text-align: left;
37
32
  text-underline-position: from-font;
38
33
  text-decoration-skip-ink: none;
@@ -43,3 +38,15 @@
43
38
  color: #FFFFFF;
44
39
  }
45
40
  }
41
+
42
+
43
+ @media only screen and (min-width: 769px) {
44
+ .filter-pill{
45
+ span{
46
+ font-size: 18px;
47
+ font-weight: 400;
48
+ line-height: 27px;
49
+ letter-spacing: 0.05em;
50
+ }
51
+ }
52
+ }
@@ -103,6 +103,10 @@
103
103
  margin-bottom: 0;
104
104
  }
105
105
 
106
+ .ant-input{
107
+ min-width: 272px;
108
+ }
109
+
106
110
  .search-button{
107
111
  width: auto;
108
112
  margin-bottom: 3px;
@@ -0,0 +1,14 @@
1
+ module Iceholidays
2
+ module Frontend
3
+ class PostsController < ApplicationController
4
+
5
+ def index
6
+ @posts = current_brand.posts
7
+ end
8
+
9
+ def show
10
+ @post = current_brand.posts.find(params[:id])
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,33 @@
1
+ import axios from "axios";
2
+ import { Agent } from "../interfaces/agent.interface";
3
+
4
+ class AgentsApi
5
+ {
6
+
7
+ getAgents(): Promise<Agent[]> {
8
+ const apiUrl = "/api/v1/users/agents";
9
+
10
+ return axios.get(apiUrl)
11
+ .then(response => {
12
+ const agents = response.data.agents.map(agentData => {
13
+ const agent:Agent = {
14
+ id: agentData.id,
15
+ name: agentData.full_name,
16
+ email: agentData.email,
17
+ image: agentData.image,
18
+ phone: agentData.phone,
19
+ whatsapp: agentData.whatsapp_no,
20
+ address: agentData.address,
21
+ city: agentData.city,
22
+ state: agentData.state,
23
+ }
24
+ return agent;
25
+ })
26
+ return Promise.resolve(agents);
27
+ });
28
+ }
29
+
30
+ }
31
+
32
+ export default AgentsApi
33
+ ;
@@ -1,5 +1,5 @@
1
1
  import axios from "axios";
2
- import { City, Country } from "../interfaces/country.interface";
2
+ import { City, Country, Location } from "../interfaces/country.interface";
3
3
 
4
4
  class LocationsApi {
5
5
 
@@ -34,6 +34,28 @@ class LocationsApi {
34
34
  });
35
35
  }
36
36
 
37
+ getLocation(locationId:number): Promise<Location> {
38
+ const apiUrl = `/api/v1/locations/${locationId}`;
39
+
40
+
41
+ return axios.get(apiUrl)
42
+ .then(response => {
43
+ const locationData = response.data.data.attributes;
44
+ const location: Location = {
45
+ id: locationData.id,
46
+ cover: locationData.cover,
47
+ name: locationData.name,
48
+ ancestry: locationData.ancestors.map(a => {
49
+ return {
50
+ id: a.id,
51
+ name: a.name
52
+ }
53
+ })
54
+ }
55
+ return Promise.resolve(location);
56
+ });
57
+ }
58
+
37
59
  private mapCity(cityData): City{
38
60
  const city:City = {
39
61
  id: cityData.id,
@@ -1,44 +1,64 @@
1
1
  import axios from "axios";
2
2
  import { Itinerary } from "../interfaces/itinerary.interface";
3
3
 
4
- interface SearchParams {
5
- keyword: string;
6
- year?: string;
7
- month?: string;
8
- }
9
4
 
10
5
  class SeriesApi {
11
6
 
12
- getItineraries(searchParams: SearchParams): Promise<Itinerary[]> {
13
- const apiUrl = `/api/v1/series?keyword=${searchParams.keyword}&type=series`;
7
+ getItineraries(searchParamsObj): Promise<Itinerary[]> {
8
+ const searchParamsQuery = new URLSearchParams(searchParamsObj).toString()
9
+ const apiUrl = `/api/v1/series?${searchParamsQuery}&type=series`;
14
10
 
15
11
  return axios.get(apiUrl)
16
12
  .then(response => {
17
- const itineraries:Itinerary[] = response.data.itineraries.map(itineraryData => {
18
- const itinerary:Itinerary = {
19
- id: itineraryData.id,
20
- description: itineraryData.description,
21
- caption: itineraryData.caption,
22
- otherCaption: itineraryData.otherCaption,
23
- code: itineraryData.code,
24
- category: itineraryData.category,
25
- country: itineraryData.country,
26
- price: itineraryData.price,
27
- images: itineraryData.images,
28
- priceCurrency: itineraryData.price_currency,
29
- departureDate: itineraryData.departure_date,
30
- guranteedDepartureDates: itineraryData.guranteed_departure_dates,
31
- almostGuaranteedDepartureDates: itineraryData.almost_guaranteed_departure_dates,
32
- departureLocations: itineraryData.departure_locations,
33
- totalItineraries: itineraryData.total_itineraries,
34
- }
35
-
36
- return itinerary;
37
- })
13
+ const itineraries:Itinerary[] = response.data.itineraries.map(itineraryData => this.mapItinerary(itineraryData));
38
14
  return Promise.resolve(itineraries);
39
15
  });
40
16
  }
41
17
 
18
+
19
+ getItinerary(id): Promise<Itinerary>{
20
+ const apiUrl = `/api/v1/series/${id}`;
21
+
22
+ return axios.get(apiUrl)
23
+ .then(response => {
24
+ const itinerary = this.mapItinerary(response.data);
25
+ return Promise.resolve(itinerary);
26
+ });
27
+ }
28
+
29
+
30
+ private mapItinerary(itineraryData):Itinerary {
31
+ const itinerary:Itinerary = {
32
+ id: itineraryData.id,
33
+ description: itineraryData.description,
34
+ caption: itineraryData.caption,
35
+ otherCaption: itineraryData.otherCaption,
36
+ code: itineraryData.code,
37
+ category: itineraryData.category,
38
+ country: itineraryData.country,
39
+ price: itineraryData.price,
40
+ images: itineraryData.images,
41
+ coverImage: itineraryData.images[0],
42
+ priceCurrency: itineraryData.price_currency,
43
+ departureDate: itineraryData.departure_date,
44
+ guranteedDepartureDates: itineraryData.guranteed_departure_dates,
45
+ almostGuaranteedDepartureDates: itineraryData.almost_guaranteed_departure_dates,
46
+ departureLocations: itineraryData.departure_locations,
47
+ totalItineraries: itineraryData.total_itineraries,
48
+ fileUrl: itineraryData.file_url,
49
+
50
+ autoCancel: itineraryData.auto_cancel,
51
+ ccRate: itineraryData.cc_rate,
52
+ includings: itineraryData.includings,
53
+ maxBookingSeats: itineraryData.max_booking_seats,
54
+ remark: itineraryData.remark,
55
+ tourType: itineraryData.tour_type,
56
+ tours: itineraryData.tours,
57
+ }
58
+
59
+ return itinerary;
60
+ }
61
+
42
62
  }
43
63
 
44
64
  export default SeriesApi;
@@ -0,0 +1,11 @@
1
+ export interface Agent {
2
+ id:number;
3
+ email:string;
4
+ name:string;
5
+ image?:string;
6
+ phone?:string;
7
+ whatsapp?:string;
8
+ address:string;
9
+ city?:string;
10
+ state:string;
11
+ }
@@ -9,10 +9,11 @@ export interface City extends Location {
9
9
  }
10
10
 
11
11
 
12
- interface Location {
12
+ export interface Location {
13
13
  id:number;
14
- cover:string;
14
+ cover?:string;
15
15
  name:string;
16
- tourCount:number;
16
+ tourCount?:number;
17
+ ancestry?: Location[];
17
18
 
18
19
  }
@@ -2,17 +2,110 @@ export interface Itinerary {
2
2
  id: number;
3
3
  description: string;
4
4
  code: string;
5
- fileUrl?: string;
6
5
  category: string;
7
6
  caption: string;
8
7
  otherCaption: string;
9
8
  country: string;
10
- price: string;
11
- departureDate: string[];
12
- guranteedDepartureDates: string[];
13
- almostGuaranteedDepartureDates: string[];
14
- departureLocations: string[];
9
+ fileUrl?: string;
10
+ price?: string;
11
+ departureDate?: string[];
12
+ guranteedDepartureDates?: string[];
13
+ almostGuaranteedDepartureDates?: string[];
14
+ departureLocations?: string[];
15
+ coverImage?:string[];
15
16
  images: string[];
16
- priceCurrency: string;
17
- totalItineraries: number;
17
+ priceCurrency?: string;
18
+ totalItineraries?: number;
19
+
20
+ autoCancel?:boolean;
21
+ ccRate?: number;
22
+ includings?: ItineraryIncludings;
23
+ maxBookingSeats?: number;
24
+ remark?: string;
25
+ tourType?: string;
26
+ tours?: Tour[];
27
+ }
28
+
29
+ interface ItineraryIncludings {
30
+ acf: boolean;
31
+ airport_taxes: boolean;
32
+ gratuities: boolean;
33
+ group_departure: boolean;
34
+ hotel: boolean;
35
+ luggage: boolean;
36
+ meal_onboard: boolean;
37
+ tour_leader: boolean;
38
+ wifi: boolean;
39
+ }
40
+
41
+ export interface Tour {
42
+ id:number;
43
+ addon_others:number;
44
+ allow_customer_pay: boolean;
45
+ arrival_date: string;
46
+ caption: string;
47
+ code: string;
48
+ compulsory_additional_fee: number;
49
+ credit_available: number;
50
+ customer_deposit: number;
51
+ day_before_departure: number;
52
+ departure_date: string;
53
+ departure_location: string;
54
+ deposit: number;
55
+ deposit_date: string;
56
+ dobw_available: any;
57
+ dobw_cor_available: any;
58
+ dobw_ret_available: any;
59
+ extra_deposit: number;
60
+ fare_type: string;
61
+ final_payment_date: string;
62
+ flights: any[];
63
+ fpxb2b_available:any;
64
+ fpxb2c_available:any;
65
+ guaranteed_departure: boolean;
66
+ guaranteed_indicator: string;
67
+ highlight: string;
68
+ insurance: string;
69
+ insurance_rebate: number;
70
+ latest_tour_confirmation: LatestTourConfirmation;
71
+ max_booking_seats: number;
72
+ min_dta: number;
73
+ pay_later: string;
74
+ pbb2_available: string;
75
+ pre_commisions: any[];
76
+ price: number;
77
+ prices: Price[];
78
+ red_luggage_protection: boolean;
79
+ single_supplement_price: string;
80
+ subtract_others: number;
81
+ visa_fee: number;
82
+ }
83
+
84
+ interface LatestTourConfirmation {
85
+ assembly_time: string;
86
+ confirmation_emergency_contact: string;
87
+ hand_carry_weight: string;
88
+ luggage_quantity: string;
89
+ luggage_weight: string;
90
+ meet_up_point: string;
91
+ tour_guide_chinese_name: string;
92
+ tour_guide_name: string;
93
+ tour_guide_phone: string;
94
+ }
95
+
96
+ interface Price {
97
+ display_price: string;
98
+ adult: number;
99
+ child_no_bed: number;
100
+ child_twin: number;
101
+ child_with_bed: number;
102
+ dta_adult: number;
103
+ dta_child_no_bed: number;
104
+ dta_child_twin: number;
105
+ dta_child_with_bed: number;
106
+ dta_infant: number;
107
+ dta_single_supplement: number;
108
+ infant: number;
109
+ single_supplement: number;
110
+ type: string;
18
111
  }
@@ -18,7 +18,7 @@ export default function App() {
18
18
  <Route path="/app" element={<MainLayout />}>
19
19
  <Route index element={<Homepage />} />
20
20
  <Route path="/app/listing" element={<ListingPage />} />
21
- <Route path="/app/show" element={<ShowPage />} />
21
+ <Route path="/app/itinerary/:id" element={<ShowPage />} />
22
22
  <Route path="/app/about-us" element={<AboutUsPage />} />
23
23
  <Route path="/app/countries" element={<CountriesPage />} />
24
24
  <Route path="/app/blog" element={<BlogPage />} />
@@ -1,19 +1,20 @@
1
- import { notification, Tabs, TabsProps } from "antd";
1
+ import { notification, Select, Tabs, TabsProps } from "antd";
2
2
  import React from "react";
3
3
  import LocationsApi from "../../api-services/locations-api.service";
4
4
  import { Country } from "../../interfaces/country.interface";
5
- import Postcard from "./shared/Postcard";
6
- import { mdiMenuRight } from "@mdi/js";
5
+ import { mdiFilterVariant, mdiMenuRight } from "@mdi/js";
7
6
  import Icon from "@mdi/react";
8
- import tour from "antd/es/tour";
9
7
  import { Link } from "react-router-dom";
8
+ import LocationPostcards from "./shared/LocationPostcards";
9
+ import LocationDropdown from "./shared/LocationDropdown";
10
10
 
11
11
 
12
12
  export default class Destinations extends React.Component {
13
13
  api = new LocationsApi;
14
14
 
15
15
  state = {
16
- countries: []
16
+ countries: [],
17
+ activeTab: "1"
17
18
  }
18
19
 
19
20
  componentDidMount() {
@@ -30,30 +31,35 @@ export default class Destinations extends React.Component {
30
31
  const pluralize = (count: number, noun: string, suffix = 's') =>
31
32
  `${count} ${noun}${count > 1 ? suffix : ''}`;
32
33
 
33
- const listingLink = (keyword: string) => {
34
- return `/app/listing?keyword=${keyword}`;
34
+ const listingLink = (locationId: number) => {
35
+ return `/app/listing?location_id=${locationId}`;
35
36
  }
36
37
 
38
+ const changeTab = (selectedKey:string) => {
39
+ this.setState({activeTab:selectedKey.toString()})
40
+ }
41
+
42
+
37
43
  var items:TabsProps["items"] = this.state.countries.map((country:Country, index)=>{
38
44
  return {
39
- key: index.toString(),
40
- label: country.name,
45
+ key: country.id.toString(),
46
+ label: <>
47
+ {country.name}
48
+ </>,
41
49
  children: (
42
50
  <div>
43
- <Link to={listingLink(country.name)} className="country">
51
+ <Link to={listingLink(country.id)} className="country">
44
52
  <img className="country-image" src={`${country.cover}`} />
45
53
  <h1 className="country-name"> {country.name} </h1>
46
- <img className="bottom-logo" src="/iceholidays-assets/images/Frame71.png"></img>
54
+ <picture className="bottom-logo">
55
+ <img src="/iceholidays-assets/images/destinations_logo.png"></img>
56
+ </picture>
47
57
  </Link>
48
58
  {
49
59
  country.topCities?.length > 0 &&
50
60
  <div className="top-cities">
51
61
  <h2>Top Cities</h2>
52
- <div className="postcards">
53
- {
54
- country.topCities?.map((city, index)=><Postcard key={index} link={listingLink(city.name)} image={city.cover} name={city.name} tourCount={city.tourCount}/>)
55
- }
56
- </div>
62
+ <LocationPostcards locations={country.topCities}/>
57
63
  </div>
58
64
  }
59
65
  {
@@ -63,7 +69,7 @@ export default class Destinations extends React.Component {
63
69
  <div className="other-destinations">
64
70
  {
65
71
  country.tags?.map((city, index)=>{
66
- return <Link key={index} to={listingLink(city.name)}> {city.name} </Link>
72
+ return <Link key={index} to={listingLink(city.id)}> {city.name} </Link>
67
73
  })
68
74
  }
69
75
  </div>
@@ -75,11 +81,11 @@ export default class Destinations extends React.Component {
75
81
  <div className="highlights">
76
82
  {
77
83
  country.highlights?.map((city, index)=>{
78
- return <Link key={index} to={listingLink(city.name)}>
84
+ return <Link key={index} to={listingLink(city.id)}>
79
85
  <div className="tour" style={{backgroundImage:`linear-gradient(180deg, rgba(0, 0, 0, 0) 50%, rgba(0, 0, 0, 0.8) 100%), url("${city.cover}")`}}>
80
86
  <div className="details">
81
87
  <span className="city-name"> {city.name} </span>
82
- <span className="tour-count"> {pluralize(city.tourCount, "tour")} <Icon path={mdiMenuRight} size={1} /> </span>
88
+ <span className="tour-count"> {pluralize(city.tourCount || 0, "tour")} <Icon path={mdiMenuRight} size={1} /> </span>
83
89
  </div>
84
90
  </div>
85
91
  </Link>
@@ -96,10 +102,14 @@ export default class Destinations extends React.Component {
96
102
  <div id="popular-destinations">
97
103
  <h1>Explore Popular Destination</h1>
98
104
 
105
+ <LocationDropdown locations={this.state.countries} selectLocation={changeTab}/>
106
+
99
107
  <Tabs
100
108
  defaultActiveKey="1"
109
+ activeKey={this.state.activeTab}
101
110
  items={items}
102
- type="card"/>
111
+ type="card"
112
+ onChange={changeTab}/>
103
113
 
104
114
  </div>
105
115
  )