bukazu-portal-react 3.3.3 → 3.3.4
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/build/index.css +1 -1
- package/build/portal.es.js +19931 -20259
- package/build/portal.umd.js +80 -82
- package/package.json +9 -7
- package/.env.development +0 -1
- package/.eslintrc +0 -25
- package/.github/dependabot.yml +0 -11
- package/.github/workflows/node.js.yml +0 -31
- package/.github/workflows/npm-publish.yml +0 -33
- package/.nvmrc +0 -1
- package/.prettierrc +0 -6
- package/.vscode/settings.json +0 -24
- package/CHANGELOG.MD +0 -93
- package/babel.config.json +0 -6
- package/calendar.html +0 -16
- package/coverage/clover.xml +0 -28
- package/coverage/coverage-final.json +0 -2
- package/coverage/lcov-report/base.css +0 -224
- package/coverage/lcov-report/block-navigation.js +0 -87
- package/coverage/lcov-report/favicon.png +0 -0
- package/coverage/lcov-report/helper.ts.html +0 -142
- package/coverage/lcov-report/index.html +0 -116
- package/coverage/lcov-report/prettify.css +0 -1
- package/coverage/lcov-report/prettify.js +0 -2
- package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/coverage/lcov-report/sorter.js +0 -196
- package/coverage/lcov.info +0 -36
- package/cypress/e2e/.examples/actions.spec.js +0 -299
- package/cypress/e2e/.examples/aliasing.spec.js +0 -39
- package/cypress/e2e/.examples/assertions.spec.js +0 -177
- package/cypress/e2e/.examples/connectors.spec.js +0 -97
- package/cypress/e2e/.examples/cookies.spec.js +0 -77
- package/cypress/e2e/.examples/cypress_api.spec.js +0 -202
- package/cypress/e2e/.examples/files.spec.js +0 -89
- package/cypress/e2e/.examples/local_storage.spec.js +0 -52
- package/cypress/e2e/.examples/location.spec.js +0 -32
- package/cypress/e2e/.examples/misc.spec.js +0 -104
- package/cypress/e2e/.examples/navigation.spec.js +0 -56
- package/cypress/e2e/.examples/network_requests.spec.js +0 -163
- package/cypress/e2e/.examples/querying.spec.js +0 -114
- package/cypress/e2e/.examples/spies_stubs_clocks.spec.js +0 -205
- package/cypress/e2e/.examples/traversal.spec.js +0 -121
- package/cypress/e2e/.examples/utilities.spec.js +0 -110
- package/cypress/e2e/.examples/viewport.spec.js +0 -59
- package/cypress/e2e/.examples/waiting.spec.js +0 -31
- package/cypress/e2e/.examples/window.spec.js +0 -22
- package/cypress/e2e/booking.spec.js +0 -81
- package/cypress/e2e/calendar.spec.js +0 -21
- package/cypress/e2e/search.spec.js +0 -25
- package/cypress/fixtures/example.json +0 -5
- package/cypress/plugins/index.js +0 -16
- package/cypress/support/commands.js +0 -25
- package/cypress/support/commands.ts +0 -37
- package/cypress/support/component-index.html +0 -12
- package/cypress/support/component.ts +0 -39
- package/cypress/support/e2e.js +0 -20
- package/cypress.config.ts +0 -15
- package/dev.tsx +0 -44
- package/index.html +0 -15
- package/invalid-calendar.html +0 -16
- package/jest.config.js +0 -195
- package/postcss.config.js +0 -17
- package/reviews.html +0 -16
- package/src/_lib/SearchQueries.ts +0 -145
- package/src/_lib/Tracking.ts +0 -51
- package/src/_lib/countries/de.json +0 -998
- package/src/_lib/countries/en.json +0 -998
- package/src/_lib/countries/es.json +0 -998
- package/src/_lib/countries/fr.json +0 -998
- package/src/_lib/countries/it.json +0 -998
- package/src/_lib/countries/nl.json +0 -998
- package/src/_lib/countries.ts +0 -15
- package/src/_lib/date_helper.ts +0 -27
- package/src/_lib/queries.ts +0 -244
- package/src/components/App.tsx +0 -108
- package/src/components/AppContext.ts +0 -14
- package/src/components/CalendarPage/BookingForm.tsx +0 -49
- package/src/components/CalendarPage/Calendar.tsx +0 -49
- package/src/components/CalendarPage/CalendarPage.tsx +0 -43
- package/src/components/CalendarPage/CalendarParts/CalendarContext.tsx +0 -89
- package/src/components/CalendarPage/CalendarParts/CalendarHeader.tsx +0 -72
- package/src/components/CalendarPage/CalendarParts/DayClasses.ts +0 -113
- package/src/components/CalendarPage/CalendarParts/GenerateCalendar.tsx +0 -72
- package/src/components/CalendarPage/CalendarParts/Legend.tsx +0 -33
- package/src/components/CalendarPage/CalendarParts/MonthHeader.tsx +0 -15
- package/src/components/CalendarPage/CalendarParts/Months.tsx +0 -37
- package/src/components/CalendarPage/CalendarParts/RenderCells.tsx +0 -97
- package/src/components/CalendarPage/CalendarParts/SingleMonth.tsx +0 -72
- package/src/components/CalendarPage/CalendarParts/StartBooking.tsx +0 -17
- package/src/components/CalendarPage/CalendarParts/WeekDays.tsx +0 -27
- package/src/components/CalendarPage/FormCreator.tsx +0 -230
- package/src/components/CalendarPage/FormItems/Date.tsx +0 -61
- package/src/components/CalendarPage/FormItems/NumberSelect.tsx +0 -39
- package/src/components/CalendarPage/FormItems/Select.tsx +0 -38
- package/src/components/CalendarPage/FormItems/index.ts +0 -4
- package/src/components/CalendarPage/PriceField/Price.tsx +0 -58
- package/src/components/CalendarPage/PriceField/Queries.ts +0 -23
- package/src/components/CalendarPage/PriceField/index.tsx +0 -129
- package/src/components/CalendarPage/Summary/CostRow.tsx +0 -58
- package/src/components/CalendarPage/Summary/CostSection.tsx +0 -15
- package/src/components/CalendarPage/Summary/CostSummary.tsx +0 -61
- package/src/components/CalendarPage/Summary/Description.tsx +0 -27
- package/src/components/CalendarPage/Summary/InsurancesAndRequired.tsx +0 -68
- package/src/components/CalendarPage/Summary/Object.tsx +0 -59
- package/src/components/CalendarPage/Summary/OnSite.tsx +0 -36
- package/src/components/CalendarPage/Summary/OptionalNotOnSite.tsx +0 -43
- package/src/components/CalendarPage/Summary/OptionalOnSite.tsx +0 -39
- package/src/components/CalendarPage/Summary/Queries.ts +0 -31
- package/src/components/CalendarPage/Summary/RentAndDiscount.tsx +0 -30
- package/src/components/CalendarPage/Summary/Totals.tsx +0 -89
- package/src/components/CalendarPage/Summary/cost_types.d.ts +0 -31
- package/src/components/CalendarPage/Summary/index.tsx +0 -24
- package/src/components/CalendarPage/calender_types.d.ts +0 -16
- package/src/components/CalendarPage/formParts/AssistanceMessage.tsx +0 -60
- package/src/components/CalendarPage/formParts/BookingHelpers.tsx +0 -47
- package/src/components/CalendarPage/formParts/BookingOrOption.tsx +0 -35
- package/src/components/CalendarPage/formParts/CancelInsuranceText.tsx +0 -69
- package/src/components/CalendarPage/formParts/DefaultBookingFields.ts +0 -105
- package/src/components/CalendarPage/formParts/DiscountCode.tsx +0 -62
- package/src/components/CalendarPage/formParts/Guests.tsx +0 -77
- package/src/components/CalendarPage/formParts/OptionalBookingFields.tsx +0 -148
- package/src/components/CalendarPage/formParts/OptionalCosts.tsx +0 -103
- package/src/components/CalendarPage/formParts/SuccessMessage.tsx +0 -31
- package/src/components/CalendarPage/formParts/Validations.tsx +0 -64
- package/src/components/CalendarPage/formParts/discount.tsx +0 -69
- package/src/components/CalendarPage/formParts/form_types.d.ts +0 -38
- package/src/components/CalendarPage/formParts/insurances.tsx +0 -62
- package/src/components/CalendarPage/formParts/radioButtons.tsx +0 -66
- package/src/components/Error/ApiError.tsx +0 -33
- package/src/components/Error/IntegrationError.tsx +0 -62
- package/src/components/Error/index.ts +0 -4
- package/src/components/ErrorBoundary.tsx +0 -34
- package/src/components/Modal/index.tsx +0 -46
- package/src/components/ReviewsPage/Queries.ts +0 -26
- package/src/components/ReviewsPage/ReviewsPage.tsx +0 -45
- package/src/components/ReviewsPage/Score.tsx +0 -29
- package/src/components/ReviewsPage/SingleReview.tsx +0 -38
- package/src/components/ReviewsPage/note.tsx +0 -17
- package/src/components/SafeBooking.tsx +0 -96
- package/src/components/SearchPage/Field.tsx +0 -75
- package/src/components/SearchPage/Filters.tsx +0 -91
- package/src/components/SearchPage/Paginator.tsx +0 -63
- package/src/components/SearchPage/Results.tsx +0 -129
- package/src/components/SearchPage/SearchPage.tsx +0 -115
- package/src/components/SearchPage/SingleResult.tsx +0 -93
- package/src/components/SearchPage/filters/Categories.tsx +0 -57
- package/src/components/SearchPage/filters/DateFilter.tsx +0 -34
- package/src/components/SearchPage/filters/List.tsx +0 -80
- package/src/components/SearchPage/filters/NumberFilter.tsx +0 -37
- package/src/components/SearchPage/filters/Radio.tsx +0 -46
- package/src/components/SearchPage/filters/Select.tsx +0 -85
- package/src/components/SearchPage/filters/__tests__/helper.spec.js +0 -13
- package/src/components/SearchPage/filters/filter_types.d.ts +0 -25
- package/src/components/SearchPage/filters/helper.ts +0 -19
- package/src/components/icons/ArrowLeft.svg.tsx +0 -20
- package/src/components/icons/ArrowRight.svg.tsx +0 -16
- package/src/components/icons/Reload.svg.tsx +0 -23
- package/src/components/icons/info.svg.tsx +0 -24
- package/src/components/icons/loading.svg.tsx +0 -98
- package/src/custom.d.ts +0 -10
- package/src/index.tsx +0 -104
- package/src/locales/de.json +0 -137
- package/src/locales/en.json +0 -137
- package/src/locales/es.json +0 -132
- package/src/locales/fr.json +0 -132
- package/src/locales/it.json +0 -128
- package/src/locales/nl.json +0 -138
- package/src/styles/calendar.css +0 -317
- package/src/styles/datepicker.css +0 -6
- package/src/styles/field.css +0 -105
- package/src/styles/filters.css +0 -92
- package/src/styles/form.css +0 -219
- package/src/styles/main.css +0 -80
- package/src/styles/modal.css +0 -79
- package/src/styles/pagination.css +0 -92
- package/src/styles/price-overview.css +0 -111
- package/src/styles/result.css +0 -142
- package/src/styles/results.css +0 -50
- package/src/styles/reviews.css +0 -90
- package/src/styles/success.css +0 -9
- package/src/types.d.ts +0 -91
- package/tmp/cache/vite/last-build-production.json +0 -7
- package/tsconfig.json +0 -17
- package/vite.config.ts +0 -31
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import List from './filters/List';
|
|
3
|
-
import { createNumberArray, createPriceArray } from './filters/helper';
|
|
4
|
-
import Select from './filters/Select';
|
|
5
|
-
import Categories from './filters/Categories';
|
|
6
|
-
import Radio from './filters/Radio';
|
|
7
|
-
import DateFilter from './filters/DateFilter';
|
|
8
|
-
import NumberFilter from './filters/NumberFilter';
|
|
9
|
-
import { PortalSiteType } from '../../types';
|
|
10
|
-
import { Field as FieldType, FiltersType } from './filters/filter_types';
|
|
11
|
-
|
|
12
|
-
interface Props {
|
|
13
|
-
PortalSite: PortalSiteType;
|
|
14
|
-
field: FieldType;
|
|
15
|
-
filters: FiltersType;
|
|
16
|
-
value: string;
|
|
17
|
-
onFilterChange: Function;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
function Field({ PortalSite, field, filters, value, onFilterChange }:Props):JSX.Element {
|
|
21
|
-
let options = [];
|
|
22
|
-
if (['countries', 'cities', 'regions'].includes(field.id)) {
|
|
23
|
-
options = PortalSite[field.id];
|
|
24
|
-
} else if (field.id === 'persons_min' || field.id === 'persons_max') {
|
|
25
|
-
options = createNumberArray(PortalSite.max_persons);
|
|
26
|
-
} else if (field.id === 'bedrooms_min') {
|
|
27
|
-
options = createNumberArray(PortalSite.max_bedrooms);
|
|
28
|
-
} else if (field.id === 'bathrooms_min') {
|
|
29
|
-
options = createNumberArray(PortalSite.max_bathrooms);
|
|
30
|
-
} else if (field.id === 'weekprice_max') {
|
|
31
|
-
options = createPriceArray(PortalSite.max_weekprice);
|
|
32
|
-
} else {
|
|
33
|
-
options = createNumberArray(PortalSite[field.id]);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
let default_settings = {
|
|
37
|
-
options,
|
|
38
|
-
field,
|
|
39
|
-
filters,
|
|
40
|
-
value
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
if (field.id === 'properties') {
|
|
44
|
-
return (
|
|
45
|
-
<Categories
|
|
46
|
-
PortalSite={PortalSite}
|
|
47
|
-
filters={filters}
|
|
48
|
-
onChange={onFilterChange}
|
|
49
|
-
/>
|
|
50
|
-
);
|
|
51
|
-
} else if (field.type === 'select') {
|
|
52
|
-
return <Select {...default_settings} onChange={onFilterChange} />;
|
|
53
|
-
} else if (field.type === 'list') {
|
|
54
|
-
return <List {...default_settings} onChange={onFilterChange} />;
|
|
55
|
-
} else if (field.type === 'radio') {
|
|
56
|
-
return <Radio {...default_settings} onChange={onFilterChange} />;
|
|
57
|
-
} else if (field.type === 'number') {
|
|
58
|
-
return (
|
|
59
|
-
<NumberFilter PortalSite={PortalSite} field={field} value={value} onChange={onFilterChange} />
|
|
60
|
-
);
|
|
61
|
-
} else if (field.type === 'date') {
|
|
62
|
-
return <DateFilter field={field} value={value} onChange={onFilterChange} />;
|
|
63
|
-
} else {
|
|
64
|
-
return (
|
|
65
|
-
<input
|
|
66
|
-
value={value}
|
|
67
|
-
onBlur={(event) => {
|
|
68
|
-
onFilterChange(field.id, event.target.value);
|
|
69
|
-
}}
|
|
70
|
-
/>
|
|
71
|
-
);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
export default Field;
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
import React, { useState } from 'react';
|
|
2
|
-
import Field from './Field';
|
|
3
|
-
import Reload from '../icons/Reload.svg';
|
|
4
|
-
import { FormattedMessage } from 'react-intl';
|
|
5
|
-
import { defaultFilter } from './filters/helper';
|
|
6
|
-
import { FiltersType } from './filters/filter_types';
|
|
7
|
-
import { PortalOptions, PortalSiteType } from '../../types';
|
|
8
|
-
|
|
9
|
-
interface Props {
|
|
10
|
-
filters: FiltersType;
|
|
11
|
-
onFilterChange: Function;
|
|
12
|
-
PortalSite: PortalSiteType;
|
|
13
|
-
options: PortalOptions;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
function Filters({
|
|
17
|
-
filters,
|
|
18
|
-
onFilterChange,
|
|
19
|
-
PortalSite,
|
|
20
|
-
options
|
|
21
|
-
}: Props): JSX.Element {
|
|
22
|
-
function saveFilters(field, input) {
|
|
23
|
-
let newFilters: any = filters;
|
|
24
|
-
newFilters[field] = input;
|
|
25
|
-
onFilterChange(newFilters);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const [show, setShow] = useState(false);
|
|
29
|
-
|
|
30
|
-
const searchFields = options.searchFields || defaultFilter;
|
|
31
|
-
let fixed = options.filtersForm
|
|
32
|
-
? options.filtersForm.fixedMobile
|
|
33
|
-
? 'fixed-mobile'
|
|
34
|
-
: null
|
|
35
|
-
: null;
|
|
36
|
-
|
|
37
|
-
let filterClass = options.filtersForm
|
|
38
|
-
? options.filtersForm.show
|
|
39
|
-
? `filters filters-${options.filtersForm.location}`
|
|
40
|
-
: 'filters-hidden'
|
|
41
|
-
: 'filters';
|
|
42
|
-
|
|
43
|
-
let showOn = show && 'showOnMobile';
|
|
44
|
-
|
|
45
|
-
return (
|
|
46
|
-
<>
|
|
47
|
-
<button
|
|
48
|
-
className={`filters-button ${fixed}`}
|
|
49
|
-
onClick={() => setShow(!show)}
|
|
50
|
-
>
|
|
51
|
-
<FormattedMessage id="filters" />
|
|
52
|
-
</button>
|
|
53
|
-
<div className={`${filterClass} ${fixed} ${showOn}`}>
|
|
54
|
-
<button
|
|
55
|
-
onClick={() => {
|
|
56
|
-
let filters = {};
|
|
57
|
-
for (var property in filters) {
|
|
58
|
-
filters[property] = '';
|
|
59
|
-
}
|
|
60
|
-
onFilterChange(filters);
|
|
61
|
-
}}
|
|
62
|
-
className="filters-reload"
|
|
63
|
-
>
|
|
64
|
-
<Reload />
|
|
65
|
-
</button>
|
|
66
|
-
{searchFields.map((field) => (
|
|
67
|
-
<div key={field.id} className="bu-field" id={field.id}>
|
|
68
|
-
<label
|
|
69
|
-
style={{
|
|
70
|
-
width: '100%',
|
|
71
|
-
display: 'block'
|
|
72
|
-
}}
|
|
73
|
-
htmlFor={field.id}
|
|
74
|
-
>
|
|
75
|
-
{PortalSite[`${field.id}_label`]}
|
|
76
|
-
</label>
|
|
77
|
-
<Field
|
|
78
|
-
field={field}
|
|
79
|
-
PortalSite={PortalSite}
|
|
80
|
-
filters={filters}
|
|
81
|
-
value={filters[field.id]}
|
|
82
|
-
onFilterChange={saveFilters}
|
|
83
|
-
/>
|
|
84
|
-
</div>
|
|
85
|
-
))}
|
|
86
|
-
</div>
|
|
87
|
-
</>
|
|
88
|
-
);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
export default Filters;
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { FormattedMessage } from 'react-intl';
|
|
3
|
-
import { HOUSE_COUNT_QUERY } from '../../_lib/SearchQueries';
|
|
4
|
-
import Loading from '../icons/loading.svg';
|
|
5
|
-
import ReactPaginate from 'react-paginate';
|
|
6
|
-
import { useQuery } from '@apollo/client';
|
|
7
|
-
|
|
8
|
-
interface Props {
|
|
9
|
-
onPageChange: Function;
|
|
10
|
-
variables: object;
|
|
11
|
-
activePage: number;
|
|
12
|
-
limit: number;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
function Paginator({
|
|
16
|
-
onPageChange,
|
|
17
|
-
variables,
|
|
18
|
-
activePage,
|
|
19
|
-
limit
|
|
20
|
-
}: Props): JSX.Element {
|
|
21
|
-
const { loading, error, data } = useQuery(HOUSE_COUNT_QUERY, { variables });
|
|
22
|
-
|
|
23
|
-
if (loading)
|
|
24
|
-
return (
|
|
25
|
-
<div
|
|
26
|
-
style={{
|
|
27
|
-
width: '100%',
|
|
28
|
-
display: 'flex',
|
|
29
|
-
justifyContent: 'center'
|
|
30
|
-
}}
|
|
31
|
-
>
|
|
32
|
-
<Loading />
|
|
33
|
-
</div>
|
|
34
|
-
);
|
|
35
|
-
if (error) {
|
|
36
|
-
return <div>Error</div>;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const results = data.PortalSite.houses;
|
|
40
|
-
|
|
41
|
-
const pageCount = Math.ceil(results.length / limit);
|
|
42
|
-
return (
|
|
43
|
-
<div className="bu-paginator">
|
|
44
|
-
<div>
|
|
45
|
-
{results.length} <FormattedMessage id="results" />
|
|
46
|
-
</div>
|
|
47
|
-
<ReactPaginate
|
|
48
|
-
pageCount={pageCount}
|
|
49
|
-
onPageChange={({ selected }) => {
|
|
50
|
-
onPageChange(selected);
|
|
51
|
-
}}
|
|
52
|
-
forcePage={activePage}
|
|
53
|
-
pageRangeDisplayed={5}
|
|
54
|
-
breakLabel="..."
|
|
55
|
-
className="bu-pagination"
|
|
56
|
-
nextLabel=">"
|
|
57
|
-
previousLabel="<"
|
|
58
|
-
/>
|
|
59
|
-
</div>
|
|
60
|
-
);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
export default Paginator;
|
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
import React, { useContext } from 'react';
|
|
2
|
-
import { FormattedMessage } from 'react-intl';
|
|
3
|
-
import { differenceInCalendarDays } from 'date-fns';
|
|
4
|
-
import Loading from '../icons/loading.svg';
|
|
5
|
-
import SingleResult from './SingleResult';
|
|
6
|
-
import Paginator from './Paginator';
|
|
7
|
-
|
|
8
|
-
import { HOUSES_PRICE_QUERY, HOUSES_QUERY } from '../../_lib/SearchQueries';
|
|
9
|
-
import { ApiError } from '../Error';
|
|
10
|
-
import { useQuery } from '@apollo/client';
|
|
11
|
-
import { FiltersType } from './filters/filter_types';
|
|
12
|
-
import { Parse_EN_US } from '../../_lib/date_helper';
|
|
13
|
-
import { AppContext } from '../AppContext';
|
|
14
|
-
import { HouseType, PortalSiteType } from '../../types';
|
|
15
|
-
|
|
16
|
-
interface Props {
|
|
17
|
-
filters: FiltersType;
|
|
18
|
-
PortalSite: PortalSiteType;
|
|
19
|
-
limit: number;
|
|
20
|
-
skip: number;
|
|
21
|
-
onPageChange: Function;
|
|
22
|
-
activePage: number;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
function Results({
|
|
26
|
-
filters,
|
|
27
|
-
PortalSite,
|
|
28
|
-
limit,
|
|
29
|
-
skip,
|
|
30
|
-
onPageChange,
|
|
31
|
-
activePage
|
|
32
|
-
}: Props): JSX.Element {
|
|
33
|
-
const { portalCode } = useContext(AppContext);
|
|
34
|
-
|
|
35
|
-
let min_nights = null;
|
|
36
|
-
let requestPrices = false;
|
|
37
|
-
if (filters.departure_date && filters.arrival_date) {
|
|
38
|
-
min_nights = differenceInCalendarDays(
|
|
39
|
-
Parse_EN_US(filters.departure_date),
|
|
40
|
-
Parse_EN_US(filters.arrival_date)
|
|
41
|
-
);
|
|
42
|
-
requestPrices = true;
|
|
43
|
-
} else if (filters.arrival_date) {
|
|
44
|
-
min_nights = 1;
|
|
45
|
-
}
|
|
46
|
-
let filterProperties = filters.properties || [];
|
|
47
|
-
filterProperties = filterProperties.map((e) => {
|
|
48
|
-
return JSON.stringify(e);
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
let properties = filterProperties.join(',');
|
|
52
|
-
|
|
53
|
-
let variables = {
|
|
54
|
-
id: portalCode,
|
|
55
|
-
country_id: filters.countries || null,
|
|
56
|
-
region_id: filters.regions || null,
|
|
57
|
-
city_id: filters.cities,
|
|
58
|
-
persons_min: Number(filters.persons_min) || null,
|
|
59
|
-
persons_max: Number(filters.persons_max) || null,
|
|
60
|
-
bedrooms_min: Number(filters.bedrooms_min),
|
|
61
|
-
bathrooms_min: Number(filters.bathrooms_min),
|
|
62
|
-
arrival_date: filters.arrival_date,
|
|
63
|
-
starts_at: filters.arrival_date,
|
|
64
|
-
ends_at: filters.departure_date,
|
|
65
|
-
no_nights: Number(min_nights) || null,
|
|
66
|
-
extra_search: filters.extra_search,
|
|
67
|
-
properties,
|
|
68
|
-
weekprice_max: Number(filters.weekprice_max) || null,
|
|
69
|
-
limit,
|
|
70
|
-
skip
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
const { loading, error, data } = useQuery(
|
|
74
|
-
requestPrices ? HOUSES_PRICE_QUERY : HOUSES_QUERY,
|
|
75
|
-
{ variables }
|
|
76
|
-
);
|
|
77
|
-
|
|
78
|
-
if (loading)
|
|
79
|
-
return (
|
|
80
|
-
<div>
|
|
81
|
-
<Loading />
|
|
82
|
-
</div>
|
|
83
|
-
);
|
|
84
|
-
if (error) {
|
|
85
|
-
return (
|
|
86
|
-
<div>
|
|
87
|
-
<ApiError errors={error}></ApiError>
|
|
88
|
-
</div>
|
|
89
|
-
);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
const Pagination = (
|
|
93
|
-
<Paginator
|
|
94
|
-
variables={variables}
|
|
95
|
-
activePage={activePage}
|
|
96
|
-
limit={limit}
|
|
97
|
-
onPageChange={onPageChange}
|
|
98
|
-
/>
|
|
99
|
-
);
|
|
100
|
-
const Results: HouseType[] = data.PortalSite.houses;
|
|
101
|
-
|
|
102
|
-
return (
|
|
103
|
-
<div
|
|
104
|
-
id="results"
|
|
105
|
-
className={
|
|
106
|
-
PortalSite.options.filtersForm
|
|
107
|
-
? PortalSite.options.filtersForm.mode
|
|
108
|
-
: ''
|
|
109
|
-
}
|
|
110
|
-
>
|
|
111
|
-
{Pagination}
|
|
112
|
-
{Results.length === 0 ? (
|
|
113
|
-
<div className="bu-noresults">
|
|
114
|
-
<FormattedMessage id="no_results" />
|
|
115
|
-
</div>
|
|
116
|
-
) : null}
|
|
117
|
-
{Results.map((result) => (
|
|
118
|
-
<SingleResult
|
|
119
|
-
key={result.id}
|
|
120
|
-
result={result}
|
|
121
|
-
options={PortalSite.options.filtersForm}
|
|
122
|
-
/>
|
|
123
|
-
))}
|
|
124
|
-
{Pagination}
|
|
125
|
-
</div>
|
|
126
|
-
);
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
export default Results;
|
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
import React, { Component } from 'react';
|
|
2
|
-
import Filters from './Filters';
|
|
3
|
-
import Results from './Results';
|
|
4
|
-
import { PortalOptions, PortalSiteType } from '../../types';
|
|
5
|
-
import { FiltersType } from './filters/filter_types';
|
|
6
|
-
import { TrackEvent } from '../../_lib/Tracking';
|
|
7
|
-
|
|
8
|
-
type MyProps = {
|
|
9
|
-
options: PortalOptions;
|
|
10
|
-
filters?: FiltersType;
|
|
11
|
-
PortalSite: PortalSiteType;
|
|
12
|
-
locale: string;
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
type MyState = {
|
|
16
|
-
filters: FiltersType;
|
|
17
|
-
activePage: number;
|
|
18
|
-
limit: number;
|
|
19
|
-
skip: number;
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
class SearchPage extends Component<MyProps, MyState> {
|
|
23
|
-
constructor(props: MyProps) {
|
|
24
|
-
super(props);
|
|
25
|
-
let limit = this.props.options.filtersForm
|
|
26
|
-
? Number(this.props.options.filtersForm.no_results)
|
|
27
|
-
: 20;
|
|
28
|
-
this.state = {
|
|
29
|
-
filters: this.props.filters || {},
|
|
30
|
-
activePage: 1,
|
|
31
|
-
limit,
|
|
32
|
-
skip: 0
|
|
33
|
-
};
|
|
34
|
-
this.onFilterChange = this.onFilterChange.bind(this);
|
|
35
|
-
this.pageChange = this.pageChange.bind(this);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
componentDidMount() {
|
|
39
|
-
let filters = localStorage.getItem('bukazuFilters');
|
|
40
|
-
let activePage = localStorage.getItem('bukazuActivePage');
|
|
41
|
-
|
|
42
|
-
if (filters) {
|
|
43
|
-
this.setState({
|
|
44
|
-
filters: JSON.parse(filters)
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
if (activePage) {
|
|
48
|
-
this.pageChange(parseInt(activePage) || 0);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
onFilterChange(data: FiltersType) {
|
|
53
|
-
let filters = data;
|
|
54
|
-
this.setState({
|
|
55
|
-
filters
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
localStorage.setItem('bukazuFilters', JSON.stringify(filters));
|
|
59
|
-
this.pageChange(0);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
pageChange(pageNumber: number) {
|
|
63
|
-
const { limit } = this.state;
|
|
64
|
-
let newSkip = pageNumber * limit;
|
|
65
|
-
|
|
66
|
-
localStorage.setItem('bukazuActivePage', pageNumber.toString());
|
|
67
|
-
this.setState({
|
|
68
|
-
activePage: pageNumber,
|
|
69
|
-
skip: newSkip
|
|
70
|
-
});
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
render() {
|
|
74
|
-
const { filters, activePage, limit, skip } = this.state;
|
|
75
|
-
const { options, PortalSite, locale } = this.props;
|
|
76
|
-
|
|
77
|
-
TrackEvent({
|
|
78
|
-
portal_code: PortalSite.portal_code,
|
|
79
|
-
interaction_type: 'search_view',
|
|
80
|
-
locale: locale
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
return (
|
|
84
|
-
<div
|
|
85
|
-
id="search-page"
|
|
86
|
-
className={
|
|
87
|
-
options.filtersForm
|
|
88
|
-
? options.filtersForm.location === 'right'
|
|
89
|
-
? 'bu-reverse'
|
|
90
|
-
: options.filtersForm.location === 'top'
|
|
91
|
-
? 'bu-column'
|
|
92
|
-
: ''
|
|
93
|
-
: ''
|
|
94
|
-
}
|
|
95
|
-
>
|
|
96
|
-
<Filters
|
|
97
|
-
PortalSite={PortalSite}
|
|
98
|
-
filters={filters}
|
|
99
|
-
onFilterChange={this.onFilterChange}
|
|
100
|
-
options={options}
|
|
101
|
-
/>
|
|
102
|
-
<Results
|
|
103
|
-
PortalSite={PortalSite}
|
|
104
|
-
filters={filters}
|
|
105
|
-
activePage={activePage}
|
|
106
|
-
onPageChange={this.pageChange}
|
|
107
|
-
skip={skip}
|
|
108
|
-
limit={limit}
|
|
109
|
-
/>
|
|
110
|
-
</div>
|
|
111
|
-
);
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
export default SearchPage;
|
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { FormattedMessage, FormattedNumber } from 'react-intl';
|
|
3
|
-
import { FiltersFormType, HouseType } from '../../types';
|
|
4
|
-
import ArrowRight from '../icons/ArrowRight.svg';
|
|
5
|
-
|
|
6
|
-
interface Props {
|
|
7
|
-
result: HouseType;
|
|
8
|
-
options: FiltersFormType;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
function SingleResult({ result, options }: Props): JSX.Element {
|
|
12
|
-
let thisOptions = options || {};
|
|
13
|
-
|
|
14
|
-
return (
|
|
15
|
-
<a className="bukazu-result bu_card" href={result.house_url}>
|
|
16
|
-
<div className="bukazu-result-inner">
|
|
17
|
-
<div className="image-holder">
|
|
18
|
-
<img src={result.image_url} alt={result.name} />
|
|
19
|
-
</div>
|
|
20
|
-
<div className="result">
|
|
21
|
-
<div className="result-title">{result.name}</div>
|
|
22
|
-
<div className="result-place">
|
|
23
|
-
{thisOptions.showCity && <span>{result.city}, </span>}
|
|
24
|
-
{thisOptions.showRegion && <span>{result.province}, </span>}
|
|
25
|
-
{thisOptions.showCountry && <span>{result.country_name}</span>}
|
|
26
|
-
</div>
|
|
27
|
-
<div
|
|
28
|
-
className="result-description"
|
|
29
|
-
dangerouslySetInnerHTML={{ __html: result.description }}
|
|
30
|
-
/>
|
|
31
|
-
<div className="result-details">
|
|
32
|
-
{thisOptions.showPersons && (
|
|
33
|
-
<div>
|
|
34
|
-
{result.persons} <FormattedMessage id="persons" />
|
|
35
|
-
</div>
|
|
36
|
-
)}
|
|
37
|
-
{thisOptions.showBedrooms && (
|
|
38
|
-
<div>
|
|
39
|
-
{result.bedrooms} <FormattedMessage id="bedrooms" />
|
|
40
|
-
</div>
|
|
41
|
-
)}
|
|
42
|
-
{thisOptions.showBathrooms && (
|
|
43
|
-
<div>
|
|
44
|
-
{result.bathrooms} <FormattedMessage id="bathrooms" />
|
|
45
|
-
</div>
|
|
46
|
-
)}
|
|
47
|
-
</div>
|
|
48
|
-
{thisOptions.showRating && result.rating && (
|
|
49
|
-
<div className="result-rating bu_card">
|
|
50
|
-
<div className="result-rating-inner">
|
|
51
|
-
{result.rating.toFixed(1)}
|
|
52
|
-
</div>
|
|
53
|
-
</div>
|
|
54
|
-
)}
|
|
55
|
-
{thisOptions.showPrice && (
|
|
56
|
-
<div className="result-price">
|
|
57
|
-
{result.booking_price ? (
|
|
58
|
-
<>
|
|
59
|
-
<FormattedMessage id="price_from" />
|
|
60
|
-
<span className="price">
|
|
61
|
-
€{' '}
|
|
62
|
-
<FormattedNumber
|
|
63
|
-
value={result.booking_price.total_price}
|
|
64
|
-
minimumFractionDigits={0}
|
|
65
|
-
maximumFractionDigits={0}
|
|
66
|
-
/>
|
|
67
|
-
</span>
|
|
68
|
-
</>
|
|
69
|
-
) : (
|
|
70
|
-
<>
|
|
71
|
-
<FormattedMessage id="minimum_week_price" />
|
|
72
|
-
<span className="price">
|
|
73
|
-
€{' '}
|
|
74
|
-
<FormattedNumber
|
|
75
|
-
value={result.minimum_week_price}
|
|
76
|
-
minimumFractionDigits={0}
|
|
77
|
-
maximumFractionDigits={0}
|
|
78
|
-
/>
|
|
79
|
-
</span>
|
|
80
|
-
</>
|
|
81
|
-
)}
|
|
82
|
-
</div>
|
|
83
|
-
)}
|
|
84
|
-
<div className="result-button">
|
|
85
|
-
<FormattedMessage id="view_details" />
|
|
86
|
-
</div>
|
|
87
|
-
</div>
|
|
88
|
-
</div>
|
|
89
|
-
</a>
|
|
90
|
-
);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
export default SingleResult;
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import React, { SyntheticEvent } from 'react';
|
|
2
|
-
import { PortalSiteType } from '../../../types';
|
|
3
|
-
import { FiltersType } from './filter_types';
|
|
4
|
-
|
|
5
|
-
interface Props {
|
|
6
|
-
PortalSite: PortalSiteType;
|
|
7
|
-
filters: FiltersType;
|
|
8
|
-
onChange: Function;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
function Categories({ PortalSite, filters, onChange }: Props): JSX.Element[] {
|
|
12
|
-
const properties = filters.properties || [];
|
|
13
|
-
let requiredCategories = PortalSite.options.filtersForm.categories;
|
|
14
|
-
let input: JSX.Element[] = [];
|
|
15
|
-
|
|
16
|
-
const handleChange = (event: SyntheticEvent<any>) => {
|
|
17
|
-
const value = Number(event.currentTarget.value);
|
|
18
|
-
|
|
19
|
-
if (properties.includes(value)) {
|
|
20
|
-
let index = properties.indexOf(value);
|
|
21
|
-
properties.splice(index, 1);
|
|
22
|
-
} else {
|
|
23
|
-
properties.push(value);
|
|
24
|
-
}
|
|
25
|
-
onChange('properties', properties);
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
PortalSite.categories.map((category) => {
|
|
29
|
-
if (requiredCategories.includes(category.id)) {
|
|
30
|
-
input.push(
|
|
31
|
-
<div className="bu-properties" key={category.id}>
|
|
32
|
-
<strong>{category.name}</strong>
|
|
33
|
-
<ul>
|
|
34
|
-
{category.properties.map((property) => (
|
|
35
|
-
<li key={property.id}>
|
|
36
|
-
<label htmlFor={property.id.toString()}>
|
|
37
|
-
<input
|
|
38
|
-
type="checkbox"
|
|
39
|
-
id={property.id.toString()}
|
|
40
|
-
value={property.id}
|
|
41
|
-
checked={properties.includes(property.id)}
|
|
42
|
-
onChange={handleChange}
|
|
43
|
-
/>
|
|
44
|
-
{property.name}
|
|
45
|
-
</label>
|
|
46
|
-
</li>
|
|
47
|
-
))}
|
|
48
|
-
</ul>
|
|
49
|
-
</div>
|
|
50
|
-
);
|
|
51
|
-
}
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
return input;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
export default Categories;
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { format } from 'date-fns';
|
|
2
|
-
import React from 'react';
|
|
3
|
-
import DatePicker from 'react-date-picker';
|
|
4
|
-
import { Field } from './filter_types';
|
|
5
|
-
|
|
6
|
-
interface Props {
|
|
7
|
-
value: any;
|
|
8
|
-
onChange: Function;
|
|
9
|
-
field: Field;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
function DateFilter({ value, onChange, field }: Props): JSX.Element {
|
|
13
|
-
let tempval;
|
|
14
|
-
if (value === '' || !value) {
|
|
15
|
-
tempval = null;
|
|
16
|
-
} else {
|
|
17
|
-
tempval = new Date(value);
|
|
18
|
-
}
|
|
19
|
-
return (
|
|
20
|
-
<DatePicker
|
|
21
|
-
onChange={(date: Date) => {
|
|
22
|
-
if (date) {
|
|
23
|
-
onChange(field.id, format(date, 'yyyy-MM-dd'));
|
|
24
|
-
} else {
|
|
25
|
-
onChange(field.id, '');
|
|
26
|
-
}
|
|
27
|
-
}}
|
|
28
|
-
value={tempval}
|
|
29
|
-
format="dd-MM-y"
|
|
30
|
-
/>
|
|
31
|
-
);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export default DateFilter;
|