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.
- checksums.yaml +4 -4
- data/app/assets/stylesheets/iceholidays/frontend/actiontext.scss +119 -0
- data/app/assets/stylesheets/iceholidays/frontend/application.sass.scss +968 -355
- data/app/assets/stylesheets/iceholidays/frontend/common.scss +159 -74
- data/app/assets/stylesheets/iceholidays/frontend/layout.scss +218 -125
- data/app/assets/stylesheets/iceholidays/frontend/utils/_antd_overrides.scss +22 -7
- data/app/assets/stylesheets/iceholidays/frontend/utils/_variables.scss +2 -1
- data/app/assets/stylesheets/iceholidays/frontend/widgets/filter_pills.scss +19 -12
- data/app/assets/stylesheets/iceholidays/frontend/widgets/search_bar.scss +4 -0
- data/app/controllers/iceholidays/frontend/posts_controller.rb +14 -0
- data/app/javascript/api-services/agents-api.service.ts +33 -0
- data/app/javascript/api-services/locations-api.service.ts +23 -1
- data/app/javascript/api-services/series-api.service.ts +48 -28
- data/app/javascript/interfaces/agent.interface.ts +11 -0
- data/app/javascript/interfaces/country.interface.ts +4 -3
- data/app/javascript/interfaces/itinerary.interface.ts +101 -8
- data/app/javascript/react/App.tsx +1 -1
- data/app/javascript/react/components/Destinations.tsx +30 -20
- data/app/javascript/react/components/PriceDetails.tsx +146 -0
- data/app/javascript/react/components/shared/ContactAgentsForm.tsx +44 -0
- data/app/javascript/react/components/shared/Headline.tsx +2 -1
- data/app/javascript/react/components/shared/LocationDropdown.tsx +34 -0
- data/app/javascript/react/components/shared/{Postcard.tsx → LocationPostcards.tsx} +22 -1
- data/app/javascript/react/layouts/MainFooter.tsx +64 -39
- data/app/javascript/react/layouts/MainHeader.tsx +68 -30
- data/app/javascript/react/pages/AboutUsPage.tsx +8 -8
- data/app/javascript/react/pages/BlogPage.tsx +6 -4
- data/app/javascript/react/pages/ContactAgentsPage.tsx +174 -5
- data/app/javascript/react/pages/ContactUsPage.tsx +5 -5
- data/app/javascript/react/pages/CountriesPage.tsx +3 -8
- data/app/javascript/react/pages/Homepage.tsx +23 -13
- data/app/javascript/react/pages/ListingPage.tsx +197 -145
- data/app/javascript/react/pages/ShowPage.tsx +275 -265
- data/app/javascript/react/widgets/FilterPills.tsx +83 -49
- data/app/javascript/react/widgets/SearchBarWidget.tsx +24 -8
- data/app/views/iceholidays/frontend/posts/index.html.erb +9 -0
- data/app/views/iceholidays/frontend/posts/show.html.erb +2 -0
- data/config/routes.rb +2 -1
- data/lib/iceholidays/frontend/version.rb +1 -1
- data/public/iceholidays-assets/application.css +1209 -437
- data/public/iceholidays-assets/application.js +91 -104
- data/public/iceholidays-assets/application.js.map +4 -4
- data/public/iceholidays-assets/images/TSTRibbon.png +0 -0
- data/public/iceholidays-assets/images/about-us_logo_mobile.png +0 -0
- data/public/iceholidays-assets/images/destinations_logo.png +0 -0
- data/public/iceholidays-assets/images/footer-bg_mobile.png +0 -0
- data/public/iceholidays-assets/images/logo_mobile.png +0 -0
- metadata +19 -27
- data/public/iceholidays-assets/images/8D7N.png +0 -0
- data/public/iceholidays-assets/images/Frame71.png +0 -0
- data/public/iceholidays-assets/images/africa.png +0 -0
- data/public/iceholidays-assets/images/banner1.png +0 -0
- data/public/iceholidays-assets/images/banner2.png +0 -0
- data/public/iceholidays-assets/images/china.png +0 -0
- data/public/iceholidays-assets/images/china2.png +0 -0
- data/public/iceholidays-assets/images/chongqing.png +0 -0
- data/public/iceholidays-assets/images/guangzhou.png +0 -0
- data/public/iceholidays-assets/images/guilin.png +0 -0
- data/public/iceholidays-assets/images/harbin.png +0 -0
- data/public/iceholidays-assets/images/hongkong.png +0 -0
- data/public/iceholidays-assets/images/inner_mongolia.png +0 -0
- data/public/iceholidays-assets/images/jiangxi.png +0 -0
- data/public/iceholidays-assets/images/kenya.png +0 -0
- data/public/iceholidays-assets/images/kenya2.png +0 -0
- data/public/iceholidays-assets/images/kunming.png +0 -0
- data/public/iceholidays-assets/images/slikroad.png +0 -0
- data/public/iceholidays-assets/images/southafrica.png +0 -0
- data/public/iceholidays-assets/images/tanzania.png +0 -0
- data/public/iceholidays-assets/images/tour1.png +0 -0
- data/public/iceholidays-assets/images/uganda.png +0 -0
- /data/public/iceholidays-assets/images/{Group_71.png → about-us_logo.png} +0 -0
- /data/public/iceholidays-assets/images/{logo_container.png → logo.png} +0 -0
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
|
|
2
|
+
import { List, Card, Space } from "antd";
|
|
3
|
+
import React from "react";
|
|
4
|
+
import { data } from "react-router-dom";
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
const pricingCategory = {
|
|
8
|
+
"adult": "Adult",
|
|
9
|
+
"child_no_bed": "Child no bed",
|
|
10
|
+
"child_twin": "Child twin",
|
|
11
|
+
"child_with_bed": "Child with bed",
|
|
12
|
+
"infant": "Infant",
|
|
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",
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const priceTypes = {
|
|
23
|
+
"normal": "normal",
|
|
24
|
+
"normal1": "normal 1",
|
|
25
|
+
"normal2": "normal 2",
|
|
26
|
+
"normal3": "normal 3",
|
|
27
|
+
"normal4": "normal 4",
|
|
28
|
+
"normal5": "normal 5",
|
|
29
|
+
"normal6": "normal 6",
|
|
30
|
+
"normal7": "normal 7",
|
|
31
|
+
"normal8": "normal 8",
|
|
32
|
+
"normal9": "normal 9",
|
|
33
|
+
"early_bird": "early bird",
|
|
34
|
+
"specialoffer": "special offer",
|
|
35
|
+
"specialdeal": "special deal",
|
|
36
|
+
"superpromo": "super promo",
|
|
37
|
+
"promo": "promo",
|
|
38
|
+
"promo1": "promo 1",
|
|
39
|
+
"promo2": "promo 2",
|
|
40
|
+
"promo3": "promo 3",
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
const PriceDetails = (
|
|
45
|
+
props: {
|
|
46
|
+
priceCurrency:string,
|
|
47
|
+
prices: any[]
|
|
48
|
+
}
|
|
49
|
+
) => {
|
|
50
|
+
const { priceCurrency, prices } = props;
|
|
51
|
+
|
|
52
|
+
var pricingTypes:any[] = [], priceTable:any = {}, priceList:any[] = [];
|
|
53
|
+
if(prices.length>0){
|
|
54
|
+
pricingTypes = prices.map((price:any) => price.type);
|
|
55
|
+
prices.forEach((price:any) => {
|
|
56
|
+
const pricingObj = {
|
|
57
|
+
label: price.display_price,
|
|
58
|
+
adult: price.adult,
|
|
59
|
+
child_no_bed: price.child_no_bed,
|
|
60
|
+
child_twin: price.child_twin,
|
|
61
|
+
child_with_bed: price.child_with_bed,
|
|
62
|
+
dta_adult: price.dta_adult,
|
|
63
|
+
dta_child_no_bed: price.dta_child_no_bed,
|
|
64
|
+
dta_child_twin: price.dta_child_twin,
|
|
65
|
+
dta_child_with_bed: price.dta_child_with_bed,
|
|
66
|
+
dta_infant: price.dta_infant,
|
|
67
|
+
dta_single_supplement: price.dta_single_supplement,
|
|
68
|
+
infant: price.infant,
|
|
69
|
+
single_supplement: price.single_supplement,
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
priceTable[price.type] = pricingObj;
|
|
73
|
+
|
|
74
|
+
priceList.push({
|
|
75
|
+
title: `${price.display_price} ${priceTypes[price.type]}`,
|
|
76
|
+
type: price.type,
|
|
77
|
+
...pricingObj
|
|
78
|
+
})
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return (
|
|
83
|
+
<div id="price-details" className="details-container">
|
|
84
|
+
<div className="details-container_header"> Price Details </div>
|
|
85
|
+
<div className="details-container_content">
|
|
86
|
+
<table id="pricing-table">
|
|
87
|
+
<thead>
|
|
88
|
+
<tr>
|
|
89
|
+
<th></th>
|
|
90
|
+
{
|
|
91
|
+
pricingTypes.map((type:any) => <th className={type}>
|
|
92
|
+
<div>{priceTable[type].label}</div>
|
|
93
|
+
<div className="price-type">{priceTypes[type]}</div>
|
|
94
|
+
</th>)
|
|
95
|
+
}
|
|
96
|
+
</tr>
|
|
97
|
+
</thead>
|
|
98
|
+
<tbody>
|
|
99
|
+
{
|
|
100
|
+
Object.entries(pricingCategory).map(category => (
|
|
101
|
+
<tr>
|
|
102
|
+
<td> {category[1]} </td>
|
|
103
|
+
{
|
|
104
|
+
pricingTypes.map((type:any) => <td className={type}> {priceCurrency} {priceTable[type][category[0]]}</td>)
|
|
105
|
+
}
|
|
106
|
+
</tr>
|
|
107
|
+
))
|
|
108
|
+
}
|
|
109
|
+
</tbody>
|
|
110
|
+
</table>
|
|
111
|
+
|
|
112
|
+
{
|
|
113
|
+
priceList.length > 0 && (
|
|
114
|
+
<List
|
|
115
|
+
id="pricing-list"
|
|
116
|
+
itemLayout="vertical"
|
|
117
|
+
dataSource={priceList}
|
|
118
|
+
renderItem={(item) => (
|
|
119
|
+
<List.Item>
|
|
120
|
+
<Card className={item.type}>
|
|
121
|
+
<div className="pricing-header"> {item.title} </div>
|
|
122
|
+
<div className="pricing-body">
|
|
123
|
+
<Space size={15} direction="vertical" style={{display: 'flex'}}>
|
|
124
|
+
{
|
|
125
|
+
Object.entries(pricingCategory).map(category => (
|
|
126
|
+
<div className="pricing">
|
|
127
|
+
<div className="category"> {category[1]} </div>
|
|
128
|
+
<div className="price">{priceCurrency} {item[category[0]]} </div>
|
|
129
|
+
</div>
|
|
130
|
+
))
|
|
131
|
+
}
|
|
132
|
+
</Space>
|
|
133
|
+
</div>
|
|
134
|
+
</Card>
|
|
135
|
+
</List.Item>
|
|
136
|
+
)}
|
|
137
|
+
/>
|
|
138
|
+
)
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
</div>
|
|
142
|
+
</div>
|
|
143
|
+
)
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export default PriceDetails;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { Form, Select, Button, Flex } from "antd";
|
|
2
|
+
import React from "react";
|
|
3
|
+
|
|
4
|
+
export default function ContactAgentsForm(
|
|
5
|
+
props: {
|
|
6
|
+
states: any[];
|
|
7
|
+
cities: any[];
|
|
8
|
+
findAgents;
|
|
9
|
+
filterCities;
|
|
10
|
+
filterStates;
|
|
11
|
+
}
|
|
12
|
+
) {
|
|
13
|
+
const {states, cities, findAgents, filterCities, filterStates} = props;
|
|
14
|
+
|
|
15
|
+
return (
|
|
16
|
+
<Form layout="vertical" onFinish={findAgents}>
|
|
17
|
+
<Form.Item wrapperCol={{ span: 24 }} label="Select State" name="state">
|
|
18
|
+
<Select
|
|
19
|
+
allowClear={true}
|
|
20
|
+
showSearch
|
|
21
|
+
filterOption={(input, option) =>
|
|
22
|
+
(option?.label ?? '').toString().toLowerCase().includes(input.toLowerCase())
|
|
23
|
+
}
|
|
24
|
+
placeholder="Please select"
|
|
25
|
+
options={states.map((s:any) => {return {label: s, value: s}})}
|
|
26
|
+
onChange={filterCities}/>
|
|
27
|
+
</Form.Item>
|
|
28
|
+
<Form.Item wrapperCol={{ span: 24 }} label="City" name="city">
|
|
29
|
+
<Select
|
|
30
|
+
allowClear={true}
|
|
31
|
+
showSearch
|
|
32
|
+
filterOption={(input, option) =>
|
|
33
|
+
(option?.label ?? '').toString().toLowerCase().includes(input.toLowerCase())
|
|
34
|
+
}
|
|
35
|
+
placeholder="Please select"
|
|
36
|
+
options={cities.map((s:any) => {return {label: s, value: s}})}
|
|
37
|
+
onChange={filterStates}/>
|
|
38
|
+
</Form.Item>
|
|
39
|
+
<Flex align="flex-end" justify="center">
|
|
40
|
+
<Button type="primary" className="find-button" htmlType="submit">Find Agent</Button>
|
|
41
|
+
</Flex>
|
|
42
|
+
</Form>
|
|
43
|
+
)
|
|
44
|
+
}
|
|
@@ -6,6 +6,7 @@ import SearchBarWidget from "../../widgets/SearchBarWidget";
|
|
|
6
6
|
const Headline = (
|
|
7
7
|
props: {
|
|
8
8
|
bannerImage: string;
|
|
9
|
+
showSearch?: boolean;
|
|
9
10
|
title?: string;
|
|
10
11
|
children?: JSX.Element;
|
|
11
12
|
breadcrumbs: any[];
|
|
@@ -14,7 +15,7 @@ const Headline = (
|
|
|
14
15
|
const { bannerImage, title, children, breadcrumbs } = props;
|
|
15
16
|
return (
|
|
16
17
|
<>
|
|
17
|
-
<SearchBarWidget/>
|
|
18
|
+
{(props.showSearch == undefined || props.showSearch && props.showSearch == true) && <SearchBarWidget/>}
|
|
18
19
|
<div id="headline">
|
|
19
20
|
<div id="headline_banner" style={{backgroundImage: `url(${bannerImage})`}}></div>
|
|
20
21
|
<div id="headline_header">
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import Icon from "@mdi/react";
|
|
3
|
+
import { Location } from "../../../interfaces/country.interface";
|
|
4
|
+
import { Select } from "antd";
|
|
5
|
+
import { mdiFilterVariant } from "@mdi/js";
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
const LocationDropdown = (
|
|
9
|
+
props: {
|
|
10
|
+
locations:Location[];
|
|
11
|
+
selectLocation;
|
|
12
|
+
}
|
|
13
|
+
) => {
|
|
14
|
+
const { locations } = props;
|
|
15
|
+
|
|
16
|
+
return (
|
|
17
|
+
<div className="location-dropdown">
|
|
18
|
+
<Select
|
|
19
|
+
className="location-filter"
|
|
20
|
+
suffixIcon={<Icon path={mdiFilterVariant} size="18px" />}
|
|
21
|
+
variant="borderless"
|
|
22
|
+
defaultValue="china"
|
|
23
|
+
options={locations.map((location) => ({label: location.name, value: location.id}))}
|
|
24
|
+
dropdownStyle={{padding: "15px 20px", borderRadius: "20px", boxShadow: "0px 3.08px 16.47px 0px #00000040"}}
|
|
25
|
+
optionRender={(option) => (
|
|
26
|
+
<div className="location-filter_option"> {option.label} </div>
|
|
27
|
+
)}
|
|
28
|
+
onChange={props.selectLocation}
|
|
29
|
+
/>
|
|
30
|
+
</div>
|
|
31
|
+
)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export default LocationDropdown;
|
|
@@ -2,6 +2,7 @@ import React from "react";
|
|
|
2
2
|
import { Link } from "react-router-dom";
|
|
3
3
|
import { mdiMenuRight } from "@mdi/js";
|
|
4
4
|
import Icon from "@mdi/react";
|
|
5
|
+
import { Location } from "../../../interfaces/country.interface";
|
|
5
6
|
|
|
6
7
|
|
|
7
8
|
const Postcard = (
|
|
@@ -28,4 +29,24 @@ const Postcard = (
|
|
|
28
29
|
)
|
|
29
30
|
}
|
|
30
31
|
|
|
31
|
-
|
|
32
|
+
const LocationPostcards = (
|
|
33
|
+
props: {
|
|
34
|
+
locations:Location[];
|
|
35
|
+
}
|
|
36
|
+
) => {
|
|
37
|
+
const { locations } = props;
|
|
38
|
+
|
|
39
|
+
const listingLink = (locationId: number) => {
|
|
40
|
+
return `/app/listing?location_id=${locationId}`;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return (
|
|
44
|
+
<div className="postcards">
|
|
45
|
+
{
|
|
46
|
+
locations.map((city, index)=><Postcard key={index} link={listingLink(city.id)} image={city.cover} name={city.name} tourCount={city.tourCount}/>)
|
|
47
|
+
}
|
|
48
|
+
</div>
|
|
49
|
+
)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export default LocationPostcards;
|
|
@@ -1,10 +1,37 @@
|
|
|
1
|
-
import { notification, Space } from "antd";
|
|
1
|
+
import { Col, Flex, notification, Row, Space } from "antd";
|
|
2
2
|
import React from "react";
|
|
3
3
|
import { Link } from "react-router-dom";
|
|
4
4
|
import LocationsApi from "../../api-services/locations-api.service";
|
|
5
5
|
import { Country } from "../../interfaces/country.interface";
|
|
6
6
|
|
|
7
7
|
|
|
8
|
+
const menus = [
|
|
9
|
+
{
|
|
10
|
+
label: "Home",
|
|
11
|
+
link: "/app"
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
label: "pdpa",
|
|
15
|
+
link: "/app"
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
label: "about us",
|
|
19
|
+
link: "/app/about-us"
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
label: "privacy policy",
|
|
23
|
+
link: "/app"
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
label: "contact us",
|
|
27
|
+
link: "/app/contact-us"
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
label: "terms & conditions",
|
|
31
|
+
link: "/app"
|
|
32
|
+
},
|
|
33
|
+
]
|
|
34
|
+
|
|
8
35
|
export default class MainFooter extends React.Component {
|
|
9
36
|
api = new LocationsApi;
|
|
10
37
|
|
|
@@ -25,44 +52,42 @@ export default class MainFooter extends React.Component {
|
|
|
25
52
|
render(){
|
|
26
53
|
return (
|
|
27
54
|
<div id="main-footer">
|
|
28
|
-
<
|
|
29
|
-
<
|
|
30
|
-
<
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
<
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
</
|
|
47
|
-
</
|
|
48
|
-
<
|
|
49
|
-
<
|
|
50
|
-
<
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
<hr/>
|
|
65
|
-
</div>
|
|
55
|
+
<Row id="main-footer_links" gutter={[12, 12]}>
|
|
56
|
+
<Col flex="1 0 25%" className="column">
|
|
57
|
+
<Space direction="vertical">
|
|
58
|
+
<div className="link-group-title">Countries</div>
|
|
59
|
+
<div className="link-group-items">
|
|
60
|
+
{
|
|
61
|
+
this.state.countries.map((country: Country)=> <Link key={country.id} to={`/app/listing?keyword=${country.name}`}>{country.name}</Link> )
|
|
62
|
+
}
|
|
63
|
+
</div>
|
|
64
|
+
</Space>
|
|
65
|
+
</Col>
|
|
66
|
+
<Col flex="1 0 30%" className="column footer-menu">
|
|
67
|
+
<Space direction="vertical">
|
|
68
|
+
<div className="link-group-items">
|
|
69
|
+
{
|
|
70
|
+
menus.map(menu => <Link to={menu.link}>{menu.label}</Link>)
|
|
71
|
+
}
|
|
72
|
+
</div>
|
|
73
|
+
</Space>
|
|
74
|
+
</Col>
|
|
75
|
+
<Col flex="1 0 20%" className="column contact-info">
|
|
76
|
+
<Space direction="vertical" align="center">
|
|
77
|
+
<Flex vertical gap="20px" align="center">
|
|
78
|
+
<div className="link-group-title">Contact Us</div>
|
|
79
|
+
<div><Link to="/app/contact-agents">contact agents</Link></div>
|
|
80
|
+
<div className="link-group-title">Follow us on</div>
|
|
81
|
+
<Flex gap={20} justify="space-between">
|
|
82
|
+
<img src="/iceholidays-assets/images/social/ico_fb.png"/>
|
|
83
|
+
<img src="/iceholidays-assets/images/social/ico_twitter.png"/>
|
|
84
|
+
<img src="/iceholidays-assets/images/social/ico_yt.png"/>
|
|
85
|
+
<img src="/iceholidays-assets/images/social/ico_ig.png"/>
|
|
86
|
+
</Flex>
|
|
87
|
+
</Flex>
|
|
88
|
+
</Space>
|
|
89
|
+
</Col>
|
|
90
|
+
</Row>
|
|
66
91
|
<div id="copyright">
|
|
67
92
|
<span>Copyright © 2024 Golden Destinations</span>
|
|
68
93
|
</div>
|
|
@@ -1,43 +1,81 @@
|
|
|
1
|
-
import { mdiFileDownload } from "@mdi/js";
|
|
1
|
+
import { mdiFileDownload, mdiMenu } from "@mdi/js";
|
|
2
2
|
import Icon from "@mdi/react";
|
|
3
|
-
import { Button } from "antd";
|
|
4
|
-
import React from "react";
|
|
5
|
-
import {
|
|
3
|
+
import { Button, Drawer, Menu } from "antd";
|
|
4
|
+
import React, { useState } from "react";
|
|
5
|
+
import type { MenuProps } from 'antd';
|
|
6
|
+
import { Link, useLocation, useMatch } from "react-router-dom";
|
|
6
7
|
|
|
8
|
+
type MenuItem = Required<MenuProps>['items'][number];
|
|
7
9
|
|
|
8
|
-
const routes = [
|
|
9
|
-
{label: "Home", path: "/app"},
|
|
10
|
-
{label: "About Us", path: "/app/about-us"},
|
|
11
|
-
{label: "Countries", path: "/app/countries"},
|
|
12
|
-
{label: "Blog", path: "/app/blog"}
|
|
13
|
-
]
|
|
14
10
|
|
|
15
|
-
const
|
|
16
|
-
{
|
|
17
|
-
|
|
11
|
+
const items: MenuItem[] = [
|
|
12
|
+
{
|
|
13
|
+
key: 'app',
|
|
14
|
+
label: <Link to="/app"> Home </Link>
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
key: 'about-us',
|
|
18
|
+
label: <Link to="/app/about-us"> About Us </Link>
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
key: 'countries',
|
|
22
|
+
label: <Link to="/app/countries"> Countries </Link>
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
key: 'blog',
|
|
26
|
+
label: <Link to="/app/blog"> Blog </Link>
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
key: 'logo',
|
|
30
|
+
label: <img src="/iceholidays-assets/images/logo.png" className="logo logo_desktop"/>,
|
|
31
|
+
disabled: true
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
key: 'contact-agents',
|
|
35
|
+
label: <Link to="/app/contact-agents"> Contact Agents </Link>
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
key: 'contact-us',
|
|
39
|
+
label: <Link to="/app/contact-us"> Contact Us </Link>
|
|
40
|
+
},
|
|
18
41
|
]
|
|
19
42
|
|
|
20
43
|
const MainHeader = () => {
|
|
44
|
+
const [open, setOpen] = useState(false);
|
|
45
|
+
const location = useLocation();
|
|
46
|
+
const activeUrlKey = location.pathname.split("/").pop() || "app";
|
|
47
|
+
const [current, setCurrent] = useState(activeUrlKey);
|
|
48
|
+
|
|
49
|
+
const onClick: MenuProps['onClick'] = (e) => {
|
|
50
|
+
setCurrent(e.key);
|
|
51
|
+
setOpen(false);
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const showDrawer = () => {
|
|
55
|
+
setOpen(true);
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const onClose = () => {
|
|
59
|
+
setOpen(false);
|
|
60
|
+
};
|
|
61
|
+
|
|
21
62
|
return (
|
|
22
63
|
<div id="main-header">
|
|
23
|
-
<
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
</
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
{
|
|
34
|
-
routes2.map((route, index)=> <NavLink key={index} to={route.path} end className={({ isActive }) => (isActive ? 'active' : '')}> {route.label} </NavLink>)
|
|
35
|
-
}
|
|
36
|
-
</div>
|
|
64
|
+
<Menu mode="horizontal" items={items} onClick={onClick} selectedKeys={[current]} className="nav-menu"/>
|
|
65
|
+
|
|
66
|
+
<a href="/app"><img src="/iceholidays-assets/images/logo_mobile.png" className="logo logo_mobile"/></a>
|
|
67
|
+
|
|
68
|
+
<div id="nav-buttons">
|
|
69
|
+
<Button id="get-brochure" type="primary"><Icon path={mdiFileDownload} size="18px" /> get brochure</Button>
|
|
70
|
+
|
|
71
|
+
<Button id="toggle-menu" type="primary" onClick={showDrawer}>
|
|
72
|
+
<Icon path={mdiMenu} size="25px" />
|
|
73
|
+
</Button>
|
|
37
74
|
</div>
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
75
|
+
|
|
76
|
+
<Drawer title={null} onClose={onClose} open={open} id="nav-drawer">
|
|
77
|
+
<Menu items={items} onClick={onClick} selectedKeys={[current]} className="nav-menu_mobile"/>
|
|
78
|
+
</Drawer>
|
|
41
79
|
</div>
|
|
42
80
|
)
|
|
43
81
|
}
|
|
@@ -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
|
|
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
|
|
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>
|
|
@@ -50,21 +50,21 @@ const AboutUsPage = React.FC = () => (
|
|
|
50
50
|
<p>ICE Holidays is committed to striving towards our customer satisfaction in areas of more quality value for money of our products & services. The management and all employees are committed to the company quality policy through effort in:</p>
|
|
51
51
|
</div>
|
|
52
52
|
</Col>
|
|
53
|
-
<Col
|
|
53
|
+
<Col xs={24} sm={24} lg={8}>
|
|
54
54
|
<div className="items">
|
|
55
55
|
<img src="/iceholidays-assets/images/innovative.png"/>
|
|
56
56
|
<label>Innovative</label>
|
|
57
57
|
<p>Talent team develops great products and services; Agile, innovative, and a quality conscious team of resourceful people dedicated to the best.</p>
|
|
58
58
|
</div>
|
|
59
59
|
</Col>
|
|
60
|
-
<Col
|
|
60
|
+
<Col xs={24} sm={24} lg={8}>
|
|
61
61
|
<div className="items">
|
|
62
62
|
<img src="/iceholidays-assets/images/competitiveness.png"/>
|
|
63
63
|
<label>Competitiveness</label>
|
|
64
64
|
<p>Provide competitive pricing to achieve customer satisfaction.</p>
|
|
65
65
|
</div>
|
|
66
66
|
</Col>
|
|
67
|
-
<Col
|
|
67
|
+
<Col xs={24} sm={24} lg={8}>
|
|
68
68
|
<div className="items">
|
|
69
69
|
<img src="/iceholidays-assets/images/ethical.png"/>
|
|
70
70
|
<label>Ethical</label>
|
|
@@ -73,17 +73,17 @@ const AboutUsPage = React.FC = () => (
|
|
|
73
73
|
</Col>
|
|
74
74
|
</Row>
|
|
75
75
|
|
|
76
|
-
<Row id="certificates" gutter={24}>
|
|
76
|
+
<Row id="certificates" align="middle" justify="center" gutter={[24, 24]}>
|
|
77
77
|
<Col span={24}>
|
|
78
78
|
<div className="section-header">
|
|
79
79
|
<h2>Our Certificates</h2>
|
|
80
80
|
<p>We have acquired recognition and certificates such as:</p>
|
|
81
81
|
</div>
|
|
82
82
|
</Col>
|
|
83
|
-
<Col
|
|
83
|
+
<Col xs={24} sm={24} md={12} lg={8}>
|
|
84
84
|
<img src="/iceholidays-assets/images/certificate1.png"/>
|
|
85
85
|
</Col>
|
|
86
|
-
<Col
|
|
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>
|
|
@@ -36,6 +36,10 @@ const blogs = [
|
|
|
36
36
|
},
|
|
37
37
|
]
|
|
38
38
|
|
|
39
|
+
const setFilter = (selectedFilter) => {
|
|
40
|
+
console.log("set filter", selectedFilter)
|
|
41
|
+
}
|
|
42
|
+
|
|
39
43
|
|
|
40
44
|
const BlogPage = React.FC = () => (
|
|
41
45
|
<div id="blog-page">
|
|
@@ -43,16 +47,14 @@ const BlogPage = React.FC = () => (
|
|
|
43
47
|
|
|
44
48
|
<div id="blog-page_body">
|
|
45
49
|
<Space size={12} direction="vertical">
|
|
46
|
-
<FilterPills items={types} allOption={true}></FilterPills>
|
|
47
|
-
<FilterPills items="years" title="Year" allOption={true}></FilterPills>
|
|
48
|
-
<FilterPills items="months" title="Month" allOption={true}></FilterPills>
|
|
50
|
+
<FilterPills items={types} allOption={true} initialValue={{keyword: "", year: "", month: ""}} selectFilter={(selected)=>setFilter(selected)}></FilterPills>
|
|
49
51
|
</Space>
|
|
50
52
|
|
|
51
53
|
<div id="blogs">
|
|
52
54
|
<Row wrap gutter={20}>
|
|
53
55
|
{
|
|
54
56
|
blogs.map(blog => (
|
|
55
|
-
<Col span={8}>
|
|
57
|
+
<Col key={blog.id} span={8}>
|
|
56
58
|
<Link to={`/app/blog/${blog.id}`}>
|
|
57
59
|
<Card
|
|
58
60
|
hoverable
|