iceholidays-frontend 0.2.0 → 0.4.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 (135) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/stylesheets/iceholidays/frontend/application.sass.scss +1588 -0
  3. data/app/assets/stylesheets/iceholidays/frontend/common.scss +233 -0
  4. data/app/assets/stylesheets/iceholidays/frontend/layout.scss +188 -0
  5. data/app/assets/stylesheets/iceholidays/frontend/utils/_antd_overrides.scss +107 -0
  6. data/app/assets/stylesheets/iceholidays/frontend/utils/_variables.scss +3 -0
  7. data/app/assets/stylesheets/iceholidays/frontend/widgets/filter_pills.scss +45 -0
  8. data/app/assets/stylesheets/iceholidays/frontend/widgets/search_bar.scss +112 -0
  9. data/app/controllers/iceholidays/frontend/application_controller.rb +1 -0
  10. data/app/controllers/iceholidays/frontend/site_controller.rb +32 -0
  11. data/app/javascript/api-services/banners-api.service.ts +28 -0
  12. data/app/javascript/api-services/locations-api.service.ts +49 -0
  13. data/app/javascript/api-services/search-api.service.ts +16 -0
  14. data/app/javascript/api-services/series-api.service.ts +44 -0
  15. data/app/javascript/api-services/testimonials-api.service.ts +27 -0
  16. data/app/javascript/interfaces/banner.interface.ts +10 -0
  17. data/app/javascript/interfaces/country.interface.ts +18 -0
  18. data/app/javascript/interfaces/itinerary.interface.ts +18 -0
  19. data/app/javascript/interfaces/testimonial.interface.ts +6 -0
  20. data/app/javascript/react/App.tsx +32 -0
  21. data/app/javascript/react/components/Destinations.tsx +67 -165
  22. data/app/javascript/react/components/Testimonials.tsx +75 -48
  23. data/app/javascript/react/components/shared/Headline.tsx +29 -0
  24. data/app/javascript/react/components/shared/Postcard.tsx +31 -0
  25. data/app/javascript/react/components/shared/RibbonSection.tsx +21 -0
  26. data/app/javascript/react/components/shared/SlickButtonFix.tsx +19 -0
  27. data/app/javascript/react/index.js +3 -5
  28. data/app/javascript/react/layouts/MainFooter.tsx +72 -0
  29. data/app/javascript/react/layouts/MainHeader.tsx +45 -0
  30. data/app/javascript/react/layouts/MainLayout.tsx +21 -0
  31. data/app/javascript/react/pages/AboutUsPage.tsx +95 -0
  32. data/app/javascript/react/pages/BlogPage.tsx +79 -0
  33. data/app/javascript/react/pages/BlogShowPage.tsx +43 -0
  34. data/app/javascript/react/pages/ContactAgentsPage.tsx +16 -0
  35. data/app/javascript/react/pages/ContactUsPage.tsx +122 -0
  36. data/app/javascript/react/pages/CountriesPage.tsx +62 -0
  37. data/app/javascript/react/pages/Homepage.tsx +90 -0
  38. data/app/javascript/react/pages/ListingPage.tsx +246 -0
  39. data/app/javascript/react/pages/ShowPage.tsx +397 -0
  40. data/app/javascript/react/widgets/FilterPills.tsx +77 -0
  41. data/app/javascript/react/widgets/SearchBarWidget.tsx +42 -0
  42. data/app/views/iceholidays/frontend/site/index.html.erb +1 -24
  43. data/app/views/layouts/iceholidays/frontend/application.html.erb +3 -7
  44. data/config/routes.rb +9 -0
  45. data/lib/iceholidays/frontend/engine.rb +11 -4
  46. data/lib/iceholidays/frontend/version.rb +1 -1
  47. data/public/iceholidays-assets/application.css +1873 -0
  48. data/public/iceholidays-assets/application.js +430 -0
  49. data/public/iceholidays-assets/application.js.map +7 -0
  50. data/public/iceholidays-assets/images/8D7N.png +0 -0
  51. data/public/iceholidays-assets/images/about_us.png +0 -0
  52. data/public/iceholidays-assets/images/about_us2.png +0 -0
  53. data/public/iceholidays-assets/images/banner_arrow.png +0 -0
  54. data/public/iceholidays-assets/images/banner_right_arrow.png +0 -0
  55. data/public/iceholidays-assets/images/blog.png +0 -0
  56. data/public/iceholidays-assets/images/blog1.png +0 -0
  57. data/public/iceholidays-assets/images/certificate1.png +0 -0
  58. data/public/iceholidays-assets/images/certificate2.png +0 -0
  59. data/public/iceholidays-assets/images/china_southern_airlines.png +0 -0
  60. data/public/iceholidays-assets/images/china_southern_airlines_icon.png +0 -0
  61. data/public/iceholidays-assets/images/competitiveness.png +0 -0
  62. data/public/iceholidays-assets/images/contact_agents.png +0 -0
  63. data/public/iceholidays-assets/images/contact_us.png +0 -0
  64. data/public/iceholidays-assets/images/contact_us_form.png +0 -0
  65. data/public/iceholidays-assets/images/ethical.png +0 -0
  66. data/public/iceholidays-assets/images/hw_logo.png +0 -0
  67. data/public/iceholidays-assets/images/innovative.png +0 -0
  68. data/public/iceholidays-assets/images/plane.png +0 -0
  69. data/public/iceholidays-assets/images/social/ico_fb.png +0 -0
  70. data/public/iceholidays-assets/images/social/ico_ig.png +0 -0
  71. data/public/iceholidays-assets/images/social/ico_twitter.png +0 -0
  72. data/public/iceholidays-assets/images/social/ico_yt.png +0 -0
  73. data/public/iceholidays-assets/images/social.png +0 -0
  74. data/public/iceholidays-assets/images/tour1.png +0 -0
  75. metadata +96 -104
  76. data/app/assets/builds/iceholidays/frontend/5star-GEMYV5WA.digested.png +0 -0
  77. data/app/assets/builds/iceholidays/frontend/Frame71-U6FKYUGB.digested.png +0 -0
  78. data/app/assets/builds/iceholidays/frontend/Layer_1-24HTXUKI.digested.png +0 -0
  79. data/app/assets/builds/iceholidays/frontend/Rectangle49-SVQRLXW6.digested.png +0 -0
  80. data/app/assets/builds/iceholidays/frontend/africa-HBPEOBHM.digested.png +0 -0
  81. data/app/assets/builds/iceholidays/frontend/application.js +0 -293
  82. data/app/assets/builds/iceholidays/frontend/application.js.map +0 -7
  83. data/app/assets/builds/iceholidays/frontend/banner1-OM6SQ5GW.digested.png +0 -0
  84. data/app/assets/builds/iceholidays/frontend/banner2-BWOLYVUE.digested.png +0 -0
  85. data/app/assets/builds/iceholidays/frontend/china-DX6D6FE2.digested.png +0 -0
  86. data/app/assets/builds/iceholidays/frontend/china2-FESATHUH.digested.png +0 -0
  87. data/app/assets/builds/iceholidays/frontend/guangzhou-JGSVPIYY.digested.png +0 -0
  88. data/app/assets/builds/iceholidays/frontend/guilin-AXXU7K32.digested.png +0 -0
  89. data/app/assets/builds/iceholidays/frontend/harbin-2YJL7HHH.digested.png +0 -0
  90. data/app/assets/builds/iceholidays/frontend/hongkong-IPUEZ35P.digested.png +0 -0
  91. data/app/assets/builds/iceholidays/frontend/inner_mongolia-EURVGQVT.digested.png +0 -0
  92. data/app/assets/builds/iceholidays/frontend/jiangxi-DTEOQGIY.digested.png +0 -0
  93. data/app/assets/builds/iceholidays/frontend/kenya-F5ZJOIBS.digested.png +0 -0
  94. data/app/assets/builds/iceholidays/frontend/kenya2-CCJWJDUN.digested.png +0 -0
  95. data/app/assets/builds/iceholidays/frontend/kunming-OCHNG2UW.digested.png +0 -0
  96. data/app/assets/builds/iceholidays/frontend/slikroad-CVUSDDRO.digested.png +0 -0
  97. data/app/assets/builds/iceholidays/frontend/southafrica-HBPEOBHM.digested.png +0 -0
  98. data/app/assets/builds/iceholidays/frontend/tanzania-VJSRMTCY.digested.png +0 -0
  99. data/app/assets/builds/iceholidays/frontend/uganda-H4JWFN3A.digested.png +0 -0
  100. data/app/assets/stylesheets/iceholidays/frontend/application.scss +0 -850
  101. data/app/javascript/react/components/Homepage.tsx +0 -16
  102. data/app/javascript/react/components/HomepageBanner.tsx +0 -54
  103. data/app/views/layouts/iceholidays/frontend/shared/_footer.html.erb +0 -42
  104. data/app/views/layouts/iceholidays/frontend/shared/_header.html.erb +0 -20
  105. /data/{app/assets/images/iceholidays/frontend → public/iceholidays-assets/images}/5star.png +0 -0
  106. /data/{app/assets/images/iceholidays/frontend → public/iceholidays-assets/images}/Frame71.png +0 -0
  107. /data/{app/assets/images/iceholidays/frontend → public/iceholidays-assets/images}/Group_71.png +0 -0
  108. /data/{app/assets/images/iceholidays/frontend → public/iceholidays-assets/images}/Layer_1.png +0 -0
  109. /data/{app/assets/images/iceholidays/frontend → public/iceholidays-assets/images}/Rectangle49.png +0 -0
  110. /data/{app/assets/images/iceholidays/frontend → public/iceholidays-assets/images}/TS_Logo.png +0 -0
  111. /data/{app/assets/images/iceholidays/frontend → public/iceholidays-assets/images}/about_st_bg.png +0 -0
  112. /data/{app/assets/images/iceholidays/frontend → public/iceholidays-assets/images}/africa.png +0 -0
  113. /data/{app/assets/images/iceholidays/frontend → public/iceholidays-assets/images}/banner1.png +0 -0
  114. /data/{app/assets/images/iceholidays/frontend → public/iceholidays-assets/images}/banner2.png +0 -0
  115. /data/{app/assets/images/iceholidays/frontend → public/iceholidays-assets/images}/china.png +0 -0
  116. /data/{app/assets/images/iceholidays/frontend → public/iceholidays-assets/images}/china2.png +0 -0
  117. /data/{app/assets/builds/iceholidays/frontend/chongqing-CCJWJDUN.digested.png → public/iceholidays-assets/images/china_listings_cover.png} +0 -0
  118. /data/{app/assets/images/iceholidays/frontend → public/iceholidays-assets/images}/chongqing.png +0 -0
  119. /data/{app/assets/images/iceholidays/frontend/cover_img.jpeg → public/iceholidays-assets/images/cover_img.jpg} +0 -0
  120. /data/{app/assets/images/iceholidays/frontend/feature.jpeg → public/iceholidays-assets/images/feature.jpg} +0 -0
  121. /data/{app/assets/images/iceholidays/frontend → public/iceholidays-assets/images}/guangzhou.png +0 -0
  122. /data/{app/assets/images/iceholidays/frontend → public/iceholidays-assets/images}/guilin.png +0 -0
  123. /data/{app/assets/images/iceholidays/frontend → public/iceholidays-assets/images}/harbin.png +0 -0
  124. /data/{app/assets/images/iceholidays/frontend → public/iceholidays-assets/images}/hongkong.png +0 -0
  125. /data/{app/assets/images/iceholidays/frontend → public/iceholidays-assets/images}/inner_mongolia.png +0 -0
  126. /data/{app/assets/images/iceholidays/frontend → public/iceholidays-assets/images}/jiangxi.png +0 -0
  127. /data/{app/assets/images/iceholidays/frontend → public/iceholidays-assets/images}/kenya.png +0 -0
  128. /data/{app/assets/images/iceholidays/frontend → public/iceholidays-assets/images}/kenya2.png +0 -0
  129. /data/{app/assets/images/iceholidays/frontend → public/iceholidays-assets/images}/kunming.png +0 -0
  130. /data/{app/assets/images/iceholidays/frontend → public/iceholidays-assets/images}/logo_container.png +0 -0
  131. /data/{app/assets/images/iceholidays/frontend → public/iceholidays-assets/images}/logomark.png +0 -0
  132. /data/{app/assets/images/iceholidays/frontend → public/iceholidays-assets/images}/slikroad.png +0 -0
  133. /data/{app/assets/images/iceholidays/frontend → public/iceholidays-assets/images}/southafrica.png +0 -0
  134. /data/{app/assets/images/iceholidays/frontend → public/iceholidays-assets/images}/tanzania.png +0 -0
  135. /data/{app/assets/images/iceholidays/frontend → public/iceholidays-assets/images}/uganda.png +0 -0
@@ -3,6 +3,38 @@ module Iceholidays
3
3
  class SiteController < ApplicationController
4
4
  def index
5
5
  end
6
+
7
+ def listing
8
+ render :index
9
+ end
10
+
11
+ def show
12
+ render :index
13
+ end
14
+
15
+ def about_us
16
+ render :index
17
+ end
18
+
19
+ def countries
20
+ render :index
21
+ end
22
+
23
+ def blog
24
+ render :index
25
+ end
26
+
27
+ def show_blog
28
+ render :index
29
+ end
30
+
31
+ def contact_agents
32
+ render :index
33
+ end
34
+
35
+ def contact_us
36
+ render :index
37
+ end
6
38
  end
7
39
  end
8
40
  end
@@ -0,0 +1,28 @@
1
+ import axios from "axios";
2
+ import { Banner } from "../interfaces/banner.interface";
3
+
4
+ class BannersApi {
5
+
6
+ getBanners(): Promise<Banner[]> {
7
+ const apiUrl = "/api/v1/banner";
8
+
9
+ return axios.get(apiUrl)
10
+ .then(response => {
11
+ const banners = response.data.data.attributes.slides.map(slide => {
12
+ const banner:Banner = {
13
+ title: slide.title,
14
+ url: slide.url,
15
+ target: slide.target,
16
+ sortOrder: slide.sort_order,
17
+ desktopImage: slide.image.desktop,
18
+ mobileImage: slide.image.mobile
19
+ }
20
+ return banner;
21
+ })
22
+ return Promise.resolve(banners);
23
+ });
24
+ }
25
+
26
+ }
27
+
28
+ export default BannersApi;
@@ -0,0 +1,49 @@
1
+ import axios from "axios";
2
+ import { City, Country } from "../interfaces/country.interface";
3
+
4
+ class LocationsApi {
5
+
6
+ getCountries(): Promise<Country[]> {
7
+ const apiUrl = "/api/v1/locations";
8
+
9
+ return axios.get(apiUrl)
10
+ .then(response => {
11
+ const countries = response.data.map(locationData => {
12
+ const countryData = locationData.data.attributes;
13
+ const citiesData = countryData.children.map(childrenData => this.mapCity(childrenData.data.attributes));
14
+
15
+ const allCities = [...citiesData];
16
+ const citiesWithImages = allCities.filter(x => x.cover != null);
17
+ const topCities = citiesWithImages.splice(0,4);
18
+ const highlights = citiesWithImages.splice(0,5);
19
+
20
+ const country:Country = {
21
+ id: countryData.id,
22
+ name: countryData.name,
23
+ cover: countryData.cover,
24
+ tourCount: countryData.itineraries,
25
+ cities: allCities,
26
+ topCities: topCities,
27
+ highlights: highlights,
28
+ tags: allCities.filter(city => !topCities.includes(city) && !highlights.includes(city)),
29
+ }
30
+
31
+ return country;
32
+ })
33
+ return Promise.resolve(countries);
34
+ });
35
+ }
36
+
37
+ private mapCity(cityData): City{
38
+ const city:City = {
39
+ id: cityData.id,
40
+ name: cityData.name,
41
+ cover: cityData.cover,
42
+ tourCount: cityData.itineraries
43
+ };
44
+ return city;
45
+ }
46
+
47
+ }
48
+
49
+ export default LocationsApi;
@@ -0,0 +1,16 @@
1
+ import axios from "axios";
2
+
3
+ class SearchApi {
4
+
5
+ search(keyword:string, month?:number): Promise<any[]> {
6
+ const apiUrl = `/api/v1/series?keyword=${keyword}${month && `&month=${month}`}&type=series`;
7
+
8
+ return axios.get(apiUrl)
9
+ .then(response => {
10
+ return Promise.resolve(response.data);
11
+ });
12
+ }
13
+
14
+ }
15
+
16
+ export default SearchApi;
@@ -0,0 +1,44 @@
1
+ import axios from "axios";
2
+ import { Itinerary } from "../interfaces/itinerary.interface";
3
+
4
+ interface SearchParams {
5
+ keyword: string;
6
+ year?: string;
7
+ month?: string;
8
+ }
9
+
10
+ class SeriesApi {
11
+
12
+ getItineraries(searchParams: SearchParams): Promise<Itinerary[]> {
13
+ const apiUrl = `/api/v1/series?keyword=${searchParams.keyword}&type=series`;
14
+
15
+ return axios.get(apiUrl)
16
+ .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
+ })
38
+ return Promise.resolve(itineraries);
39
+ });
40
+ }
41
+
42
+ }
43
+
44
+ export default SeriesApi;
@@ -0,0 +1,27 @@
1
+ import axios from "axios";
2
+ import { Testimonial } from "../interfaces/testimonial.interface";
3
+
4
+ class TestimonialsApi {
5
+
6
+ getTestimonials(): Promise<Testimonial[]> {
7
+ const apiUrl = "/api/v1/testimonials";
8
+
9
+ return axios.get(apiUrl)
10
+ .then(response => {
11
+ const testimonials = response.data.data.map(responseData => {
12
+ const testimonialData = responseData.attributes;
13
+ const testimonial:Testimonial = {
14
+ id: testimonialData.id,
15
+ tour: testimonialData.tour,
16
+ author: testimonialData.author,
17
+ comment: testimonialData.body,
18
+ }
19
+ return testimonial;
20
+ })
21
+ return Promise.resolve(testimonials);
22
+ });
23
+ }
24
+
25
+ }
26
+
27
+ export default TestimonialsApi;
@@ -0,0 +1,10 @@
1
+ export interface Banner {
2
+ id?:number;
3
+ title:string;
4
+ url?:string;
5
+ target?:string;
6
+ sortOrder?:number;
7
+ isActive?:boolean;
8
+ desktopImage?:string;
9
+ mobileImage?:string;
10
+ }
@@ -0,0 +1,18 @@
1
+ export interface Country extends Location {
2
+ cities:City[];
3
+ topCities:City[];
4
+ highlights:City[];
5
+ tags:City[];
6
+ }
7
+
8
+ export interface City extends Location {
9
+ }
10
+
11
+
12
+ interface Location {
13
+ id:number;
14
+ cover:string;
15
+ name:string;
16
+ tourCount:number;
17
+
18
+ }
@@ -0,0 +1,18 @@
1
+ export interface Itinerary {
2
+ id: number;
3
+ description: string;
4
+ code: string;
5
+ fileUrl?: string;
6
+ category: string;
7
+ caption: string;
8
+ otherCaption: string;
9
+ country: string;
10
+ price: string;
11
+ departureDate: string[];
12
+ guranteedDepartureDates: string[];
13
+ almostGuaranteedDepartureDates: string[];
14
+ departureLocations: string[];
15
+ images: string[];
16
+ priceCurrency: string;
17
+ totalItineraries: number;
18
+ }
@@ -0,0 +1,6 @@
1
+ export interface Testimonial {
2
+ id:number;
3
+ tour:string;
4
+ comment:string;
5
+ author:string;
6
+ }
@@ -0,0 +1,32 @@
1
+ import React from "react";
2
+ import { BrowserRouter, Routes, Route } from "react-router-dom";
3
+ import Homepage from "./pages/Homepage";
4
+ import ListingPage from "./pages/ListingPage";
5
+ import ShowPage from "./pages/ShowPage";
6
+ import MainLayout from "./layouts/MainLayout";
7
+ import AboutUsPage from "./pages/AboutUsPage";
8
+ import CountriesPage from "./pages/CountriesPage";
9
+ import BlogPage from "./pages/BlogPage";
10
+ import ContactAgentsPage from "./pages/ContactAgentsPage";
11
+ import ContactUsPage from "./pages/ContactUsPage";
12
+ import BlogShowPage from "./pages/BlogShowPage";
13
+
14
+ export default function App() {
15
+ return (
16
+ <BrowserRouter>
17
+ <Routes>
18
+ <Route path="/app" element={<MainLayout />}>
19
+ <Route index element={<Homepage />} />
20
+ <Route path="/app/listing" element={<ListingPage />} />
21
+ <Route path="/app/show" element={<ShowPage />} />
22
+ <Route path="/app/about-us" element={<AboutUsPage />} />
23
+ <Route path="/app/countries" element={<CountriesPage />} />
24
+ <Route path="/app/blog" element={<BlogPage />} />
25
+ <Route path="/app/blog/1" element={<BlogShowPage />} />
26
+ <Route path="/app/contact-agents" element={<ContactAgentsPage />} />
27
+ <Route path="/app/contact-us" element={<ContactUsPage />} />
28
+ </Route>
29
+ </Routes>
30
+ </BrowserRouter>
31
+ );
32
+ }
@@ -1,167 +1,69 @@
1
- import { Tabs, TabsProps } from "antd";
1
+ import { notification, Tabs, TabsProps } from "antd";
2
2
  import React from "react";
3
- import africa from "../../../assets/images/iceholidays/frontend/africa.png";
3
+ import LocationsApi from "../../api-services/locations-api.service";
4
+ import { Country } from "../../interfaces/country.interface";
5
+ import Postcard from "./shared/Postcard";
6
+ import { mdiMenuRight } from "@mdi/js";
7
+ import Icon from "@mdi/react";
8
+ import tour from "antd/es/tour";
9
+ import { Link } from "react-router-dom";
4
10
 
5
- import kenya from "../../../assets/images/iceholidays/frontend/kenya.png";
6
- import kenya2 from "../../../assets/images/iceholidays/frontend/kenya2.png";
7
- import southafrica from "../../../assets/images/iceholidays/frontend/southafrica.png";
8
11
 
9
- import tanzania from "../../../assets/images/iceholidays/frontend/tanzania.png";
10
- import uganda from "../../../assets/images/iceholidays/frontend/uganda.png";
12
+ export default class Destinations extends React.Component {
13
+ api = new LocationsApi;
11
14
 
12
- import china from "../../../assets/images/iceholidays/frontend/china.png";
13
- import china2 from "../../../assets/images/iceholidays/frontend/china2.png";
14
- import chongqing from "../../../assets/images/iceholidays/frontend/chongqing.png";
15
- import guangzhou from "../../../assets/images/iceholidays/frontend/guangzhou.png";
15
+ state = {
16
+ countries: []
17
+ }
16
18
 
17
- import frame71 from "../../../assets/images/iceholidays/frontend/Frame71.png";
18
- import guilin from "../../../assets/images/iceholidays/frontend/guilin.png";
19
- import hongkong from "../../../assets/images/iceholidays/frontend/hongkong.png";
20
- import harbin from "../../../assets/images/iceholidays/frontend/harbin.png";
21
- import inner_mongolia from "../../../assets/images/iceholidays/frontend/inner_mongolia.png";
22
- import jiangxi from "../../../assets/images/iceholidays/frontend/jiangxi.png";
23
- import kunming from "../../../assets/images/iceholidays/frontend/kunming.png";
24
- import slikroad from "../../../assets/images/iceholidays/frontend/slikroad.png";
19
+ componentDidMount() {
20
+ this.api.getCountries()
21
+ .then(locationsData => {
22
+ this.setState({countries: locationsData})
23
+ })
24
+ .catch(error => {
25
+ notification.error({ message: 'An error occured while loading countries.'});
26
+ });
27
+ }
25
28
 
29
+ render(){
30
+ const pluralize = (count: number, noun: string, suffix = 's') =>
31
+ `${count} ${noun}${count > 1 ? suffix : ''}`;
26
32
 
27
- const countries = [
28
- {
29
- name: "Africa",
30
- image: africa,
31
- image2: africa,
32
- topCities: [{
33
- name: "Kenya",
34
- image: kenya,
35
- image2: kenya2,
36
- },
37
- {
38
- name: "South Africa",
39
- image: southafrica,
40
- },
41
- {
42
- name: "Tanzania",
43
- image: tanzania,
44
- },
45
- {
46
- name: "Uaganda",
47
- image: uganda,
48
- }]
49
- },
50
- {
51
- name: "China",
52
- image: china,
53
- image2: china2,
54
- topCities: [{
55
- name: "Chong Qing",
56
- image: chongqing,
57
- },
58
- {
59
- name: "Guangzhou",
60
- image: guangzhou,
61
- },
62
- {
63
- name: "Guilin",
64
- image: guilin,
65
- },
66
- {
67
- name: "Hongkong",
68
- image: hongkong,
69
- }],
70
- moreCities: [
71
- "Leizhou", "Ningxia", "Qinghai", "Shanghai", "Tibet", "Xiamen", "Yunnan"
72
- ],
73
- tours: [
74
- {
75
- name: "Harbin",
76
- image: harbin,
77
- },
78
- {
79
- name: "Inner Mongolia",
80
- image: inner_mongolia,
81
- },
82
- {
83
- name: "Jiangxi",
84
- image: jiangxi,
85
- },
86
- {
87
- name: "Kun Ming",
88
- image: kunming,
89
- },
90
- {
91
- name: "Silk Road",
92
- image: slikroad,
93
- }
94
- ]
95
- },
96
- {
97
- name: "Europe"
98
- },
99
- {
100
- name: "Exotic"
101
- },
102
- {
103
- name: "japan"
104
- },
105
- {
106
- name: "korea"
107
- },
108
- {
109
- name: "maldives"
110
- },
111
- {
112
- name: "taiwan"
113
- },
114
- ]
33
+ const listingLink = (keyword: string) => {
34
+ return `/app/listing?keyword=${keyword}`;
35
+ }
115
36
 
116
- function Destinations(){
117
- var items:TabsProps["items"] = countries.map((country, index)=>{
118
- return {
119
- key: index.toString(),
120
- label: country.name,
121
- children: (
122
- <>
37
+ var items:TabsProps["items"] = this.state.countries.map((country:Country, index)=>{
38
+ return {
39
+ key: index.toString(),
40
+ label: country.name,
41
+ children: (
123
42
  <div>
124
- <div className="country-info">
125
- <img className="country-image"
126
- src={`${country.image}`}
127
- onMouseOver={e => (e.currentTarget.src = `${country.image2}`)}
128
- onMouseOut={e => (e.currentTarget.src = `${country.image}`)}/>
43
+ <Link to={listingLink(country.name)} className="country">
44
+ <img className="country-image" src={`${country.cover}`} />
129
45
  <h1 className="country-name"> {country.name} </h1>
130
- <img className="bottom-logo" src={frame71}></img>
131
- </div>
46
+ <img className="bottom-logo" src="/iceholidays-assets/images/Frame71.png"></img>
47
+ </Link>
132
48
  {
133
- country.topCities?.length &&
49
+ country.topCities?.length > 0 &&
134
50
  <div className="top-cities">
135
51
  <h2>Top Cities</h2>
136
- <div id="city-group">
52
+ <div className="postcards">
137
53
  {
138
- country.topCities?.map((city, index)=>{
139
- return (
140
- <div key={index} className="city-cover">
141
- <img
142
- src={`${city.image}`}
143
- onMouseOver={e => (e.currentTarget.src = `${city.image2}`)}
144
- onMouseOut={e => (e.currentTarget.src = `${city.image}`)}/>
145
- <div className="city-details">
146
- <span className="city-name">{city.name}</span>
147
- <span className="tour-count">1 Tour</span>
148
- </div>
149
- </div>
150
- )
151
- })
54
+ country.topCities?.map((city, index)=><Postcard key={index} link={listingLink(city.name)} image={city.cover} name={city.name} tourCount={city.tourCount}/>)
152
55
  }
153
56
  </div>
154
57
  </div>
155
58
  }
156
-
157
59
  {
158
- country.moreCities?.length &&
60
+ country.tags?.length > 0 &&
159
61
  <div className="more-cities">
160
62
  <h2>Browse more {country.name} destination</h2>
161
63
  <div className="other-destinations">
162
64
  {
163
- country.moreCities?.map((otherCity, index)=>{
164
- return <a key={index} href="/"> {otherCity} </a>
65
+ country.tags?.map((city, index)=>{
66
+ return <Link key={index} to={listingLink(city.name)}> {city.name} </Link>
165
67
  })
166
68
  }
167
69
  </div>
@@ -169,37 +71,37 @@ function Destinations(){
169
71
  }
170
72
 
171
73
  {
172
- country.tours?.length &&
173
- <div className="other-tours">
74
+ country.highlights?.length > 0 &&
75
+ <div className="highlights">
174
76
  {
175
- country.tours?.map((tour, index)=>{
176
- return <div key={index} className={"tour-story"} style={{backgroundImage:`linear-gradient(180deg, rgba(0, 0, 0, 0) 50%, rgba(0, 0, 0, 0.8) 100%), url("${tour.image}")`}}>
177
- <div className="tour-detail">
178
- <span className="city-name"> {tour.name} </span>
179
- <span className="tour-count"> 1 tour </span>
77
+ country.highlights?.map((city, index)=>{
78
+ return <Link key={index} to={listingLink(city.name)}>
79
+ <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
+ <div className="details">
81
+ <span className="city-name"> {city.name} </span>
82
+ <span className="tour-count"> {pluralize(city.tourCount, "tour")} <Icon path={mdiMenuRight} size={1} /> </span>
83
+ </div>
180
84
  </div>
181
- </div>
85
+ </Link>
182
86
  })
183
87
  }
184
88
  </div>
185
89
  }
186
90
  </div>
187
- </>
188
- )
189
- }
190
- })
191
-
192
- return (
193
- <div id="popular-destinations">
194
- <h1>Explore Popular Destination</h1>
91
+ )
92
+ }
93
+ })
195
94
 
196
- <Tabs
197
- defaultActiveKey="1"
198
- items={items}
199
- type="card"/>
95
+ return (
96
+ <div id="popular-destinations">
97
+ <h1>Explore Popular Destination</h1>
200
98
 
201
- </div>
202
- )
203
- }
99
+ <Tabs
100
+ defaultActiveKey="1"
101
+ items={items}
102
+ type="card"/>
204
103
 
205
- export default Destinations;
104
+ </div>
105
+ )
106
+ }
107
+ }