iceholidays-frontend 0.3.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.
- checksums.yaml +4 -4
- data/app/assets/stylesheets/iceholidays/frontend/application.sass.scss +1588 -0
- data/app/assets/stylesheets/iceholidays/frontend/common.scss +233 -0
- data/app/assets/stylesheets/iceholidays/frontend/layout.scss +188 -0
- data/app/assets/stylesheets/iceholidays/frontend/utils/_antd_overrides.scss +107 -0
- data/app/assets/stylesheets/iceholidays/frontend/utils/_variables.scss +3 -0
- data/app/assets/stylesheets/iceholidays/frontend/widgets/filter_pills.scss +45 -0
- data/app/assets/stylesheets/iceholidays/frontend/widgets/search_bar.scss +112 -0
- data/app/controllers/iceholidays/frontend/site_controller.rb +32 -0
- data/app/javascript/api-services/banners-api.service.ts +28 -0
- data/app/javascript/api-services/locations-api.service.ts +49 -0
- data/app/javascript/api-services/search-api.service.ts +16 -0
- data/app/javascript/api-services/series-api.service.ts +44 -0
- data/app/javascript/api-services/testimonials-api.service.ts +27 -0
- data/app/javascript/interfaces/banner.interface.ts +10 -0
- data/app/javascript/interfaces/country.interface.ts +18 -0
- data/app/javascript/interfaces/itinerary.interface.ts +18 -0
- data/app/javascript/interfaces/testimonial.interface.ts +6 -0
- data/app/javascript/react/App.tsx +32 -0
- data/app/javascript/react/components/Destinations.tsx +72 -141
- data/app/javascript/react/components/Testimonials.tsx +68 -61
- data/app/javascript/react/components/shared/Headline.tsx +29 -0
- data/app/javascript/react/components/shared/Postcard.tsx +31 -0
- data/app/javascript/react/components/shared/RibbonSection.tsx +21 -0
- data/app/javascript/react/index.js +3 -5
- data/app/javascript/react/layouts/MainFooter.tsx +72 -0
- data/app/javascript/react/layouts/MainHeader.tsx +45 -0
- data/app/javascript/react/layouts/MainLayout.tsx +21 -0
- data/app/javascript/react/pages/AboutUsPage.tsx +95 -0
- data/app/javascript/react/pages/BlogPage.tsx +79 -0
- data/app/javascript/react/pages/BlogShowPage.tsx +43 -0
- data/app/javascript/react/pages/ContactAgentsPage.tsx +16 -0
- data/app/javascript/react/pages/ContactUsPage.tsx +122 -0
- data/app/javascript/react/pages/CountriesPage.tsx +62 -0
- data/app/javascript/react/pages/Homepage.tsx +90 -0
- data/app/javascript/react/pages/ListingPage.tsx +246 -0
- data/app/javascript/react/pages/ShowPage.tsx +397 -0
- data/app/javascript/react/widgets/FilterPills.tsx +77 -0
- data/app/javascript/react/widgets/SearchBarWidget.tsx +42 -0
- data/app/views/iceholidays/frontend/site/index.html.erb +1 -24
- data/app/views/layouts/iceholidays/frontend/application.html.erb +2 -6
- data/config/routes.rb +9 -0
- data/lib/iceholidays/frontend/version.rb +1 -1
- data/public/iceholidays-assets/application.css +1873 -0
- data/public/iceholidays-assets/application.js +225 -651
- data/public/iceholidays-assets/application.js.map +4 -4
- data/public/iceholidays-assets/images/8D7N.png +0 -0
- data/public/iceholidays-assets/images/about_us.png +0 -0
- data/public/iceholidays-assets/images/about_us2.png +0 -0
- data/public/iceholidays-assets/images/blog.png +0 -0
- data/public/iceholidays-assets/images/blog1.png +0 -0
- data/public/iceholidays-assets/images/certificate1.png +0 -0
- data/public/iceholidays-assets/images/certificate2.png +0 -0
- data/public/iceholidays-assets/images/china_listings_cover.png +0 -0
- data/public/iceholidays-assets/images/china_southern_airlines.png +0 -0
- data/public/iceholidays-assets/images/china_southern_airlines_icon.png +0 -0
- data/public/iceholidays-assets/images/competitiveness.png +0 -0
- data/public/iceholidays-assets/images/contact_agents.png +0 -0
- data/public/iceholidays-assets/images/contact_us.png +0 -0
- data/public/iceholidays-assets/images/contact_us_form.png +0 -0
- data/public/iceholidays-assets/images/ethical.png +0 -0
- data/public/iceholidays-assets/images/hw_logo.png +0 -0
- data/public/iceholidays-assets/images/innovative.png +0 -0
- data/public/iceholidays-assets/images/plane.png +0 -0
- data/public/iceholidays-assets/images/social/ico_fb.png +0 -0
- data/public/iceholidays-assets/images/social/ico_ig.png +0 -0
- data/public/iceholidays-assets/images/social/ico_twitter.png +0 -0
- data/public/iceholidays-assets/images/social/ico_yt.png +0 -0
- data/public/iceholidays-assets/images/social.png +0 -0
- data/public/iceholidays-assets/images/tour1.png +0 -0
- metadata +61 -49
- data/app/assets/stylesheets/iceholidays/frontend/application.scss +0 -904
- data/app/javascript/react/components/Homepage.tsx +0 -15
- data/app/javascript/react/components/HomepageBanner.tsx +0 -62
- data/app/views/layouts/iceholidays/frontend/shared/_footer.html.erb +0 -42
- data/app/views/layouts/iceholidays/frontend/shared/_header.html.erb +0 -20
|
@@ -0,0 +1,397 @@
|
|
|
1
|
+
import React, { useState } from "react";
|
|
2
|
+
import { Button, Carousel, Col, Flex, Form, Layout, Modal, Row, Select } from "antd";
|
|
3
|
+
import SlickButtonFix from "../components/shared/SlickButtonFix";
|
|
4
|
+
import { mdiAccountCash, mdiAccountGroup, mdiAirplane, mdiBagChecked, mdiBedKing, mdiEmailOutline, mdiFileDownload, mdiFlagTriangle, mdiMapMarker, mdiMapMarkerOutline, mdiMenuLeft, mdiMenuRight, mdiPhoneInTalkOutline, mdiReceiptText, mdiShieldAccount, mdiShieldAirplane, mdiSilverwareForkKnife, mdiWhatsapp } from "@mdi/js";
|
|
5
|
+
import Icon from "@mdi/react";
|
|
6
|
+
import Headline from "../components/shared/Headline";
|
|
7
|
+
import { Content } from "antd/es/layout/layout";
|
|
8
|
+
import Sider from "antd/es/layout/Sider";
|
|
9
|
+
|
|
10
|
+
const bannerPath = '/iceholidays-assets/images/8D7N.png';
|
|
11
|
+
|
|
12
|
+
const details = {
|
|
13
|
+
title: "8D7N NETIZEN HOT SPOTS TWIN CITIES: 8D MAGIC CITY & SUMMER CAPITAL (CHONG QING | KAILI | AN SHUN | XING YI | GUI YANG)",
|
|
14
|
+
country: "China",
|
|
15
|
+
code: "8SCCKD",
|
|
16
|
+
description: `
|
|
17
|
+
**FREE COVID-19 TRAVEL INSURANCE!!**
|
|
18
|
+
*\*\*Applicable for passenger up to 69 years old (T&C APPLIED)*
|
|
19
|
+
|
|
20
|
+
> All non Malaysia passport holder surcharge RM300 per person!! Except Singapore passport holder.
|
|
21
|
+
|
|
22
|
+
**Special Arrangement:**
|
|
23
|
+
**✓** Essential for traveling abroad!!️ Keeps you in touch with your family at all times - **Travel Sim Card per person per card**.
|
|
24
|
+
**✓** Bottle Mineral Water per person per day.
|
|
25
|
+
**✓**2+1 Luxury VIP Air-conditioned Coach.
|
|
26
|
+
|
|
27
|
+
**Itinerary Highlight:**
|
|
28
|
+
**✓** **Liberation Monument Street** is a great place for locals to relax and hang out on weekends and was also a key location for the movie "I Belonged to You".
|
|
29
|
+
**✓** **Hongyadong** is the most popular attraction in Chongqing and is the number one must-visit attraction in Chongqing because of its peculiar architectural appearance and spectacular night view. Here is not a cave, but a most Bayu traditional characteristics of the foot-hanging building, the whole building is built according to the cliff, has more than 2000 years of history.
|
|
30
|
+
**✓** The remodeled and renovated old town of **Ciqikou** boasts a large number of gourmet and handicraft stores. In addition to the old winding stone road steps, the real life of the old generation of Chongqing people is also shown here.
|
|
31
|
+
**✓** Standing on the **Kaibu Yizhi Park** platform, you will be greeted by the breeze of the river. Drink Ba Ba Tea and taste pastries at the open-air tea houses along the river to experience the leisurely life of Chongqing people.
|
|
32
|
+
**✓** **Xijiang Qianhu Miao Village** it consists of more than ten natural villages built on the hillside, which is the largest Miao settlement in China and even in the world. On the hillside, there are layers and layers of Miao wooden footstools, coffee-colored old houses clinging to the turquoise mountains, which are very characteristic of the nationalities. It is a good place to experience the Miao flavor!
|
|
33
|
+
**✓** As a world-class business card of Guizhou, **Huangguoshu Waterfall** is one of the must-see attractions in Guizhou. The most essential ones are mainly the **Great Falls**, **Tianxingqiao Scenic Area** and **Dou Po Tang waterfall**. The scenic spots of Huangguoshu Falls, such as Shuilian Cave and Dou Po Tang waterfall, were the setting for the 86 version of the TV series \. After viewing the spectacular Huangguoshu Falls in the daytime, when night falls, immerse yourself in a **large-scale light show** staged between the mountains and the water, and feel a different travel experience from daytime play.
|
|
34
|
+
**✓** **Maling River Canyon** is known as "the most beautiful scar on earth". Its **Tian Xing Gallery** is the core part of the essence of the canyon scenic area, which is characterized by the magnificent scale of waterfalls and rock page wall hangings forming the main landscape.
|
|
35
|
+
**✓** **Guiyang netizens hot spots:** Huaxi Shi Zhi Street, Qingyun marketplace, Jai Xiu Pavilion, Hua guo yuan bai gong. **Local Cuisine:**Sichuan Cuisine,Chongqing Jianghu Cuisine, Mala Hot Pot, Long Table Feast of Miao, Sour Soup Fish Flavor, Yao Flavor, Buyi Fortune Feast, Qian Flavor
|
|
36
|
+
|
|
37
|
+
**All 5★ Hotel:*****\*\*Subject to change in the event of conflicting conferences or events.\*\****
|
|
38
|
+
**✓** 2 Nights at Chongqing Hotel
|
|
39
|
+
**✓** 1 Nights at KailiHotel
|
|
40
|
+
**✓** 1 Night at Anshun Hotel
|
|
41
|
+
**✓** 1 Night at XingyiHotel
|
|
42
|
+
**✓** 2 Nights at GuiyangHotel
|
|
43
|
+
**Note: Triple Room Sharing Will Be Base on Extra Roll in Bed Basis!**
|
|
44
|
+
`
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const agentSearchResults = [
|
|
48
|
+
{
|
|
49
|
+
company: "HO WAH GENTING HOLIDAY SDN BHD",
|
|
50
|
+
logo: "/iceholidays-assets/images/hw_logo.png",
|
|
51
|
+
contactNumbers: [ "+6018 982 6422" ],
|
|
52
|
+
address: "Ground Floor No. 31 & 33, Jalan Maharajalela, 50150 Kuala Lumpur",
|
|
53
|
+
phone: "+603 2141 6422",
|
|
54
|
+
whatsapp: "+6018 982 6422",
|
|
55
|
+
email: "enquiries@hwgholidays.com"
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
company: "CHANG HONG TRAVEL & TOUR SDN BHD",
|
|
59
|
+
contactNumbers: [ "+6012 608 0287", "+6018 669 3238" ]
|
|
60
|
+
|
|
61
|
+
}
|
|
62
|
+
]
|
|
63
|
+
|
|
64
|
+
const breadcrumbs = [
|
|
65
|
+
{ title: 'Home' },
|
|
66
|
+
]
|
|
67
|
+
|
|
68
|
+
const dates = [
|
|
69
|
+
{
|
|
70
|
+
date: "23/10/24",
|
|
71
|
+
price: "RM 8,288"
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
date: "23/10/24",
|
|
75
|
+
price: "RM 8,288"
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
date: "23/10/24",
|
|
79
|
+
price: "RM 8,288"
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
date: "23/10/24",
|
|
83
|
+
price: "RM 8,288"
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
date: "23/10/24",
|
|
87
|
+
price: "RM 8,288"
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
date: "23/10/24",
|
|
91
|
+
price: "RM 8,288"
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
date: "23/10/24",
|
|
95
|
+
price: "RM 8,288"
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
date: "23/10/24",
|
|
99
|
+
price: "RM 8,288"
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
date: "23/10/24",
|
|
103
|
+
price: "RM 8,288"
|
|
104
|
+
},
|
|
105
|
+
]
|
|
106
|
+
|
|
107
|
+
const thingsToKnow = [
|
|
108
|
+
{icon: <Icon path={mdiShieldAccount} size={1} />, label: "Free Travel Insurance"},
|
|
109
|
+
{icon: <Icon path={mdiReceiptText} size={1} /> , label: "Airport Taxes"},
|
|
110
|
+
{icon: <Icon path={mdiFlagTriangle} size={1} />, label: "Tour Leader"},
|
|
111
|
+
{icon: <Icon path={mdiBagChecked} size={1} />, label: "Check-in Baggage"},
|
|
112
|
+
{icon: <Icon path={mdiSilverwareForkKnife} size={1} />, label: "Meal Onboard"},
|
|
113
|
+
{icon: <Icon path={mdiBedKing} size={1} />, label: "Hotel"},
|
|
114
|
+
{icon: <Icon path={mdiAccountCash} size={1} />, label: "Gratuities"},
|
|
115
|
+
{icon: <Icon path={mdiAccountGroup} size={1} />, label: "Group Departure"},
|
|
116
|
+
{icon: <Icon path={mdiFileDownload} size={1} />, label: "Itinerary Download EN | CN"}
|
|
117
|
+
]
|
|
118
|
+
|
|
119
|
+
const layoutStyle = {
|
|
120
|
+
overflow: 'hidden',
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
const siderStyle = {
|
|
124
|
+
backgroundColor: 'transparent'
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
export default class ShowPage extends React.Component {
|
|
129
|
+
|
|
130
|
+
state = {
|
|
131
|
+
showResult: true,
|
|
132
|
+
setIsModalOpen: false,
|
|
133
|
+
agentData: {
|
|
134
|
+
company: "HO WAH GENTING HOLIDAY SDN BHD",
|
|
135
|
+
logo: "/iceholidays-assets/images/hw_logo.png",
|
|
136
|
+
contactNumbers: [ "+6018 982 6422" ],
|
|
137
|
+
address: "Ground Floor No. 31 & 33, Jalan Maharajalela, 50150 Kuala Lumpur",
|
|
138
|
+
phone: "+603 2141 6422",
|
|
139
|
+
whatsapp: "+6018 982 6422",
|
|
140
|
+
email: "enquiries@hwgholidays.com"
|
|
141
|
+
},
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
showModal(agentData){
|
|
145
|
+
this.setState({setIsModalOpen: true, agentData: agentData});
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
closeModal(){
|
|
149
|
+
this.setState({setIsModalOpen: false});
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
render(){
|
|
153
|
+
return (
|
|
154
|
+
<div id="show-page">
|
|
155
|
+
|
|
156
|
+
<Layout style={layoutStyle}>
|
|
157
|
+
|
|
158
|
+
<>
|
|
159
|
+
<Headline bannerImage={bannerPath} breadcrumbs={breadcrumbs}>
|
|
160
|
+
<div id="show-page_header">
|
|
161
|
+
<Flex justify="space-between" vertical gap={45}>
|
|
162
|
+
<h1>{details.title}</h1>
|
|
163
|
+
<div className="tour_details">
|
|
164
|
+
<span className="tour_details_country"> <Icon path={mdiMapMarkerOutline} size="16px" /> {details.country} </span>
|
|
165
|
+
<span className="tour_details_code"> <Icon path={mdiFileDownload} size="16px" /> {details.code} </span>
|
|
166
|
+
</div>
|
|
167
|
+
</Flex>
|
|
168
|
+
</div>
|
|
169
|
+
</Headline>
|
|
170
|
+
|
|
171
|
+
<div id="date-selector">
|
|
172
|
+
<Carousel autoplay arrows dots={false} draggable slidesToScroll= {1} slidesToShow={8}
|
|
173
|
+
prevArrow={
|
|
174
|
+
<SlickButtonFix>
|
|
175
|
+
<Icon path={mdiMenuLeft} size={2} />
|
|
176
|
+
</SlickButtonFix>
|
|
177
|
+
}
|
|
178
|
+
nextArrow={
|
|
179
|
+
<SlickButtonFix>
|
|
180
|
+
<Icon path={mdiMenuRight} size={2} />
|
|
181
|
+
</SlickButtonFix>
|
|
182
|
+
}>
|
|
183
|
+
{
|
|
184
|
+
dates.map((ddate, index) => {
|
|
185
|
+
return <div key={index} className="date-box">
|
|
186
|
+
<Flex justify="space-between" align="center" vertical gap={8}>
|
|
187
|
+
<div className="date-box_date"> {ddate.date} </div>
|
|
188
|
+
<div>
|
|
189
|
+
<span>From</span>
|
|
190
|
+
<div className="date-box_price"> {ddate.price} </div>
|
|
191
|
+
</div>
|
|
192
|
+
</Flex>
|
|
193
|
+
</div>
|
|
194
|
+
})
|
|
195
|
+
}
|
|
196
|
+
</Carousel>
|
|
197
|
+
</div>
|
|
198
|
+
</>
|
|
199
|
+
|
|
200
|
+
<Layout id="show-page_body">
|
|
201
|
+
<Content>
|
|
202
|
+
<div className="details">
|
|
203
|
+
<Flex gap={10} vertical>
|
|
204
|
+
<div className="details-container">
|
|
205
|
+
<div className="details-container_header"> Things to know </div>
|
|
206
|
+
<div className="details-container_content">
|
|
207
|
+
<div id="things-to-know">
|
|
208
|
+
{
|
|
209
|
+
thingsToKnow.map(item => (
|
|
210
|
+
<div className="item">
|
|
211
|
+
<div className="icon"> {item.icon} </div>
|
|
212
|
+
<label>{item.label}</label>
|
|
213
|
+
</div>
|
|
214
|
+
))
|
|
215
|
+
}
|
|
216
|
+
<div className="item guaranteed">
|
|
217
|
+
<div className="icon"> <Icon path={mdiShieldAirplane} size={1} /></div>
|
|
218
|
+
<label>Guaranteed Departure</label>
|
|
219
|
+
</div>
|
|
220
|
+
</div>
|
|
221
|
+
</div>
|
|
222
|
+
</div>
|
|
223
|
+
|
|
224
|
+
<div className="details-container">
|
|
225
|
+
<div className="details-container_header"> Description </div>
|
|
226
|
+
<div className="details-container_content">
|
|
227
|
+
<div id="description" className="pre-wrap">{details.description}</div>
|
|
228
|
+
</div>
|
|
229
|
+
</div>
|
|
230
|
+
|
|
231
|
+
<div className="details-container">
|
|
232
|
+
<div className="details-container_header"> Schedule Flight(s) </div>
|
|
233
|
+
<div className="details-container_content">
|
|
234
|
+
<Flex gap={20} vertical>
|
|
235
|
+
<div className="schedule">
|
|
236
|
+
<div className="flight-date">
|
|
237
|
+
<Icon path={mdiAirplane} size="12px" />
|
|
238
|
+
<span>23/10/2024</span>
|
|
239
|
+
</div>
|
|
240
|
+
<div className="flight-details">
|
|
241
|
+
<label> Kuala Lumpur (KUL) > Guangzhou (CAN) </label>
|
|
242
|
+
<div className="flight-details_airline">
|
|
243
|
+
<img src="/iceholidays-assets/images/china_southern_airlines_icon.png" />
|
|
244
|
+
<span>China Southern Airlines CZ366</span>
|
|
245
|
+
</div>
|
|
246
|
+
</div>
|
|
247
|
+
<div className="flight-time">
|
|
248
|
+
<Flex gap={13}>
|
|
249
|
+
<div className="from">
|
|
250
|
+
<label>08:55</label>
|
|
251
|
+
<span>Kuala Lumpur (KUL)</span>
|
|
252
|
+
</div>
|
|
253
|
+
<div className="flight-time_icon">
|
|
254
|
+
<img src="/iceholidays-assets/images/plane.png" />
|
|
255
|
+
</div>
|
|
256
|
+
<div className="to">
|
|
257
|
+
<label>12:55</label>
|
|
258
|
+
<span>Guangzhou (CAN)</span>
|
|
259
|
+
</div>
|
|
260
|
+
</Flex>
|
|
261
|
+
</div>
|
|
262
|
+
</div>
|
|
263
|
+
</Flex>
|
|
264
|
+
</div>
|
|
265
|
+
</div>
|
|
266
|
+
|
|
267
|
+
<div className="details-container">
|
|
268
|
+
<div className="details-container_header"> Price Details </div>
|
|
269
|
+
<div className="details-container_content">
|
|
270
|
+
<table id="pricing-table">
|
|
271
|
+
<thead>
|
|
272
|
+
<tr>
|
|
273
|
+
<th></th>
|
|
274
|
+
<th className="super-promo">1st-4th Pax
|
|
275
|
+
Super Promo</th>
|
|
276
|
+
<th className="promo">5th-6th Pax
|
|
277
|
+
Promo</th>
|
|
278
|
+
<th className="promo">Promo</th>
|
|
279
|
+
<th className="promo">Promo</th>
|
|
280
|
+
<th className="normal">Normal</th>
|
|
281
|
+
</tr>
|
|
282
|
+
</thead>
|
|
283
|
+
<tbody>
|
|
284
|
+
<tr>
|
|
285
|
+
<td>Adult</td>
|
|
286
|
+
<td className="super-promo">MYR 8,288</td>
|
|
287
|
+
<td className="promo">MYR 8,288</td>
|
|
288
|
+
<td className="promo">MYR 8,288</td>
|
|
289
|
+
<td className="promo">MYR 8,288</td>
|
|
290
|
+
<td className="normal">MYR 8,288</td>
|
|
291
|
+
</tr>
|
|
292
|
+
<tr>
|
|
293
|
+
<td>Child with extra bed</td>
|
|
294
|
+
<td className="super-promo">MYR 8,288</td>
|
|
295
|
+
<td className="promo">MYR 8,288</td>
|
|
296
|
+
<td className="promo">MYR 8,288</td>
|
|
297
|
+
<td className="promo">MYR 8,288</td>
|
|
298
|
+
<td className="normal">MYR 8,288</td>
|
|
299
|
+
</tr>
|
|
300
|
+
</tbody>
|
|
301
|
+
</table>
|
|
302
|
+
</div>
|
|
303
|
+
</div>
|
|
304
|
+
</Flex>
|
|
305
|
+
</div>
|
|
306
|
+
</Content>
|
|
307
|
+
<Sider width="265px" style={siderStyle}>
|
|
308
|
+
<div className="contact-agent">
|
|
309
|
+
<div className="contact-agent_header"> Contact Agent </div>
|
|
310
|
+
<div className="contact-agent_content">
|
|
311
|
+
<Form layout="vertical">
|
|
312
|
+
<Form.Item label="Select State">
|
|
313
|
+
<Select placeholder="Please select" options={[{ value: 'sample', label: <span>sample</span> }]} />
|
|
314
|
+
</Form.Item>
|
|
315
|
+
<Form.Item label="City">
|
|
316
|
+
<Select placeholder="Please select" options={[{ value: 'sample', label: <span>sample</span> }]} />
|
|
317
|
+
</Form.Item>
|
|
318
|
+
<Form.Item>
|
|
319
|
+
<Button type="primary" block>Find Agent</Button>
|
|
320
|
+
</Form.Item>
|
|
321
|
+
</Form>
|
|
322
|
+
{
|
|
323
|
+
this.state.showResult && (
|
|
324
|
+
<div className="search-results">
|
|
325
|
+
<Flex vertical gap={20}>
|
|
326
|
+
{
|
|
327
|
+
agentSearchResults.length > 0 && agentSearchResults.map(result => {
|
|
328
|
+
return (
|
|
329
|
+
<Row gutter={2} justify="space-between" className="agent-info">
|
|
330
|
+
<Col flex="180px"><span className="company" onClick={()=>this.showModal(result)}>
|
|
331
|
+
{result.company}</span>
|
|
332
|
+
</Col>
|
|
333
|
+
<Col flex="none"><Button color="default" variant="filled" shape="circle" size="small" icon={<Icon path={mdiPhoneInTalkOutline} size="16px" />}/></Col>
|
|
334
|
+
<Col flex="none"><Button color="default" variant="filled" shape="circle" size="small" icon={<Icon path={mdiEmailOutline} size="16px" />}/></Col>
|
|
335
|
+
<Col>
|
|
336
|
+
{
|
|
337
|
+
result.contactNumbers.length > 0 && (
|
|
338
|
+
<div className="contact-numbers">
|
|
339
|
+
{
|
|
340
|
+
result.contactNumbers.map(contactNumber => {
|
|
341
|
+
return (
|
|
342
|
+
<Button size="small" color="primary" variant="outlined">
|
|
343
|
+
<Icon path={mdiWhatsapp} size="12px" />
|
|
344
|
+
{contactNumber}
|
|
345
|
+
</Button>
|
|
346
|
+
)
|
|
347
|
+
})
|
|
348
|
+
}
|
|
349
|
+
</div>
|
|
350
|
+
)
|
|
351
|
+
}
|
|
352
|
+
</Col>
|
|
353
|
+
</Row>
|
|
354
|
+
)
|
|
355
|
+
})
|
|
356
|
+
}
|
|
357
|
+
</Flex>
|
|
358
|
+
</div>
|
|
359
|
+
)
|
|
360
|
+
}
|
|
361
|
+
</div>
|
|
362
|
+
</div>
|
|
363
|
+
</Sider>
|
|
364
|
+
</Layout>
|
|
365
|
+
</Layout>
|
|
366
|
+
|
|
367
|
+
|
|
368
|
+
<Modal title={<img src={this.state.agentData?.logo}/>} open={this.state.setIsModalOpen} onCancel={()=>this.closeModal()} footer={null} width={650} centered className="agent-full-contact-details">
|
|
369
|
+
<h2> {this.state.agentData?.company} </h2>
|
|
370
|
+
<div className="contact-details">
|
|
371
|
+
<Row gutter={[15, 15]} align="middle">
|
|
372
|
+
<Col span={24}>
|
|
373
|
+
<Icon path={mdiMapMarker} size="15px" />
|
|
374
|
+
<span>{this.state.agentData?.address}</span>
|
|
375
|
+
</Col>
|
|
376
|
+
{/* </Row>
|
|
377
|
+
<Row gutter={15} align="middle"> */}
|
|
378
|
+
<Col>
|
|
379
|
+
<Icon path={mdiPhoneInTalkOutline} size="15px" />
|
|
380
|
+
<span>{this.state.agentData?.phone}</span>
|
|
381
|
+
</Col>
|
|
382
|
+
<Col>
|
|
383
|
+
<Icon path={mdiWhatsapp} size="15px" />
|
|
384
|
+
<span>{this.state.agentData?.whatsapp}</span>
|
|
385
|
+
</Col>
|
|
386
|
+
<Col>
|
|
387
|
+
<Icon path={mdiEmailOutline} size="15px" />
|
|
388
|
+
<span>{this.state.agentData?.email}</span>
|
|
389
|
+
</Col>
|
|
390
|
+
</Row>
|
|
391
|
+
</div>
|
|
392
|
+
</Modal>
|
|
393
|
+
</div>
|
|
394
|
+
)
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { Space } from "antd";
|
|
2
|
+
import React, { useState } from "react";
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
const years = [ 2024, 2025];
|
|
6
|
+
const months = Array.from({length: 12}, (item, i) => {
|
|
7
|
+
return new Date(0, i).toLocaleString('en-US', {month: 'long'})
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
function FilterPills(
|
|
12
|
+
props: {
|
|
13
|
+
items:any[];
|
|
14
|
+
title?:string;
|
|
15
|
+
initialValue?:{keyword:string, year?:string, month?: string}
|
|
16
|
+
label?:string;
|
|
17
|
+
allOption?:boolean;
|
|
18
|
+
selectFilter;
|
|
19
|
+
}){
|
|
20
|
+
|
|
21
|
+
const { items, title, label, initialValue, allOption } = props;
|
|
22
|
+
|
|
23
|
+
const [selected, setSelected] = useState({});
|
|
24
|
+
var filterObject: {[k: string]: any} = {};
|
|
25
|
+
const selectFilter = (label, value) => {
|
|
26
|
+
filterObject[label] = value;
|
|
27
|
+
setSelected(filterObject);
|
|
28
|
+
props.selectFilter(filterObject);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return (
|
|
32
|
+
<Space size={12} direction="vertical">
|
|
33
|
+
{
|
|
34
|
+
allOption && <div className="filter-pill selected"> <span> All </span></div>
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
{
|
|
38
|
+
items && (
|
|
39
|
+
<>
|
|
40
|
+
{ title && <div className="filter-title"> {title} </div> }
|
|
41
|
+
<Space size={10} wrap>
|
|
42
|
+
{
|
|
43
|
+
items.map(item => {
|
|
44
|
+
const selectedItem = (selected["keyword"] ? selected["keyword"] : initialValue && initialValue.keyword );
|
|
45
|
+
const value = label ? item[label] : item;
|
|
46
|
+
return <div onClick={()=>selectFilter("keyword", value)} className={`filter-pill ${selectedItem == value && 'selected'}`}> <span>{ value } </span></div>
|
|
47
|
+
})
|
|
48
|
+
}
|
|
49
|
+
</Space>
|
|
50
|
+
</>
|
|
51
|
+
)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
<div className="filter-title"> Year </div>
|
|
55
|
+
<Space size={10} wrap>
|
|
56
|
+
{
|
|
57
|
+
years.map(year => {
|
|
58
|
+
const selectedItem = (selected["year"] ? selected["year"] : initialValue && initialValue.year);
|
|
59
|
+
return <div onClick={()=>selectFilter("item", year)} className={`filter-pill ${selectedItem == year.toString() && 'selected'}`}> <span>{year} </span></div>
|
|
60
|
+
})
|
|
61
|
+
}
|
|
62
|
+
</Space>
|
|
63
|
+
|
|
64
|
+
<div className="filter-title"> Month </div>
|
|
65
|
+
<Space size={10} wrap>
|
|
66
|
+
{
|
|
67
|
+
months.map(month => {
|
|
68
|
+
const selectedItem = (selected["month"] ? selected["month"] : initialValue && initialValue.month );
|
|
69
|
+
return <div onClick={()=>selectFilter("item", month)} className={`filter-pill ${selectedItem == month && 'selected'}`}> <span>{month} </span></div>
|
|
70
|
+
})
|
|
71
|
+
}
|
|
72
|
+
</Space>
|
|
73
|
+
</Space>
|
|
74
|
+
)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export default FilterPills;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { Form, Space, Input, DatePicker, Button, Flex } from "antd";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import SearchApi from "../../api-services/search-api.service";
|
|
4
|
+
import { useNavigate } from "react-router-dom";
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
function SearchBarWidget() {
|
|
8
|
+
const searchApi = new SearchApi;
|
|
9
|
+
const navigate= useNavigate();
|
|
10
|
+
|
|
11
|
+
const save = (formValues) => {
|
|
12
|
+
searchApi.search(formValues.keyword, formValues.month)
|
|
13
|
+
.then(result => {
|
|
14
|
+
navigate(`/app/listing?keyword=${formValues.keyword}`);
|
|
15
|
+
})
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
<div id="search-bar">
|
|
20
|
+
<img src="/iceholidays-assets/images/Rectangle49.png"/>
|
|
21
|
+
<div id="search-bar-widget">
|
|
22
|
+
<Form
|
|
23
|
+
onFinish={save}
|
|
24
|
+
layout="vertical"
|
|
25
|
+
>
|
|
26
|
+
<Form.Item wrapperCol={{ span: 24 }} label="Search" name="keyword">
|
|
27
|
+
<Input placeholder="Destinations, Attractions, etc" />
|
|
28
|
+
</Form.Item>
|
|
29
|
+
<Form.Item wrapperCol={{ span: 24 }} label="Travel Period" name="month">
|
|
30
|
+
<DatePicker picker="month" />
|
|
31
|
+
</Form.Item>
|
|
32
|
+
<Flex align="flex-end" justify="center">
|
|
33
|
+
<Button type="primary" className="search-button" htmlType="submit">Search</Button>
|
|
34
|
+
</Flex>
|
|
35
|
+
</Form>
|
|
36
|
+
</div>
|
|
37
|
+
<img src="/iceholidays-assets/images/Rectangle49.png" className="flip"/>
|
|
38
|
+
</div>
|
|
39
|
+
)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export default SearchBarWidget;
|
|
@@ -1,24 +1 @@
|
|
|
1
|
-
<%= react_component "
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
<div id="about-signature-tours" style="background: url(<%=asset_path('/iceholidays-assets/images/about_st_bg.png')%>) no-repeat 70% 7%, linear-gradient(65.77deg, rgba(170, 133, 62, 0.5) 33.44%, rgba(249, 225, 151, 0.5) 67.37%)">
|
|
5
|
-
<div>
|
|
6
|
-
<h1>ABOUT SIGNATURE TOURS</h1>
|
|
7
|
-
<p>
|
|
8
|
-
From charming accommodations to curated cultural encounters, every aspect is thoughtfully crafted to elevate your travel experience. At The Signature Tours, we believe in the S-Tour’s philosophy —where every moment is a signature memory.
|
|
9
|
-
</p>
|
|
10
|
-
<%=image_tag("/iceholidays-assets/images/Group_71.png")%>
|
|
11
|
-
<div id="about-st-feature">
|
|
12
|
-
<div style="max-width: 449px">
|
|
13
|
-
<p>Every experience is meticulously designed to create memories that last a lifetime. Our journeys go beyond the ordinary, offering experiences that are as unique as you are.</p>
|
|
14
|
-
</div>
|
|
15
|
-
<div id="feature">
|
|
16
|
-
<%=image_tag("/iceholidays-assets/images/feature.jpg")%>
|
|
17
|
-
<div id="st-brand">
|
|
18
|
-
<span>Signature Tours</span>
|
|
19
|
-
<%=image_tag("/iceholidays-assets/images/logomark.png", id: "st-logo")%>
|
|
20
|
-
</div>
|
|
21
|
-
</div>
|
|
22
|
-
</div>
|
|
23
|
-
</div>
|
|
24
|
-
</div>
|
|
1
|
+
<%= react_component "App"%>
|
|
@@ -4,21 +4,17 @@
|
|
|
4
4
|
<title>Iceholidays frontend</title>
|
|
5
5
|
<%= csrf_meta_tags %>
|
|
6
6
|
<%= csp_meta_tag %>
|
|
7
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
7
8
|
|
|
8
9
|
<%= yield :head %>
|
|
9
10
|
|
|
10
11
|
<%= javascript_include_tag "/iceholidays-assets/application", "data-turbo-track": "reload", type: "module" %>
|
|
11
|
-
<%= stylesheet_link_tag
|
|
12
|
+
<%= stylesheet_link_tag "/iceholidays-assets/application", media: "all" %>
|
|
12
13
|
</head>
|
|
13
14
|
<body>
|
|
14
|
-
|
|
15
|
-
<%=render partial:"layouts/iceholidays/frontend/shared/header"%>
|
|
16
|
-
|
|
17
15
|
<main>
|
|
18
16
|
<%= yield %>
|
|
19
17
|
</main>
|
|
20
|
-
|
|
21
|
-
<%=render partial:"layouts/iceholidays/frontend/shared/footer"%>
|
|
22
18
|
</body>
|
|
23
19
|
|
|
24
20
|
</html>
|
data/config/routes.rb
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
1
|
Iceholidays::Frontend::Engine.routes.draw do
|
|
2
2
|
root to: 'site#index'
|
|
3
|
+
|
|
4
|
+
get '/listing' => 'site#listing', as: :listing
|
|
5
|
+
get '/show' => 'site#show', as: :show
|
|
6
|
+
get '/about-us' => 'site#about_us', as: :about_us
|
|
7
|
+
get '/countries' => 'site#countries', as: :countries
|
|
8
|
+
get '/blog' => 'site#blog', as: :blog
|
|
9
|
+
get '/blog/1' => 'site#show_blog', as: :show_blog
|
|
10
|
+
get '/contact-agents' => 'site#contact_agents', as: :contact_agents
|
|
11
|
+
get '/contact-us' => 'site#contact_us', as: :contact_us
|
|
3
12
|
end
|