iceholidays-frontend 0.4.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/stylesheets/iceholidays/frontend/actiontext.scss +119 -0
  3. data/app/assets/stylesheets/iceholidays/frontend/application.sass.scss +968 -355
  4. data/app/assets/stylesheets/iceholidays/frontend/common.scss +159 -74
  5. data/app/assets/stylesheets/iceholidays/frontend/layout.scss +218 -125
  6. data/app/assets/stylesheets/iceholidays/frontend/utils/_antd_overrides.scss +22 -7
  7. data/app/assets/stylesheets/iceholidays/frontend/utils/_variables.scss +2 -1
  8. data/app/assets/stylesheets/iceholidays/frontend/widgets/filter_pills.scss +19 -12
  9. data/app/assets/stylesheets/iceholidays/frontend/widgets/search_bar.scss +4 -0
  10. data/app/controllers/iceholidays/frontend/posts_controller.rb +14 -0
  11. data/app/javascript/api-services/agents-api.service.ts +33 -0
  12. data/app/javascript/api-services/locations-api.service.ts +23 -1
  13. data/app/javascript/api-services/series-api.service.ts +48 -28
  14. data/app/javascript/interfaces/agent.interface.ts +11 -0
  15. data/app/javascript/interfaces/country.interface.ts +4 -3
  16. data/app/javascript/interfaces/itinerary.interface.ts +101 -8
  17. data/app/javascript/react/App.tsx +1 -1
  18. data/app/javascript/react/components/Destinations.tsx +30 -20
  19. data/app/javascript/react/components/PriceDetails.tsx +146 -0
  20. data/app/javascript/react/components/shared/ContactAgentsForm.tsx +44 -0
  21. data/app/javascript/react/components/shared/Headline.tsx +2 -1
  22. data/app/javascript/react/components/shared/LocationDropdown.tsx +34 -0
  23. data/app/javascript/react/components/shared/{Postcard.tsx → LocationPostcards.tsx} +22 -1
  24. data/app/javascript/react/layouts/MainFooter.tsx +64 -39
  25. data/app/javascript/react/layouts/MainHeader.tsx +68 -30
  26. data/app/javascript/react/pages/AboutUsPage.tsx +8 -8
  27. data/app/javascript/react/pages/BlogPage.tsx +6 -4
  28. data/app/javascript/react/pages/ContactAgentsPage.tsx +174 -5
  29. data/app/javascript/react/pages/ContactUsPage.tsx +5 -5
  30. data/app/javascript/react/pages/CountriesPage.tsx +3 -8
  31. data/app/javascript/react/pages/Homepage.tsx +23 -13
  32. data/app/javascript/react/pages/ListingPage.tsx +197 -145
  33. data/app/javascript/react/pages/ShowPage.tsx +275 -265
  34. data/app/javascript/react/widgets/FilterPills.tsx +83 -49
  35. data/app/javascript/react/widgets/SearchBarWidget.tsx +24 -8
  36. data/app/views/iceholidays/frontend/posts/index.html.erb +9 -0
  37. data/app/views/iceholidays/frontend/posts/show.html.erb +2 -0
  38. data/config/routes.rb +2 -1
  39. data/lib/iceholidays/frontend/version.rb +1 -1
  40. data/public/iceholidays-assets/application.css +1209 -437
  41. data/public/iceholidays-assets/application.js +91 -104
  42. data/public/iceholidays-assets/application.js.map +4 -4
  43. data/public/iceholidays-assets/images/TSTRibbon.png +0 -0
  44. data/public/iceholidays-assets/images/about-us_logo_mobile.png +0 -0
  45. data/public/iceholidays-assets/images/destinations_logo.png +0 -0
  46. data/public/iceholidays-assets/images/footer-bg_mobile.png +0 -0
  47. data/public/iceholidays-assets/images/logo_mobile.png +0 -0
  48. metadata +19 -27
  49. data/public/iceholidays-assets/images/8D7N.png +0 -0
  50. data/public/iceholidays-assets/images/Frame71.png +0 -0
  51. data/public/iceholidays-assets/images/africa.png +0 -0
  52. data/public/iceholidays-assets/images/banner1.png +0 -0
  53. data/public/iceholidays-assets/images/banner2.png +0 -0
  54. data/public/iceholidays-assets/images/china.png +0 -0
  55. data/public/iceholidays-assets/images/china2.png +0 -0
  56. data/public/iceholidays-assets/images/chongqing.png +0 -0
  57. data/public/iceholidays-assets/images/guangzhou.png +0 -0
  58. data/public/iceholidays-assets/images/guilin.png +0 -0
  59. data/public/iceholidays-assets/images/harbin.png +0 -0
  60. data/public/iceholidays-assets/images/hongkong.png +0 -0
  61. data/public/iceholidays-assets/images/inner_mongolia.png +0 -0
  62. data/public/iceholidays-assets/images/jiangxi.png +0 -0
  63. data/public/iceholidays-assets/images/kenya.png +0 -0
  64. data/public/iceholidays-assets/images/kenya2.png +0 -0
  65. data/public/iceholidays-assets/images/kunming.png +0 -0
  66. data/public/iceholidays-assets/images/slikroad.png +0 -0
  67. data/public/iceholidays-assets/images/southafrica.png +0 -0
  68. data/public/iceholidays-assets/images/tanzania.png +0 -0
  69. data/public/iceholidays-assets/images/tour1.png +0 -0
  70. data/public/iceholidays-assets/images/uganda.png +0 -0
  71. /data/public/iceholidays-assets/images/{Group_71.png → about-us_logo.png} +0 -0
  72. /data/public/iceholidays-assets/images/{logo_container.png → logo.png} +0 -0
@@ -1,5 +1,13 @@
1
1
  import React from "react";
2
2
  import Headline from "../components/shared/Headline";
3
+ import ContactAgentsForm from "../components/shared/ContactAgentsForm";
4
+ import AgentsApi from "../../api-services/agents-api.service";
5
+ import { Button, Card, Col, Modal, notification, Row } from "antd";
6
+ import { Agent } from "../../interfaces/agent.interface";
7
+ import { mdiMapMarker, mdiPhoneInTalkOutline, mdiWhatsapp, mdiEmailOutline } from "@mdi/js";
8
+ import Icon from "@mdi/react";
9
+
10
+ const { Meta } = Card;
3
11
 
4
12
  const bannerPath = '/iceholidays-assets/images/contact_agents.png';
5
13
  const breadcrumbs = [
@@ -7,10 +15,171 @@ const breadcrumbs = [
7
15
  { title: 'Contact Agents' }
8
16
  ]
9
17
 
10
- const ContactAgentsPage = React.FC = () => (
11
- <div id="contact-agents-page">
12
- <Headline bannerImage={bannerPath} breadcrumbs={breadcrumbs} title="CONTACT AGENTS"/>
13
- </div>
14
- );
18
+ class ContactAgentsPage extends React.Component {
19
+ agentsApi = new AgentsApi;
20
+
21
+ state = {
22
+ loading: true,
23
+ allAgents: [],
24
+ agents: [],
25
+ states: [],
26
+ cities: [],
27
+ setIsModalOpen: false,
28
+ agentData: { name: "", image: "", address: "", phone: "", whatsapp: "", email: "", city: "", state: "" },
29
+ }
30
+
31
+
32
+ componentDidMount() {
33
+ this.agentsApi.getAgents()
34
+ .then((agentsData:Agent[]) => {
35
+ const states = agentsData.filter(a => a.state != null).map(a => a.state);
36
+ const cities = agentsData.filter(a => a.city != null).map(a => a.city);
37
+ this.setState({agents: agentsData, allAgents: agentsData, loadingAgents:false, states, cities});
38
+ })
39
+ .finally(()=>this.setState({loading: false}))
40
+ .catch(error => {
41
+ notification.error({ message: 'An error occured while loading agents.'});
42
+ });
43
+ }
44
+
45
+ showModal(agentData){
46
+ this.setState({setIsModalOpen: true, agentData: agentData});
47
+ };
48
+
49
+ closeModal(){
50
+ this.setState({setIsModalOpen: false});
51
+ };
52
+
53
+
54
+ filterCities = (searchStr) => {
55
+ const allAgents:Agent[] = this.state.allAgents;
56
+
57
+ if(searchStr == undefined){
58
+ this.resetAgents();
59
+ return;
60
+ }
61
+ const agents:Agent[] = allAgents.filter(a => a.state == searchStr);
62
+ const results = agents.map(a => a.city);
63
+ this.setState({cities: results});
64
+ }
65
+
66
+
67
+ filterStates= (searchStr) => {
68
+ const allAgents:Agent[] = this.state.allAgents;
69
+
70
+ if(searchStr == undefined){
71
+ this.resetAgents();
72
+ return;
73
+ }
74
+
75
+ const agents:Agent[] = allAgents.filter(a => a.city == searchStr);
76
+ const results = agents.map(a => a.state);
77
+ this.setState({states: results});
78
+ }
79
+
80
+ resetAgents(){
81
+ const allAgents:Agent[] = this.state.allAgents;
82
+ const states = allAgents.filter(a => a.state != null).map(a => a.state);
83
+ const cities = allAgents.filter(a => a.city != null).map(a => a.city);
84
+ this.setState({states, cities});
85
+ }
86
+
87
+ findAgents = (formValues) => {
88
+ const allAgents:Agent[] = this.state.allAgents;
89
+ const agents = allAgents.filter(a =>
90
+ (formValues.state == undefined || a.state === formValues.state) &&
91
+ (formValues.city == undefined || a.city === formValues.city));
92
+ this.setState({agents, showAgentsResults: true})
93
+ }
94
+
95
+
96
+ render(){
97
+ const {agents, states, cities, agentData} = this.state;
98
+ return (
99
+ <div id="contact-agents-page">
100
+ <Headline bannerImage={bannerPath} breadcrumbs={breadcrumbs} title="CONTACT AGENTS"/>
101
+
102
+ <div id="contact-agents-page_body">
103
+ <div id="find-agents">
104
+ <div id="find-agents_header"><span>Get Your City</span></div>
105
+ <div id="find-agents_form">
106
+ <ContactAgentsForm
107
+ states={states}
108
+ cities={cities}
109
+ findAgents={this.findAgents}
110
+ filterCities={this.filterCities}
111
+ filterStates={this.filterStates}/>
112
+ </div>
113
+ </div>
114
+
115
+ <div id="agents-list">
116
+ <Row gutter={[20, 20]}>
117
+ {
118
+ agents.map((agent:Agent) => (
119
+ <Col xs={24} sm={24} md={12} lg={6}>
120
+ <Card
121
+ hoverable
122
+ cover={<img alt={agent.name} src={agent.image} />}
123
+ >
124
+ <Meta title={agent.name} description={
125
+ <>
126
+ <div className="agent-details">
127
+ <Row gutter={[20, 20]} align="middle">
128
+ <Col span={24}>
129
+ <Icon path={mdiMapMarker} size="15px" />
130
+ <span>{agent.address}</span>
131
+ </Col>
132
+ <Col span={24}>
133
+ <Icon path={mdiPhoneInTalkOutline} size="15px" />
134
+ <span>{agent.phone}</span>
135
+ </Col>
136
+ <Col span={24}>
137
+ <Icon path={mdiWhatsapp} size="15px" />
138
+ <span>{agent.whatsapp}</span>
139
+ </Col>
140
+ <Col span={24}>
141
+ <Icon path={mdiEmailOutline} size="15px" />
142
+ <span>{agent.email}</span>
143
+ </Col>
144
+ </Row>
145
+ </div>
146
+ <Button color="primary" variant="outlined" className="more-info-button"
147
+ onClick={()=>this.showModal(agent)}>
148
+ More info
149
+ </Button>
150
+ </>
151
+ } />
152
+ </Card>
153
+ </Col>
154
+ ))
155
+ }
156
+ </Row>
157
+ </div>
158
+
159
+ <Modal title={
160
+ <>
161
+ <img src={agentData?.image}/>
162
+ <span> {agentData.name} </span>
163
+ </>
164
+ } open={this.state.setIsModalOpen} onCancel={()=>this.closeModal()} footer={null} width={350} centered className="agent-full-details">
165
+ <Row gutter={[10,10]}>
166
+ <Col span={12}> <label>Agent Name</label> </Col>
167
+ <Col span={12}> <span> {agentData.name} </span></Col>
168
+ <Col span={12}> <label>State</label> </Col>
169
+ <Col span={12}> <span> {agentData.state} </span></Col>
170
+ <Col span={12}> <label>Address</label> </Col>
171
+ <Col span={12}> <span> {agentData.address} </span></Col>
172
+ <Col span={12}> <label>Tel</label> </Col>
173
+ <Col span={12}> <span> {agentData.phone} </span></Col>
174
+ <Col span={12}> <label>Email</label> </Col>
175
+ <Col span={12}> <span> {agentData.email} </span></Col>
176
+ </Row>
177
+ {/* google maps */}
178
+ </Modal>
179
+ </div>
180
+ </div>
181
+ )
182
+ }
183
+ }
15
184
 
16
185
  export default ContactAgentsPage;
@@ -83,25 +83,25 @@ const ContactUsPage = React.FC = () => {
83
83
  <TextArea rows={4} placeholder="Write Here"/>
84
84
  </Form.Item>
85
85
 
86
- <Form.Item wrapperCol={{ offset: 10, span: 14 }}>
86
+ <Flex align="center" justify="center">
87
87
  <Button type="primary" htmlType="submit">
88
88
  Submit
89
89
  </Button>
90
- </Form.Item>
90
+ </Flex>
91
91
 
92
92
  </Form>
93
93
  </div>
94
94
  </div>
95
95
 
96
96
  <div id="contact-us-page_footer">
97
- <Row gutter={29}>
98
- <Col span={12}>
97
+ <Row gutter={[29, 20]} >
98
+ <Col xs={24} sm={24} lg={12}>
99
99
  <div>
100
100
  <label>Contact Us</label>
101
101
  <span>feedback@gd.my</span>
102
102
  </div>
103
103
  </Col>
104
- <Col span={12}>
104
+ <Col xs={24} sm={24} lg={12}>
105
105
  <div>
106
106
  <label>Connect with Us</label>
107
107
  <Space size={29}>
@@ -1,9 +1,8 @@
1
1
  import React from "react";
2
2
  import Headline from "../components/shared/Headline";
3
3
  import LocationsApi from "../../api-services/locations-api.service";
4
- import { Col, Flex, notification, Row } from "antd";
5
- import { Country } from "../../interfaces/country.interface";
6
- import Postcard from "../components/shared/Postcard";
4
+ import { Flex, notification } from "antd";
5
+ import LocationPostcards from "../components/shared/LocationPostcards";
7
6
 
8
7
  const bannerPath = '/iceholidays-assets/images/about_us.png';
9
8
  const breadcrumbs = [
@@ -49,11 +48,7 @@ export default class CountriesPage extends React.Component {
49
48
  </div>
50
49
 
51
50
  <h2> Countries </h2>
52
- <div className="postcards">
53
- {
54
- this.state.countries.map((country:Country, index) => <Postcard key={index} link={`/app/listing?keyword=${country.name}`} image={country.cover} name={country.name} tourCount={country.tourCount}/>)
55
- }
56
- </div>
51
+ <LocationPostcards locations={this.state.countries}/>
57
52
  </div>
58
53
 
59
54
  </div>
@@ -2,7 +2,7 @@ import React from "react";
2
2
  import Testimonials from "../components/Testimonials";
3
3
  import Destinations from "../components/Destinations";
4
4
  import SearchBarWidget from "../widgets/SearchBarWidget";
5
- import { Carousel, notification } from "antd";
5
+ import { Carousel, Col, notification, Row } from "antd";
6
6
  import SlickButtonFix from "../components/shared/SlickButtonFix";
7
7
  import BannersApi from "../../api-services/banners-api.service";
8
8
  import { Banner } from "../../interfaces/banner.interface";
@@ -61,7 +61,9 @@ export default class Homepage extends React.Component {
61
61
  </div>
62
62
 
63
63
  <Destinations/>
64
- <Testimonials/>
64
+ <div id="testimonials-section">
65
+ <Testimonials/>
66
+ </div>
65
67
 
66
68
  <div id="about-signature-tours" style={{background: "url('/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%)"}}>
67
69
  <div>
@@ -69,18 +71,26 @@ export default class Homepage extends React.Component {
69
71
  <p>
70
72
  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.
71
73
  </p>
72
- <img src="/iceholidays-assets/images/Group_71.png"/>
74
+ <picture>
75
+ <source media="(min-width: 600px)" srcSet="/iceholidays-assets/images/about-us_logo.png" />
76
+ <source media="(max-width: 599px)" srcSet="/iceholidays-assets/images/about-us_logo_mobile.png" />
77
+ <img src="/iceholidays-assets/images/about-us_logo.png" alt="About Signature Tours Logo Line"/>
78
+ </picture>
73
79
  <div id="about-st-feature">
74
- <div style={{maxWidth: "449px"}}>
75
- <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>
76
- </div>
77
- <div id="feature">
78
- <img src="/iceholidays-assets/images/feature.jpg"/>
79
- <div id="st-brand">
80
- <span>Signature Tours</span>
81
- <img src="/iceholidays-assets/images/logomark.png" id="st-logo"/>
82
- </div>
83
- </div>
80
+ <Row gutter={[20, 20]} align="middle">
81
+ <Col flex="1 0 50%" className="column">
82
+ <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>
83
+ </Col>
84
+ <Col flex="1 0 50%" className="column">
85
+ <div id="feature">
86
+ <img src="/iceholidays-assets/images/feature.jpg"/>
87
+ <div id="st-brand">
88
+ <span>Signature Tours</span>
89
+ <img src="/iceholidays-assets/images/logomark.png" id="st-logo"/>
90
+ </div>
91
+ </div>
92
+ </Col>
93
+ </Row>
84
94
  </div>
85
95
  </div>
86
96
  </div>