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
|
@@ -1,10 +1,17 @@
|
|
|
1
|
-
import { Space } from "antd";
|
|
2
|
-
import React, { useState } from "react";
|
|
1
|
+
import { Col, Row, Space } from "antd";
|
|
2
|
+
import React, { useEffect, useState } from "react";
|
|
3
3
|
|
|
4
4
|
|
|
5
|
-
const years =
|
|
5
|
+
const years = () => {
|
|
6
|
+
const currentYear = new Date().getFullYear();
|
|
7
|
+
const nextYear = new Date(new Date().setFullYear(currentYear + 1)).getFullYear();
|
|
8
|
+
return [currentYear, nextYear]
|
|
9
|
+
};
|
|
6
10
|
const months = Array.from({length: 12}, (item, i) => {
|
|
7
|
-
return
|
|
11
|
+
return {
|
|
12
|
+
shortMonth: new Date(0, i).toLocaleString('en-US', {month: 'short'}),
|
|
13
|
+
name: new Date(0, i).toLocaleString('en-US', {month: 'long'})
|
|
14
|
+
}
|
|
8
15
|
});
|
|
9
16
|
|
|
10
17
|
|
|
@@ -12,66 +19,93 @@ function FilterPills(
|
|
|
12
19
|
props: {
|
|
13
20
|
items:any[];
|
|
14
21
|
title?:string;
|
|
15
|
-
initialValue
|
|
16
|
-
|
|
22
|
+
initialValue:{keyword?:string, year?:string, month?: string, location_id?:any}
|
|
23
|
+
bindLabel?:string;
|
|
24
|
+
bindValue?:string;
|
|
17
25
|
allOption?:boolean;
|
|
18
26
|
selectFilter;
|
|
19
27
|
}){
|
|
20
28
|
|
|
21
|
-
const { items, title,
|
|
29
|
+
const { items, title, bindLabel, bindValue, initialValue, allOption } = props;
|
|
30
|
+
|
|
31
|
+
const [selected, setSelected] = useState(initialValue);
|
|
22
32
|
|
|
23
|
-
const
|
|
24
|
-
|
|
33
|
+
const allHasValues = () => {
|
|
34
|
+
const {keyword, ...noKeyword} = selected;
|
|
35
|
+
return Object.entries(noKeyword).every(o => o[1] != "");
|
|
36
|
+
}
|
|
37
|
+
const [collapseFilters, setcollapseFilters] = useState(allHasValues);
|
|
38
|
+
|
|
25
39
|
const selectFilter = (label, value) => {
|
|
26
|
-
|
|
27
|
-
setSelected(
|
|
28
|
-
|
|
40
|
+
selected[label] = value;
|
|
41
|
+
setSelected(selected);
|
|
42
|
+
|
|
43
|
+
setcollapseFilters(allHasValues);
|
|
44
|
+
|
|
45
|
+
props.selectFilter(selected);
|
|
29
46
|
}
|
|
30
47
|
|
|
31
48
|
return (
|
|
32
|
-
|
|
33
|
-
{
|
|
34
|
-
allOption && <div className="filter-pill selected"> <span> All </span></div>
|
|
35
|
-
}
|
|
36
|
-
|
|
49
|
+
<>
|
|
37
50
|
{
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
51
|
+
collapseFilters==false && (
|
|
52
|
+
|
|
53
|
+
<Space size={12} direction="vertical">
|
|
54
|
+
{
|
|
55
|
+
items && (
|
|
56
|
+
<>
|
|
57
|
+
{ title && <div className="filter-title"> {title} </div> }
|
|
58
|
+
<Space size={10} wrap>
|
|
59
|
+
{
|
|
60
|
+
allOption && <div className="filter-pill selected"> <span> All </span></div>
|
|
61
|
+
}
|
|
62
|
+
{
|
|
63
|
+
items.map((item, index) => {
|
|
64
|
+
//special case for location id
|
|
65
|
+
const id:any = bindValue == "location_id" ? "id" : bindValue;
|
|
66
|
+
const label = bindLabel ? item[bindLabel] : item;
|
|
67
|
+
const value = bindValue ? item[id] : item;
|
|
68
|
+
const selectedItem = selected && bindValue ? selected[bindValue]: item ;
|
|
69
|
+
return <div key={index} onClick={()=>selectFilter(bindValue, value)} className={`filter-pill ${selectedItem == value && 'selected'}`}> <span>{ label } </span></div>
|
|
70
|
+
})
|
|
71
|
+
}
|
|
72
|
+
</Space>
|
|
73
|
+
</>
|
|
74
|
+
)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
<div className="filter-title"> Year </div>
|
|
41
78
|
<Space size={10} wrap>
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
79
|
+
{
|
|
80
|
+
allOption && <div className="filter-pill selected"> <span> All </span></div>
|
|
81
|
+
}
|
|
82
|
+
{
|
|
83
|
+
years().map((year, index) => {
|
|
84
|
+
const selectedItem = selected && selected.year;
|
|
85
|
+
return <div key={index} onClick={()=>selectFilter("year", year)} className={`filter-pill default-filter ${selectedItem == year.toString() && 'selected'}`}> <span>{year} </span></div>
|
|
86
|
+
})
|
|
87
|
+
}
|
|
49
88
|
</Space>
|
|
50
|
-
|
|
89
|
+
|
|
90
|
+
<div className="filter-title"> Month </div>
|
|
91
|
+
<Row gutter={[10, 10]} justify="space-between">
|
|
92
|
+
{
|
|
93
|
+
allOption && <Col className="filter-pill selected"> <span> All </span></Col>
|
|
94
|
+
}
|
|
95
|
+
{
|
|
96
|
+
months.map((month, index) => {
|
|
97
|
+
const selectedItem = selected && selected.month ;
|
|
98
|
+
return <Col xs={8} md={6} lg={4}> <div key={index} onClick={()=>selectFilter("month", month.shortMonth)} className={`filter-pill default-filter ${selectedItem?.toString() == month.shortMonth && 'selected'}`}> <span>{month.name} </span></div> </Col>
|
|
99
|
+
})
|
|
100
|
+
}
|
|
101
|
+
</Row>
|
|
102
|
+
</Space>
|
|
51
103
|
)
|
|
104
|
+
|
|
52
105
|
}
|
|
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>
|
|
106
|
+
</>
|
|
74
107
|
)
|
|
108
|
+
|
|
75
109
|
}
|
|
76
110
|
|
|
77
111
|
export default FilterPills;
|
|
@@ -1,20 +1,36 @@
|
|
|
1
1
|
import { Form, Space, Input, DatePicker, Button, Flex } from "antd";
|
|
2
2
|
import React from "react";
|
|
3
3
|
import SearchApi from "../../api-services/search-api.service";
|
|
4
|
-
import { useNavigate } from "react-router-dom";
|
|
4
|
+
import { useNavigate, useSearchParams } from "react-router-dom";
|
|
5
|
+
import dayjs from "dayjs";
|
|
5
6
|
|
|
7
|
+
const monthFormat = "MMM YYYY";
|
|
6
8
|
|
|
7
9
|
function SearchBarWidget() {
|
|
8
10
|
const searchApi = new SearchApi;
|
|
9
11
|
const navigate= useNavigate();
|
|
12
|
+
const [searchParams] = useSearchParams();
|
|
10
13
|
|
|
11
14
|
const save = (formValues) => {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
15
|
+
let searchObj = {};
|
|
16
|
+
if(formValues.keyword) searchObj = {keyword: formValues.keyword};
|
|
17
|
+
|
|
18
|
+
if(formValues.date){
|
|
19
|
+
searchObj["year"] = formValues.date.$y;
|
|
20
|
+
searchObj["month"] = new Date(formValues.date).toLocaleString('default', { month: 'short' });
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const searchParams = new URLSearchParams(searchObj).toString();
|
|
24
|
+
navigate(`/app/listing?${searchParams}`);
|
|
25
|
+
navigate(0);
|
|
26
|
+
|
|
27
|
+
// searchApi.search(formValues.keyword, formValues.month)
|
|
28
|
+
// .then(result => {
|
|
29
|
+
// navigate(`/app/listing?keyword=${formValues.keyword}`);
|
|
30
|
+
// })
|
|
16
31
|
}
|
|
17
32
|
|
|
33
|
+
|
|
18
34
|
return (
|
|
19
35
|
<div id="search-bar">
|
|
20
36
|
<img src="/iceholidays-assets/images/Rectangle49.png"/>
|
|
@@ -24,10 +40,10 @@ function SearchBarWidget() {
|
|
|
24
40
|
layout="vertical"
|
|
25
41
|
>
|
|
26
42
|
<Form.Item wrapperCol={{ span: 24 }} label="Search" name="keyword">
|
|
27
|
-
<Input placeholder="Destinations, Attractions, etc"
|
|
43
|
+
<Input placeholder="Destinations, Attractions, etc"/>
|
|
28
44
|
</Form.Item>
|
|
29
|
-
<Form.Item wrapperCol={{ span: 24 }} label="Travel Period" name="
|
|
30
|
-
<DatePicker picker="month" />
|
|
45
|
+
<Form.Item wrapperCol={{ span: 24 }} label="Travel Period" name="date">
|
|
46
|
+
<DatePicker picker="month" format={monthFormat} inputReadOnly/>
|
|
31
47
|
</Form.Item>
|
|
32
48
|
<Flex align="flex-end" justify="center">
|
|
33
49
|
<Button type="primary" className="search-button" htmlType="submit">Search</Button>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
<% @posts.each do |post| %>
|
|
2
|
+
<%= post.title %>
|
|
3
|
+
|
|
4
|
+
<% if post.thumbnail.attached? %>
|
|
5
|
+
<%= image_tag( post.thumbnail.blob.service_name.in?(%w[local test test_fixtures]) ? main_app.url_for(post.thumbnail) : post.thumbnail.attachment.url, height:300) %>
|
|
6
|
+
<% else %>
|
|
7
|
+
<%#= image_tag('nothumbnail.png', width:300) %>
|
|
8
|
+
<%end%>
|
|
9
|
+
<% end %>
|
data/config/routes.rb
CHANGED
|
@@ -2,11 +2,12 @@ Iceholidays::Frontend::Engine.routes.draw do
|
|
|
2
2
|
root to: 'site#index'
|
|
3
3
|
|
|
4
4
|
get '/listing' => 'site#listing', as: :listing
|
|
5
|
-
get '/
|
|
5
|
+
get '/itinerary/:id' => 'site#show', as: :show
|
|
6
6
|
get '/about-us' => 'site#about_us', as: :about_us
|
|
7
7
|
get '/countries' => 'site#countries', as: :countries
|
|
8
8
|
get '/blog' => 'site#blog', as: :blog
|
|
9
9
|
get '/blog/1' => 'site#show_blog', as: :show_blog
|
|
10
10
|
get '/contact-agents' => 'site#contact_agents', as: :contact_agents
|
|
11
11
|
get '/contact-us' => 'site#contact_us', as: :contact_us
|
|
12
|
+
resources :posts, only:[:index, :show]
|
|
12
13
|
end
|