diff --git a/src/components/grw-app/grw-app.tsx b/src/components/grw-app/grw-app.tsx index 808c0ef..f65977a 100644 --- a/src/components/grw-app/grw-app.tsx +++ b/src/components/grw-app/grw-app.tsx @@ -147,6 +147,11 @@ export class GrwApp { } componentWillLoad() { + if (this.treks) { + state.mode = 'treks'; + } else if (this.touristicContents) { + state.mode = 'touristicContents'; + } const url = new URL(window.location.toString()); const trekParam = url.searchParams.get('trek'); const parentTrekId = url.searchParams.get('parenttrek'); diff --git a/src/components/grw-app/readme.md b/src/components/grw-app/readme.md index fb6faa7..09f324d 100644 --- a/src/components/grw-app/readme.md +++ b/src/components/grw-app/readme.md @@ -42,7 +42,7 @@ | `themes` | `themes` | | `string` | `undefined` | | `touristicContents` | `touristic-contents` | | `boolean` | `false` | | `touristicEvents` | `touristic-events` | | `boolean` | `false` | -| `treks` | `treks` | | `boolean` | `false` | +| `treks` | `treks` | | `boolean` | `true` | | `urlLayer` | `url-layer` | | `string` | `undefined` | | `useGradient` | `use-gradient` | | `boolean` | `false` | | `weather` | `weather` | | `boolean` | `false` | diff --git a/src/components/grw-filter/grw-filter.scss b/src/components/grw-filter/grw-filter.scss index 9a398bf..f0730a3 100644 --- a/src/components/grw-filter/grw-filter.scss +++ b/src/components/grw-filter/grw-filter.scss @@ -34,7 +34,7 @@ font-size: 14px; font-weight: 500; margin: 8px 0px 0px 8px; - padding: 8px 16px; + padding: 8px 0px; .choices__inner { border: 1px solid var(--color-outline); border-radius: 8px; @@ -67,7 +67,7 @@ } .choices__list--dropdown, .choices__list[aria-expanded] { - width: calc(100% - 32px); + width: 100%; color: var(--color-on-secondary-container); background-color: var(--color-secondary-container); border: 1px solid var(--color-outline); diff --git a/src/components/grw-filter/grw-filter.tsx b/src/components/grw-filter/grw-filter.tsx index 67b4e15..0ef83b1 100644 --- a/src/components/grw-filter/grw-filter.tsx +++ b/src/components/grw-filter/grw-filter.tsx @@ -1,6 +1,6 @@ import { Component, Host, h, Prop, Listen, forceUpdate, Element } from '@stencil/core'; import state from 'store/store'; -import { filters, handleFiltersAndSearch } from 'utils/utils'; +import { treksFilters, handleTreksFiltersAndSearch, touristicContentsFilters, handleTouristicContentsFiltersAndSearch } from 'utils/utils'; import 'choices.js/public/assets/scripts/choices.min.js'; @Component({ @@ -32,13 +32,24 @@ export class GrwFilter { state[this.filterType] = filterFromState; state[this.segment] = 0; - filters - .filter(filter => filter.segment === this.segment) - .forEach(filter => { - state[this.segment] += state[filter.property].filter(filter => filter.selected).length; - }); - state.currentTreks = handleFiltersAndSearch(); + if (state.mode === 'treks') { + treksFilters + .filter(filter => filter.segment === this.segment) + .forEach(filter => { + state[this.segment] += state[filter.property].filter(filter => filter.selected).length; + }); + + state.currentTreks = handleTreksFiltersAndSearch(); + } else if (state.mode === 'touristicContents') { + touristicContentsFilters + .filter(filter => filter.segment === this.segment) + .forEach(filter => { + state[this.segment] += state[filter.property].filter(filter => filter.selected).length; + }); + + state.currentTouristicContents = handleTouristicContentsFiltersAndSearch(); + } } resetFilter() { diff --git a/src/components/grw-filters/grw-filters.scss b/src/components/grw-filters/grw-filters.scss index 56fc9ea..8176d78 100644 --- a/src/components/grw-filters/grw-filters.scss +++ b/src/components/grw-filters/grw-filters.scss @@ -12,6 +12,10 @@ width: 100%; height: 100%; z-index: 1100; + .filters-treks-container, + .filters-touristic-contents-container { + height: 100%; + } .segmented-buttons-container { display: flex; justify-content: center; @@ -56,9 +60,9 @@ } .filters-segment-container { - overflow-y: scroll; - padding-bottom: 32px; - height: calc(100% - 64px - 42px - 32px); + overflow-y: visible; + height: 100%; + max-height: calc(100% - 64px - 42px - 32px); } .back-filters-container { @@ -104,7 +108,8 @@ } .segment-container { - margin-bottom: 64px; + overflow: scroll; + height: 100%; } .filter-container { @@ -116,4 +121,7 @@ border-top: 1px solid var(--color-outline); } } + &:last-child { + margin-bottom: 16px; + } } diff --git a/src/components/grw-filters/grw-filters.tsx b/src/components/grw-filters/grw-filters.tsx index f3ead02..ddefc10 100644 --- a/src/components/grw-filters/grw-filters.tsx +++ b/src/components/grw-filters/grw-filters.tsx @@ -1,7 +1,7 @@ import { Component, Event, EventEmitter, Host, Prop, State, h } from '@stencil/core'; import { translate } from 'i18n/i18n'; import state from 'store/store'; -import { filters, handleFiltersAndSearch } from 'utils/utils'; +import { treksFilters, handleTreksFiltersAndSearch, touristicContentsFilters, handleTouristicContentsFiltersAndSearch } from 'utils/utils'; @Component({ tag: 'grw-filters', @@ -15,26 +15,44 @@ export class GrwFilters { @Prop() handleFilters: Function; - handleEraseFilters() { - filters.forEach(filter => { + handleEraseTreksFilters() { + treksFilters.forEach(filter => { state[filter.property].forEach(currentFilter => (currentFilter.selected = false)); }); state.selectedActivitiesFilters = 0; state.selectedThemesFilters = 0; state.selectedLocationFilters = 0; - state.currentTreks = handleFiltersAndSearch(); + state.currentTreks = handleTreksFiltersAndSearch(); this.resetFilter.emit(); } + handleOkTreksFilters() { + this.handleFilters(); + } + handleSelectedSegment(selectedSegment) { this.selectedSegment = selectedSegment; } handleSegment(segment) { - return filters.filter(filter => filter.segment === segment).some(filter => state[filter.property] && state[filter.property].length > 0); + if (state.mode === 'treks') { + return treksFilters.filter(filter => filter.segment === segment).some(filter => state[filter.property] && state[filter.property].length > 0); + } else if (state.mode === 'touristicContents') { + return touristicContentsFilters.filter(filter => filter.segment === segment).some(filter => state[filter.property] && state[filter.property].length > 0); + } } - handleOkFilters() { + handleEraseTouristicContentsFilters() { + touristicContentsFilters.forEach(filter => { + state[filter.property].forEach(currentFilter => (currentFilter.selected = false)); + }); + state.selectedActivitiesFilters = 0; + state.selectedLocationFilters = 0; + state.currentTouristicContents = handleTouristicContentsFiltersAndSearch(); + this.resetFilter.emit(); + } + + handleOkTouristicContentsFilters() { this.handleFilters(); } @@ -43,169 +61,245 @@ export class GrwFilters {
-
- {state.treksWithinBounds && ( -
{`${state.treksWithinBounds.length} ${ - state.treksWithinBounds.length > 1 ? translate[state.language].treks : translate[state.language].trek - }`}
- )} -
- - -
-
-
- {this.handleSegment('selectedActivitiesFilters') && ( - - )} - {this.handleSegment('selectedThemesFilters') && ( - - )} - {this.handleSegment('selectedLocationFilters') && ( - - )} -
-
-
- {this.selectedSegment === 'selectedActivitiesFilters' && ( -
- {state['practices'].length > 0 && ( -
- -
- )} - {state['difficulties'].length > 0 && ( -
- -
- )} - {state['durations'].length > 0 && ( -
- -
- )} - {state['lengths'].length > 0 && ( -
- -
- )} - {state['elevations'].length > 0 && ( -
- -
- )} - {state['routes'].length > 0 && ( -
- -
- )} - {state['accessibilities'].length > 0 && ( -
- -
- )} - {state['labels'].length > 0 && ( -
- -
- )} -
- )} -
-
- {this.selectedSegment === 'selectedThemesFilters' && ( -
- {state['themes'].length > 0 && ( -
- -
- )} + {state.mode === 'treks' && ( +
+
+ {state.treksWithinBounds && ( +
{`${state.treksWithinBounds.length} ${ + state.treksWithinBounds.length > 1 ? translate[state.language].treks : translate[state.language].trek + }`}
+ )} +
+ +
- )} +
+
+ {this.handleSegment('selectedActivitiesFilters') && ( + + )} + {this.handleSegment('selectedThemesFilters') && ( + + )} + {this.handleSegment('selectedLocationFilters') && ( + + )} +
+
+ {this.selectedSegment === 'selectedActivitiesFilters' && ( +
+ {state['practices'].length > 0 && ( +
+ +
+ )} + {state['difficulties'].length > 0 && ( +
+ +
+ )} + {state['durations'].length > 0 && ( +
+ +
+ )} + {state['lengths'].length > 0 && ( +
+ +
+ )} + {state['elevations'].length > 0 && ( +
+ +
+ )} + {state['routes'].length > 0 && ( +
+ +
+ )} + {state['accessibilities'].length > 0 && ( +
+ +
+ )} + {state['labels'].length > 0 && ( +
+ +
+ )} +
+ )} + {this.selectedSegment === 'selectedThemesFilters' && ( +
+ {state['themes'].length > 0 && ( +
+ +
+ )} +
+ )} + {this.selectedSegment === 'selectedLocationFilters' && ( +
+ {state['districts'].length > 0 && ( +
+ +
+ )} + {state['cities'].length > 0 && ( +
+ +
+ )} +
+ )} +
-
- {this.selectedSegment === 'selectedLocationFilters' && ( -
- {state['districts'].length > 0 && ( -
- -
- )} - {state['cities'].length > 0 && ( -
- -
- )} + )} + {state.mode === 'touristicContents' && ( +
+
+ {state.touristicContentsWithinBounds && ( +
{`${state.touristicContentsWithinBounds.length} ${ + state.touristicContentsWithinBounds.length > 1 ? translate[state.language].home.touristicContents : translate[state.language].home.touristicContent + }`}
+ )} +
+ +
- )} +
+
+ {this.handleSegment('selectedActivitiesFilters') && ( + + )} + {this.handleSegment('selectedLocationFilters') && ( + + )} +
+
+ {this.selectedSegment === 'selectedActivitiesFilters' && ( +
+ {state['touristicContentCategories'].length > 0 && ( +
+ +
+ )} +
+ )} + {this.selectedSegment === 'selectedLocationFilters' && ( +
+ {state['districts'].length > 0 && ( +
+ +
+ )} + {state['cities'].length > 0 && ( +
+ +
+ )} +
+ )} +
-
+ )}
this.handleFilters()} class="back-filters-container">
diff --git a/src/components/grw-map/grw-map.tsx b/src/components/grw-map/grw-map.tsx index c73b864..4e6681f 100644 --- a/src/components/grw-map/grw-map.tsx +++ b/src/components/grw-map/grw-map.tsx @@ -167,26 +167,15 @@ export class GrwMap { @Listen('cardTouristicContentMouseOver', { target: 'window' }) onTouristicContentMouseOver(event: CustomEvent) { - // if (!state.parentTrek && (!state.selectedTrekId || state.selectedTrekId !== event.detail)) { - // state.selectedTrekId = event.detail; - // this.addSelectedCurrentTrek(event.detail); - // } else if (state.parentTrek) { this.touristicContentPopupIsOpen = false; state.selectedTouristicContentId = null; this.addSelectedTouristicContent(event.detail); - // } } @Listen('cardTouristicContentMouseLeave', { target: 'window' }) onTouristicContentMouseLeave() { - // if (!this.trekPopupIsOpen && state.selectedTrekId) { - // this.trekPopupIsOpen = false; - // state.selectedTrekId = null; - // this.removeSelectedCurrentTrek(); - // } else if (this.currentStepsLayer) { state.selectedTouristicContentId = null; this.removeSelectedTouristicContent(); - // } } componentDidLoad() { @@ -313,11 +302,11 @@ export class GrwMap { } }); - onChange('touristicContents', () => { + onChange('currentTouristicContents', () => { if (state.currentTouristicContent) { this.removeTouristicContents(); this.addTouristicContent(); - } else if (state.touristicContents) { + } else if (state.currentTouristicContents) { this.removeTouristicContent(); this.addTouristicContents(); } @@ -457,10 +446,10 @@ export class GrwMap { handleTouristicContentsWithinBounds() { if ( - (state.touristicContents && !state.currentMapBounds) || - (state.touristicContents && state.currentMapBounds && state.currentMapBounds.toBBoxString() !== this.map.getBounds().toBBoxString()) + (state.currentTouristicContents && !state.currentMapBounds) || + (state.currentTouristicContents && state.currentMapBounds && state.currentMapBounds.toBBoxString() !== this.map.getBounds().toBBoxString()) ) { - state.touristicContentsWithinBounds = state.touristicContents.filter(touristicContent => + state.touristicContentsWithinBounds = state.currentTouristicContents.filter(touristicContent => this.map.getBounds().contains(L.latLng(touristicContent.geometry.coordinates[1], touristicContent.geometry.coordinates[0])), ); } @@ -1227,16 +1216,16 @@ export class GrwMap { this.bounds = state.currentMapBounds; } } - for (const touristicContent of state.touristicContents) { - touristicContentsCurrentCoordinates.push(touristicContent.geometry.coordinates); + for (const currentTouristicContent of state.currentTouristicContents) { + touristicContentsCurrentCoordinates.push(currentTouristicContent.geometry.coordinates); touristicContentsFeatureCollection.features.push({ type: 'Feature', - geometry: { type: 'Point', coordinates: touristicContent.geometry.coordinates }, + geometry: { type: 'Point', coordinates: currentTouristicContent.geometry.coordinates }, properties: { - id: touristicContent.id, - name: touristicContent.name, - practice: state.touristicContentCategories.find(touristicContentCategory => touristicContentCategory.id === touristicContent.category).pictogram, + id: currentTouristicContent.id, + name: currentTouristicContent.name, + practice: state.touristicContentCategories.find(touristicContentCategory => touristicContentCategory.id === currentTouristicContent.category).pictogram, }, }); } @@ -1314,8 +1303,8 @@ export class GrwMap { } this.toutisticContentsLayer.clearLayers(); this.toutisticContentsLayer.addData(touristicContentsFeatureCollection); - this.treksMarkerClusterGroup.clearLayers(); - this.treksMarkerClusterGroup.addLayer(this.toutisticContentsLayer); + this.touristicContentsMarkerClusterGroup.clearLayers(); + this.touristicContentsMarkerClusterGroup.addLayer(this.toutisticContentsLayer); } this.bounds && this.map.fitBounds(this.bounds); diff --git a/src/components/grw-search/grw-search.tsx b/src/components/grw-search/grw-search.tsx index e3c585a..54666a3 100644 --- a/src/components/grw-search/grw-search.tsx +++ b/src/components/grw-search/grw-search.tsx @@ -1,6 +1,6 @@ import { Component, Host, h } from '@stencil/core'; import state from 'store/store'; -import { handleFiltersAndSearch } from 'utils/utils'; +import { handleTouristicContentsFiltersAndSearch, handleTreksFiltersAndSearch } from 'utils/utils'; @Component({ tag: 'grw-search', @@ -10,7 +10,11 @@ import { handleFiltersAndSearch } from 'utils/utils'; export class GrwSearch { onSearchChange(event: InputEvent) { state.searchValue = (event.target as any).value; - state.currentTreks = handleFiltersAndSearch(); + if (state.mode === 'treks') { + state.currentTreks = handleTreksFiltersAndSearch(); + } else if (state.mode === 'touristicContents') { + state.currentTouristicContents = handleTouristicContentsFiltersAndSearch(); + } } render() { diff --git a/src/components/grw-touristic-contents-list/grw-touristic-contents-list.scss b/src/components/grw-touristic-contents-list/grw-touristic-contents-list.scss index 1bd733a..25a0884 100644 --- a/src/components/grw-touristic-contents-list/grw-touristic-contents-list.scss +++ b/src/components/grw-touristic-contents-list/grw-touristic-contents-list.scss @@ -11,9 +11,11 @@ width: 100%; height: 100%; overflow-y: auto; + width: 100%; } grw-touristic-content-card { + width: 100% !important; margin: 0px 8px 8px 8px; } diff --git a/src/components/grw-touristic-contents-list/grw-touristic-contents-list.tsx b/src/components/grw-touristic-contents-list/grw-touristic-contents-list.tsx index 8685b72..9d43bda 100644 --- a/src/components/grw-touristic-contents-list/grw-touristic-contents-list.tsx +++ b/src/components/grw-touristic-contents-list/grw-touristic-contents-list.tsx @@ -27,20 +27,20 @@ export class GrwTouristicContentsList { connectedCallback() { this.handleInfiniteScrollEvent(true); - if (state.touristicContents) { - this.touristicContentsToDisplay = [...state.touristicContents.slice(0, this.step)]; + if (state.currentTouristicContents) { + this.touristicContentsToDisplay = [...state.currentTouristicContents.slice(0, this.step)]; } - onChange('touristicContents', () => { + onChange('currentTouristicContents', () => { this.handleInfiniteScrollEvent(true); this.element.scroll({ top: 0 }); - if (state.touristicContents) { - this.touristicContentsToDisplay = [...state.touristicContents.slice(0, this.step)]; + if (state.currentTouristicContents) { + this.touristicContentsToDisplay = [...state.currentTouristicContents.slice(0, this.step)]; } }); onChange('touristicContentsWithinBounds', () => { this.handleInfiniteScrollEvent(true); this.element.scroll({ top: 0 }); - if (state.touristicContents) { + if (state.touristicContentsWithinBounds) { this.touristicContentsToDisplay = [...state.touristicContentsWithinBounds.slice(0, this.step)]; } }); diff --git a/src/i18n/i18n.ts b/src/i18n/i18n.ts index bd09da3..0efa4d0 100644 --- a/src/i18n/i18n.ts +++ b/src/i18n/i18n.ts @@ -77,6 +77,8 @@ interface Translation { contact: string; email: string; website: string; + category: string; + services: string; } interface AvailableTranslations { @@ -164,6 +166,8 @@ export const translate: AvailableTranslations = { contact: 'Contact', email: 'Email', website: 'Site web', + category: 'Catégorie', + services: 'Services', }, en: { filter: 'Filter', @@ -244,5 +248,7 @@ export const translate: AvailableTranslations = { contact: 'Contact', email: 'Email', website: 'Website', + category: 'Category', + services: 'Services', }, }; diff --git a/src/store/grw-touristic-content-provider.tsx b/src/store/grw-touristic-content-provider.tsx index 48f821b..53ec268 100644 --- a/src/store/grw-touristic-content-provider.tsx +++ b/src/store/grw-touristic-content-provider.tsx @@ -39,7 +39,7 @@ export class GrwTouristicContentProvider { ), ]) .then(responses => Promise.all(responses.map(response => response.json()))) - .then(async ([cities, touristicContentCategory, touristicContent]) => { + .then(([cities, touristicContentCategory, touristicContent]) => { state.trekNetworkError = false; if (cities) { diff --git a/src/store/grw-touristic-contents-provider.tsx b/src/store/grw-touristic-contents-provider.tsx index 48e6bad..f62fd45 100644 --- a/src/store/grw-touristic-contents-provider.tsx +++ b/src/store/grw-touristic-contents-provider.tsx @@ -25,26 +25,31 @@ export class GrwTouristicContentsProvider { handleTouristicContents() { const requests = []; requests.push(!state.cities ? fetch(`${state.api}city/?language=${state.language}&fields=id,name&published=true&page_size=999`, this.init) : new Response('null')); - requests.push( - !state.touristicContentCategories - ? fetch(`${state.api}touristiccontent_category/?language=${state.language}&published=true&fields=id,label,pictogram&page_size=999`, this.init) - : new Response('null'), - ); + requests.push(!state.districts ? fetch(`${state.api}district/?language=${state.language}&fields=id,name&published=true&page_size=999`, this.init) : new Response('null')), + requests.push( + !state.touristicContentCategories + ? fetch(`${state.api}touristiccontent_category/?language=${state.language}&published=true&fields=id,label,pictogram&page_size=999`, this.init) + : new Response('null'), + ); Promise.all([ ...requests, - fetch(`${state.api}touristiccontent/?language=${state.language}&published=true&fields=id,name,attachments,category,geometry&page_size=999`, this.init), + fetch(`${state.api}touristiccontent/?language=${state.language}&published=true&fields=id,name,attachments,category,geometry,cities,districts&page_size=999`, this.init), ]) .then(responses => Promise.all(responses.map(response => response.json()))) - .then(async ([cities, touristicContentCategory, touristicContents]) => { + .then(([cities, districts, touristicContentCategory, touristicContents]) => { state.trekNetworkError = false; if (cities) { state.cities = cities.results; } + if (districts) { + state.districts = districts.results; + } if (touristicContentCategory) { state.touristicContentCategories = touristicContentCategory.results; } + state.currentTouristicContents = touristicContents.results; state.touristicContentsWithinBounds = touristicContents.results; state.touristicContents = touristicContents.results; }) diff --git a/src/store/grw-touristic-event-provider.tsx b/src/store/grw-touristic-event-provider.tsx index 671805c..d7cf7eb 100644 --- a/src/store/grw-touristic-event-provider.tsx +++ b/src/store/grw-touristic-event-provider.tsx @@ -39,7 +39,7 @@ export class GrwTouristicEventProvider { ), ]) .then(responses => Promise.all(responses.map(response => response.json()))) - .then(async ([cities, touristicContentTypes, touristicEvent]) => { + .then(([cities, touristicContentTypes, touristicEvent]) => { state.trekNetworkError = false; if (cities) { diff --git a/src/store/store.ts b/src/store/store.ts index 46caa7a..afadcc4 100644 --- a/src/store/store.ts +++ b/src/store/store.ts @@ -29,6 +29,7 @@ import { } from 'types/types'; const { state, onChange, reset } = createStore<{ + mode: string; api: string; languages: string[]; language: string; @@ -67,6 +68,7 @@ const { state, onChange, reset } = createStore<{ selectedStepId: number; trekTouristicContents: TouristicContents; touristicContents: TouristicContents; + currentTouristicContents: TouristicContents; touristicContentsWithinBounds: TouristicContents; touristicContentCategories: TouristicContentCategories; currentTouristicContent: TouristicContent; @@ -75,6 +77,7 @@ const { state, onChange, reset } = createStore<{ currentTouristicEvent: TouristicEvent; selectedTouristicContentId: number; }>({ + mode: null, api: null, languages: null, language: null, @@ -113,6 +116,7 @@ const { state, onChange, reset } = createStore<{ selectedStepId: null, trekTouristicContents: null, touristicContents: null, + currentTouristicContents: null, touristicContentsWithinBounds: null, touristicContentCategories: null, currentTouristicContent: null, diff --git a/src/types/types.ts b/src/types/types.ts index 519a2d9..527860b 100644 --- a/src/types/types.ts +++ b/src/types/types.ts @@ -282,17 +282,21 @@ export type TouristicEventType = { export type TouristicEventTypes = TouristicEventType[]; -export type Filters = Filter[]; +export type TrekFilters = TrekFilter[]; -export type Filter = { property: string; trekProperty: string; trekPropertyIsArray: boolean; type: string; segment: string }; +export type TrekFilter = { property: string; trekProperty: string; trekPropertyIsArray: boolean; type: string; segment: string }; -export interface Option { +export type TouristicContentsFilters = TouristicContentsFilter[]; + +export type TouristicContentsFilter = { property: string; touristicContentProperty: string; touristicContentPropertyIsArray: boolean; type: string; segment: string }; + +export type Option = { visible: boolean; width: number; indicator: boolean; -} +}; -export interface Options { +export type Options = { presentation: Option; steps: Option; description: Option; @@ -302,4 +306,6 @@ export interface Options { pois: Option; touristicContents: Option; touristicEvents: Option; -} +}; + +export type mode = 'treks' | 'touristicContents'; diff --git a/src/utils/utils.ts b/src/utils/utils.ts index 6499a4d..ed6467f 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -1,5 +1,5 @@ import state from 'store/store'; -import { Filters, Treks } from 'types/types'; +import { TouristicContents, TouristicContentsFilters, TrekFilters, Treks } from 'types/types'; export function formatDuration(duration: number) { let formattedDuration; @@ -22,7 +22,7 @@ export function formatAscent(ascent: number) { return `${ascent}m`; } -export const filters: Filters = [ +export const treksFilters: TrekFilters = [ { property: 'practices', trekProperty: 'practice', trekPropertyIsArray: false, type: 'include', segment: 'selectedActivitiesFilters' }, { property: 'difficulties', trekProperty: 'difficulty', trekPropertyIsArray: false, type: 'include', segment: 'selectedActivitiesFilters' }, { property: 'durations', trekProperty: 'duration', trekPropertyIsArray: false, type: 'interval', segment: 'selectedActivitiesFilters' }, @@ -36,10 +36,16 @@ export const filters: Filters = [ { property: 'districts', trekProperty: 'districts', trekPropertyIsArray: true, type: 'include', segment: 'selectedLocationFilters' }, ]; -export function handleFiltersAndSearch(): Treks { +export const touristicContentsFilters: TouristicContentsFilters = [ + { property: 'touristicContentCategories', touristicContentProperty: 'category', touristicContentPropertyIsArray: false, type: 'include', segment: 'selectedActivitiesFilters' }, + { property: 'cities', touristicContentProperty: 'cities', touristicContentPropertyIsArray: true, type: 'include', segment: 'selectedLocationFilters' }, + { property: 'districts', touristicContentProperty: 'districts', touristicContentPropertyIsArray: true, type: 'include', segment: 'selectedLocationFilters' }, +]; + +export function handleTreksFiltersAndSearch(): Treks { let isUsingFilter = false; let filtersTreks = []; - for (const filter of filters) { + for (const filter of treksFilters) { const currentFiltersId: number[] = state[filter.property].filter(currentFilter => currentFilter.selected).map(currentFilter => currentFilter.id); if (currentFiltersId.length > 0) { if (filtersTreks.length > 0) { @@ -93,3 +99,75 @@ export function handleFiltersAndSearch(): Treks { const searchTreks = isUsingFilter ? filtersTreks : state.treks; return Boolean(state.searchValue) ? searchTreks.filter(currentTrek => currentTrek.name.toLowerCase().includes(state.searchValue.toLowerCase())) : searchTreks; } + +export function handleTouristicContentsFiltersAndSearch(): TouristicContents { + let isUsingFilter = false; + let filtersTouristicContents = []; + for (const filter of touristicContentsFilters) { + const currentFiltersId: number[] = state[filter.property].filter(currentFilter => currentFilter.selected).map(currentFilter => currentFilter.id); + if (currentFiltersId.length > 0) { + if (filtersTouristicContents.length > 0) { + if (filter.type === 'include') { + if (filter.touristicContentPropertyIsArray) { + filtersTouristicContents = [ + ...filtersTouristicContents.filter(touristicContent => + touristicContent[filter.touristicContentProperty].some(touristicContentProperty => currentFiltersId.includes(touristicContentProperty)), + ), + ]; + } else { + filtersTouristicContents = [...filtersTouristicContents.filter(touristicContent => currentFiltersId.includes(touristicContent[filter.touristicContentProperty]))]; + } + } else if (filter.type === 'interval') { + filtersTouristicContents = [ + ...filtersTouristicContents.filter(touristicContent => { + for (const currentFilterId of currentFiltersId) { + const currentFilter = state[filter.property].find(property => property.id === currentFilterId); + if (touristicContent[filter.touristicContentProperty] >= currentFilter.minValue && touristicContent[filter.touristicContentProperty] <= currentFilter.maxValue) { + return true; + } + } + return false; + }), + ]; + } + } else { + if (!isUsingFilter) { + isUsingFilter = true; + } + if (filter.type === 'include') { + if (filter.touristicContentPropertyIsArray) { + filtersTouristicContents = [ + ...state.touristicContents.filter(touristicContent => + touristicContent[filter.touristicContentProperty].some(touristicContentProperty => currentFiltersId.includes(touristicContentProperty)), + ), + ]; + } else { + filtersTouristicContents = [...state.touristicContents.filter(touristicContent => currentFiltersId.includes(touristicContent[filter.touristicContentProperty]))]; + } + } else if (filter.type === 'interval') { + let minValue: number; + let maxValue: number; + for (const currentFilterId of currentFiltersId) { + const currentFilter = state[filter.property].find(property => property.id === currentFilterId); + if (isNaN(minValue) || currentFilter.minValue < minValue) { + minValue = currentFilter.minValue; + } + if (isNaN(maxValue) || currentFilter.maxValue > maxValue) { + maxValue = currentFilter.maxValue; + } + } + filtersTouristicContents = [ + ...state.touristicContents.filter( + touristicContent => touristicContent[filter.touristicContentProperty] >= minValue && touristicContent[filter.touristicContentProperty] <= maxValue, + ), + ]; + } + } + } + } + + const searchTouristicContents = isUsingFilter ? filtersTouristicContents : state.touristicContents; + return Boolean(state.searchValue) + ? searchTouristicContents.filter(currentTouristicContents => currentTouristicContents.name.toLowerCase().includes(state.searchValue.toLowerCase())) + : searchTouristicContents; +}