WIP Migrate filter panel
This commit is contained in:
@@ -1,108 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace EP\EpProducts\Controller;
|
|
||||||
|
|
||||||
/***************************************************************
|
|
||||||
*
|
|
||||||
* Copyright notice
|
|
||||||
*
|
|
||||||
* (c) 2016 Björn Fromme <[email protected]>, dreipunktnull
|
|
||||||
*
|
|
||||||
* All rights reserved
|
|
||||||
*
|
|
||||||
* This script is part of the TYPO3 project. The TYPO3 project is
|
|
||||||
* free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* The GNU General Public License can be found at
|
|
||||||
* http://www.gnu.org/copyleft/gpl.html.
|
|
||||||
*
|
|
||||||
* This script is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* This copyright notice MUST APPEAR in all copies of the script!
|
|
||||||
***************************************************************/
|
|
||||||
|
|
||||||
use EP\EpProducts\Domain\Model\FilterSettings;
|
|
||||||
use EP\EpProducts\Service\DateService;
|
|
||||||
use EP\EpProducts\Service\FilterService;
|
|
||||||
use EP\EpProducts\Traits\RequestArgumentTypeConversionTrait;
|
|
||||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
|
||||||
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
|
|
||||||
|
|
||||||
class AjaxFilterpanelController extends ActionController
|
|
||||||
{
|
|
||||||
|
|
||||||
use RequestArgumentTypeConversionTrait;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \EP\EpProducts\Service\FilterService
|
|
||||||
*/
|
|
||||||
protected $filterService;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var DateService
|
|
||||||
*/
|
|
||||||
protected $dateService;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param FilterService $filterService
|
|
||||||
*/
|
|
||||||
public function __construct(FilterService $filterService, DateService $dateService)
|
|
||||||
{
|
|
||||||
parent::__construct();
|
|
||||||
$this->filterService = $filterService;
|
|
||||||
$this->dateService = $dateService;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function initializeAction()
|
|
||||||
{
|
|
||||||
$forcedConceptUids = GeneralUtility::trimExplode(',', $this->settings['forcedConceptUids'], true);
|
|
||||||
$this->processFilterSettingsArgument($forcedConceptUids);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param FilterSettings $filterSettings
|
|
||||||
*/
|
|
||||||
public function panelAction(FilterSettings $filterSettings)
|
|
||||||
{
|
|
||||||
$excludedConceptUids = GeneralUtility::trimExplode(',', $this->settings['excludedConceptUids']);
|
|
||||||
$excludedRegionUids = GeneralUtility::trimExplode(',', $this->settings['excludedRegionUids']);
|
|
||||||
|
|
||||||
$filterOptions = $this->filterService->getFilterOptions(
|
|
||||||
$filterSettings,
|
|
||||||
$excludedConceptUids,
|
|
||||||
$excludedRegionUids
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->view->assignMultiple([
|
|
||||||
'filterOptions' => $filterOptions,
|
|
||||||
'filterSettings' => $filterSettings,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param FilterSettings $filterSettings
|
|
||||||
* @param string $search
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function autocompleteAction(FilterSettings $filterSettings, $search)
|
|
||||||
{
|
|
||||||
$excludedConceptUids = GeneralUtility::trimExplode(',', $this->settings['excludedConceptUids']);
|
|
||||||
$excludedRegionUids = GeneralUtility::trimExplode(',', $this->settings['excludedRegionUids']);
|
|
||||||
|
|
||||||
$destinations = $this->dateService->getAutocompleteOptions(
|
|
||||||
$filterSettings,
|
|
||||||
$search,
|
|
||||||
$excludedConceptUids,
|
|
||||||
$excludedRegionUids
|
|
||||||
);
|
|
||||||
return json_encode($destinations, JSON_THROW_ON_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -92,6 +92,7 @@ class AjaxSearchController extends ActionController
|
|||||||
$organic = true;
|
$organic = true;
|
||||||
$forcedConceptUids = GeneralUtility::trimExplode(',', $this->settings['forcedConceptUids'], true);
|
$forcedConceptUids = GeneralUtility::trimExplode(',', $this->settings['forcedConceptUids'], true);
|
||||||
$excludedConceptUids = GeneralUtility::trimExplode(',', $this->settings['excludedConceptUids']);
|
$excludedConceptUids = GeneralUtility::trimExplode(',', $this->settings['excludedConceptUids']);
|
||||||
|
$excludedRegionUids = GeneralUtility::trimExplode(',', $this->settings['excludedRegionUids']);
|
||||||
|
|
||||||
if ($filterSettings === null) {
|
if ($filterSettings === null) {
|
||||||
$filterSettings = $this->filterService->getDefaultFilterSettings($forcedConceptUids);
|
$filterSettings = $this->filterService->getDefaultFilterSettings($forcedConceptUids);
|
||||||
@@ -115,6 +116,13 @@ class AjaxSearchController extends ActionController
|
|||||||
|
|
||||||
$this->searchResultUrlService->process($searchResult, $options);
|
$this->searchResultUrlService->process($searchResult, $options);
|
||||||
|
|
||||||
|
$filterOptions = $this->filterService->getFilterOptions(
|
||||||
|
$filterSettings,
|
||||||
|
$excludedConceptUids,
|
||||||
|
$excludedRegionUids,
|
||||||
|
$forcedConceptUids
|
||||||
|
);
|
||||||
|
|
||||||
$referringPageUri = $this
|
$referringPageUri = $this
|
||||||
->uriBuilder
|
->uriBuilder
|
||||||
->reset()
|
->reset()
|
||||||
@@ -129,12 +137,13 @@ class AjaxSearchController extends ActionController
|
|||||||
;
|
;
|
||||||
|
|
||||||
$this->view->assignMultiple([
|
$this->view->assignMultiple([
|
||||||
|
'filterSettings' => $filterSettings,
|
||||||
|
'filterOptions' => $filterOptions,
|
||||||
'searchResult' => $searchResult->getData(),
|
'searchResult' => $searchResult->getData(),
|
||||||
'referringPageUri' => $referringPageUri,
|
'referringPageUri' => $referringPageUri,
|
||||||
'meta' => [
|
'meta' => [
|
||||||
'organic' => $organic,
|
'organic' => $organic,
|
||||||
'total' => $searchResult->getTotal(),
|
'total' => $searchResult->getTotal(),
|
||||||
'destinationName' => $filterSettings->getDestinationName(),
|
|
||||||
'dateRange' => DateUtility::formatDateRange($filterSettings->getDateFrom(), $filterSettings->getDateTo()),
|
'dateRange' => DateUtility::formatDateRange($filterSettings->getDateFrom(), $filterSettings->getDateTo()),
|
||||||
'dateSelected' => $dateSelected,
|
'dateSelected' => $dateSelected,
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -55,8 +55,7 @@ class AjaxSearchbarController extends ActionController
|
|||||||
|
|
||||||
public function initializeAction()
|
public function initializeAction()
|
||||||
{
|
{
|
||||||
$forcedConceptUids = GeneralUtility::trimExplode(',', $this->settings['forcedConceptUids'], true);
|
$this->processSearchParamsArgument();
|
||||||
$this->processSearchParamsArgument($forcedConceptUids);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -65,16 +64,23 @@ class AjaxSearchbarController extends ActionController
|
|||||||
*/
|
*/
|
||||||
public function updateAction(SearchParams $searchParams = null)
|
public function updateAction(SearchParams $searchParams = null)
|
||||||
{
|
{
|
||||||
|
$forcedConceptUids = GeneralUtility::trimExplode(',', $this->settings['forcedConceptUids'], true);
|
||||||
|
|
||||||
if ($searchParams === null) {
|
if ($searchParams === null) {
|
||||||
$searchParams = new SearchParams();
|
$searchParams = new SearchParams();
|
||||||
$forcedConceptUids = GeneralUtility::trimExplode(',', $this->settings['forcedConceptUids'], true);
|
|
||||||
$filterSettings = $this->filterService->getDefaultFilterSettings($forcedConceptUids);
|
$filterSettings = $this->filterService->getDefaultFilterSettings($forcedConceptUids);
|
||||||
} else {
|
} else {
|
||||||
$filterSettings = FilterSettings::fromSearchParams($searchParams);
|
$filterSettings = FilterSettings::fromSearchParams($searchParams);
|
||||||
}
|
}
|
||||||
$excludedConceptUids = GeneralUtility::trimExplode(',', $this->settings['excludedConceptUids']);
|
$excludedConceptUids = GeneralUtility::trimExplode(',', $this->settings['excludedConceptUids']);
|
||||||
$excludedRegionUids = GeneralUtility::trimExplode(',', $this->settings['excludedRegionUids']);
|
$excludedRegionUids = GeneralUtility::trimExplode(',', $this->settings['excludedRegionUids']);
|
||||||
$filterOptions = $this->filterService->getFilterOptions($filterSettings, $excludedConceptUids, $excludedRegionUids);
|
$filterOptions = $this->filterService->getFilterOptions(
|
||||||
|
$filterSettings,
|
||||||
|
$excludedConceptUids,
|
||||||
|
$excludedRegionUids,
|
||||||
|
$forcedConceptUids
|
||||||
|
);
|
||||||
|
|
||||||
return json_encode([
|
return json_encode([
|
||||||
'filterOptions' => $filterOptions,
|
'filterOptions' => $filterOptions,
|
||||||
'searchParams' => $searchParams,
|
'searchParams' => $searchParams,
|
||||||
|
|||||||
@@ -33,7 +33,6 @@ use EP\EpProducts\Domain\Repository\HotelRepository;
|
|||||||
use EP\EpProducts\Domain\Repository\ProductRepository;
|
use EP\EpProducts\Domain\Repository\ProductRepository;
|
||||||
use EP\EpProducts\Service\DateService;
|
use EP\EpProducts\Service\DateService;
|
||||||
use EP\EpProducts\Service\FilterService;
|
use EP\EpProducts\Service\FilterService;
|
||||||
use EP\EpProducts\Service\FilterSettingsEncoder;
|
|
||||||
use EP\EpProducts\Service\HotelDataService;
|
use EP\EpProducts\Service\HotelDataService;
|
||||||
use EP\EpProducts\Service\ProductDataService;
|
use EP\EpProducts\Service\ProductDataService;
|
||||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||||
@@ -119,12 +118,11 @@ class ProductController extends ActionController
|
|||||||
// Redirect to search page in case no product can be determined
|
// Redirect to search page in case no product can be determined
|
||||||
if ($product === null) {
|
if ($product === null) {
|
||||||
$filterSettings = $this->filterService->getDefaultFilterSettings();
|
$filterSettings = $this->filterService->getDefaultFilterSettings();
|
||||||
$filterSettingsEncoded = FilterSettingsEncoder::encode($filterSettings);
|
|
||||||
$this->redirect(
|
$this->redirect(
|
||||||
'searchresult',
|
'searchresult',
|
||||||
'Search',
|
'Search',
|
||||||
null,
|
null,
|
||||||
['filterSettings' => $filterSettingsEncoded],
|
['filterSettings' => $filterSettings->toArray()],
|
||||||
$this->settings['defaultSearchPageUid']
|
$this->settings['defaultSearchPageUid']
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ use EP\EpProducts\Domain\Model\SearchParams;
|
|||||||
use EP\EpProducts\Service\FilterService;
|
use EP\EpProducts\Service\FilterService;
|
||||||
use EP\EpProducts\Service\FilterSettingsEncoder;
|
use EP\EpProducts\Service\FilterSettingsEncoder;
|
||||||
use EP\EpProducts\Traits\RequestArgumentTypeConversionTrait;
|
use EP\EpProducts\Traits\RequestArgumentTypeConversionTrait;
|
||||||
use TYPO3\CMS\Core\Log\LogManager;
|
|
||||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||||
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
|
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
|
||||||
use TYPO3\CMS\Extbase\Mvc\Exception\StopActionException;
|
use TYPO3\CMS\Extbase\Mvc\Exception\StopActionException;
|
||||||
@@ -64,18 +63,15 @@ class SearchController extends ActionController
|
|||||||
{
|
{
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
$this->filterService = $filterService;
|
$this->filterService = $filterService;
|
||||||
}
|
|
||||||
|
|
||||||
public function initializeAction()
|
|
||||||
{
|
|
||||||
$forcedConceptUids = GeneralUtility::trimExplode(',', $this->settings['forcedConceptUids'], true);
|
$forcedConceptUids = GeneralUtility::trimExplode(',', $this->settings['forcedConceptUids'], true);
|
||||||
|
$excludedConceptUids = GeneralUtility::trimExplode(',', $this->settings['excludedConceptUids'], true);
|
||||||
|
$excludedRegionUids = GeneralUtility::trimExplode(',', $this->settings['excludedRegionUids'], true);
|
||||||
$this->defaultFilterSettings = $this->filterService->getDefaultFilterSettings($forcedConceptUids);
|
$this->defaultFilterSettings = $this->filterService->getDefaultFilterSettings($forcedConceptUids);
|
||||||
$excludedConceptUids = GeneralUtility::trimExplode(',', $this->settings['excludedConceptUids']);
|
|
||||||
$excludedRegionUids = GeneralUtility::trimExplode(',', $this->settings['excludedRegionUids']);
|
|
||||||
$this->defaultFilterOptions = $this->filterService->getFilterOptions(
|
$this->defaultFilterOptions = $this->filterService->getFilterOptions(
|
||||||
$this->defaultFilterSettings,
|
$this->defaultFilterSettings,
|
||||||
$excludedConceptUids,
|
$excludedConceptUids,
|
||||||
$excludedRegionUids
|
$excludedRegionUids,
|
||||||
|
$forcedConceptUids
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,8 +99,7 @@ class SearchController extends ActionController
|
|||||||
|
|
||||||
public function initializeProcessSearchAction()
|
public function initializeProcessSearchAction()
|
||||||
{
|
{
|
||||||
$forcedConceptUids = GeneralUtility::trimExplode(',', $this->settings['forcedConceptUids'], true);
|
$this->processSearchParamsArgument();
|
||||||
$this->processSearchParamsArgument($forcedConceptUids);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -143,11 +138,13 @@ class SearchController extends ActionController
|
|||||||
{
|
{
|
||||||
$excludedConceptUids = GeneralUtility::trimExplode(',', $this->settings['excludedConceptUids']);
|
$excludedConceptUids = GeneralUtility::trimExplode(',', $this->settings['excludedConceptUids']);
|
||||||
$excludedRegionUids = GeneralUtility::trimExplode(',', $this->settings['excludedRegionUids']);
|
$excludedRegionUids = GeneralUtility::trimExplode(',', $this->settings['excludedRegionUids']);
|
||||||
|
$forcedConceptUids = GeneralUtility::trimExplode(',', $this->settings['forcedConceptUids'], true);
|
||||||
|
|
||||||
$filterOptions = $this->filterService->getFilterOptions(
|
$filterOptions = $this->filterService->getFilterOptions(
|
||||||
$filterSettings,
|
$filterSettings,
|
||||||
$excludedConceptUids,
|
$excludedConceptUids,
|
||||||
$excludedRegionUids
|
$excludedRegionUids,
|
||||||
|
$forcedConceptUids
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->view->assignMultiple([
|
$this->view->assignMultiple([
|
||||||
@@ -172,21 +169,4 @@ class SearchController extends ActionController
|
|||||||
['filterSettings' => $filterSettings]
|
['filterSettings' => $filterSettings]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param SearchParams $searchParams
|
|
||||||
*/
|
|
||||||
private function logSearch(SearchParams $searchParams)
|
|
||||||
{
|
|
||||||
$ignoreIps = GeneralUtility::trimExplode(',', $this->settings['searchLogIgnoreIps'], true);
|
|
||||||
$remoteIp = GeneralUtility::getIndpEnv('REMOTE_ADDR');
|
|
||||||
if (\in_array($remoteIp, $ignoreIps, false)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
/** @var $logger \TYPO3\CMS\Core\Log\Logger */
|
|
||||||
$logger = GeneralUtility::makeInstance(LogManager::class)->getLogger(__CLASS__);
|
|
||||||
$logger->info('Searchresult processed', [
|
|
||||||
'searchParams' => $searchParams,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,18 @@ namespace EP\EpProducts\Domain\Model;
|
|||||||
|
|
||||||
class FilterOptions implements \JsonSerializable
|
class FilterOptions implements \JsonSerializable
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
public static $priceRangeOptions = [
|
||||||
|
1 => [ 1, 200 ],
|
||||||
|
2 => [ 200, 300 ],
|
||||||
|
3 => [ 300, 400 ],
|
||||||
|
4 => [ 400, 500 ],
|
||||||
|
5 => [ 500, 600 ],
|
||||||
|
6 => [ 600, 999 ],
|
||||||
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -34,46 +34,13 @@ use TYPO3\CMS\Extbase\Mvc\Request;
|
|||||||
class FilterSettings implements \JsonSerializable
|
class FilterSettings implements \JsonSerializable
|
||||||
{
|
{
|
||||||
|
|
||||||
const DESTINATION_TYPE_COUNTRY = 'country';
|
public const DURATION_SHORT = 4;
|
||||||
const DESTINATION_TYPE_REGION = 'region';
|
public const DURATION_LONG = 5;
|
||||||
const DESTINATION_TYPE_CITY = 'city';
|
|
||||||
const DESTINATION_TYPE_HOTEL = 'hotel';
|
|
||||||
const DESTINATION_TYPE_PRODUCT = 'product';
|
|
||||||
|
|
||||||
const DURATION_SHORT = 4;
|
|
||||||
const DURATION_LONG = 5;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
public static $priceRanges = [
|
protected $priceRanges = [];
|
||||||
1 => [ 1, 200 ],
|
|
||||||
2 => [ 200, 300 ],
|
|
||||||
3 => [ 300, 400 ],
|
|
||||||
4 => [ 400, 500 ],
|
|
||||||
5 => [ 500, 600 ],
|
|
||||||
6 => [ 600, 999 ],
|
|
||||||
];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var int
|
|
||||||
*/
|
|
||||||
protected $priceRange = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
protected $destinationName = '';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var int
|
|
||||||
*/
|
|
||||||
protected $destinationUid = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
protected $destinationType = '';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var array
|
* @var array
|
||||||
@@ -159,26 +126,39 @@ class FilterSettings implements \JsonSerializable
|
|||||||
public static function fromSearchParams(SearchParams $searchParams): self
|
public static function fromSearchParams(SearchParams $searchParams): self
|
||||||
{
|
{
|
||||||
$filterSettings = new self;
|
$filterSettings = new self;
|
||||||
$filterSettings->setDateFrom($searchParams->getDateFrom());
|
|
||||||
$filterSettings->setDateTo($searchParams->getDateTo());
|
|
||||||
$filterSettings->setDestinationUid($searchParams->getDestinationUid());
|
|
||||||
$filterSettings->setDestinationType($searchParams->getDestinationType());
|
|
||||||
if ($searchParams->getDestinationType() && $searchParams->getDestinationUid()) {
|
if ($searchParams->getDestinationType() && $searchParams->getDestinationUid()) {
|
||||||
|
$destinationUid = $searchParams->getDestinationUid();
|
||||||
switch ($searchParams->getDestinationType()) {
|
switch ($searchParams->getDestinationType()) {
|
||||||
case self::DESTINATION_TYPE_COUNTRY:
|
case SearchParams::DESTINATION_TYPE_COUNTRY:
|
||||||
$filterSettings->setCountryUids([$searchParams->getDestinationUid()]);
|
$filterSettings->setCountryUids([$destinationUid]);
|
||||||
break;
|
break;
|
||||||
case self::DESTINATION_TYPE_REGION:
|
case SearchParams::DESTINATION_TYPE_REGION:
|
||||||
$filterSettings->setRegionUids([$searchParams->getDestinationUid()]);
|
$filterSettings->setRegionUids([$destinationUid]);
|
||||||
|
break;
|
||||||
|
case SearchParams::DESTINATION_TYPE_CITY:
|
||||||
|
$filterSettings->setCityUids([$destinationUid]);
|
||||||
|
break;
|
||||||
|
case SearchParams::DESTINATION_TYPE_CONCEPT:
|
||||||
|
$filterSettings->setConceptUids([$destinationUid]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($searchParams->getConceptUids()) {
|
if (null !== $searchParams->getDateFrom()) {
|
||||||
$filterSettings->setConceptUids($searchParams->getConceptUids());
|
$filterSettings->setDateFrom($searchParams->getDateFrom());
|
||||||
}
|
}
|
||||||
$filterSettings->setPriceRange($searchParams->getPriceRange());
|
if (null !== $searchParams->getDateTo()) {
|
||||||
|
$filterSettings->setDateTo($searchParams->getDateTo());
|
||||||
|
}
|
||||||
|
if (null !== $searchParams->getPriceRange()) {
|
||||||
|
$filterSettings->setPriceRanges([$searchParams->getPriceRange()]);
|
||||||
|
}
|
||||||
|
if (null !== $searchParams->getPax()) {
|
||||||
$filterSettings->setPax($searchParams->getPax());
|
$filterSettings->setPax($searchParams->getPax());
|
||||||
|
}
|
||||||
|
if (null !== $searchParams->getNights()) {
|
||||||
$filterSettings->setNights($searchParams->getNights());
|
$filterSettings->setNights($searchParams->getNights());
|
||||||
|
}
|
||||||
|
|
||||||
return $filterSettings;
|
return $filterSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -256,67 +236,19 @@ class FilterSettings implements \JsonSerializable
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return int
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function getPriceRange()
|
public function getPriceRanges()
|
||||||
{
|
{
|
||||||
return $this->priceRange;
|
return $this->priceRanges;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param int $priceRange
|
* @param array $priceRanges
|
||||||
*/
|
*/
|
||||||
public function setPriceRange($priceRange)
|
public function setPriceRanges($priceRanges)
|
||||||
{
|
{
|
||||||
$this->priceRange = $priceRange;
|
$this->priceRanges = $priceRanges;
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getDestinationName()
|
|
||||||
{
|
|
||||||
return $this->destinationName;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $destinationName
|
|
||||||
*/
|
|
||||||
public function setDestinationName($destinationName)
|
|
||||||
{
|
|
||||||
$this->destinationName = $destinationName;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return int
|
|
||||||
*/
|
|
||||||
public function getDestinationUid()
|
|
||||||
{
|
|
||||||
return $this->destinationUid;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param int $destinationUid
|
|
||||||
*/
|
|
||||||
public function setDestinationUid($destinationUid)
|
|
||||||
{
|
|
||||||
$this->destinationUid = (int) $destinationUid;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getDestinationType()
|
|
||||||
{
|
|
||||||
return $this->destinationType;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $destinationType
|
|
||||||
*/
|
|
||||||
public function setDestinationType($destinationType)
|
|
||||||
{
|
|
||||||
$this->destinationType = $destinationType;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -542,22 +474,10 @@ class FilterSettings implements \JsonSerializable
|
|||||||
$this->bus = $bus;
|
$this->bus = $bus;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function getDestinationSelected()
|
|
||||||
{
|
|
||||||
return $this->destinationType !== '';
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public function toArray(): array
|
public function toArray(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'priceRange' => $this->getPriceRange(),
|
'priceRanges' => $this->getPriceRanges(),
|
||||||
'destinationName' => $this->getDestinationName(),
|
|
||||||
'destinationUid' => $this->getDestinationUid(),
|
|
||||||
'destinationType' => $this->getDestinationType(),
|
|
||||||
'countryUids' => $this->getCountryUids(),
|
'countryUids' => $this->getCountryUids(),
|
||||||
'regionUids' => $this->getRegionUids(),
|
'regionUids' => $this->getRegionUids(),
|
||||||
'cityUids' => $this->getCityUids(),
|
'cityUids' => $this->getCityUids(),
|
||||||
|
|||||||
@@ -32,10 +32,15 @@ use TYPO3\CMS\Extbase\Mvc\Request;
|
|||||||
|
|
||||||
class SearchParams implements \JsonSerializable
|
class SearchParams implements \JsonSerializable
|
||||||
{
|
{
|
||||||
|
public const DESTINATION_TYPE_COUNTRY = 'country';
|
||||||
|
public const DESTINATION_TYPE_REGION = 'region';
|
||||||
|
public const DESTINATION_TYPE_CITY = 'city';
|
||||||
|
public const DESTINATION_TYPE_CONCEPT = 'concept';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var int
|
* @var int
|
||||||
*/
|
*/
|
||||||
protected $priceRange = 0;
|
protected $priceRange;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var \DateTime
|
* @var \DateTime
|
||||||
@@ -50,22 +55,17 @@ class SearchParams implements \JsonSerializable
|
|||||||
/**
|
/**
|
||||||
* @var int
|
* @var int
|
||||||
*/
|
*/
|
||||||
protected $destinationUid = 0;
|
protected $destinationUid;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
protected $destinationType;
|
protected $destinationType;
|
||||||
|
|
||||||
/**
|
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
protected $conceptUids = [];
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var int
|
* @var int
|
||||||
*/
|
*/
|
||||||
protected $nights = 0;
|
protected $nights;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var int
|
* @var int
|
||||||
@@ -75,7 +75,7 @@ class SearchParams implements \JsonSerializable
|
|||||||
/**
|
/**
|
||||||
* @var int
|
* @var int
|
||||||
*/
|
*/
|
||||||
protected $pageUid = 0;
|
protected $pageUid;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param int $pageUid
|
* @param int $pageUid
|
||||||
@@ -187,22 +187,6 @@ class SearchParams implements \JsonSerializable
|
|||||||
$this->destinationType = $destinationType;
|
$this->destinationType = $destinationType;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function getConceptUids()
|
|
||||||
{
|
|
||||||
return $this->conceptUids;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param array $conceptUids
|
|
||||||
*/
|
|
||||||
public function setConceptUids(array $conceptUids)
|
|
||||||
{
|
|
||||||
$this->conceptUids = $conceptUids;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return int
|
* @return int
|
||||||
*/
|
*/
|
||||||
@@ -257,7 +241,6 @@ class SearchParams implements \JsonSerializable
|
|||||||
'priceRange' => $this->getPriceRange(),
|
'priceRange' => $this->getPriceRange(),
|
||||||
'destinationUid' => $this->getDestinationUid(),
|
'destinationUid' => $this->getDestinationUid(),
|
||||||
'destinationType' => $this->getDestinationType(),
|
'destinationType' => $this->getDestinationType(),
|
||||||
'conceptUids' => $this->getConceptUids(),
|
|
||||||
'nights' => $this->getNights(),
|
'nights' => $this->getNights(),
|
||||||
'pax' => $this->getPax(),
|
'pax' => $this->getPax(),
|
||||||
'pageUid' => $this->getPageUid(),
|
'pageUid' => $this->getPageUid(),
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ namespace EP\EpProducts\Domain\Repository;
|
|||||||
* This copyright notice MUST APPEAR in all copies of the script!
|
* This copyright notice MUST APPEAR in all copies of the script!
|
||||||
***************************************************************/
|
***************************************************************/
|
||||||
|
|
||||||
|
use EP\EpProducts\Domain\Model\FilterOptions;
|
||||||
use EP\EpProducts\Domain\Model\FilterSettings;
|
use EP\EpProducts\Domain\Model\FilterSettings;
|
||||||
use EP\EpProducts\Traits\DbConnectionTrait;
|
use EP\EpProducts\Traits\DbConnectionTrait;
|
||||||
use TYPO3\CMS\Core\Database\Connection;
|
use TYPO3\CMS\Core\Database\Connection;
|
||||||
@@ -163,17 +164,22 @@ abstract class AbstractRepository extends \TYPO3\CMS\Extbase\Persistence\Reposit
|
|||||||
*/
|
*/
|
||||||
protected function addPriceRangeFilterConditions(QueryBuilder $query, FilterSettings $filterSettings)
|
protected function addPriceRangeFilterConditions(QueryBuilder $query, FilterSettings $filterSettings)
|
||||||
{
|
{
|
||||||
// Price range
|
// Price ranges
|
||||||
$priceRange = (int) $filterSettings->getPriceRange();
|
if (count($filterSettings->getPriceRanges()) > 0) {
|
||||||
if ($priceRange > 0) {
|
$orX = $query->expr()->orX();
|
||||||
[ $priceMin, $priceMax ] = FilterSettings::$priceRanges[$priceRange];
|
foreach ($filterSettings->getPriceRanges() as $priceRange) {
|
||||||
|
[ $priceMin, $priceMax ] = FilterOptions::$priceRangeOptions[$priceRange];
|
||||||
|
$orX->add($query->expr()->andX(
|
||||||
|
$query->expr()->gte('date.min_price', ':priceMin'),
|
||||||
|
$query->expr()->lt('date.min_price', ':priceMax')
|
||||||
|
));
|
||||||
$query
|
$query
|
||||||
->andWhere('date.min_price >= :priceMin')
|
|
||||||
->andWhere('date.min_price < :priceMax')
|
|
||||||
->setParameter('priceMin', $priceMin)
|
->setParameter('priceMin', $priceMin)
|
||||||
->setParameter('priceMax', $priceMax)
|
->setParameter('priceMax', $priceMax)
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
$query->andWhere($orX);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -72,21 +72,18 @@ class DateRepository extends AbstractRepository
|
|||||||
return [$dateRangeFrom, $dateRangeTo];
|
return [$dateRangeFrom, $dateRangeTo];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function getFilterOptions(
|
||||||
* @param FilterSettings $filterSettings
|
FilterSettings $filterSettings,
|
||||||
* @param array $excludedConceptUids
|
array $excludedConceptUids = [],
|
||||||
* @param array $excludedRegionUids
|
array $excludedRegionUids = [],
|
||||||
* @return array
|
array $forcedConceptUids = []
|
||||||
* @throws \Doctrine\DBAL\DBALException
|
) {
|
||||||
*/
|
|
||||||
public function getFilterOptions(FilterSettings $filterSettings, $excludedConceptUids = [], $excludedRegionUids = [])
|
|
||||||
{
|
|
||||||
$qb = $this->getDbConnection()->createQueryBuilder();
|
$qb = $this->getDbConnection()->createQueryBuilder();
|
||||||
|
|
||||||
$query = $qb
|
$query = $qb
|
||||||
->select(
|
->select(
|
||||||
'date.concept as conceptUid', 'date.concept_name as conceptName', 'date.concept_sorting as conceptSorting',
|
'date.concept as conceptUid', 'date.concept_name as conceptName', 'date.concept_sorting as conceptSorting',
|
||||||
'date.concept_code as conceptCode', 'date.min_price as minPrice',
|
'date.concept_code as conceptCode', 'date.min_price as minPrice', 'date.date_start as dateStart', 'date.date_end as dateEnd',
|
||||||
'date.country as countryUid','date.country_name as countryName', 'date.country_code as countryCode',
|
'date.country as countryUid','date.country_name as countryName', 'date.country_code as countryCode',
|
||||||
'date.region as regionUid', 'date.region_name as regionName',
|
'date.region as regionUid', 'date.region_name as regionName',
|
||||||
'date.nights as nights', 'date.board as boardType', 'date.board_bus_pro_id as boardUid',
|
'date.nights as nights', 'date.board as boardType', 'date.board_bus_pro_id as boardUid',
|
||||||
@@ -120,6 +117,13 @@ class DateRepository extends AbstractRepository
|
|||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (count($forcedConceptUids) > 0) {
|
||||||
|
$query
|
||||||
|
->andWhere('date.concept IN (:forcedConceptUids)')
|
||||||
|
->setParameter('forcedConceptUids', $forcedConceptUids, Connection::PARAM_INT_ARRAY)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
$this->addFiltersettingsConditions($query, $filterSettings);
|
$this->addFiltersettingsConditions($query, $filterSettings);
|
||||||
|
|
||||||
return $query->execute()->fetchAllAssociative();
|
return $query->execute()->fetchAllAssociative();
|
||||||
|
|||||||
@@ -27,10 +27,8 @@ namespace EP\EpProducts\Service;
|
|||||||
* This copyright notice MUST APPEAR in all copies of the script!
|
* This copyright notice MUST APPEAR in all copies of the script!
|
||||||
***************************************************************/
|
***************************************************************/
|
||||||
|
|
||||||
use EP\EpProducts\Domain\Model\Date;
|
|
||||||
use EP\EpProducts\Domain\Model\FilterOptions;
|
use EP\EpProducts\Domain\Model\FilterOptions;
|
||||||
use EP\EpProducts\Domain\Model\FilterSettings;
|
use EP\EpProducts\Domain\Model\FilterSettings;
|
||||||
use EP\EpProducts\Domain\Model\Product;
|
|
||||||
use EP\EpProducts\Domain\Repository\DateRepository;
|
use EP\EpProducts\Domain\Repository\DateRepository;
|
||||||
use TYPO3\CMS\Core\SingletonInterface;
|
use TYPO3\CMS\Core\SingletonInterface;
|
||||||
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
|
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
|
||||||
@@ -57,17 +55,14 @@ class FilterService implements SingletonInterface
|
|||||||
$this->dateRepository = $dateRepository;
|
$this->dateRepository = $dateRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function getDefaultFilterSettings
|
||||||
* @param array $forcedConceptUids
|
(
|
||||||
* @param bool $respectBookableDaterange
|
array $forcedConceptUids = [],
|
||||||
* @param string $dateFromYmd
|
bool $respectBookableDaterange = true,
|
||||||
* @param string $dateToYmd
|
string $dateFromYmd = null,
|
||||||
* @return FilterSettings
|
string $dateToYmd = null
|
||||||
* @throws \Exception
|
): FilterSettings {
|
||||||
*/
|
[ $dateFrom, $dateTo ] = $this->constrainDateRange($this->dateRepository->getDateRange());
|
||||||
public function getDefaultFilterSettings(array $forcedConceptUids = [], $respectBookableDaterange = true, $dateFromYmd = null, $dateToYmd = null)
|
|
||||||
{
|
|
||||||
[ $dateFrom, $dateTo ] = $this->constrainDateRange($this->getDateRange());
|
|
||||||
|
|
||||||
if (null !== $dateFromYmd) {
|
if (null !== $dateFromYmd) {
|
||||||
$dateFrom = new \DateTime($dateFromYmd);
|
$dateFrom = new \DateTime($dateFromYmd);
|
||||||
@@ -87,37 +82,27 @@ class FilterService implements SingletonInterface
|
|||||||
return $filterSettings;
|
return $filterSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function getFilterOptions
|
||||||
* @param FilterSettings $filterSettings
|
(
|
||||||
* @param array $excludedConceptUids
|
FilterSettings $filterSettings,
|
||||||
* @param array $excludedRegionUids
|
array $excludedConceptUids = [],
|
||||||
* @return FilterOptions
|
array $excludedRegionUids = [],
|
||||||
* @throws \Doctrine\DBAL\DBALException
|
array $forcedConceptUids = []
|
||||||
*/
|
): FilterOptions {
|
||||||
public function getFilterOptions(FilterSettings $filterSettings, $excludedConceptUids = [], $excludedRegionUids = [])
|
$filterOptionsData = $this->dateRepository->getFilterOptions(
|
||||||
{
|
|
||||||
$key = md5(serialize($filterSettings) . serialize($excludedConceptUids). serialize($excludedRegionUids));
|
|
||||||
if (empty(static::$cache['filterOptions'][$key])) {
|
|
||||||
static::$cache['filterOptions'][$key] = $this->dateRepository->getFilterOptions(
|
|
||||||
$filterSettings,
|
$filterSettings,
|
||||||
$excludedConceptUids,
|
$excludedConceptUids,
|
||||||
$excludedRegionUids
|
$excludedRegionUids,
|
||||||
|
$forcedConceptUids
|
||||||
);
|
);
|
||||||
}
|
|
||||||
$filterOptionsData = static::$cache['filterOptions'][$key];
|
|
||||||
if (count($filterOptionsData) === 0) {
|
if (count($filterOptionsData) === 0) {
|
||||||
return new FilterOptions();
|
return new FilterOptions();
|
||||||
}
|
}
|
||||||
$dateRange = $this->constrainDateRange($this->getDateRange());
|
|
||||||
return $this->preprocessFilterOptions($filterOptionsData, $dateRange);
|
return $this->preprocessFilterOptions($filterOptionsData);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function preprocessFilterOptions(array $filterOptionsData): FilterOptions
|
||||||
* @param array $filterOptionsData
|
|
||||||
* @param array $dateRange
|
|
||||||
* @return FilterOptions
|
|
||||||
*/
|
|
||||||
public function preprocessFilterOptions(array $filterOptionsData, array $dateRange)
|
|
||||||
{
|
{
|
||||||
$priceRanges = [];
|
$priceRanges = [];
|
||||||
$busAvailable = false;
|
$busAvailable = false;
|
||||||
@@ -127,12 +112,21 @@ class FilterService implements SingletonInterface
|
|||||||
$hotelTypes = [];
|
$hotelTypes = [];
|
||||||
$roomTypes = [];
|
$roomTypes = [];
|
||||||
$boardTypes = [];
|
$boardTypes = [];
|
||||||
|
$dateMin = $dateMax = null;
|
||||||
|
|
||||||
$absPath = ExtensionManagementUtility::extPath('ep_theme');
|
$absPath = ExtensionManagementUtility::extPath('ep_theme');
|
||||||
$baseUrl = '/' . PathUtility::stripPathSitePrefix($absPath);
|
$baseUrl = '/' . PathUtility::stripPathSitePrefix($absPath);
|
||||||
|
|
||||||
foreach ($filterOptionsData as $row)
|
foreach ($filterOptionsData as $row)
|
||||||
{
|
{
|
||||||
|
// Date
|
||||||
|
if (null === $dateMin || $row['dateStart'] < $dateMin) {
|
||||||
|
$dateMin = $row['dateStart'];
|
||||||
|
}
|
||||||
|
if (null === $dateMax || $row['dateEnd'] > $dateMax) {
|
||||||
|
$dateMax = $row['dateEnd'];
|
||||||
|
}
|
||||||
|
|
||||||
// Bus
|
// Bus
|
||||||
if ((bool) $row['busAvailable'] === true) {
|
if ((bool) $row['busAvailable'] === true) {
|
||||||
$busAvailable = true;
|
$busAvailable = true;
|
||||||
@@ -193,14 +187,14 @@ class FilterService implements SingletonInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Price range
|
// Price range
|
||||||
foreach (FilterSettings::$priceRanges as $index => $priceRange)
|
foreach (FilterOptions::$priceRangeOptions as $index => $priceRange)
|
||||||
{
|
{
|
||||||
if (array_key_exists($index, $priceRanges)) {
|
if (array_key_exists($index, $priceRanges)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
[$min, $max] = $priceRange;
|
[$min, $max] = $priceRange;
|
||||||
if ($row['minPrice'] >= $min && $row['minPrice'] < $max) {
|
if ($row['minPrice'] >= $min && $row['minPrice'] < $max) {
|
||||||
$range = FilterSettings::$priceRanges[$index];
|
$range = FilterOptions::$priceRangeOptions[$index];
|
||||||
$priceRanges[$index] = [
|
$priceRanges[$index] = [
|
||||||
'uid' => $index,
|
'uid' => $index,
|
||||||
'min' => $range[0],
|
'min' => $range[0],
|
||||||
@@ -225,12 +219,10 @@ class FilterService implements SingletonInterface
|
|||||||
return strcmp($a['label'], $b['label']);
|
return strcmp($a['label'], $b['label']);
|
||||||
});
|
});
|
||||||
|
|
||||||
list ($dateMin, $dateMax) = $dateRange;
|
|
||||||
|
|
||||||
$filterOptions = new FilterOptions();
|
$filterOptions = new FilterOptions();
|
||||||
$filterOptions->setPriceRanges($priceRanges);
|
$filterOptions->setPriceRanges($priceRanges);
|
||||||
$filterOptions->setDateFrom($dateMin);
|
$filterOptions->setDateFrom(new \DateTime($dateMin));
|
||||||
$filterOptions->setDateTo($dateMax);
|
$filterOptions->setDateTo(new \DateTime($dateMax));
|
||||||
$filterOptions->setConcepts($concepts);
|
$filterOptions->setConcepts($concepts);
|
||||||
$filterOptions->setDestinations($destinations);
|
$filterOptions->setDestinations($destinations);
|
||||||
$filterOptions->setHotelTypes($hotelTypes);
|
$filterOptions->setHotelTypes($hotelTypes);
|
||||||
@@ -242,42 +234,7 @@ class FilterService implements SingletonInterface
|
|||||||
return $filterOptions;
|
return $filterOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function constrainDateRange(array $dateRange, FilterSettings $filterSettings = null): array
|
||||||
* @param FilterSettings $filterSettings
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function getDateRange(FilterSettings $filterSettings = null)
|
|
||||||
{
|
|
||||||
$key = md5(serialize($filterSettings));
|
|
||||||
if (empty(static::$cache['dateRange'][$key])) {
|
|
||||||
static::$cache['dateRange'][$key] = $this->dateRepository->getDateRange();
|
|
||||||
}
|
|
||||||
return static::$cache['dateRange'][$key];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Product $product
|
|
||||||
* @param FilterSettings $filterSettings
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function getProductDateRange(Product $product, FilterSettings $filterSettings = null)
|
|
||||||
{
|
|
||||||
$key = md5($product->getUid() . serialize($filterSettings));
|
|
||||||
if (empty(static::$cache['productDateRange'][$key])) {
|
|
||||||
static::$cache['productDateRange'][$key] = $this->dateRepository->getDateRange($product);
|
|
||||||
}
|
|
||||||
return $this->constrainDateRange(static::$cache['productDateRange'][$key], $filterSettings);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param array $dateRange
|
|
||||||
* @param FilterSettings $filterSettings
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function constrainDateRange(array $dateRange, FilterSettings $filterSettings = null)
|
|
||||||
{
|
{
|
||||||
[ $dateFrom, $dateTo ] = $dateRange;
|
[ $dateFrom, $dateTo ] = $dateRange;
|
||||||
if ($filterSettings !== null) {
|
if ($filterSettings !== null) {
|
||||||
@@ -293,67 +250,7 @@ class FilterService implements SingletonInterface
|
|||||||
return [$dateFrom, $dateTo];
|
return [$dateFrom, $dateTo];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function getFiltersettingsFromSettings(array $settings): FilterSettings
|
||||||
* @param FilterSettings $filterSettings
|
|
||||||
* @param int $conceptUid
|
|
||||||
*
|
|
||||||
* @return FilterSettings
|
|
||||||
*/
|
|
||||||
public function forceConceptUid(FilterSettings $filterSettings, $conceptUid = null)
|
|
||||||
{
|
|
||||||
if ($conceptUid) {
|
|
||||||
$conceptUids = $filterSettings->getConceptUids();
|
|
||||||
if (!\in_array($conceptUid, $conceptUids, false)) {
|
|
||||||
$conceptUids[] = (int) $conceptUid;
|
|
||||||
$filterSettings->setConceptUids($conceptUids);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $filterSettings;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts destination type and destination id combo
|
|
||||||
* from searchbar into appropriate filter setting for
|
|
||||||
* further processing
|
|
||||||
*
|
|
||||||
* @param FilterSettings $filterSettings
|
|
||||||
*/
|
|
||||||
public function convertDestinationData(FilterSettings $filterSettings)
|
|
||||||
{
|
|
||||||
if ($filterSettings->getDestinationUid() === 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$destinationUid = $filterSettings->getDestinationUid();
|
|
||||||
$destinationType = $filterSettings->getDestinationType();
|
|
||||||
|
|
||||||
switch ($destinationType)
|
|
||||||
{
|
|
||||||
case FilterSettings::DESTINATION_TYPE_COUNTRY:
|
|
||||||
$filterSettings->setCountryUids([$destinationUid]);
|
|
||||||
break;
|
|
||||||
case FilterSettings::DESTINATION_TYPE_REGION:
|
|
||||||
$filterSettings->setRegionUids([$destinationUid]);
|
|
||||||
break;
|
|
||||||
case FilterSettings::DESTINATION_TYPE_CITY:
|
|
||||||
$filterSettings->setCityUids([$destinationUid]);
|
|
||||||
break;
|
|
||||||
case FilterSettings::DESTINATION_TYPE_HOTEL:
|
|
||||||
$filterSettings->setHotelUid($destinationUid);
|
|
||||||
break;
|
|
||||||
case FilterSettings::DESTINATION_TYPE_PRODUCT:
|
|
||||||
$filterSettings->setProductUid($destinationUid);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param array $settings
|
|
||||||
* @return FilterSettings
|
|
||||||
*/
|
|
||||||
public function getFiltersettingsFromSettings(array $settings)
|
|
||||||
{
|
{
|
||||||
$filterSettings = new FilterSettings();
|
$filterSettings = new FilterSettings();
|
||||||
if (isset($settings['regionUid']) && (int) $settings['regionUid'] > 0) {
|
if (isset($settings['regionUid']) && (int) $settings['regionUid'] > 0) {
|
||||||
@@ -384,6 +281,7 @@ class FilterService implements SingletonInterface
|
|||||||
$hotelTypes = GeneralUtility::trimExplode(',', $settings['hotelTypes'], true);
|
$hotelTypes = GeneralUtility::trimExplode(',', $settings['hotelTypes'], true);
|
||||||
$filterSettings->setHotelTypes($hotelTypes);
|
$filterSettings->setHotelTypes($hotelTypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $filterSettings;
|
return $filterSettings;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,9 +38,6 @@ class FilterSettingsEncoder
|
|||||||
protected static function getMapping()
|
protected static function getMapping()
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
[ 'destinationName', 'string' ],
|
|
||||||
[ 'destinationUid', 'string' ],
|
|
||||||
[ 'destinationType', 'string' ],
|
|
||||||
[ 'countryUids', 'array' ],
|
[ 'countryUids', 'array' ],
|
||||||
[ 'regionUids', 'array' ],
|
[ 'regionUids', 'array' ],
|
||||||
[ 'cityUids', 'array' ],
|
[ 'cityUids', 'array' ],
|
||||||
@@ -84,7 +81,7 @@ class FilterSettingsEncoder
|
|||||||
$values = explode('|', $data);
|
$values = explode('|', $data);
|
||||||
foreach (static::getMapping() as $index => $property)
|
foreach (static::getMapping() as $index => $property)
|
||||||
{
|
{
|
||||||
list($name, $type) = $property;
|
[$name, $type] = $property;
|
||||||
$value = $values[$index];
|
$value = $values[$index];
|
||||||
if ($type === 'array') {
|
if ($type === 'array') {
|
||||||
$value = GeneralUtility::trimExplode(';', $value, true);
|
$value = GeneralUtility::trimExplode(';', $value, true);
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ namespace EP\EpProducts\Service;
|
|||||||
* This copyright notice MUST APPEAR in all copies of the script!
|
* This copyright notice MUST APPEAR in all copies of the script!
|
||||||
***************************************************************/
|
***************************************************************/
|
||||||
|
|
||||||
use EP\EpProducts\Domain\Model\FilterSettings;
|
use EP\EpProducts\Domain\Model\FilterOptions;
|
||||||
use EP\EpProducts\Traits\DbConnectionTrait;
|
use EP\EpProducts\Traits\DbConnectionTrait;
|
||||||
use TYPO3\CMS\Backend\Utility\BackendUtility;
|
use TYPO3\CMS\Backend\Utility\BackendUtility;
|
||||||
use TYPO3\CMS\Core\SingletonInterface;
|
use TYPO3\CMS\Core\SingletonInterface;
|
||||||
@@ -75,7 +75,7 @@ class LogService implements SingletonInterface
|
|||||||
$searchParams = $data->searchParams;
|
$searchParams = $data->searchParams;
|
||||||
$priceRange = null;
|
$priceRange = null;
|
||||||
if ($searchParams->priceRange) {
|
if ($searchParams->priceRange) {
|
||||||
list ($priceFrom, $priceTo) = FilterSettings::$priceRanges[$searchParams->priceRange];
|
list ($priceFrom, $priceTo) = FilterOptions::$priceRangeOptions[$searchParams->priceRange];
|
||||||
$priceRange = sprintf('%s - %s', $priceFrom, $priceTo);
|
$priceRange = sprintf('%s - %s', $priceFrom, $priceTo);
|
||||||
}
|
}
|
||||||
$pageTitle = '';
|
$pageTitle = '';
|
||||||
|
|||||||
+1
-8
@@ -38,17 +38,12 @@ trait RequestArgumentTypeConversionTrait
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts array to searchparams object
|
* Converts array to searchparams object
|
||||||
* @param array $forcedConceptUids
|
|
||||||
*/
|
*/
|
||||||
public function processSearchParamsArgument(array $forcedConceptUids = [])
|
public function processSearchParamsArgument()
|
||||||
{
|
{
|
||||||
if ($this->request->hasArgument('searchParams')) {
|
if ($this->request->hasArgument('searchParams')) {
|
||||||
$searchParamsObject = SearchParams::fromRequest($this->request);
|
$searchParamsObject = SearchParams::fromRequest($this->request);
|
||||||
|
|
||||||
if ($forcedConceptUids) {
|
|
||||||
$searchParamsObject->setConceptUids($forcedConceptUids);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->request->setArgument('searchParams', $searchParamsObject);
|
$this->request->setArgument('searchParams', $searchParamsObject);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -75,8 +70,6 @@ trait RequestArgumentTypeConversionTrait
|
|||||||
array_push($conceptUids, ...$forcedConceptUids);
|
array_push($conceptUids, ...$forcedConceptUids);
|
||||||
$filterSettingsObject->setConceptUids($conceptUids);
|
$filterSettingsObject->setConceptUids($conceptUids);
|
||||||
}
|
}
|
||||||
|
|
||||||
$filterService->convertDestinationData($filterSettingsObject);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->request->setArgument('filterSettings', $filterSettingsObject);
|
$this->request->setArgument('filterSettings', $filterSettingsObject);
|
||||||
|
|||||||
@@ -24,6 +24,9 @@ class TypeConversionUtility
|
|||||||
return static::convertType($item);
|
return static::convertType($item);
|
||||||
}, $value);
|
}, $value);
|
||||||
}
|
}
|
||||||
|
if (empty($value)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
return $value;
|
return $value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -158,10 +158,6 @@ tx_epproducts_ajax_json {
|
|||||||
AjaxSearchbar {
|
AjaxSearchbar {
|
||||||
1 = update
|
1 = update
|
||||||
}
|
}
|
||||||
AjaxFilterpanel {
|
|
||||||
1 = panel
|
|
||||||
2 = autocomplete
|
|
||||||
}
|
|
||||||
AjaxTable {
|
AjaxTable {
|
||||||
1 = pricetable
|
1 = pricetable
|
||||||
2 = pricetableHtml
|
2 = pricetableHtml
|
||||||
|
|||||||
@@ -371,7 +371,6 @@ $iconRegistry->registerIcon(
|
|||||||
[
|
[
|
||||||
'AjaxSearch' => 'searchresult',
|
'AjaxSearch' => 'searchresult',
|
||||||
'AjaxDate' => 'dates',
|
'AjaxDate' => 'dates',
|
||||||
'AjaxFilterpanel' => 'panel,autocomplete',
|
|
||||||
'AjaxSearchbar' => 'update',
|
'AjaxSearchbar' => 'update',
|
||||||
'AjaxContingent' => 'list,rooms',
|
'AjaxContingent' => 'list,rooms',
|
||||||
'AjaxTable' => 'pricetable,pricetableHtml,eventPricetable',
|
'AjaxTable' => 'pricetable,pricetableHtml,eventPricetable',
|
||||||
@@ -382,7 +381,6 @@ $iconRegistry->registerIcon(
|
|||||||
[
|
[
|
||||||
'AjaxSearch' => 'searchresult',
|
'AjaxSearch' => 'searchresult',
|
||||||
'AjaxDate' => 'dates',
|
'AjaxDate' => 'dates',
|
||||||
'AjaxFilterpanel' => 'panel,autocomplete',
|
|
||||||
'AjaxSearchbar' => 'update',
|
'AjaxSearchbar' => 'update',
|
||||||
'AjaxContingent' => 'list,rooms',
|
'AjaxContingent' => 'list,rooms',
|
||||||
'AjaxTable' => 'pricetable,pricetableHtml,eventPricetable',
|
'AjaxTable' => 'pricetable,pricetableHtml,eventPricetable',
|
||||||
|
|||||||
@@ -28,8 +28,7 @@ import osmMap from './components/osm-map'
|
|||||||
import productDetail from './components/product-detail'
|
import productDetail from './components/product-detail'
|
||||||
import daytripDateSelect from './components/daytrip-date-select'
|
import daytripDateSelect from './components/daytrip-date-select'
|
||||||
import searchBar from './components/search-bar'
|
import searchBar from './components/search-bar'
|
||||||
import searchResult from './components/search-result'
|
import search from './components/search'
|
||||||
import filterPanel from './components/filter-panel'
|
|
||||||
|
|
||||||
import defaultFilterSettings from './_filtersettings'
|
import defaultFilterSettings from './_filtersettings'
|
||||||
import defaultFilterOptions from './_filteroptions'
|
import defaultFilterOptions from './_filteroptions'
|
||||||
@@ -63,8 +62,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
Alpine.data('productDetail', productDetail)
|
Alpine.data('productDetail', productDetail)
|
||||||
Alpine.data('daytripDateSelect', daytripDateSelect)
|
Alpine.data('daytripDateSelect', daytripDateSelect)
|
||||||
Alpine.data('searchBar', searchBar)
|
Alpine.data('searchBar', searchBar)
|
||||||
Alpine.data('searchResult', searchResult)
|
Alpine.data('search', search)
|
||||||
Alpine.data('filterPanel', filterPanel)
|
|
||||||
Alpine.start()
|
Alpine.start()
|
||||||
|
|
||||||
Glightbox({
|
Glightbox({
|
||||||
|
|||||||
@@ -1,7 +1,4 @@
|
|||||||
export default {
|
export default {
|
||||||
destinationName: '',
|
|
||||||
destinationUid: 0,
|
|
||||||
destinationType: '',
|
|
||||||
productUid: 0,
|
productUid: 0,
|
||||||
hotelUid: 0,
|
hotelUid: 0,
|
||||||
countryUids: [],
|
countryUids: [],
|
||||||
@@ -10,7 +7,7 @@ export default {
|
|||||||
conceptUids: [],
|
conceptUids: [],
|
||||||
dateFrom: null,
|
dateFrom: null,
|
||||||
dateTo: null,
|
dateTo: null,
|
||||||
priceRange: 0,
|
priceRanges: [],
|
||||||
nights: 0,
|
nights: 0,
|
||||||
pax: 1,
|
pax: 1,
|
||||||
hotelTypes: [],
|
hotelTypes: [],
|
||||||
|
|||||||
@@ -2,4 +2,4 @@ require('font-awesome/css/font-awesome.min.css')
|
|||||||
require('cookieconsent/build/cookieconsent.min.css')
|
require('cookieconsent/build/cookieconsent.min.css')
|
||||||
require('glightbox/dist/css/glightbox.css')
|
require('glightbox/dist/css/glightbox.css')
|
||||||
require('leaflet/dist/leaflet.css')
|
require('leaflet/dist/leaflet.css')
|
||||||
require('flatpickr/dist/flatpickr.css')
|
|
||||||
|
|||||||
+10
-14
@@ -53,9 +53,11 @@ export default props => ({
|
|||||||
this.filterOptions.destinations = filterOptions.destinations
|
this.filterOptions.destinations = filterOptions.destinations
|
||||||
if (filterOptions.dateFrom !== null) {
|
if (filterOptions.dateFrom !== null) {
|
||||||
this.filterOptions.selectableRangeFrom = filterOptions.dateFrom
|
this.filterOptions.selectableRangeFrom = filterOptions.dateFrom
|
||||||
|
this.picker.set('minDate', new Date(filterOptions.dateFrom))
|
||||||
}
|
}
|
||||||
if (filterOptions.dateTo !== null) {
|
if (filterOptions.dateTo !== null) {
|
||||||
this.filterOptions.selectableRangeTo = filterOptions.dateTo
|
this.filterOptions.selectableRangeTo = filterOptions.dateTo
|
||||||
|
this.picker.set('maxDate', new Date(filterOptions.dateTo))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
updateSearchParam(param, value) {
|
updateSearchParam(param, value) {
|
||||||
@@ -75,24 +77,18 @@ export default props => ({
|
|||||||
},
|
},
|
||||||
selectDestination(uid, name, type) {
|
selectDestination(uid, name, type) {
|
||||||
this.destinationName = name
|
this.destinationName = name
|
||||||
this.destinationSelected = true
|
this.destinationSelected = type !== 'concept'
|
||||||
this.conceptSelected = false
|
this.conceptSelected = type === 'concept'
|
||||||
this.searchParams.destinationUid = uid
|
this.searchParams.destinationUid = uid
|
||||||
this.searchParams.destinationType = type
|
this.searchParams.destinationType = type
|
||||||
this.load()
|
this.load()
|
||||||
},
|
},
|
||||||
selectConcept(uid, name) {
|
|
||||||
this.destinationName = name
|
|
||||||
this.destinationSelected = false
|
|
||||||
this.conceptSelected = true
|
|
||||||
this.searchParams.destinationUid = uid
|
|
||||||
this.searchParams.destinationType = 'concept'
|
|
||||||
this.load()
|
|
||||||
},
|
|
||||||
resetDestination() {
|
resetDestination() {
|
||||||
this.destinationName = 'beliebig'
|
this.destinationName = 'beliebig'
|
||||||
this.destinationSelected = false
|
this.destinationSelected = false
|
||||||
this.conceptSelected = false
|
this.conceptSelected = false
|
||||||
|
this.searchParams.destinationUid = null
|
||||||
|
this.searchParams.destinationType = null
|
||||||
this.load()
|
this.load()
|
||||||
},
|
},
|
||||||
initDatePicker() {
|
initDatePicker() {
|
||||||
@@ -106,14 +102,14 @@ export default props => ({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
let minDate = this.filterOptions.minDate ? new Date(this.filterOptions.minDate) : new Date
|
let minDate = this.filterOptions.dateFrom ? new Date(this.filterOptions.dateFrom) : new Date
|
||||||
this.picker.set('minDate', minDate)
|
this.picker.set('minDate', minDate)
|
||||||
if (this.filterOptions.maxDate) {
|
if (this.filterOptions.dateTo) {
|
||||||
this.picker.set('maxDate', new Date(this.filterOptions.maxDate))
|
this.picker.set('maxDate', new Date(this.filterOptions.dateTo))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
priceRangeLabel() {
|
priceRangeLabel() {
|
||||||
if (this.searchParams.priceRange === 0) {
|
if (null === this.searchParams.priceRange) {
|
||||||
return 'beliebig'
|
return 'beliebig'
|
||||||
}
|
}
|
||||||
let range = this.filterOptions.priceRanges[this.searchParams.priceRange]
|
let range = this.filterOptions.priceRanges[this.searchParams.priceRange]
|
||||||
|
|||||||
@@ -1,27 +0,0 @@
|
|||||||
import axios from 'axios'
|
|
||||||
|
|
||||||
export default props => ({
|
|
||||||
loading: false,
|
|
||||||
uri: props.uri,
|
|
||||||
filterSettings: props.initialFilterSettings,
|
|
||||||
init() {
|
|
||||||
this.load()
|
|
||||||
},
|
|
||||||
onFilterSettingsUpdated(e) {
|
|
||||||
this.filterSettings = e.detail
|
|
||||||
this.load()
|
|
||||||
},
|
|
||||||
load() {
|
|
||||||
this.loading = true
|
|
||||||
let data = new URLSearchParams({
|
|
||||||
'tx_epproducts_ajax[filterSettings]': JSON.stringify(this.filterSettings)
|
|
||||||
})
|
|
||||||
axios.post(this.uri, data)
|
|
||||||
.then(response => {
|
|
||||||
this.$refs.results.innerHTML = response.data
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
this.loading = false
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
+10
-44
@@ -14,15 +14,16 @@ export default props => ({
|
|||||||
filterCount: 0,
|
filterCount: 0,
|
||||||
dateRangeSelected: { from: null, to: null },
|
dateRangeSelected: { from: null, to: null },
|
||||||
dateRangeLabel: null,
|
dateRangeLabel: null,
|
||||||
|
contentWrapper: null,
|
||||||
init() {
|
init() {
|
||||||
|
this.contentWrapper = this.$refs.container
|
||||||
this.updateFilterCount()
|
this.updateFilterCount()
|
||||||
this.load()
|
this.load()
|
||||||
this.$watch('filterSettings', () => {
|
},
|
||||||
this.$dispatch('filter-settings-updated', this.filterSettings)
|
refresh() {
|
||||||
this.updateFilterCount()
|
this.updateFilterCount()
|
||||||
this.updateDateRangeLabel()
|
this.updateDateRangeLabel()
|
||||||
this.load()
|
this.load()
|
||||||
})
|
|
||||||
},
|
},
|
||||||
load() {
|
load() {
|
||||||
this.loading = true
|
this.loading = true
|
||||||
@@ -31,7 +32,7 @@ export default props => ({
|
|||||||
})
|
})
|
||||||
axios.post(this.uri, data)
|
axios.post(this.uri, data)
|
||||||
.then(response => {
|
.then(response => {
|
||||||
this.$refs.panel.innerHTML = response.data
|
this.contentWrapper.innerHTML = response.data
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
this.loading = false
|
this.loading = false
|
||||||
@@ -45,6 +46,7 @@ export default props => ({
|
|||||||
},
|
},
|
||||||
reset() {
|
reset() {
|
||||||
this.filterSettings = {...this.defaultFilterSettings}
|
this.filterSettings = {...this.defaultFilterSettings}
|
||||||
|
this.dateRangeSelected = { from: null, to: null }
|
||||||
this.dateRangeLabel = null
|
this.dateRangeLabel = null
|
||||||
},
|
},
|
||||||
initDatePicker(minDate, maxDate) {
|
initDatePicker(minDate, maxDate) {
|
||||||
@@ -61,7 +63,6 @@ export default props => ({
|
|||||||
dateFrom: flatpickr.formatDate(selectedDates[0], 'Y-m-d'),
|
dateFrom: flatpickr.formatDate(selectedDates[0], 'Y-m-d'),
|
||||||
dateTo: flatpickr.formatDate(selectedDates[1], 'Y-m-d'),
|
dateTo: flatpickr.formatDate(selectedDates[1], 'Y-m-d'),
|
||||||
})
|
})
|
||||||
this.updateDateRangeLabel()
|
|
||||||
this.show = null
|
this.show = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -74,13 +75,12 @@ export default props => ({
|
|||||||
selectDateRangePreset(preset) {
|
selectDateRangePreset(preset) {
|
||||||
let dateFrom = new Date(preset.dateFrom)
|
let dateFrom = new Date(preset.dateFrom)
|
||||||
let dateTo = new Date(preset.dateTo)
|
let dateTo = new Date(preset.dateTo)
|
||||||
|
this.picker.setDate([ dateFrom, dateTo ])
|
||||||
this.dateRangeSelected = { from: dateFrom, to: dateTo }
|
this.dateRangeSelected = { from: dateFrom, to: dateTo }
|
||||||
this.updateFilterSettings({
|
this.updateFilterSettings({
|
||||||
dateFrom: flatpickr.formatDate(dateFrom, 'Y-m-d'),
|
dateFrom: flatpickr.formatDate(dateFrom, 'Y-m-d'),
|
||||||
dateTo: flatpickr.formatDate(dateTo, 'Y-m-d'),
|
dateTo: flatpickr.formatDate(dateTo, 'Y-m-d'),
|
||||||
})
|
})
|
||||||
this.updateDateRangeLabel()
|
|
||||||
this.picker.setDate([ dateFrom, dateTo ])
|
|
||||||
this.show = null
|
this.show = null
|
||||||
},
|
},
|
||||||
resetDateRange() {
|
resetDateRange() {
|
||||||
@@ -89,40 +89,8 @@ export default props => ({
|
|||||||
dateFrom: null,
|
dateFrom: null,
|
||||||
dateTo: null,
|
dateTo: null,
|
||||||
})
|
})
|
||||||
this.updateDateRangeLabel()
|
|
||||||
this.show = null
|
this.show = null
|
||||||
},
|
},
|
||||||
toggleFilterValue(name, value, multiple = false) {
|
|
||||||
let updates = {}
|
|
||||||
let newValue = this.filterSettings[name]
|
|
||||||
if (!multiple) {
|
|
||||||
newValue = newValue === value ? null : value
|
|
||||||
} else {
|
|
||||||
let index = newValue.indexOf(value)
|
|
||||||
if (index !== -1) {
|
|
||||||
newValue.splice(index, 1)
|
|
||||||
} else {
|
|
||||||
newValue.push(value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
updates[name] = newValue
|
|
||||||
this.updateFilterSettings(updates)
|
|
||||||
},
|
|
||||||
toggleDestinationOrConcept(uid, name, type) {
|
|
||||||
let values = { destinationUid: null, destinationName: null, destinationType: null }
|
|
||||||
if ('concept' === type) {
|
|
||||||
values = {...values, conceptUids: []}
|
|
||||||
}
|
|
||||||
let currentUid = this.filterSettings.destinationUid
|
|
||||||
let currentType = this.filterSettings.destinationType
|
|
||||||
if (currentUid !== uid || currentType !== type) {
|
|
||||||
values = { destinationUid: uid, destinationName: name, destinationType: type }
|
|
||||||
if ('concept' === type) {
|
|
||||||
values = {...values, conceptUids: [uid]}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.updateFilterSettings(values)
|
|
||||||
},
|
|
||||||
updateDateRangeLabel() {
|
updateDateRangeLabel() {
|
||||||
let dateRangeLabel = ''
|
let dateRangeLabel = ''
|
||||||
if (null !== this.dateRangeSelected.from && null !== this.dateRangeSelected.to) {
|
if (null !== this.dateRangeSelected.from && null !== this.dateRangeSelected.to) {
|
||||||
@@ -134,8 +102,8 @@ export default props => ({
|
|||||||
},
|
},
|
||||||
updateFilterCount() {
|
updateFilterCount() {
|
||||||
let count = 0
|
let count = 0
|
||||||
if (this.filterSettings.destinationUid) count++
|
if (this.filterSettings.dateFrom !== null) count++
|
||||||
if (this.filterSettings.destinationName) count++
|
if (this.filterSettings.dateTo !== null) count++
|
||||||
if (this.filterSettings.countryUids.length > 0) count++
|
if (this.filterSettings.countryUids.length > 0) count++
|
||||||
if (this.filterSettings.regionUids.length > 0) count++
|
if (this.filterSettings.regionUids.length > 0) count++
|
||||||
if (this.filterSettings.cityUids.length > 0) count++
|
if (this.filterSettings.cityUids.length > 0) count++
|
||||||
@@ -143,9 +111,7 @@ export default props => ({
|
|||||||
if (this.filterSettings.hotelTypes.length > 0) count++
|
if (this.filterSettings.hotelTypes.length > 0) count++
|
||||||
if (this.filterSettings.boardTypes.length > 0) count++
|
if (this.filterSettings.boardTypes.length > 0) count++
|
||||||
if (this.filterSettings.roomTypes.length > 0) count++
|
if (this.filterSettings.roomTypes.length > 0) count++
|
||||||
if (this.filterSettings.dateFrom !== null) count++
|
if (this.filterSettings.priceRanges.length > 0) count++
|
||||||
if (this.filterSettings.dateTo !== null) count++
|
|
||||||
if (this.filterSettings.priceRange > 0) count++
|
|
||||||
if (this.filterSettings.bus) count++
|
if (this.filterSettings.bus) count++
|
||||||
if (this.filterSettings.pax > 2) count++
|
if (this.filterSettings.pax > 2) count++
|
||||||
this.filterCount = count
|
this.filterCount = count
|
||||||
@@ -1,5 +1,10 @@
|
|||||||
|
@import "~flatpickr/dist/flatpickr.css";
|
||||||
|
|
||||||
.flatpickr-calendar {
|
.flatpickr-calendar {
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
|
&.inline {
|
||||||
|
border: none !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.daterange {
|
.daterange {
|
||||||
|
|||||||
@@ -1,223 +0,0 @@
|
|||||||
<html data-namespace-typo3-fluid="true" lang="en"
|
|
||||||
xmlns="http://www.w3.org/1999/xhtml"
|
|
||||||
xmlns:f="http://typo3.org/ns/fluid/ViewHelpers"
|
|
||||||
xmlns:ep="http://typo3.org/ns/EP/EpTheme/ViewHelpers">
|
|
||||||
|
|
||||||
<form class="border rounded p-4">
|
|
||||||
<div x-data="collapse" x-init='initDatePicker(
|
|
||||||
"<f:format.raw>{filterOptions.dateFrom -> f:format.date(format: 'Y-m-d')}</f:format.raw>",
|
|
||||||
"<f:format.raw>{filterOptions.dateTo -> f:format.date(format: 'Y-m-d')}</f:format.raw>"
|
|
||||||
)'>
|
|
||||||
<label x-bind="trigger">
|
|
||||||
Zeitraum
|
|
||||||
</label>
|
|
||||||
<div x-bind="container" class="relative">
|
|
||||||
<input type="text"
|
|
||||||
class="form-control cursor-pointer"
|
|
||||||
placeholder="von... bis"
|
|
||||||
x-bind:value="dateRangeLabel"
|
|
||||||
x-bind:class="loading && 'cursor-not-allowed'"
|
|
||||||
x-on:click.prevent="show = show === 'dateRange' ? null : 'dateRange'"/>
|
|
||||||
<div class="absolute top-100 left-0 z-20 bg-white p-4 shadow-md" x-show="show === 'dateRange'" x-transition x-cloak>
|
|
||||||
<template x-if="datePresets">
|
|
||||||
<div class="flex items-center justify-between pb-2">
|
|
||||||
<template x-for="preset in datePresets">
|
|
||||||
<a class="daterange__preset" href="#"
|
|
||||||
x-on:click.prevent="selectDateRangePreset(preset)">
|
|
||||||
<i class="fa fa-calendar"></i> <span x-text="preset.label"></span>
|
|
||||||
</a>
|
|
||||||
</template>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<input x-ref="picker" type="hidden">
|
|
||||||
<div class="flex items-center justify-between pt-2">
|
|
||||||
<button class="daterange__button focus:outline-none" x-on:click.prevent="show = null">
|
|
||||||
<i class="fa fa-times"></i> schließen
|
|
||||||
</button>
|
|
||||||
<button class="daterange__button focus:outline-none" x-on:click.prevent="resetDateRange()">
|
|
||||||
<i class="fa fa-trash-o"></i> zurücksetzen
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div x-data="collapse">
|
|
||||||
<label x-bind="trigger" class="cursor-pointer">
|
|
||||||
Reiseziel
|
|
||||||
</label>
|
|
||||||
<div x-bind="container" x-transition>
|
|
||||||
<ul class="border rounded shadow-md mb-0">
|
|
||||||
<f:for each="{filterOptions.destinations}" as="destination">
|
|
||||||
<li>
|
|
||||||
<a href="#"
|
|
||||||
x-on:click.prevent="toggleDestinationOrConcept(<f:format.raw>{destination.country.uid}, '{destination.country.label}', 'country'</f:format.raw>)"
|
|
||||||
class="{f:if(condition: '{filterSettings.destinationType} == "country" && {filterSettings.destinationUid} == {destination.country.uid}', then: 'underline')}">
|
|
||||||
{destination.country.label}
|
|
||||||
</a>
|
|
||||||
<f:if condition="{destination.regions -> f:count()}">
|
|
||||||
<ul>
|
|
||||||
<f:for each="{destination.regions}" as="region">
|
|
||||||
<li>
|
|
||||||
<a href="#"
|
|
||||||
x-on:click.prevent="toggleDestinationOrConcept(<f:format.raw>{region.uid}, '{region.label}', 'region'</f:format.raw>)"
|
|
||||||
class="{f:if(condition: '{filterSettings.destinationType} == "region" && {filterSettings.destinationUid} == {region.uid}', then: 'underline')}">
|
|
||||||
{region.label}
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</f:for>
|
|
||||||
</ul>
|
|
||||||
</f:if>
|
|
||||||
</li>
|
|
||||||
</f:for>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div x-data="collapse">
|
|
||||||
<label x-bind="trigger">
|
|
||||||
Reisekonzepte
|
|
||||||
</label>
|
|
||||||
<div x-bind="container" x-transition>
|
|
||||||
<ul class="border rounded shadow-md mb-0">
|
|
||||||
<f:for each="{filterOptions.concepts}" as="concept">
|
|
||||||
<li>
|
|
||||||
<a href="#"
|
|
||||||
x-on:click.prevent="toggleDestinationOrConcept(<f:format.raw>{concept.uid}, '{concept.name}', 'concept'</f:format.raw>)"
|
|
||||||
class="{f:if(condition: '{filterSettings.destinationType} == "concept" && {filterSettings.destinationUid} == {concept.uid}', then: 'underline')}">
|
|
||||||
{concept.name}
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</f:for>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div x-data="collapse">
|
|
||||||
<label x-bind="trigger">
|
|
||||||
Preis
|
|
||||||
</label>
|
|
||||||
<div x-bind="container" x-transition>
|
|
||||||
<ul class="border rounded shadow-md mb-0">
|
|
||||||
<f:for each="{filterOptions.priceRanges}" as="range">
|
|
||||||
<li>
|
|
||||||
<a href="#"
|
|
||||||
x-on:click.prevent="toggleFilterValue('priceRange', <f:format.raw>{range.uid}</f:format.raw>)"
|
|
||||||
class="{f:if(condition: '{filterSettings.priceRange} == {range.uid}', then: 'underline')}">
|
|
||||||
{ep:priceRange(min: range.min, max: range.max)}
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</f:for>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div x-data="collapse">
|
|
||||||
<label x-bind="trigger">
|
|
||||||
Personen
|
|
||||||
</label>
|
|
||||||
<div x-bind="container" x-transition>
|
|
||||||
<ul class="h-48 overflow-y-scroll border rounded shadow-md mb-0">
|
|
||||||
<f:for each="{filterOptions.pax}" as="option">
|
|
||||||
<li>
|
|
||||||
<a href="#"
|
|
||||||
x-on:click.prevent="toggleFilterValue('pax', <f:format.raw>{option}</f:format.raw>)">
|
|
||||||
{option}
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</f:for>
|
|
||||||
<li><a href="{f:uri.typolink(parameter: settings.groupsPageUid)}">> 20</a></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<f:variable name="hotelTypes" value="{
|
|
||||||
1: 'Ferienwohnung',
|
|
||||||
2: 'Sportclub',
|
|
||||||
3: 'Appartment',
|
|
||||||
4: 'Gästehaus',
|
|
||||||
5: 'Pension'
|
|
||||||
}"/>
|
|
||||||
<div x-data="collapse">
|
|
||||||
<label x-bind="trigger">
|
|
||||||
Unterkunft
|
|
||||||
</label>
|
|
||||||
<div x-bind="container" x-transition>
|
|
||||||
<ul class="border rounded shadow-md mb-0">
|
|
||||||
<f:for each="{filterOptions.hotelTypes}" as="type">
|
|
||||||
<li>
|
|
||||||
<a href="#"
|
|
||||||
x-on:click.prevent="toggleFilterValue('hotelTypes', <f:format.raw>{type}</f:format.raw>, true)">
|
|
||||||
{hotelTypes.{type}}
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</f:for>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div x-data="collapse">
|
|
||||||
<label x-bind="trigger">
|
|
||||||
Verpflegung
|
|
||||||
</label>
|
|
||||||
<div x-bind="container" x-transition>
|
|
||||||
<ul class="border rounded shadow-md mb-0">
|
|
||||||
<f:for each="{filterOptions.boardTypes}" as="type">
|
|
||||||
<li>
|
|
||||||
<a href="#"
|
|
||||||
x-on:click.prevent="toggleFilterValue('boardTypes', <f:format.raw>{type.uid}</f:format.raw>, true)">
|
|
||||||
{type.label}
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</f:for>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<f:variable name="roomTypes" value="{
|
|
||||||
1: 'EZ',
|
|
||||||
2: 'DZ / 2er',
|
|
||||||
3: '3er',
|
|
||||||
4: '4er',
|
|
||||||
5: 'ab 5 Pers.',
|
|
||||||
6: 'mit anderen'
|
|
||||||
}"/>
|
|
||||||
<div x-data="collapse">
|
|
||||||
<label x-bind="trigger">
|
|
||||||
Zimmerarten/Apart.
|
|
||||||
</label>
|
|
||||||
<div x-bind="container" x-transition>
|
|
||||||
<ul class="border rounded shadow-md mb-0">
|
|
||||||
<f:for each="{filterOptions.roomTypes}" as="type">
|
|
||||||
<li>
|
|
||||||
<a href="#"
|
|
||||||
x-on:click.prevent="toggleFilterValue('roomTypes', <f:format.raw>{type}</f:format.raw>, true)">
|
|
||||||
{roomTypes.{type}}
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</f:for>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<f:if condition="{filterOptions.busAvailable}">
|
|
||||||
<div x-data="collapse">
|
|
||||||
<label x-bind="trigger">
|
|
||||||
Anreise
|
|
||||||
</label>
|
|
||||||
<div x-bind="container" x-transition>
|
|
||||||
<ul class="border rounded shadow-md mb-0">
|
|
||||||
<li>
|
|
||||||
<a href="#"
|
|
||||||
x-on:click.prevent="toggleFilterValue('bus', true)"
|
|
||||||
class="{f:if(condition: filterSettings.bus, then: 'underline')}">
|
|
||||||
Busanreise
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</f:if>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
</html>
|
|
||||||
+275
@@ -3,6 +3,38 @@
|
|||||||
xmlns:f="http://typo3.org/ns/fluid/ViewHelpers"
|
xmlns:f="http://typo3.org/ns/fluid/ViewHelpers"
|
||||||
xmlns:ep="http://typo3.org/ns/EP/EpTheme/ViewHelpers">
|
xmlns:ep="http://typo3.org/ns/EP/EpTheme/ViewHelpers">
|
||||||
|
|
||||||
|
<f:layout name="Default"/>
|
||||||
|
|
||||||
|
<f:section name="Main">
|
||||||
|
<div class="row" x-ref="container">
|
||||||
|
<div class="col-md-3 relative" x-data="collapse(false, 991)">
|
||||||
|
<p class="lg:hidden">
|
||||||
|
<button class="button button--full button--small" role="button" x-bind="trigger">
|
||||||
|
<i class="fa fa-toggle-on"></i> Filter ein-/ausblenden
|
||||||
|
</button>
|
||||||
|
</p>
|
||||||
|
<div class="lg:block"
|
||||||
|
x-bind="container"
|
||||||
|
x-transition
|
||||||
|
x-cloak
|
||||||
|
>
|
||||||
|
<h3>Filter</h3>
|
||||||
|
<button class="button button--sidebar button--small"
|
||||||
|
x-show="filterCount > 0"
|
||||||
|
x-cloak
|
||||||
|
x-on:click.prevent="reset">
|
||||||
|
Filter zurücksetzen
|
||||||
|
</button>
|
||||||
|
<f:render section="FilterPanel" arguments="{_all}"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-9 relative">
|
||||||
|
<f:render section="SearchResult" arguments="{_all}"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</f:section>
|
||||||
|
|
||||||
|
<f:section name="SearchResult">
|
||||||
<div class="searchresult__info alert alert-info">
|
<div class="searchresult__info alert alert-info">
|
||||||
Deine Suche
|
Deine Suche
|
||||||
<f:if condition="{meta.organic}">
|
<f:if condition="{meta.organic}">
|
||||||
@@ -138,5 +170,248 @@
|
|||||||
</div>
|
</div>
|
||||||
</f:for>
|
</f:for>
|
||||||
</div>
|
</div>
|
||||||
|
</f:section>
|
||||||
|
|
||||||
|
<f:section name="FilterPanel">
|
||||||
|
<div class="border rounded p-4">
|
||||||
|
<div class="mb-2 pb-2 border-b" x-data="collapse(<f:if condition="{filterSettings.dateFrom} || {filterSettings.dateTo}">false</f:if>)"
|
||||||
|
x-init='initDatePicker(
|
||||||
|
<f:format.raw>
|
||||||
|
"{filterOptions.dateFrom -> f:format.date(format: 'Y-m-d')}",
|
||||||
|
"{filterOptions.dateTo -> f:format.date(format: 'Y-m-d')}"
|
||||||
|
</f:format.raw>
|
||||||
|
)'>
|
||||||
|
<label x-bind="trigger">
|
||||||
|
Zeitraum
|
||||||
|
</label>
|
||||||
|
<div x-bind="container" class="relative">
|
||||||
|
<input type="text"
|
||||||
|
class="cursor-pointer focus:outline-none"
|
||||||
|
placeholder="von... bis"
|
||||||
|
x-bind:value="dateRangeLabel"
|
||||||
|
x-bind:class="loading && 'cursor-not-allowed'"
|
||||||
|
x-on:click.prevent="show = show === 'dateRange' ? null : 'dateRange'"/>
|
||||||
|
<div class="absolute top-100 left-0 z-20 bg-white p-4 shadow-md" x-show="show === 'dateRange'" x-transition x-cloak>
|
||||||
|
<template x-if="datePresets">
|
||||||
|
<div class="flex items-center justify-between pb-2">
|
||||||
|
<template x-for="preset in datePresets">
|
||||||
|
<a class="daterange__preset" href="#"
|
||||||
|
x-on:click.prevent="selectDateRangePreset(preset)">
|
||||||
|
<i class="fa fa-calendar"></i> <span x-text="preset.label"></span>
|
||||||
|
</a>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<input x-ref="picker" type="hidden">
|
||||||
|
<div class="flex items-center justify-between pt-2">
|
||||||
|
<button class="daterange__button focus:outline-none" x-on:click.prevent="show = null">
|
||||||
|
<i class="fa fa-times"></i> schließen
|
||||||
|
</button>
|
||||||
|
<button class="daterange__button focus:outline-none" x-on:click.prevent="resetDateRange()">
|
||||||
|
<i class="fa fa-trash-o"></i> zurücksetzen
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-2 pb-2 border-b" x-data="collapse(<f:if condition="{filterSettings.countryUids -> f:count()} || {filterSettings.regionUids -> f:count()}">false</f:if>)">
|
||||||
|
<label x-bind="trigger" class="cursor-pointer">
|
||||||
|
Reiseziel
|
||||||
|
</label>
|
||||||
|
<div x-bind="container" x-transition>
|
||||||
|
<ul class="mb-0 p-0">
|
||||||
|
<f:for each="{filterOptions.destinations}" as="destination">
|
||||||
|
<li>
|
||||||
|
<input type="checkbox"
|
||||||
|
class="mr-2"
|
||||||
|
x-on:change="refresh"
|
||||||
|
x-model.number="filterSettings.countryUids"
|
||||||
|
value="{destination.country.uid}">
|
||||||
|
{destination.country.label}
|
||||||
|
<f:if condition="{destination.regions -> f:count()}">
|
||||||
|
<ul>
|
||||||
|
<f:for each="{destination.regions}" as="region">
|
||||||
|
<li>
|
||||||
|
<input type="checkbox"
|
||||||
|
class="mr-2"
|
||||||
|
x-on:change="refresh"
|
||||||
|
x-model.number="filterSettings.regionUids"
|
||||||
|
value="{region.uid}">
|
||||||
|
{region.label}
|
||||||
|
</li>
|
||||||
|
</f:for>
|
||||||
|
</ul>
|
||||||
|
</f:if>
|
||||||
|
</li>
|
||||||
|
</f:for>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-2 pb-2 border-b" x-data="collapse(<f:if condition="{filterSettings.conceptUids -> f:count()}">false</f:if>)">
|
||||||
|
<label x-bind="trigger">
|
||||||
|
Reisekonzepte
|
||||||
|
</label>
|
||||||
|
<div x-bind="container" x-transition>
|
||||||
|
<ul class="mb-0 p-0">
|
||||||
|
<f:for each="{filterOptions.concepts}" as="concept">
|
||||||
|
<li>
|
||||||
|
<input type="checkbox"
|
||||||
|
class="mr-2"
|
||||||
|
x-on:change="refresh"
|
||||||
|
x-model.number="filterSettings.conceptUids"
|
||||||
|
value="{concept.uid}">
|
||||||
|
{concept.name}
|
||||||
|
</li>
|
||||||
|
</f:for>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-2 pb-2 border-b" x-data="collapse(<f:if condition="{filterSettings.priceRanges -> f:count()}">false</f:if>)">
|
||||||
|
<label x-bind="trigger">
|
||||||
|
Preis
|
||||||
|
</label>
|
||||||
|
<div x-bind="container" x-transition>
|
||||||
|
<ul class="mb-0 p-0">
|
||||||
|
<f:for each="{filterOptions.priceRanges}" as="range">
|
||||||
|
<li>
|
||||||
|
<label>
|
||||||
|
<input type="checkbox"
|
||||||
|
class="mr-2"
|
||||||
|
x-on:change="refresh"
|
||||||
|
x-model.number="filterSettings.priceRanges"
|
||||||
|
value="<f:format.raw>{range.uid}</f:format.raw>">
|
||||||
|
{ep:priceRange(min: range.min, max: range.max)}
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
</f:for>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-2 pb-2 border-b" x-data="collapse(<f:if condition="{filterSettings.pax} > 1">false</f:if>)">
|
||||||
|
<label x-bind="trigger">
|
||||||
|
Personen
|
||||||
|
</label>
|
||||||
|
<div x-bind="container" x-transition>
|
||||||
|
<div class="border rounded">
|
||||||
|
<select x-model="filterSettings.pax" x-on:change="refresh">
|
||||||
|
<f:for each="{filterOptions.pax}" as="option">
|
||||||
|
<option value="<f:format.raw>{option}</f:format.raw>">
|
||||||
|
<f:format.raw>{option}</f:format.raw>
|
||||||
|
</option>
|
||||||
|
</f:for>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<f:variable name="hotelTypes" value="{
|
||||||
|
1: 'Ferienwohnung',
|
||||||
|
2: 'Sportclub',
|
||||||
|
3: 'Appartment',
|
||||||
|
4: 'Gästehaus',
|
||||||
|
5: 'Pension'
|
||||||
|
}"/>
|
||||||
|
<div class="mb-2 pb-2 border-b" x-data="collapse(<f:if condition="{filterSettings.hotelTypes -> f:count()}">false</f:if>)">
|
||||||
|
<label x-bind="trigger">
|
||||||
|
Unterkunft
|
||||||
|
</label>
|
||||||
|
<div x-bind="container" x-transition>
|
||||||
|
<ul class="mb-0 p-0">
|
||||||
|
<f:for each="{filterOptions.hotelTypes}" as="type">
|
||||||
|
<li>
|
||||||
|
<label>
|
||||||
|
<input type="checkbox"
|
||||||
|
class="mr-2"
|
||||||
|
x-on:change="refresh"
|
||||||
|
x-model.number="filterSettings.hotelTypes"
|
||||||
|
value="<f:format.raw>{type}</f:format.raw>">
|
||||||
|
{hotelTypes.{type}}
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
</f:for>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-2 pb-2 border-b" x-data="collapse(<f:if condition="{filterSettings.boardTypes -> f:count()}">false</f:if>)">
|
||||||
|
<label x-bind="trigger">
|
||||||
|
Verpflegung
|
||||||
|
</label>
|
||||||
|
<div x-bind="container" x-transition>
|
||||||
|
<ul class="mb-0 p-0">
|
||||||
|
<f:for each="{filterOptions.boardTypes}" as="type">
|
||||||
|
<f:if condition="{type.label}">
|
||||||
|
<li>
|
||||||
|
<label>
|
||||||
|
<input type="checkbox"
|
||||||
|
class="mr-2"
|
||||||
|
x-on:change="refresh"
|
||||||
|
x-model.number="filterSettings.boardTypes"
|
||||||
|
value="<f:format.raw>{type.uid}</f:format.raw>">
|
||||||
|
{type.label}
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
</f:if>
|
||||||
|
</f:for>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<f:variable name="roomTypes" value="{
|
||||||
|
1: 'EZ',
|
||||||
|
2: 'DZ / 2er',
|
||||||
|
3: '3er',
|
||||||
|
4: '4er',
|
||||||
|
5: 'ab 5 Pers.',
|
||||||
|
6: 'mit anderen'
|
||||||
|
}"/>
|
||||||
|
<div class="mb-2 pb-2 border-b" x-data="collapse(<f:if condition="{filterSettings.roomTypes -> f:count()}">false</f:if>)">
|
||||||
|
<label x-bind="trigger">
|
||||||
|
Zimmerarten/Apart.
|
||||||
|
</label>
|
||||||
|
<div x-bind="container" x-transition>
|
||||||
|
<ul class="mb-0 p-0 p-0">
|
||||||
|
<f:for each="{filterOptions.roomTypes}" as="type">
|
||||||
|
<li>
|
||||||
|
<label>
|
||||||
|
<input type="checkbox"
|
||||||
|
class="mr-2"
|
||||||
|
x-on:change="refresh"
|
||||||
|
x-model.number="filterSettings.roomTypes"
|
||||||
|
value="<f:format.raw>{type}</f:format.raw>">
|
||||||
|
{roomTypes.{type}}
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
</f:for>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<f:if condition="{filterOptions.busAvailable}">
|
||||||
|
<div x-data="collapse(<f:if condition="{filterSettings.bus}">false</f:if>)">
|
||||||
|
<label x-bind="trigger">
|
||||||
|
Anreise
|
||||||
|
</label>
|
||||||
|
<div x-bind="container" x-transition>
|
||||||
|
<ul class="mb-0 p-0">
|
||||||
|
<li>
|
||||||
|
<label>
|
||||||
|
<input type="checkbox"
|
||||||
|
class="mr-2"
|
||||||
|
x-on:change="refresh"
|
||||||
|
x-model="filterSettings.bus">
|
||||||
|
Busanreise
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</f:if>
|
||||||
|
</div>
|
||||||
|
</f:section>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -495,9 +495,9 @@
|
|||||||
|
|
||||||
<f:section name="DaytripDateSelect">
|
<f:section name="DaytripDateSelect">
|
||||||
<div class="date-select-wrapper" x-data='daytripDateSelect({
|
<div class="date-select-wrapper" x-data='daytripDateSelect({
|
||||||
hotelName: "{hotel.name}",
|
hotelName: "<f:format.raw>{hotel.name}</f:format.raw>",
|
||||||
hotelUid: {hotel.uid},
|
hotelUid: <f:format.raw>{hotel.uid}</f:format.raw>,
|
||||||
productUid: {product.uid},
|
productUid: <f:format.raw>{product.uid}</f:format.raw>,
|
||||||
contingentEndpointUri: "<f:format.raw>{ep:uri.ajax(action: 'list', controller: 'AjaxContingent', format: 'json', pageUid: settings.defaultAjaxUid)}</f:format.raw>",
|
contingentEndpointUri: "<f:format.raw>{ep:uri.ajax(action: 'list', controller: 'AjaxContingent', format: 'json', pageUid: settings.defaultAjaxUid)}</f:format.raw>",
|
||||||
roomsEndpointUri: "<f:format.raw>{ep:uri.ajax(action: 'rooms', controller: 'AjaxContingent', format: 'json', pageUid: settings.defaultAjaxUid)}</f:format.raw>"
|
roomsEndpointUri: "<f:format.raw>{ep:uri.ajax(action: 'rooms', controller: 'AjaxContingent', format: 'json', pageUid: settings.defaultAjaxUid)}</f:format.raw>"
|
||||||
})'>
|
})'>
|
||||||
|
|||||||
@@ -6,10 +6,12 @@
|
|||||||
|
|
||||||
<f:section name="Main">
|
<f:section name="Main">
|
||||||
<div id="searchbar" x-data='searchBar({
|
<div id="searchbar" x-data='searchBar({
|
||||||
uri: "<ep:uri.ajax controller="AjaxSearchbar" action="update" pageUid="{settings.defaultAjaxUid}" />",
|
<f:format.raw>
|
||||||
initialSearchParams: {searchParams -> f:format.json() -> f:format.raw()},
|
uri: "{ep:uri.ajax(controller: "AjaxSearchbar", action: "update", pageUid: settings.defaultAjaxUid)}",
|
||||||
initialFilterOptions: {filterOptions -> f:format.json() -> f:format.raw()},
|
initialSearchParams: {searchParams -> f:format.json()},
|
||||||
datePresets: {settings.datePickerPresets -> f:format.json() -> f:format.raw()}
|
initialFilterOptions: {filterOptions -> f:format.json()},
|
||||||
|
datePresets: {settings.datePickerPresets -> f:format.json()}
|
||||||
|
</f:format.raw>
|
||||||
})'>
|
})'>
|
||||||
<div class="container searchbar{f:if(condition: fixed, then: ' affix')}"{f:if(condition: fixed, else: ' x-data="sticky(650)" x-bind:class="sticky && \'affix\'"')}">
|
<div class="container searchbar{f:if(condition: fixed, then: ' affix')}"{f:if(condition: fixed, else: ' x-data="sticky(650)" x-bind:class="sticky && \'affix\'"')}">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
@@ -22,7 +24,6 @@
|
|||||||
<f:form.hidden property="dateTo" value="" additionalAttributes="{x-model: 'searchParams.dateTo'}"/>
|
<f:form.hidden property="dateTo" value="" additionalAttributes="{x-model: 'searchParams.dateTo'}"/>
|
||||||
<f:form.hidden property="nights" additionalAttributes="{x-model: 'searchParams.nights'}"/>
|
<f:form.hidden property="nights" additionalAttributes="{x-model: 'searchParams.nights'}"/>
|
||||||
<f:form.hidden property="pax" additionalAttributes="{x-model: 'searchParams.pax'}"/>
|
<f:form.hidden property="pax" additionalAttributes="{x-model: 'searchParams.pax'}"/>
|
||||||
<f:form.hidden property="conceptUid" additionalAttributes="{x-model: 'searchParams.conceptUid'}"/>
|
|
||||||
<f:form.hidden property="priceRange" additionalAttributes="{x-model: 'searchParams.priceRange'}"/>
|
<f:form.hidden property="priceRange" additionalAttributes="{x-model: 'searchParams.priceRange'}"/>
|
||||||
<f:form.hidden property="pageUid" additionalAttributes="{x-model: 'searchParams.pageUid'}"/>
|
<f:form.hidden property="pageUid" additionalAttributes="{x-model: 'searchParams.pageUid'}"/>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
@@ -108,7 +109,7 @@
|
|||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="w-1/2">
|
<div class="w-1/2">
|
||||||
<ul class="plain-list">
|
<ul class="plain-list mb-0">
|
||||||
<template x-for="region in destination.regions">
|
<template x-for="region in destination.regions">
|
||||||
<li>
|
<li>
|
||||||
<a href="#" x-on:click.prevent="selectDestination(region.uid, region.label, 'region')" x-text="region.label"></a>
|
<a href="#" x-on:click.prevent="selectDestination(region.uid, region.label, 'region')" x-text="region.label"></a>
|
||||||
@@ -125,10 +126,10 @@
|
|||||||
<strong>Konzept</strong>
|
<strong>Konzept</strong>
|
||||||
</div>
|
</div>
|
||||||
<div class="w-1/2">
|
<div class="w-1/2">
|
||||||
<ul class="plain-list">
|
<ul class="plain-list mb-0">
|
||||||
<template x-for="concept in filterOptions.concepts">
|
<template x-for="concept in filterOptions.concepts">
|
||||||
<li>
|
<li>
|
||||||
<a href="#" x-on:click.prevent="selectConcept(concept.uid, concept.name)" x-text="concept.name"></a>
|
<a href="#" x-on:click.prevent="selectDestination(concept.uid, concept.name, 'concept')" x-text="concept.name"></a>
|
||||||
</li>
|
</li>
|
||||||
</template>
|
</template>
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
@@ -12,57 +12,21 @@
|
|||||||
<div class="pagehead__image"
|
<div class="pagehead__image"
|
||||||
style="background-image: url({f:uri.image(src: settings.searchPageHeaderImage, width: '1366', height: '160c+100')})"></div>
|
style="background-image: url({f:uri.image(src: settings.searchPageHeaderImage, width: '1366', height: '160c+100')})"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="container">
|
<div class="container relative"
|
||||||
<div class="row">
|
x-data='search({
|
||||||
<div class="col-md-3 relative" x-data="collapse(false, 991)">
|
|
||||||
<p class="lg:hidden">
|
|
||||||
<button class="button button--full button--small" role="button" x-bind="trigger">
|
|
||||||
<i class="fa fa-toggle-on"></i> Filter ein-/ausblenden
|
|
||||||
</button>
|
|
||||||
</p>
|
|
||||||
<f:spaceless>
|
|
||||||
<div class="lg:block"
|
|
||||||
x-bind="container"
|
|
||||||
x-transition
|
|
||||||
x-cloak
|
|
||||||
x-data='filterPanel({
|
|
||||||
<f:format.raw>
|
<f:format.raw>
|
||||||
uri: "{ep:uri.ajax(controller: 'AjaxFilterpanel', action: 'panel', pageUid: settings.defaultAjaxUid, format: 'html')}",
|
uri: "{ep:uri.ajax(controller: 'AjaxSearch', action: 'searchresult', pageUid: settings.defaultAjaxUid, format: 'html')}",
|
||||||
initialFilterSettings: {filterSettings -> f:format.json()},
|
initialFilterSettings: {filterSettings -> f:format.json()},
|
||||||
datePresets: {settings.datePickerPresets -> f:format.json()}
|
datePresets: {settings.datePickerPresets -> f:format.json()}
|
||||||
</f:format.raw>
|
</f:format.raw>
|
||||||
})'>
|
})'>
|
||||||
<h3>Filter</h3>
|
<div class="row" x-ref="container"></div>
|
||||||
<button class="button button--sidebar button--small"
|
|
||||||
x-show="filterCount > 0"
|
|
||||||
x-cloak
|
|
||||||
x-on:click.prevent="reset">
|
|
||||||
Filter zurücksetzen
|
|
||||||
</button>
|
|
||||||
<div x-ref="panel"></div>
|
|
||||||
<div x-show="loading" class="absolute z-20 inset-0 w-full h-fill bg-overlay-white">
|
<div x-show="loading" class="absolute z-20 inset-0 w-full h-fill bg-overlay-white">
|
||||||
<f:image src="EXT:ep_theme/Resources/Public/images/ajax-loader-white.gif" alt="Loading" class="absolute top-1/2 left-1/2 -translate-xy-1/2"/>
|
<div class="absolute mt-16 top-0 left-1/2 -translate-x-1/2 flex items-center space-x-4">
|
||||||
|
<f:image src="EXT:ep_theme/Resources/Public/images/ajax-loader-white.gif" alt="Loading" />
|
||||||
|
<span>Suchergebnis wird geladen...</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</f:spaceless>
|
|
||||||
</div>
|
|
||||||
<f:spaceless>
|
|
||||||
<div class="col-md-9 relative"
|
|
||||||
x-data='searchResult({
|
|
||||||
<f:format.raw>
|
|
||||||
uri: "{ep:uri.ajax(controller: 'AjaxSearch', action: 'searchresult', pageUid: settings.defaultAjaxUid, format: 'html')}",
|
|
||||||
initialFilterSettings: {filterSettings -> f:format.json()}
|
|
||||||
</f:format.raw>
|
|
||||||
})'
|
|
||||||
x-on:filter-settings-updated.window="onFilterSettingsUpdated($event)"
|
|
||||||
>
|
|
||||||
<div x-ref="results"></div>
|
|
||||||
<div x-show="loading" class="absolute z-20 inset-0 w-full h-fill bg-overlay-white">
|
|
||||||
<f:image src="EXT:ep_theme/Resources/Public/images/ajax-loader-white.gif" alt="Loading" class="absolute top-1/2 left-1/2 -translate-xy-1/2"/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</f:spaceless>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user