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.
Files changed (191) hide show
  1. package/.github/workflows/dependabot.yml +11 -0
  2. package/.github/workflows/node.js.yml +31 -0
  3. package/.prettierrc +3 -6
  4. package/CHANGELOG.MD +5 -0
  5. package/babel.config.json +1 -1
  6. package/build/index.css +1 -2312
  7. package/build/portal.es.js +35483 -0
  8. package/build/portal.umd.js +596 -0
  9. package/{build/calendar.html → calendar.html} +2 -4
  10. package/coverage/clover.xml +28 -0
  11. package/coverage/coverage-final.json +2 -0
  12. package/coverage/lcov-report/base.css +224 -0
  13. package/coverage/lcov-report/block-navigation.js +87 -0
  14. package/coverage/lcov-report/favicon.png +0 -0
  15. package/coverage/lcov-report/helper.ts.html +142 -0
  16. package/coverage/lcov-report/index.html +116 -0
  17. package/coverage/lcov-report/prettify.css +1 -0
  18. package/coverage/lcov-report/prettify.js +2 -0
  19. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  20. package/coverage/lcov-report/sorter.js +196 -0
  21. package/coverage/lcov.info +36 -0
  22. package/cypress/{integration → e2e}/.examples/actions.spec.js +0 -0
  23. package/cypress/{integration → e2e}/.examples/aliasing.spec.js +0 -0
  24. package/cypress/{integration → e2e}/.examples/assertions.spec.js +0 -0
  25. package/cypress/{integration → e2e}/.examples/connectors.spec.js +0 -0
  26. package/cypress/{integration → e2e}/.examples/cookies.spec.js +0 -0
  27. package/cypress/{integration → e2e}/.examples/cypress_api.spec.js +0 -0
  28. package/cypress/{integration → e2e}/.examples/files.spec.js +0 -0
  29. package/cypress/{integration → e2e}/.examples/local_storage.spec.js +0 -0
  30. package/cypress/{integration → e2e}/.examples/location.spec.js +0 -0
  31. package/cypress/{integration → e2e}/.examples/misc.spec.js +0 -0
  32. package/cypress/{integration → e2e}/.examples/navigation.spec.js +0 -0
  33. package/cypress/{integration → e2e}/.examples/network_requests.spec.js +0 -0
  34. package/cypress/{integration → e2e}/.examples/querying.spec.js +0 -0
  35. package/cypress/{integration → e2e}/.examples/spies_stubs_clocks.spec.js +0 -0
  36. package/cypress/{integration → e2e}/.examples/traversal.spec.js +0 -0
  37. package/cypress/{integration → e2e}/.examples/utilities.spec.js +0 -0
  38. package/cypress/{integration → e2e}/.examples/viewport.spec.js +0 -0
  39. package/cypress/{integration → e2e}/.examples/waiting.spec.js +0 -0
  40. package/cypress/{integration → e2e}/.examples/window.spec.js +0 -0
  41. package/cypress/{integration → e2e}/booking.spec.js +0 -0
  42. package/cypress/{integration → e2e}/calendar.spec.js +0 -0
  43. package/cypress/{integration → e2e}/search.spec.js +0 -0
  44. package/cypress/support/commands.ts +37 -0
  45. package/cypress/support/component-index.html +12 -0
  46. package/cypress/support/component.ts +39 -0
  47. package/cypress/support/{index.js → e2e.js} +0 -0
  48. package/cypress.config.ts +15 -0
  49. package/{dev.js → dev.tsx} +1 -1
  50. package/index.html +15 -0
  51. package/{build/invalid-calendar.html → invalid-calendar.html} +0 -0
  52. package/jest.config.js +195 -0
  53. package/package.json +35 -40
  54. package/reviews.html +16 -0
  55. package/src/_lib/{SearchQueries.js → SearchQueries.ts} +8 -2
  56. package/src/_lib/{countries.js → countries.ts} +0 -0
  57. package/src/_lib/date_helper.ts +27 -0
  58. package/src/_lib/{queries.js → queries.ts} +24 -5
  59. package/src/components/App.tsx +132 -0
  60. package/src/components/AppContext.ts +14 -0
  61. package/src/components/CalendarPage/BookingForm.tsx +42 -0
  62. package/src/components/CalendarPage/Calendar.tsx +50 -0
  63. package/src/components/CalendarPage/CalendarPage.tsx +43 -0
  64. package/src/components/CalendarPage/CalendarParts/CalendarContext.tsx +89 -0
  65. package/src/components/CalendarPage/CalendarParts/CalendarHeader.tsx +72 -0
  66. package/src/components/CalendarPage/CalendarParts/DayClasses.ts +111 -0
  67. package/src/components/CalendarPage/CalendarParts/GenerateCalendar.tsx +64 -0
  68. package/src/components/CalendarPage/CalendarParts/Legend.tsx +33 -0
  69. package/src/components/CalendarPage/CalendarParts/MonthHeader.tsx +15 -0
  70. package/src/components/CalendarPage/CalendarParts/Months.tsx +37 -0
  71. package/src/components/CalendarPage/CalendarParts/RenderCells.tsx +94 -0
  72. package/src/components/CalendarPage/CalendarParts/SingleMonth.tsx +72 -0
  73. package/src/components/CalendarPage/CalendarParts/StartBooking.tsx +17 -0
  74. package/src/components/CalendarPage/CalendarParts/WeekDays.tsx +27 -0
  75. package/src/components/CalendarPage/FormCreator.tsx +213 -0
  76. package/src/components/CalendarPage/FormItems/{Date.js → Date.tsx} +10 -2
  77. package/src/components/CalendarPage/FormItems/{NumberSelect.js → NumberSelect.tsx} +1 -1
  78. package/src/components/CalendarPage/FormItems/{Select.js → Select.tsx} +0 -0
  79. package/src/components/CalendarPage/FormItems/{index.js → index.ts} +0 -0
  80. package/src/components/CalendarPage/PriceField/Price.tsx +58 -0
  81. package/src/components/CalendarPage/PriceField/Queries.ts +23 -0
  82. package/src/components/CalendarPage/PriceField/index.tsx +127 -0
  83. package/src/components/CalendarPage/Summary/{CostRow.js → CostRow.tsx} +19 -3
  84. package/src/components/CalendarPage/Summary/{CostSection.js → CostSection.tsx} +5 -1
  85. package/src/components/CalendarPage/Summary/{CostSummary.js → CostSummary.tsx} +19 -10
  86. package/src/components/CalendarPage/Summary/Description.tsx +27 -0
  87. package/src/components/CalendarPage/Summary/{InsurancesAndRequired.js → InsurancesAndRequired.tsx} +21 -2
  88. package/src/components/CalendarPage/Summary/Object.tsx +59 -0
  89. package/src/components/CalendarPage/Summary/{OnSite.js → OnSite.tsx} +9 -9
  90. package/src/components/CalendarPage/Summary/{OptionalNotOnSite.js → OptionalNotOnSite.tsx} +19 -18
  91. package/src/components/CalendarPage/Summary/{OptionalOnSite.js → OptionalOnSite.tsx} +6 -1
  92. package/src/components/CalendarPage/Summary/{Queries.js → Queries.ts} +3 -3
  93. package/src/components/CalendarPage/Summary/RentAndDiscount.tsx +30 -0
  94. package/src/components/CalendarPage/Summary/{Totals.js → Totals.tsx} +8 -3
  95. package/src/components/CalendarPage/Summary/cost_types.d.ts +31 -0
  96. package/src/components/CalendarPage/Summary/index.tsx +24 -0
  97. package/src/components/CalendarPage/calender_types.d.ts +16 -0
  98. package/src/components/CalendarPage/formParts/AssistanceMessage.tsx +60 -0
  99. package/src/components/CalendarPage/formParts/{BookingHelpers.js → BookingHelpers.tsx} +3 -3
  100. package/src/components/CalendarPage/formParts/{BookingOrOption.js → BookingOrOption.tsx} +6 -1
  101. package/src/components/CalendarPage/formParts/CancelInsuranceText.tsx +105 -0
  102. package/src/components/CalendarPage/formParts/{DefaultBookingFields.js → DefaultBookingFields.ts} +3 -1
  103. package/src/components/CalendarPage/formParts/DiscountCode.tsx +62 -0
  104. package/src/components/CalendarPage/formParts/{Guests.js → Guests.tsx} +10 -4
  105. package/src/components/CalendarPage/formParts/{OptionalBookingFields.js → OptionalBookingFields.tsx} +0 -0
  106. package/src/components/CalendarPage/formParts/{OptionalCosts.js → OptionalCosts.tsx} +1 -2
  107. package/src/components/CalendarPage/formParts/{SuccessMessage.js → SuccessMessage.tsx} +0 -0
  108. package/src/components/CalendarPage/formParts/Validations.tsx +78 -0
  109. package/src/components/CalendarPage/formParts/{discount.js → discount.tsx} +11 -2
  110. package/src/components/CalendarPage/formParts/form_types.d.ts +38 -0
  111. package/src/components/CalendarPage/formParts/{insurances.js → insurances.tsx} +14 -10
  112. package/src/components/CalendarPage/formParts/{radioButtons.js → radioButtons.tsx} +0 -0
  113. package/src/components/Error/{ApiError.js → ApiError.tsx} +6 -4
  114. package/src/components/Error/{IntegrationError.js → IntegrationError.tsx} +17 -11
  115. package/src/components/Error/{index.js → index.ts} +0 -0
  116. package/src/components/{ErrorBoundary.js → ErrorBoundary.tsx} +13 -5
  117. package/src/components/Modal/index.tsx +46 -0
  118. package/src/components/ReviewsPage/Queries.ts +26 -0
  119. package/src/components/ReviewsPage/ReviewsPage.tsx +43 -0
  120. package/src/components/ReviewsPage/Score.tsx +25 -0
  121. package/src/components/ReviewsPage/SingleReview.tsx +38 -0
  122. package/src/components/SafeBooking.tsx +97 -0
  123. package/src/components/SearchPage/Field.tsx +75 -0
  124. package/src/components/SearchPage/Filters.tsx +91 -0
  125. package/src/components/SearchPage/Paginator.tsx +63 -0
  126. package/src/components/SearchPage/Results.tsx +129 -0
  127. package/src/components/SearchPage/{SearchPage.js → SearchPage.tsx} +42 -31
  128. package/src/components/SearchPage/{SingleResult.js → SingleResult.tsx} +15 -8
  129. package/src/components/SearchPage/filters/Categories.tsx +57 -0
  130. package/src/components/SearchPage/filters/DateFilter.tsx +34 -0
  131. package/src/components/SearchPage/filters/List.tsx +80 -0
  132. package/src/components/SearchPage/filters/NumberFilter.tsx +37 -0
  133. package/src/components/SearchPage/filters/Radio.tsx +46 -0
  134. package/src/components/SearchPage/filters/Select.tsx +85 -0
  135. package/src/components/SearchPage/filters/__tests__/helper.spec.js +15 -0
  136. package/src/components/SearchPage/filters/filter_types.d.ts +25 -0
  137. package/src/components/SearchPage/filters/helper.ts +19 -0
  138. package/src/components/icons/ArrowLeft.svg.tsx +20 -0
  139. package/src/components/icons/{ArrowRight.svg.js → ArrowRight.svg.tsx} +0 -0
  140. package/src/components/icons/{Reload.svg.js → Reload.svg.tsx} +0 -0
  141. package/src/components/icons/{info.svg.js → info.svg.tsx} +0 -0
  142. package/src/components/icons/{loading.svg.js → loading.svg.tsx} +1 -1
  143. package/src/custom.d.ts +10 -0
  144. package/src/index.tsx +93 -0
  145. package/src/locales/de.json +4 -3
  146. package/src/locales/en.json +4 -3
  147. package/src/locales/es.json +4 -3
  148. package/src/locales/fr.json +4 -3
  149. package/src/locales/it.json +4 -3
  150. package/src/locales/nl.json +4 -3
  151. package/src/styles/main.css +2 -1
  152. package/src/styles/modal.css +1 -1
  153. package/src/styles/pagination.css +25 -23
  154. package/src/styles/result.css +33 -2
  155. package/src/styles/reviews.css +76 -0
  156. package/src/types.d.ts +85 -0
  157. package/tsconfig.json +17 -0
  158. package/vite.config.ts +31 -0
  159. package/build/index.html +0 -16
  160. package/build/index.js +0 -48528
  161. package/cypress.json +0 -9
  162. package/rollup.config.js +0 -30
  163. package/src/_lib/format.js +0 -16
  164. package/src/components/App.js +0 -164
  165. package/src/components/CalendarPage/BookingForm.js +0 -57
  166. package/src/components/CalendarPage/Calendar.js +0 -373
  167. package/src/components/CalendarPage/CalendarHeader.js +0 -58
  168. package/src/components/CalendarPage/CalendarPage.js +0 -158
  169. package/src/components/CalendarPage/FormCreator.js +0 -278
  170. package/src/components/CalendarPage/FormItems/Wrapper.js +0 -0
  171. package/src/components/CalendarPage/PriceField.js +0 -203
  172. package/src/components/CalendarPage/Summary/Description.js +0 -22
  173. package/src/components/CalendarPage/Summary/Object.js +0 -46
  174. package/src/components/CalendarPage/Summary/RentAndDiscount.js +0 -21
  175. package/src/components/CalendarPage/Summary/index.js +0 -19
  176. package/src/components/CalendarPage/formParts/AssistanceMessage.js +0 -47
  177. package/src/components/CalendarPage/formParts/CancelInsuranceText.js +0 -91
  178. package/src/components/CalendarPage/formParts/DiscountCode.js +0 -62
  179. package/src/components/CalendarPage/formParts/summary.js +0 -43
  180. package/src/components/Modal/index.js +0 -58
  181. package/src/components/ReviewsPage/ReviewsPage.js +0 -15
  182. package/src/components/SafeBooking.js +0 -69
  183. package/src/components/SearchPage/Field.js +0 -241
  184. package/src/components/SearchPage/Filters.js +0 -108
  185. package/src/components/SearchPage/Paginator.js +0 -59
  186. package/src/components/SearchPage/Results.js +0 -130
  187. package/src/components/SearchPage/filters/List.js +0 -63
  188. package/src/components/icons/ArrowLeft.svg.js +0 -18
  189. package/src/index.js +0 -74
  190. package/webpack.config.dev.js +0 -53
  191. package/webpack.config.js +0 -67
package/cypress.json DELETED
@@ -1,9 +0,0 @@
1
- {
2
- "baseUrl": "http://localhost:8080/",
3
- "experimentalStudio": true,
4
- "component": {
5
- "testFiles": "**/*.test.{js,ts,jsx,tsx}",
6
- "componentFolder": "src"
7
- },
8
- "projectId": "rpsk7v"
9
- }
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
- };
@@ -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
- };
@@ -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;