iceholidays-frontend 0.5.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9543a8bab876ad4982f485380d55661e2be5bfc331c5aeac759e9bc7994956db
4
- data.tar.gz: 66a5be926856f9cb40f5cff827168e2d4d3f33ad10b60505680be62bd5f90cd4
3
+ metadata.gz: 6247a8c09cfbda6553642ceb846d1a1661d98edbfa83a891f3ae54dc1cc8db14
4
+ data.tar.gz: 5551d3ff2200d552fe3449604ff5ee3159a5096a06c19436b630e721ce2f3632
5
5
  SHA512:
6
- metadata.gz: 116f2957d4e6557c76fb96a8477cd4d8316f2e0309a8a3fb412563089e13fefbe63287148095255532e29e5256c5bff7116ed07e2e0c0471f516d75a2b04066d
7
- data.tar.gz: fb90a122c99796f4388378857fde351a57b8daf4baa025d2fdb0aa5d222853ef88b3840924d2e4339c78c921e765e38cbe54eced1813ae9a798061552f226afb
6
+ metadata.gz: f69e3e14e999712b65290da68cfda945d889b63d23acbfa94aad05351d6df78e77ca02150830688860187af1a724a763cb2402b673397140fc415eba4d99cb23
7
+ data.tar.gz: ad72cf692918fac66f81acf70a12790a6eec52cc34127bc8acf82ad8d1892ca5242d98a629c132066ab0bcb289452bb30f92bdc2511804eb7ff325fa46f668bc
@@ -467,6 +467,13 @@ body{
467
467
  }
468
468
  }
469
469
  }
470
+
471
+ #no-tours-found{
472
+ font-family: $font-default;
473
+ font-weight: 400;
474
+ text-align: center;
475
+ color: #00000c99;
476
+ }
470
477
  }
471
478
 
472
479
  .tour_details_description.ant-modal{
@@ -1233,7 +1240,7 @@ body{
1233
1240
  font-size: 24px;
1234
1241
  font-weight: 500;
1235
1242
  line-height: 36px;
1236
- text-align: left;
1243
+ text-align: center;
1237
1244
  text-underline-position: from-font;
1238
1245
  text-decoration-skip-ink: none;
1239
1246
  }
@@ -199,10 +199,11 @@
199
199
  margin-top: 100px;
200
200
 
201
201
  &_header{
202
- height: 138px;
202
+ height: 150px;
203
203
  text-align: center;
204
204
  position: relative;
205
- background-image: url('/iceholidays-assets/images/Layer_1.png');
205
+ background-image: url('/iceholidays-assets/images/TSTRibbon.png');
206
+ background-repeat: no-repeat;
206
207
 
207
208
  h1{
208
209
  font-family: $font-default;
@@ -11,12 +11,12 @@ const pricingCategory = {
11
11
  "child_with_bed": "Child with bed",
12
12
  "infant": "Infant",
13
13
  "single_supplement": "Single Supplement",
14
- "dta_adult": "DTA Adult",
15
- "dta_child_no_bed": "DTA Child no bed",
16
- "dta_child_twin": "DTA Child twin",
17
- "dta_child_with_bed": "DTA Child with bed",
18
- "dta_infant": "DTA Infant",
19
- "dta_single_supplement": "DTA Single Supplement",
14
+ // "dta_adult": "DTA Adult",
15
+ // "dta_child_no_bed": "DTA Child no bed",
16
+ // "dta_child_twin": "DTA Child twin",
17
+ // "dta_child_with_bed": "DTA Child with bed",
18
+ // "dta_infant": "DTA Infant",
19
+ // "dta_single_supplement": "DTA Single Supplement",
20
20
  };
21
21
 
22
22
  const priceTypes = {
@@ -26,12 +26,12 @@ const AboutUsPage = React.FC = () => (
26
26
  <Col span={24}>
27
27
  <img src="/iceholidays-assets/images/about_us2.png"/>
28
28
  </Col>
29
- <Col span={12}>
29
+ <Col xs={24} sm={24} lg={12}>
30
30
  <p>The Signature Tours was born from a passion for redefining travel. We believe that journeys should be more than just trips—they should be transformative experiences, filled with moments that leave an indelible mark on the soul. Catering to discerning travelers who seek more than the ordinary, The Signature Tours crafts bespoke journeys that combine sophistication, cultural immersion, and unparalleled quality. </p>
31
31
  <p>Our story begins with a vision: to create journeys that linger in the heart long after the traveler returns home. Each itinerary we design reflects our dedication to perfection. From the charm of boutique accommodations nestled in picturesque landscapes to handpicked cultural experiences that unveil the soul of a destination, every detail is thoughtfully considered to ensure your journey is as seamless as it is extraordinary.</p>
32
32
  <p>At The Signature Tours, we embrace the philosophy of the S-Tours experience—where every moment is a masterpiece. Imagine strolling through the cobblestone streets of a quaint village, savoring the aroma of freshly baked bread as locals welcome you with warm smiles. </p>
33
33
  </Col>
34
- <Col span={12}>
34
+ <Col xs={24} sm={24} lg={12}>
35
35
  <p>Picture yourself standing atop a majestic mountain at sunrise,the golden hues of the horizon reflecting the sense of awe within you. These are the kinds of moments we strive to create—authentic, meaningful, and unforgettable.</p>
36
36
  <p>But our commitment goes beyond premium and comfort. It’s about forging connections—with places, cultures, and people. It’s about stepping into a story, whether it’s exploring ancient ruins with a seasoned archaeologist, learning the art of wine making from a passionate vintner, or sharing laughter with a local family over a home-cooked meal.</p>
37
37
  <p>At The Signature Tours, every journey is an invitation to step out of the ordinary and into a world of wonder. We’re not just about travel; we’re about creating memories that stay with you forever. This is our promise, and this is what we call the S-Tours philosophy where we deliver S-Class Journeys, Signature Memories. Because every journey should be as unique as your signature.</p>
@@ -80,10 +80,10 @@ const AboutUsPage = React.FC = () => (
80
80
  <p>We have acquired recognition and certificates such as:</p>
81
81
  </div>
82
82
  </Col>
83
- <Col xs={24} sm={24} lg={8}>
83
+ <Col xs={24} sm={24} md={12} lg={8}>
84
84
  <img src="/iceholidays-assets/images/certificate1.png"/>
85
85
  </Col>
86
- <Col xs={24} sm={24} lg={8}>
86
+ <Col xs={24} sm={24} md={12} lg={8}>
87
87
  <img src="/iceholidays-assets/images/certificate2.png"/>
88
88
  </Col>
89
89
  </Row>
@@ -180,77 +180,83 @@ class ListingPage extends React.Component <{searchParams}> {
180
180
  <FilterPills items={selectedCountry.cities} bindLabel="name" bindValue="location_id" initialValue={searchParamsObj} selectFilter={(selected) => this.getItineraries(selected)}></FilterPills>
181
181
  </Space>
182
182
 
183
- <div id="legends">
184
- <Space size={17}>
185
- {
186
- legends.map(legend => <Badge key={legend.id} color={legend.color} text={legend.label} />)
187
- }
188
- </Space>
189
- </div>
190
-
191
- <div id="tours">
192
- <Flex vertical gap={30}>
193
- {
194
- itineraries.map((itinerary:Itinerary) => {
195
- const departureDates = itinerary.departureDate ? itinerary.departureDate.map(ddate => {
196
- var type = (itinerary.guranteedDepartureDates && itinerary.guranteedDepartureDates.includes(ddate)) ? "guaranteed" :
197
- (itinerary.almostGuaranteedDepartureDates && itinerary.almostGuaranteedDepartureDates.includes(ddate)) ? "almost-guaranteed" : "";
198
-
199
- return { type, date: ddate }
200
- }) : [];
201
-
202
- return (
203
- <Row key={itinerary.id} className="tour">
204
- <Col flex="1 0 25%" className="column">
205
- <div className="tour_image"> <img src={itinerary.images[0]}/> </div>
206
- </Col>
207
- <Col flex="1 0 55%" className="column">
208
- <div className="tour_details">
209
- <Space size={20} direction="vertical" style={{ display: 'flex' }}>
210
- <Space size={10} direction="vertical">
211
- <div className="tour_details_title"> {itinerary.caption} </div>
212
- <div className="tour_details_info">
213
- <span onClick={()=>this.showModal("descriptionModalOpen", "descriptionData", itinerary.description)}><Icon path={mdiInformationOutline} size={1}/></span>
214
- </div>
215
- <div>
216
- <span className="tour_details_country"> <Icon path={mdiMapMarkerOutline} size="18px" /> {itinerary.country} </span>
217
- <span className="tour_details_code" onClick={()=>this.showModal("itineraryModalOpen", "fileUrlData", itinerary.fileUrl)}> <Icon path={mdiFileDownload} size="18px" /> {itinerary.code} </span>
218
- </div>
219
- </Space>
220
- <div className="tour_details_dates">
221
- <Space size={6} direction="vertical" style={{ display: 'flex' }}>
222
- <label>Departure Date(s)</label>
223
- <div className="date-selector">
224
- {
225
- departureDates && departureDates.map((ddate, index) => <span key={index} style={{borderColor: getColorByType(ddate.type)}}> {ddate.date} </span>)
226
- }
227
- {
228
- departureDates.length >= 9 && <div className="show-all-dates" onClick={()=>this.showModal("dateModalOpen", "departureDatesData", departureDates)}> <Icon path={mdiDotsHorizontalCircleOutline} size="15px" /> Show All </div>
229
- }
183
+ {
184
+ itineraries.length > 0 ? (
185
+ <>
186
+ <div id="legends">
187
+ <Space size={17}>
188
+ {
189
+ legends.map(legend => <Badge key={legend.id} color={legend.color} text={legend.label} />)
190
+ }
191
+ </Space>
192
+ </div>
193
+ <div id="tours">
194
+ <Flex vertical gap={30}>
195
+ {
196
+ itineraries.map((itinerary:Itinerary) => {
197
+ const departureDates = itinerary.departureDate ? itinerary.departureDate.map(ddate => {
198
+ var type = (itinerary.guranteedDepartureDates && itinerary.guranteedDepartureDates.includes(ddate)) ? "guaranteed" :
199
+ (itinerary.almostGuaranteedDepartureDates && itinerary.almostGuaranteedDepartureDates.includes(ddate)) ? "almost-guaranteed" : "";
200
+
201
+ return { type, date: ddate }
202
+ }) : [];
203
+
204
+ return (
205
+ <Row key={itinerary.id} className="tour">
206
+ <Col flex="1 0 25%" className="column">
207
+ <div className="tour_image"> <img src={itinerary.images[0]}/> </div>
208
+ </Col>
209
+ <Col flex="1 0 55%" className="column">
210
+ <div className="tour_details">
211
+ <Space size={20} direction="vertical" style={{ display: 'flex' }}>
212
+ <Space size={10} direction="vertical">
213
+ <div className="tour_details_title"> {itinerary.caption} </div>
214
+ <div className="tour_details_info">
215
+ <span onClick={()=>this.showModal("descriptionModalOpen", "descriptionData", itinerary.description)}><Icon path={mdiInformationOutline} size={1}/></span>
216
+ </div>
217
+ <div>
218
+ <span className="tour_details_country"> <Icon path={mdiMapMarkerOutline} size="18px" /> {itinerary.country} </span>
219
+ <span className="tour_details_code" onClick={()=>this.showModal("itineraryModalOpen", "fileUrlData", itinerary.fileUrl)}> <Icon path={mdiFileDownload} size="18px" /> {itinerary.code} </span>
220
+ </div>
221
+ </Space>
222
+ <div className="tour_details_dates">
223
+ <Space size={6} direction="vertical" style={{ display: 'flex' }}>
224
+ <label>Departure Date(s)</label>
225
+ <div className="date-selector">
226
+ {
227
+ departureDates && departureDates.map((ddate, index) => <span key={index} style={{borderColor: getColorByType(ddate.type)}}> {ddate.date} </span>)
228
+ }
229
+ {
230
+ departureDates.length >= 9 && <div className="show-all-dates" onClick={()=>this.showModal("dateModalOpen", "departureDatesData", departureDates)}> <Icon path={mdiDotsHorizontalCircleOutline} size="15px" /> Show All </div>
231
+ }
232
+ </div>
233
+ </Space>
230
234
  </div>
231
235
  </Space>
232
236
  </div>
233
- </Space>
234
- </div>
235
- </Col>
236
- <Col flex="1 0 20%" className="column">
237
- <div className="tour_pricing">
238
- <Space size={20} direction="vertical" align="center">
239
- <Flex className="tour_pricing_details">
240
- <span>From</span>
241
- <span className="price">{itinerary.priceCurrency} {itinerary.price}</span>
242
- <span>All In</span>
243
- </Flex>
244
- <Link className="select-tour" to={`/app/itinerary/${itinerary.id}`}>Select</Link>
245
- </Space>
246
- </div>
247
- </Col>
248
- </Row>
249
- )
250
- })
251
- }
252
- </Flex>
253
- </div>
237
+ </Col>
238
+ <Col flex="1 0 20%" className="column">
239
+ <div className="tour_pricing">
240
+ <Space size={20} direction="vertical" align="center">
241
+ <Flex className="tour_pricing_details">
242
+ <span>From</span>
243
+ <span className="price">{itinerary.priceCurrency} {itinerary.price}</span>
244
+ <span>All In</span>
245
+ </Flex>
246
+ <Link className="select-tour" to={`/app/itinerary/${itinerary.id}`}>Select</Link>
247
+ </Space>
248
+ </div>
249
+ </Col>
250
+ </Row>
251
+ )
252
+ })
253
+ }
254
+ </Flex>
255
+ </div>
256
+ </>
257
+ ) : <h1 id="no-tours-found">Not tour package is found.</h1>
258
+ }
259
+
254
260
  </div>
255
261
 
256
262
  <Modal title="Description" open={this.state.descriptionModalOpen} onCancel={()=>this.closeModal("descriptionModalOpen")} footer={null} width={1000} centered className="tour_details_description">
@@ -86,11 +86,10 @@ class ShowPage extends React.Component <{params;}> {
86
86
  getAgents(){
87
87
  this.agentsApi.getAgents()
88
88
  .then((agentsData:Agent[]) => {
89
- const states = agentsData.filter(a => a.state != null).map(a => a.state);
90
- const cities = agentsData.filter(a => a.city != null).map(a => a.city);
91
- this.setState({agents: agentsData, allAgents: agentsData, loadingAgents:false, states, cities});
89
+ this.setState({agents: agentsData, allAgents: agentsData});
90
+ this.resetAgents(agentsData);
92
91
  })
93
- .finally(()=>this.setState({loading: false}))
92
+ .finally(()=>this.setState({loading: false}))
94
93
  .catch(error => {
95
94
  notification.error({ message: 'An error occured while loading agents.'});
96
95
  });
@@ -138,11 +137,13 @@ class ShowPage extends React.Component <{params;}> {
138
137
  this.setState({states: results});
139
138
  }
140
139
 
141
- resetAgents(){
142
- const allAgents:Agent[] = this.state.allAgents;
143
- const states = allAgents.filter(a => a.state != null).map(a => a.state);
144
- const cities = allAgents.filter(a => a.city != null).map(a => a.city);
145
- this.setState({states, cities});
140
+ resetAgents(agents?){
141
+ const allAgents:Agent[] = agents || this.state.allAgents;
142
+ const states = allAgents.filter(a => a.state?.replace(/\s/g, "") != '').map(a => a.state);
143
+ const cities = allAgents.filter(a => a.city?.replace(/\s/g, "") != '').map(a => a.city);
144
+ let uniqStates = [... new Set(states.map(x=>x))];
145
+ let uniqCities = [... new Set(cities.map(x=>x))];
146
+ this.setState({states: uniqStates, cities: uniqCities});
146
147
  }
147
148
 
148
149
  findAgents = (formValues) => {
@@ -190,7 +191,7 @@ class ShowPage extends React.Component <{params;}> {
190
191
  </Headline>
191
192
 
192
193
  <div id="date-selector">
193
- <Carousel autoplay arrows dots={false} draggable slidesToScroll= {1} slidesToShow={8}
194
+ <Carousel infinite={false} arrows dots={false} draggable={true} slidesToScroll= {1} slidesToShow={8}
194
195
  prevArrow={
195
196
  <SlickButtonFix>
196
197
  <Icon path={mdiMenuLeft} size={2} />
@@ -272,41 +273,45 @@ class ShowPage extends React.Component <{params;}> {
272
273
  <div className="details-container_header"> Schedule Flight(s) </div>
273
274
  <div className="details-container_content">
274
275
  <Flex gap={20} vertical>
275
- <div className="schedule">
276
- <div className="flight-date">
277
- <Icon path={mdiAirplane} size="12px" />
278
- <span>23/10/2024</span>
279
- </div>
280
- <div className="flight-details">
281
- <label> Kuala Lumpur (KUL) &gt; Guangzhou (CAN) </label>
282
- <div className="flight-details_airline">
283
- <img src="/iceholidays-assets/images/china_southern_airlines_icon.png" />
284
- <span>China Southern Airlines CZ366</span>
285
- </div>
286
- </div>
287
- <div className="flight-time">
288
- <Flex gap={13}>
289
- <div className="from">
290
- <label>08:55</label>
291
- <span>Kuala Lumpur (KUL)</span>
276
+ {
277
+ selectedTour?.flights.map((flight:any) => (
278
+ <div className="schedule" key={flight.id}>
279
+ <div className="flight-date">
280
+ <Icon path={mdiAirplane} size="12px" />
281
+ <span>{flight.departure_date}</span>
292
282
  </div>
293
- <div className="flight-time_icon">
294
- <img src="/iceholidays-assets/images/plane.png" />
283
+ <div className="flight-details">
284
+ <label> {flight.from_airport} &gt; {flight.to_airport} </label>
285
+ <div className="flight-details_airline">
286
+ <img src={flight.airline_logo} />
287
+ <span>{flight.airline}</span>
288
+ </div>
295
289
  </div>
296
- <div className="to">
297
- <label>12:55</label>
298
- <span>Guangzhou (CAN)</span>
290
+ <div className="flight-time">
291
+ <Flex gap={13}>
292
+ <div className="from">
293
+ <label>{flight.departure_time}</label>
294
+ <span>{flight.from_airport}</span>
295
+ </div>
296
+ <div className="flight-time_icon">
297
+ <img src="/iceholidays-assets/images/plane.png" />
298
+ </div>
299
+ <div className="to">
300
+ <label>{flight.arrival_time}</label>
301
+ <span>{flight.to_airport}</span>
302
+ </div>
303
+ </Flex>
299
304
  </div>
300
- </Flex>
301
- </div>
302
- </div>
305
+ </div>
306
+ ))
307
+ }
303
308
  </Flex>
304
309
  </div>
305
310
  </div>
306
311
  )
307
312
  }
308
313
 
309
- <PriceDetails priceCurrency={itinerary.priceCurrency} prices={selectedTour?.prices}/>
314
+ {selectedTour?.prices.length > 0 && <PriceDetails priceCurrency={itinerary.priceCurrency} prices={selectedTour?.prices}/>}
310
315
 
311
316
  </Flex>
312
317
  </div>
@@ -1,5 +1,5 @@
1
1
  module Iceholidays
2
2
  module Frontend
3
- VERSION = "0.5.0"
3
+ VERSION = "0.6.0"
4
4
  end
5
5
  end
@@ -484,10 +484,11 @@ a {
484
484
  margin-top: 100px;
485
485
  }
486
486
  #ribbon-section_header {
487
- height: 138px;
487
+ height: 150px;
488
488
  text-align: center;
489
489
  position: relative;
490
- background-image: url("/iceholidays-assets/images/Layer_1.png");
490
+ background-image: url("/iceholidays-assets/images/TSTRibbon.png");
491
+ background-repeat: no-repeat;
491
492
  }
492
493
  #ribbon-section_header h1 {
493
494
  font-family: Poppins, san-serif;
@@ -1243,6 +1244,12 @@ body {
1243
1244
  display: block;
1244
1245
  width: 100%;
1245
1246
  }
1247
+ #listing-page #no-tours-found {
1248
+ font-family: Poppins, san-serif;
1249
+ font-weight: 400;
1250
+ text-align: center;
1251
+ color: rgba(0, 0, 12, 0.6);
1252
+ }
1246
1253
 
1247
1254
  .tour_details_description.ant-modal .ant-modal-title {
1248
1255
  font-family: Poppins, san-serif;
@@ -1873,7 +1880,7 @@ body {
1873
1880
  font-size: 24px;
1874
1881
  font-weight: 500;
1875
1882
  line-height: 36px;
1876
- text-align: left;
1883
+ text-align: center;
1877
1884
  text-underline-position: from-font;
1878
1885
  text-decoration-skip-ink: none;
1879
1886
  }