bukazu-portal-react 2.1.21 → 3.0.2
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.
- package/.github/workflows/dependabot.yml +11 -0
- package/.github/workflows/node.js.yml +31 -0
- package/.prettierrc +3 -6
- package/CHANGELOG.MD +5 -0
- package/babel.config.json +1 -1
- package/build/index.css +1 -2312
- package/build/portal.es.js +35483 -0
- package/build/portal.umd.js +596 -0
- package/{build/calendar.html → calendar.html} +2 -4
- package/coverage/clover.xml +28 -0
- package/coverage/coverage-final.json +2 -0
- package/coverage/lcov-report/base.css +224 -0
- package/coverage/lcov-report/block-navigation.js +87 -0
- package/coverage/lcov-report/favicon.png +0 -0
- package/coverage/lcov-report/helper.ts.html +142 -0
- package/coverage/lcov-report/index.html +116 -0
- package/coverage/lcov-report/prettify.css +1 -0
- package/coverage/lcov-report/prettify.js +2 -0
- package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/coverage/lcov-report/sorter.js +196 -0
- package/coverage/lcov.info +36 -0
- package/cypress/{integration → e2e}/.examples/actions.spec.js +0 -0
- package/cypress/{integration → e2e}/.examples/aliasing.spec.js +0 -0
- package/cypress/{integration → e2e}/.examples/assertions.spec.js +0 -0
- package/cypress/{integration → e2e}/.examples/connectors.spec.js +0 -0
- package/cypress/{integration → e2e}/.examples/cookies.spec.js +0 -0
- package/cypress/{integration → e2e}/.examples/cypress_api.spec.js +0 -0
- package/cypress/{integration → e2e}/.examples/files.spec.js +0 -0
- package/cypress/{integration → e2e}/.examples/local_storage.spec.js +0 -0
- package/cypress/{integration → e2e}/.examples/location.spec.js +0 -0
- package/cypress/{integration → e2e}/.examples/misc.spec.js +0 -0
- package/cypress/{integration → e2e}/.examples/navigation.spec.js +0 -0
- package/cypress/{integration → e2e}/.examples/network_requests.spec.js +0 -0
- package/cypress/{integration → e2e}/.examples/querying.spec.js +0 -0
- package/cypress/{integration → e2e}/.examples/spies_stubs_clocks.spec.js +0 -0
- package/cypress/{integration → e2e}/.examples/traversal.spec.js +0 -0
- package/cypress/{integration → e2e}/.examples/utilities.spec.js +0 -0
- package/cypress/{integration → e2e}/.examples/viewport.spec.js +0 -0
- package/cypress/{integration → e2e}/.examples/waiting.spec.js +0 -0
- package/cypress/{integration → e2e}/.examples/window.spec.js +0 -0
- package/cypress/{integration → e2e}/booking.spec.js +0 -0
- package/cypress/{integration → e2e}/calendar.spec.js +0 -0
- package/cypress/{integration → e2e}/search.spec.js +0 -0
- package/cypress/support/commands.ts +37 -0
- package/cypress/support/component-index.html +12 -0
- package/cypress/support/component.ts +39 -0
- package/cypress/support/{index.js → e2e.js} +0 -0
- package/cypress.config.ts +15 -0
- package/{dev.js → dev.tsx} +1 -1
- package/index.html +15 -0
- package/{build/invalid-calendar.html → invalid-calendar.html} +0 -0
- package/jest.config.js +195 -0
- package/package.json +35 -40
- package/reviews.html +16 -0
- package/src/_lib/{SearchQueries.js → SearchQueries.ts} +8 -2
- package/src/_lib/{countries.js → countries.ts} +0 -0
- package/src/_lib/date_helper.ts +27 -0
- package/src/_lib/{queries.js → queries.ts} +24 -5
- package/src/components/App.tsx +132 -0
- package/src/components/AppContext.ts +14 -0
- package/src/components/CalendarPage/BookingForm.tsx +42 -0
- package/src/components/CalendarPage/Calendar.tsx +50 -0
- package/src/components/CalendarPage/CalendarPage.tsx +43 -0
- package/src/components/CalendarPage/CalendarParts/CalendarContext.tsx +89 -0
- package/src/components/CalendarPage/CalendarParts/CalendarHeader.tsx +72 -0
- package/src/components/CalendarPage/CalendarParts/DayClasses.ts +111 -0
- package/src/components/CalendarPage/CalendarParts/GenerateCalendar.tsx +64 -0
- package/src/components/CalendarPage/CalendarParts/Legend.tsx +33 -0
- package/src/components/CalendarPage/CalendarParts/MonthHeader.tsx +15 -0
- package/src/components/CalendarPage/CalendarParts/Months.tsx +37 -0
- package/src/components/CalendarPage/CalendarParts/RenderCells.tsx +94 -0
- package/src/components/CalendarPage/CalendarParts/SingleMonth.tsx +72 -0
- package/src/components/CalendarPage/CalendarParts/StartBooking.tsx +17 -0
- package/src/components/CalendarPage/CalendarParts/WeekDays.tsx +27 -0
- package/src/components/CalendarPage/FormCreator.tsx +213 -0
- package/src/components/CalendarPage/FormItems/{Date.js → Date.tsx} +10 -2
- package/src/components/CalendarPage/FormItems/{NumberSelect.js → NumberSelect.tsx} +1 -1
- package/src/components/CalendarPage/FormItems/{Select.js → Select.tsx} +0 -0
- package/src/components/CalendarPage/FormItems/{index.js → index.ts} +0 -0
- package/src/components/CalendarPage/PriceField/Price.tsx +58 -0
- package/src/components/CalendarPage/PriceField/Queries.ts +23 -0
- package/src/components/CalendarPage/PriceField/index.tsx +127 -0
- package/src/components/CalendarPage/Summary/{CostRow.js → CostRow.tsx} +19 -3
- package/src/components/CalendarPage/Summary/{CostSection.js → CostSection.tsx} +5 -1
- package/src/components/CalendarPage/Summary/{CostSummary.js → CostSummary.tsx} +19 -10
- package/src/components/CalendarPage/Summary/Description.tsx +27 -0
- package/src/components/CalendarPage/Summary/{InsurancesAndRequired.js → InsurancesAndRequired.tsx} +21 -2
- package/src/components/CalendarPage/Summary/Object.tsx +59 -0
- package/src/components/CalendarPage/Summary/{OnSite.js → OnSite.tsx} +9 -9
- package/src/components/CalendarPage/Summary/{OptionalNotOnSite.js → OptionalNotOnSite.tsx} +19 -18
- package/src/components/CalendarPage/Summary/{OptionalOnSite.js → OptionalOnSite.tsx} +6 -1
- package/src/components/CalendarPage/Summary/{Queries.js → Queries.ts} +3 -3
- package/src/components/CalendarPage/Summary/RentAndDiscount.tsx +30 -0
- package/src/components/CalendarPage/Summary/{Totals.js → Totals.tsx} +8 -3
- package/src/components/CalendarPage/Summary/cost_types.d.ts +31 -0
- package/src/components/CalendarPage/Summary/index.tsx +24 -0
- package/src/components/CalendarPage/calender_types.d.ts +16 -0
- package/src/components/CalendarPage/formParts/AssistanceMessage.tsx +60 -0
- package/src/components/CalendarPage/formParts/{BookingHelpers.js → BookingHelpers.tsx} +3 -3
- package/src/components/CalendarPage/formParts/{BookingOrOption.js → BookingOrOption.tsx} +6 -1
- package/src/components/CalendarPage/formParts/CancelInsuranceText.tsx +105 -0
- package/src/components/CalendarPage/formParts/{DefaultBookingFields.js → DefaultBookingFields.ts} +3 -1
- package/src/components/CalendarPage/formParts/DiscountCode.tsx +62 -0
- package/src/components/CalendarPage/formParts/{Guests.js → Guests.tsx} +10 -4
- package/src/components/CalendarPage/formParts/{OptionalBookingFields.js → OptionalBookingFields.tsx} +0 -0
- package/src/components/CalendarPage/formParts/{OptionalCosts.js → OptionalCosts.tsx} +1 -2
- package/src/components/CalendarPage/formParts/{SuccessMessage.js → SuccessMessage.tsx} +0 -0
- package/src/components/CalendarPage/formParts/Validations.tsx +78 -0
- package/src/components/CalendarPage/formParts/{discount.js → discount.tsx} +11 -2
- package/src/components/CalendarPage/formParts/form_types.d.ts +38 -0
- package/src/components/CalendarPage/formParts/{insurances.js → insurances.tsx} +14 -10
- package/src/components/CalendarPage/formParts/{radioButtons.js → radioButtons.tsx} +0 -0
- package/src/components/Error/{ApiError.js → ApiError.tsx} +6 -4
- package/src/components/Error/{IntegrationError.js → IntegrationError.tsx} +17 -11
- package/src/components/Error/{index.js → index.ts} +0 -0
- package/src/components/{ErrorBoundary.js → ErrorBoundary.tsx} +13 -5
- package/src/components/Modal/index.tsx +46 -0
- package/src/components/ReviewsPage/Queries.ts +26 -0
- package/src/components/ReviewsPage/ReviewsPage.tsx +43 -0
- package/src/components/ReviewsPage/Score.tsx +25 -0
- package/src/components/ReviewsPage/SingleReview.tsx +38 -0
- package/src/components/SafeBooking.tsx +97 -0
- package/src/components/SearchPage/Field.tsx +75 -0
- package/src/components/SearchPage/Filters.tsx +91 -0
- package/src/components/SearchPage/Paginator.tsx +63 -0
- package/src/components/SearchPage/Results.tsx +129 -0
- package/src/components/SearchPage/{SearchPage.js → SearchPage.tsx} +42 -31
- package/src/components/SearchPage/{SingleResult.js → SingleResult.tsx} +15 -8
- package/src/components/SearchPage/filters/Categories.tsx +57 -0
- package/src/components/SearchPage/filters/DateFilter.tsx +34 -0
- package/src/components/SearchPage/filters/List.tsx +80 -0
- package/src/components/SearchPage/filters/NumberFilter.tsx +37 -0
- package/src/components/SearchPage/filters/Radio.tsx +46 -0
- package/src/components/SearchPage/filters/Select.tsx +85 -0
- package/src/components/SearchPage/filters/__tests__/helper.spec.js +15 -0
- package/src/components/SearchPage/filters/filter_types.d.ts +25 -0
- package/src/components/SearchPage/filters/helper.ts +19 -0
- package/src/components/icons/ArrowLeft.svg.tsx +20 -0
- package/src/components/icons/{ArrowRight.svg.js → ArrowRight.svg.tsx} +0 -0
- package/src/components/icons/{Reload.svg.js → Reload.svg.tsx} +0 -0
- package/src/components/icons/{info.svg.js → info.svg.tsx} +0 -0
- package/src/components/icons/{loading.svg.js → loading.svg.tsx} +1 -1
- package/src/custom.d.ts +10 -0
- package/src/index.tsx +93 -0
- package/src/locales/de.json +4 -3
- package/src/locales/en.json +4 -3
- package/src/locales/es.json +4 -3
- package/src/locales/fr.json +4 -3
- package/src/locales/it.json +4 -3
- package/src/locales/nl.json +4 -3
- package/src/styles/main.css +2 -1
- package/src/styles/modal.css +1 -1
- package/src/styles/pagination.css +25 -23
- package/src/styles/result.css +33 -2
- package/src/styles/reviews.css +76 -0
- package/src/types.d.ts +85 -0
- package/tsconfig.json +17 -0
- package/vite.config.ts +31 -0
- package/build/index.html +0 -16
- package/build/index.js +0 -48528
- package/cypress.json +0 -9
- package/rollup.config.js +0 -30
- package/src/_lib/format.js +0 -16
- package/src/components/App.js +0 -164
- package/src/components/CalendarPage/BookingForm.js +0 -57
- package/src/components/CalendarPage/Calendar.js +0 -373
- package/src/components/CalendarPage/CalendarHeader.js +0 -58
- package/src/components/CalendarPage/CalendarPage.js +0 -158
- package/src/components/CalendarPage/FormCreator.js +0 -278
- package/src/components/CalendarPage/FormItems/Wrapper.js +0 -0
- package/src/components/CalendarPage/PriceField.js +0 -203
- package/src/components/CalendarPage/Summary/Description.js +0 -22
- package/src/components/CalendarPage/Summary/Object.js +0 -46
- package/src/components/CalendarPage/Summary/RentAndDiscount.js +0 -21
- package/src/components/CalendarPage/Summary/index.js +0 -19
- package/src/components/CalendarPage/formParts/AssistanceMessage.js +0 -47
- package/src/components/CalendarPage/formParts/CancelInsuranceText.js +0 -91
- package/src/components/CalendarPage/formParts/DiscountCode.js +0 -62
- package/src/components/CalendarPage/formParts/summary.js +0 -43
- package/src/components/Modal/index.js +0 -58
- package/src/components/ReviewsPage/ReviewsPage.js +0 -15
- package/src/components/SafeBooking.js +0 -69
- package/src/components/SearchPage/Field.js +0 -241
- package/src/components/SearchPage/Filters.js +0 -108
- package/src/components/SearchPage/Paginator.js +0 -59
- package/src/components/SearchPage/Results.js +0 -130
- package/src/components/SearchPage/filters/List.js +0 -63
- package/src/components/icons/ArrowLeft.svg.js +0 -18
- package/src/index.js +0 -74
- package/webpack.config.dev.js +0 -53
- package/webpack.config.js +0 -67
package/cypress.json
DELETED
package/rollup.config.js
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import resolve from 'rollup-plugin-node-resolve';
|
|
2
|
-
import babel from 'rollup-plugin-babel';
|
|
3
|
-
import json from '@rollup/plugin-json';
|
|
4
|
-
import commonjs from '@rollup/plugin-commonjs';
|
|
5
|
-
import postcss from 'rollup-plugin-postcss';
|
|
6
|
-
|
|
7
|
-
export default {
|
|
8
|
-
input: 'src/index.js',
|
|
9
|
-
output: [
|
|
10
|
-
{
|
|
11
|
-
file: 'build/index.js',
|
|
12
|
-
format: 'cjs',
|
|
13
|
-
exports: 'auto',
|
|
14
|
-
},
|
|
15
|
-
],
|
|
16
|
-
plugins: [
|
|
17
|
-
babel({
|
|
18
|
-
exclude: 'node_modules/**',
|
|
19
|
-
}),
|
|
20
|
-
postcss({
|
|
21
|
-
extract: true,
|
|
22
|
-
}),
|
|
23
|
-
commonjs(),
|
|
24
|
-
resolve(),
|
|
25
|
-
json({
|
|
26
|
-
namedExports: false,
|
|
27
|
-
}),
|
|
28
|
-
],
|
|
29
|
-
external: ['react', 'react-dom'],
|
|
30
|
-
};
|
package/src/_lib/format.js
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
var format = require('date-fns/format');
|
|
2
|
-
|
|
3
|
-
var locales = {
|
|
4
|
-
en: require('date-fns/locale/en'),
|
|
5
|
-
nl: require('date-fns/locale/nl'),
|
|
6
|
-
de: require('date-fns/locale/de'),
|
|
7
|
-
fr: require('date-fns/locale/fr'),
|
|
8
|
-
it: require('date-fns/locale/it'),
|
|
9
|
-
es: require('date-fns/locale/es'),
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
module.exports = function(date, formatStr) {
|
|
13
|
-
return format(date, formatStr, {
|
|
14
|
-
locale: locales[window.__localeId__], // or global.__localeId__
|
|
15
|
-
});
|
|
16
|
-
};
|
package/src/components/App.js
DELETED
|
@@ -1,164 +0,0 @@
|
|
|
1
|
-
import React, { Component } from 'react';
|
|
2
|
-
import PropTypes from 'prop-types';
|
|
3
|
-
import { Query } from '@apollo/client/react/components';
|
|
4
|
-
import Loading from './icons/loading.svg';
|
|
5
|
-
|
|
6
|
-
import 'react-date-picker/dist/DatePicker.css';
|
|
7
|
-
import 'react-calendar/dist/Calendar.css';
|
|
8
|
-
|
|
9
|
-
import { PORTAL_QUERY } from '../_lib/queries';
|
|
10
|
-
|
|
11
|
-
import SearchPage from './SearchPage/SearchPage';
|
|
12
|
-
import CalendarPage from './CalendarPage/CalendarPage';
|
|
13
|
-
import ReviewsPage from './ReviewsPage/ReviewsPage';
|
|
14
|
-
import SafeBooking from './SafeBooking';
|
|
15
|
-
import { ApiError } from './Error';
|
|
16
|
-
import ErrorBoundary from './ErrorBoundary';
|
|
17
|
-
|
|
18
|
-
// import 'react-dates/lib/css/_datepicker.css';
|
|
19
|
-
|
|
20
|
-
class App extends Component {
|
|
21
|
-
constructor(props) {
|
|
22
|
-
super(props);
|
|
23
|
-
|
|
24
|
-
this.pageWidth = React.createRef();
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Calculate & Update state of new dimensions
|
|
29
|
-
*/
|
|
30
|
-
updateDimensions() {
|
|
31
|
-
if (this.pageWidth.current.offsetWidth < 875) {
|
|
32
|
-
this.pageWidth.current.classList.add('bu-smaller');
|
|
33
|
-
} else {
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Add event listener
|
|
39
|
-
*/
|
|
40
|
-
componentDidMount() {
|
|
41
|
-
this.updateDimensions();
|
|
42
|
-
// window.addEventListener("resize", this.updateDimensions.bind(this));
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
render() {
|
|
46
|
-
const { portalCode, objectCode, pageType, locale, filters, id, className } =
|
|
47
|
-
this.props;
|
|
48
|
-
|
|
49
|
-
return (
|
|
50
|
-
<div ref={this.pageWidth} id={id} className={className}>
|
|
51
|
-
<Query query={PORTAL_QUERY} variables={{ id: portalCode, locale }}>
|
|
52
|
-
{({ loading, error, data }) => {
|
|
53
|
-
if (loading)
|
|
54
|
-
return (
|
|
55
|
-
<div>
|
|
56
|
-
<Loading />
|
|
57
|
-
</div>
|
|
58
|
-
);
|
|
59
|
-
if (error) {
|
|
60
|
-
return (
|
|
61
|
-
<div>
|
|
62
|
-
<ApiError errors={{ ...error }} />
|
|
63
|
-
</div>
|
|
64
|
-
);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
const PortalSite = data.PortalSite;
|
|
68
|
-
let options = data.PortalSite.options;
|
|
69
|
-
|
|
70
|
-
let root = document.documentElement;
|
|
71
|
-
|
|
72
|
-
root.style.setProperty(
|
|
73
|
-
'--bukazu-discount',
|
|
74
|
-
`${options.colors ? options.colors.discount : 'orange'}`
|
|
75
|
-
);
|
|
76
|
-
root.style.setProperty(
|
|
77
|
-
'--bukazu-cell',
|
|
78
|
-
`${options.colors ? options.colors.cell : '#fff'}`
|
|
79
|
-
);
|
|
80
|
-
root.style.setProperty(
|
|
81
|
-
'--bukazu-arrival',
|
|
82
|
-
`${options.colors ? options.colors.arrival : '#6eeb83'}`
|
|
83
|
-
);
|
|
84
|
-
root.style.setProperty(
|
|
85
|
-
'--bukazu-booked',
|
|
86
|
-
`${options.colors ? options.colors.booked : '#ea2b1f'}`
|
|
87
|
-
);
|
|
88
|
-
root.style.setProperty(
|
|
89
|
-
'--bukazu-departure',
|
|
90
|
-
`${options.colors ? options.colors.departure : 'yellow'}`
|
|
91
|
-
);
|
|
92
|
-
|
|
93
|
-
root.style.setProperty(
|
|
94
|
-
'--bukazu-button',
|
|
95
|
-
`${
|
|
96
|
-
options.colors
|
|
97
|
-
? options.colors.button
|
|
98
|
-
: 'rgba(23, 190, 187, 0.75)'
|
|
99
|
-
}`
|
|
100
|
-
);
|
|
101
|
-
root.style.setProperty(
|
|
102
|
-
'--bukazu-button_cta',
|
|
103
|
-
`${options.colors ? options.colors.buttonCta : '#e28413'}`
|
|
104
|
-
);
|
|
105
|
-
root.style.setProperty(
|
|
106
|
-
'--bukazu-background_month',
|
|
107
|
-
`${options.colors ? options.colors.month_background : '#e28413'}`
|
|
108
|
-
);
|
|
109
|
-
|
|
110
|
-
if (objectCode && objectCode !== null && pageType !== 'reviews') {
|
|
111
|
-
return (
|
|
112
|
-
<section>
|
|
113
|
-
<ErrorBoundary>
|
|
114
|
-
<CalendarPage
|
|
115
|
-
PortalSite={PortalSite}
|
|
116
|
-
objectCode={objectCode}
|
|
117
|
-
locale={locale}
|
|
118
|
-
/>
|
|
119
|
-
<SafeBooking locale={locale} />
|
|
120
|
-
</ErrorBoundary>
|
|
121
|
-
</section>
|
|
122
|
-
);
|
|
123
|
-
} else if (
|
|
124
|
-
objectCode &&
|
|
125
|
-
objectCode !== null &&
|
|
126
|
-
pageType === 'reviews'
|
|
127
|
-
) {
|
|
128
|
-
return (
|
|
129
|
-
<ReviewsPage
|
|
130
|
-
PortalSite={PortalSite}
|
|
131
|
-
locale={locale}
|
|
132
|
-
options={options}
|
|
133
|
-
filters={filters}
|
|
134
|
-
/>
|
|
135
|
-
);
|
|
136
|
-
} else {
|
|
137
|
-
return (
|
|
138
|
-
<SearchPage
|
|
139
|
-
PortalSite={PortalSite}
|
|
140
|
-
locale={locale}
|
|
141
|
-
options={options}
|
|
142
|
-
filters={filters}
|
|
143
|
-
/>
|
|
144
|
-
);
|
|
145
|
-
}
|
|
146
|
-
}}
|
|
147
|
-
</Query>
|
|
148
|
-
</div>
|
|
149
|
-
);
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
App.defaultProps = {
|
|
154
|
-
filters: {},
|
|
155
|
-
};
|
|
156
|
-
|
|
157
|
-
App.propTypes = {
|
|
158
|
-
portalCode: PropTypes.string.isRequired,
|
|
159
|
-
objectCode: PropTypes.string,
|
|
160
|
-
locale: PropTypes.string.isRequired,
|
|
161
|
-
filters: PropTypes.object.isRequired,
|
|
162
|
-
};
|
|
163
|
-
|
|
164
|
-
export default App;
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import PropTypes from 'prop-types';
|
|
3
|
-
import { Query } from '@apollo/client/react/components';
|
|
4
|
-
import Loading from '../icons/loading.svg';
|
|
5
|
-
import FormCreator from './FormCreator';
|
|
6
|
-
import { BOOKING_PRICE_QUERY } from '../../_lib/queries';
|
|
7
|
-
|
|
8
|
-
function BookingForm({ booking, locale, onReturn }) {
|
|
9
|
-
return (
|
|
10
|
-
<Query
|
|
11
|
-
query={BOOKING_PRICE_QUERY}
|
|
12
|
-
variables={{
|
|
13
|
-
id: booking.portalCode,
|
|
14
|
-
house_id: booking.objectCode,
|
|
15
|
-
starts_at: booking.arrivalDate.date,
|
|
16
|
-
ends_at: booking.departureDate.date,
|
|
17
|
-
locale,
|
|
18
|
-
}}
|
|
19
|
-
>
|
|
20
|
-
{({ loading, error, data }) => {
|
|
21
|
-
if (loading)
|
|
22
|
-
return (
|
|
23
|
-
<div>
|
|
24
|
-
<Loading />
|
|
25
|
-
</div>
|
|
26
|
-
);
|
|
27
|
-
if (error) {
|
|
28
|
-
return <div>Error</div>;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
const result = data.PortalSite.houses[0];
|
|
32
|
-
const options = data.PortalSite.options;
|
|
33
|
-
|
|
34
|
-
return (
|
|
35
|
-
<FormCreator
|
|
36
|
-
house={result}
|
|
37
|
-
options={options}
|
|
38
|
-
booking={booking}
|
|
39
|
-
PortalSite={data.PortalSite}
|
|
40
|
-
locale={locale}
|
|
41
|
-
onReturn={() => {
|
|
42
|
-
onReturn(booking);
|
|
43
|
-
}}
|
|
44
|
-
/>
|
|
45
|
-
);
|
|
46
|
-
}}
|
|
47
|
-
</Query>
|
|
48
|
-
);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
BookingForm.propTypes = {
|
|
52
|
-
booking: PropTypes.object.isRequired,
|
|
53
|
-
locale: PropTypes.string.isRequired,
|
|
54
|
-
onReturn: PropTypes.func.isRequired,
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
export default BookingForm;
|
|
@@ -1,373 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import PropTypes from "prop-types";
|
|
3
|
-
import dateFns from "date-fns";
|
|
4
|
-
import { Query } from "@apollo/client/react/components";
|
|
5
|
-
import Loading from "../icons/loading.svg";
|
|
6
|
-
import format from "../../_lib/format";
|
|
7
|
-
import isAfter from "date-fns/is_after";
|
|
8
|
-
import CalendarHeader from "./CalendarHeader";
|
|
9
|
-
import PriceField from "./PriceField";
|
|
10
|
-
import differenceInCalendarDays from "date-fns/difference_in_calendar_days";
|
|
11
|
-
|
|
12
|
-
import { CALENDAR_QUERY } from "../../_lib/queries";
|
|
13
|
-
import { FormattedMessage } from "react-intl";
|
|
14
|
-
import AssistanceMessage from "./formParts/AssistanceMessage";
|
|
15
|
-
|
|
16
|
-
class Calendar extends React.Component {
|
|
17
|
-
constructor(props) {
|
|
18
|
-
super(props);
|
|
19
|
-
|
|
20
|
-
this.bookingStart = this.bookingStart.bind(this);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
state = {
|
|
24
|
-
currentMonth: new Date(),
|
|
25
|
-
selectedDate: "",
|
|
26
|
-
numberOfMonths: this.props.numberOfMonths,
|
|
27
|
-
numberOfMonthsInARow: this.props.numberOfMonthsInARow,
|
|
28
|
-
house: this.props.house,
|
|
29
|
-
arrivalDate: "",
|
|
30
|
-
departureDate: "",
|
|
31
|
-
minNights: null,
|
|
32
|
-
startBooking: false,
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
renderHeader(month) {
|
|
36
|
-
const dateFormat = "MMMM YYYY";
|
|
37
|
-
|
|
38
|
-
return (
|
|
39
|
-
<div className="header row flex-middle">
|
|
40
|
-
<div className="col col-center" style={{ textAlign: "center" }}>
|
|
41
|
-
<span>{format(month, dateFormat)}</span>
|
|
42
|
-
</div>
|
|
43
|
-
</div>
|
|
44
|
-
);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
renderDays() {
|
|
48
|
-
const dateFormat = "dd";
|
|
49
|
-
const days = [];
|
|
50
|
-
|
|
51
|
-
let startDate = dateFns.startOfWeek(this.state.currentMonth);
|
|
52
|
-
|
|
53
|
-
for (let i = 0; i < 7; i++) {
|
|
54
|
-
days.push(
|
|
55
|
-
<div className="col col-center" key={i}>
|
|
56
|
-
{format(dateFns.addDays(startDate, i), dateFormat)}
|
|
57
|
-
</div>
|
|
58
|
-
);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
return <div className="days row">{days}</div>;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
renderCells(availabilities, month, discounts) {
|
|
65
|
-
const { selectedDate, departureDate, house, arrivalDate } = this.state;
|
|
66
|
-
const monthStart = dateFns.startOfMonth(month);
|
|
67
|
-
const monthEnd = dateFns.endOfMonth(monthStart);
|
|
68
|
-
const startDate = dateFns.startOfWeek(monthStart);
|
|
69
|
-
const endDate = dateFns.endOfWeek(monthEnd);
|
|
70
|
-
const today = new Date();
|
|
71
|
-
|
|
72
|
-
const dateFormat = "D";
|
|
73
|
-
const rows = [];
|
|
74
|
-
|
|
75
|
-
let days = [];
|
|
76
|
-
let day = startDate;
|
|
77
|
-
let formattedDate = "";
|
|
78
|
-
let dayz = availabilities;
|
|
79
|
-
|
|
80
|
-
while (day <= endDate) {
|
|
81
|
-
// for (let daz of dayz) {
|
|
82
|
-
for (let i = 0; i < 7; i++) {
|
|
83
|
-
formattedDate = dateFns.format(day, dateFormat);
|
|
84
|
-
let date = dateFns.format(day, "YYYY-MM-DD");
|
|
85
|
-
let yesterday = dateFns.format(dateFns.subDays(date, 1), "YYYY-MM-DD");
|
|
86
|
-
let daz = dayz.find((x) => x.date === date);
|
|
87
|
-
|
|
88
|
-
const prevBooked = dayz.find((x) => x.date === yesterday);
|
|
89
|
-
const cloneDay = daz;
|
|
90
|
-
const discount = discounts.find(
|
|
91
|
-
(x) =>
|
|
92
|
-
dateFns.isBefore(dateFns.subDays(x.discount_starts_at, 1), date) &&
|
|
93
|
-
isAfter(dateFns.addDays(x.discount_ends_at, 1), date)
|
|
94
|
-
);
|
|
95
|
-
const minimum =
|
|
96
|
-
differenceInCalendarDays(daz.date, selectedDate) >=
|
|
97
|
-
arrivalDate.min_nights;
|
|
98
|
-
const maximum =
|
|
99
|
-
differenceInCalendarDays(daz.date, selectedDate) <=
|
|
100
|
-
house.max_nights &&
|
|
101
|
-
differenceInCalendarDays(daz.date, selectedDate) <=
|
|
102
|
-
arrivalDate.max_nights;
|
|
103
|
-
|
|
104
|
-
const daysFromToday = differenceInCalendarDays(daz.date, today);
|
|
105
|
-
const last_minute =
|
|
106
|
-
daysFromToday <= house.last_minute_days && daysFromToday > 0;
|
|
107
|
-
|
|
108
|
-
const highlight =
|
|
109
|
-
daz.departure && isAfter(daz.date, selectedDate)
|
|
110
|
-
? minimum
|
|
111
|
-
? maximum
|
|
112
|
-
? prevBooked.max_nights !== 0
|
|
113
|
-
? "departure"
|
|
114
|
-
: null
|
|
115
|
-
: ""
|
|
116
|
-
: ""
|
|
117
|
-
: "";
|
|
118
|
-
|
|
119
|
-
days.push(
|
|
120
|
-
<div
|
|
121
|
-
className={`col cell
|
|
122
|
-
${
|
|
123
|
-
!dateFns.isSameMonth(day, monthStart)
|
|
124
|
-
? "disabled"
|
|
125
|
-
: dateFns.isSameDay(day, selectedDate) ||
|
|
126
|
-
dateFns.isSameDay(day, departureDate.date)
|
|
127
|
-
? "selected"
|
|
128
|
-
: ""
|
|
129
|
-
}
|
|
130
|
-
${
|
|
131
|
-
dateFns.isAfter(day, selectedDate) &&
|
|
132
|
-
dateFns.isBefore(day, departureDate.date)
|
|
133
|
-
? "selected"
|
|
134
|
-
: ""
|
|
135
|
-
}
|
|
136
|
-
${
|
|
137
|
-
(last_minute || daz.special_offer > 0)
|
|
138
|
-
? "discount"
|
|
139
|
-
: ""
|
|
140
|
-
}
|
|
141
|
-
${discount ? "discount" : ""}
|
|
142
|
-
${
|
|
143
|
-
daz.arrival
|
|
144
|
-
? dateFns.isAfter(daz.date, new Date())
|
|
145
|
-
? daz.max_nights !== 0
|
|
146
|
-
? prevBooked.max_nights === 0
|
|
147
|
-
? "departure-arrival"
|
|
148
|
-
: "arrival"
|
|
149
|
-
: ""
|
|
150
|
-
: ""
|
|
151
|
-
: ""
|
|
152
|
-
}
|
|
153
|
-
${highlight}
|
|
154
|
-
${
|
|
155
|
-
daz.max_nights === 0
|
|
156
|
-
? prevBooked.max_nights !== 0
|
|
157
|
-
? "booked-departure"
|
|
158
|
-
: "booked"
|
|
159
|
-
: prevBooked.max_nights === 0
|
|
160
|
-
? "booked"
|
|
161
|
-
: ""
|
|
162
|
-
}`}
|
|
163
|
-
key={day}
|
|
164
|
-
date={daz.date}
|
|
165
|
-
role="button"
|
|
166
|
-
tabIndex={0}
|
|
167
|
-
onClick={() => this.onDateClick(cloneDay)}
|
|
168
|
-
onKeyPress={() => this.onDateClick(cloneDay)}
|
|
169
|
-
>
|
|
170
|
-
<span>
|
|
171
|
-
{!dateFns.isSameMonth(day, monthStart) ? "" : formattedDate}
|
|
172
|
-
</span>
|
|
173
|
-
</div>
|
|
174
|
-
);
|
|
175
|
-
day = dateFns.addDays(day, 1);
|
|
176
|
-
}
|
|
177
|
-
rows.push(
|
|
178
|
-
<div className="row" key={day}>
|
|
179
|
-
{days}
|
|
180
|
-
</div>
|
|
181
|
-
);
|
|
182
|
-
days = [];
|
|
183
|
-
}
|
|
184
|
-
return <div className="body">{rows}</div>;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
renderMonths() {
|
|
188
|
-
let template = [];
|
|
189
|
-
for (let i = 0; i < this.state.numberOfMonths; i++) {
|
|
190
|
-
template.push(this.renderSingleMonth(i));
|
|
191
|
-
}
|
|
192
|
-
return template;
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
renderSingleMonth(count) {
|
|
196
|
-
const { numberOfMonthsInARow } = this.state;
|
|
197
|
-
let month = dateFns.addMonths(this.state.currentMonth, count);
|
|
198
|
-
let monthStart = dateFns.startOfMonth(month);
|
|
199
|
-
let monthEnd = dateFns.endOfMonth(month);
|
|
200
|
-
const variables = {
|
|
201
|
-
id: this.props.portalCode,
|
|
202
|
-
house_id: this.props.objectCode,
|
|
203
|
-
starts_at: dateFns.startOfWeek(monthStart),
|
|
204
|
-
ends_at: dateFns.endOfWeek(monthEnd),
|
|
205
|
-
locale: this.props.locale,
|
|
206
|
-
};
|
|
207
|
-
|
|
208
|
-
return (
|
|
209
|
-
<div className={`calendar calendar-${numberOfMonthsInARow}`} key={month}>
|
|
210
|
-
{this.renderHeader(month)}
|
|
211
|
-
{this.renderDays()}
|
|
212
|
-
<Query query={CALENDAR_QUERY} variables={variables}>
|
|
213
|
-
{({ loading, error, data }) => {
|
|
214
|
-
if (loading)
|
|
215
|
-
return (
|
|
216
|
-
<div>
|
|
217
|
-
<Loading />
|
|
218
|
-
</div>
|
|
219
|
-
);
|
|
220
|
-
if (error) {
|
|
221
|
-
return <div>Error</div>;
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
const results = data.PortalSite.houses[0].availabilities;
|
|
225
|
-
const discounts = data.Discounts;
|
|
226
|
-
|
|
227
|
-
return this.renderCells(results, month, discounts);
|
|
228
|
-
}}
|
|
229
|
-
</Query>
|
|
230
|
-
</div>
|
|
231
|
-
);
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
onDateClick = (day) => {
|
|
235
|
-
const { arrivalDate, selectedDate, house } = this.state;
|
|
236
|
-
if (
|
|
237
|
-
day.departure &&
|
|
238
|
-
isAfter(day.date, selectedDate) &&
|
|
239
|
-
differenceInCalendarDays(day.date, selectedDate) <= house.max_nights &&
|
|
240
|
-
differenceInCalendarDays(day.date, selectedDate) >=
|
|
241
|
-
arrivalDate.min_nights &&
|
|
242
|
-
differenceInCalendarDays(day.date, selectedDate) <= arrivalDate.max_nights
|
|
243
|
-
) {
|
|
244
|
-
this.setState({
|
|
245
|
-
departureDate: day,
|
|
246
|
-
startBooking: true,
|
|
247
|
-
});
|
|
248
|
-
} else if (day.arrival) {
|
|
249
|
-
this.setState({
|
|
250
|
-
startBooking: false,
|
|
251
|
-
selectedDate: dateFns.parse(day.date),
|
|
252
|
-
arrivalDate: day,
|
|
253
|
-
minNights: day.min_nights,
|
|
254
|
-
departureDate: "",
|
|
255
|
-
});
|
|
256
|
-
}
|
|
257
|
-
};
|
|
258
|
-
|
|
259
|
-
nextMonth = () => {
|
|
260
|
-
const { numberOfMonths, currentMonth } = this.state;
|
|
261
|
-
this.setState({
|
|
262
|
-
currentMonth: dateFns.addMonths(currentMonth, numberOfMonths),
|
|
263
|
-
});
|
|
264
|
-
};
|
|
265
|
-
|
|
266
|
-
prevMonth = () => {
|
|
267
|
-
const { numberOfMonths, currentMonth } = this.state;
|
|
268
|
-
this.setState({
|
|
269
|
-
currentMonth: dateFns.subMonths(currentMonth, numberOfMonths),
|
|
270
|
-
});
|
|
271
|
-
};
|
|
272
|
-
|
|
273
|
-
reset = () => {
|
|
274
|
-
this.setState({
|
|
275
|
-
selectedDate: "",
|
|
276
|
-
arrivalDate: "",
|
|
277
|
-
departureDate: "",
|
|
278
|
-
startBooking: false,
|
|
279
|
-
});
|
|
280
|
-
};
|
|
281
|
-
|
|
282
|
-
showBooking() {
|
|
283
|
-
const { startBooking, arrivalDate, departureDate, house, minNights } = this.state;
|
|
284
|
-
const { portalCode, objectCode, locale } = this.props;
|
|
285
|
-
|
|
286
|
-
return (
|
|
287
|
-
<PriceField
|
|
288
|
-
portalCode={portalCode}
|
|
289
|
-
objectCode={objectCode}
|
|
290
|
-
locale={locale}
|
|
291
|
-
startsAt={arrivalDate.date || null}
|
|
292
|
-
endsAt={departureDate.date || null}
|
|
293
|
-
minNights={minNights}
|
|
294
|
-
disabled={startBooking}
|
|
295
|
-
onStartBooking={this.bookingStart}
|
|
296
|
-
house={house}
|
|
297
|
-
/>
|
|
298
|
-
);
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
bookingStart(status, persons) {
|
|
302
|
-
const { arrivalDate, departureDate } = this.state;
|
|
303
|
-
const { portalCode, objectCode, locale } = this.props;
|
|
304
|
-
const booking = {
|
|
305
|
-
portalCode,
|
|
306
|
-
objectCode,
|
|
307
|
-
arrivalDate,
|
|
308
|
-
departureDate,
|
|
309
|
-
is_option: status,
|
|
310
|
-
locale,
|
|
311
|
-
persons,
|
|
312
|
-
};
|
|
313
|
-
this.props.onBooking(booking);
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
render() {
|
|
317
|
-
const { house, arrivalDate, departureDate, minNights } = this.state;
|
|
318
|
-
|
|
319
|
-
return (
|
|
320
|
-
<div className="calendar-container ">
|
|
321
|
-
<div className="price-overview">{this.showBooking()}</div>
|
|
322
|
-
<div className="calendar-section">
|
|
323
|
-
<CalendarHeader
|
|
324
|
-
onGoNext={this.nextMonth}
|
|
325
|
-
onGoPrev={this.prevMonth}
|
|
326
|
-
onReset={this.reset}
|
|
327
|
-
/>
|
|
328
|
-
<div className="calendars-row">{this.renderMonths()}</div>
|
|
329
|
-
<div className="legend">
|
|
330
|
-
<div>
|
|
331
|
-
<span className="legend-field arrival" />
|
|
332
|
-
<FormattedMessage id={`${house.house_type}.arrival_date`} />
|
|
333
|
-
</div>
|
|
334
|
-
<div>
|
|
335
|
-
<span className="legend-field booked" />
|
|
336
|
-
<FormattedMessage id="booked" />
|
|
337
|
-
</div>
|
|
338
|
-
<div>
|
|
339
|
-
<span className="legend-field departure" />
|
|
340
|
-
<FormattedMessage id={`${house.house_type}.departure_date`} />
|
|
341
|
-
</div>
|
|
342
|
-
<div>
|
|
343
|
-
<span className="legend-field last_minute_discount" />
|
|
344
|
-
<FormattedMessage id="discount" />
|
|
345
|
-
</div>
|
|
346
|
-
</div>
|
|
347
|
-
<AssistanceMessage
|
|
348
|
-
house={house}
|
|
349
|
-
arrivalDate={arrivalDate}
|
|
350
|
-
departureDate={departureDate}
|
|
351
|
-
minNights={minNights}
|
|
352
|
-
/>
|
|
353
|
-
</div>
|
|
354
|
-
</div>
|
|
355
|
-
);
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
Calendar.defaultProps = {
|
|
360
|
-
numberOfMonths: 4,
|
|
361
|
-
numberOfMonthsInARow: 2,
|
|
362
|
-
};
|
|
363
|
-
|
|
364
|
-
Calendar.propTypes = {
|
|
365
|
-
numberOfMonths: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
|
366
|
-
house: PropTypes.object.isRequired,
|
|
367
|
-
onBooking: PropTypes.func.isRequired,
|
|
368
|
-
objectCode: PropTypes.string.isRequired,
|
|
369
|
-
portalCode: PropTypes.string.isRequired,
|
|
370
|
-
locale: PropTypes.string.isRequired,
|
|
371
|
-
};
|
|
372
|
-
|
|
373
|
-
export default Calendar;
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
import React, { Component } from 'react';
|
|
2
|
-
import PropTypes from 'prop-types';
|
|
3
|
-
import ArrowRight from '../icons/ArrowRight.svg';
|
|
4
|
-
import ArrowLeft from '../icons/ArrowLeft.svg';
|
|
5
|
-
import Reload from '../icons/Reload.svg';
|
|
6
|
-
|
|
7
|
-
function CalendarHeader({ onGoPrev, onReset, onGoNext }) {
|
|
8
|
-
return (
|
|
9
|
-
<div className="calendars-header">
|
|
10
|
-
<div
|
|
11
|
-
className="col bu-prev"
|
|
12
|
-
style={{ textAlign: 'center' }}
|
|
13
|
-
onClick={onGoPrev}
|
|
14
|
-
onKeyPress={onGoPrev}
|
|
15
|
-
tabIndex={0}
|
|
16
|
-
role="button"
|
|
17
|
-
>
|
|
18
|
-
<div className="icon">
|
|
19
|
-
{' '}
|
|
20
|
-
<ArrowLeft />
|
|
21
|
-
</div>
|
|
22
|
-
</div>
|
|
23
|
-
<div
|
|
24
|
-
className="col bu-reset"
|
|
25
|
-
onClick={onReset}
|
|
26
|
-
onKeyPress={onReset}
|
|
27
|
-
style={{ textAlign: 'center' }}
|
|
28
|
-
tabIndex={0}
|
|
29
|
-
role="button"
|
|
30
|
-
>
|
|
31
|
-
<div className="icon">
|
|
32
|
-
<Reload />
|
|
33
|
-
</div>
|
|
34
|
-
</div>
|
|
35
|
-
<div
|
|
36
|
-
className="col bu-next"
|
|
37
|
-
onClick={onGoNext}
|
|
38
|
-
onKeyPress={onGoNext}
|
|
39
|
-
style={{ textAlign: 'center' }}
|
|
40
|
-
tabIndex={0}
|
|
41
|
-
role="button"
|
|
42
|
-
>
|
|
43
|
-
<div className="icon">
|
|
44
|
-
<ArrowRight />
|
|
45
|
-
</div>
|
|
46
|
-
</div>
|
|
47
|
-
</div>
|
|
48
|
-
);
|
|
49
|
-
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
CalendarHeader.propTypes = {
|
|
53
|
-
onGoNext: PropTypes.func.isRequired,
|
|
54
|
-
onGoPrev: PropTypes.func.isRequired,
|
|
55
|
-
onReset: PropTypes.func.isRequired,
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
export default CalendarHeader;
|