WIP Migrate mobile search
This commit is contained in:
@@ -0,0 +1,100 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace EP\EpProducts\Controller;
|
||||||
|
|
||||||
|
/***************************************************************
|
||||||
|
*
|
||||||
|
* Copyright notice
|
||||||
|
*
|
||||||
|
* (c) 2021 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\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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param FilterService $filterService
|
||||||
|
*/
|
||||||
|
public function __construct(FilterService $filterService)
|
||||||
|
{
|
||||||
|
$this->filterService = $filterService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function initializeAction()
|
||||||
|
{
|
||||||
|
$forcedConceptUids = GeneralUtility::trimExplode(',', $this->settings['forcedConceptUids'], true);
|
||||||
|
$this->processFilterSettingsArgument($forcedConceptUids);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $filterSettings
|
||||||
|
*/
|
||||||
|
public function optionsAction(array $filterSettings)
|
||||||
|
{
|
||||||
|
$forcedConceptUids = GeneralUtility::trimExplode(',', $this->settings['forcedConceptUids'], true);
|
||||||
|
$excludedConceptUids = GeneralUtility::trimExplode(',', $this->settings['excludedConceptUids']);
|
||||||
|
$excludedRegionUids = GeneralUtility::trimExplode(',', $this->settings['excludedRegionUids']);
|
||||||
|
|
||||||
|
$filterOptions = $this->filterService->getFilterOptions(
|
||||||
|
$filterSettings,
|
||||||
|
$excludedConceptUids,
|
||||||
|
$excludedRegionUids,
|
||||||
|
$forcedConceptUids
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->view->assignMultiple([
|
||||||
|
'filterSettings' => $filterSettings,
|
||||||
|
'filterOptions' => $filterOptions,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $filterSettings
|
||||||
|
*/
|
||||||
|
public function searchAction(array $filterSettings)
|
||||||
|
{
|
||||||
|
$uri = $this->uriBuilder
|
||||||
|
->reset()
|
||||||
|
->setCreateAbsoluteUri(true)
|
||||||
|
->setTargetPageUid($this->settings['defaultSearchPageUid'])
|
||||||
|
->uriFor(
|
||||||
|
'searchresult',
|
||||||
|
['filterSettings' => $filterSettings],
|
||||||
|
'Search',
|
||||||
|
'epproducts',
|
||||||
|
'searchresult'
|
||||||
|
);
|
||||||
|
|
||||||
|
return json_encode($uri, JSON_THROW_ON_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -74,19 +74,6 @@ class SearchController extends ActionController
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function searchboxAction()
|
|
||||||
{
|
|
||||||
$searchParams = $this->searchResultService->getNormalizedSearchParams();
|
|
||||||
$filterSettings = $this->filterService->getNormalizedFilterSettings();
|
|
||||||
$filterOptions = $this->filterService->getFilterOptions($filterSettings);
|
|
||||||
|
|
||||||
$this->view->assignMultiple([
|
|
||||||
'filterSettings' => $filterSettings,
|
|
||||||
'filterOptions' => $filterOptions,
|
|
||||||
'searchParams' => $searchParams,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function initializeProcessSearchAction()
|
public function initializeProcessSearchAction()
|
||||||
{
|
{
|
||||||
$this->processSearchParamsArgument();
|
$this->processSearchParamsArgument();
|
||||||
|
|||||||
@@ -148,6 +148,10 @@ tx_epproducts_ajax_json {
|
|||||||
1 = pricetable
|
1 = pricetable
|
||||||
2 = searchresult
|
2 = searchresult
|
||||||
}
|
}
|
||||||
|
AjaxFilterPanel {
|
||||||
|
1 = options
|
||||||
|
2 = search
|
||||||
|
}
|
||||||
AjaxDate {
|
AjaxDate {
|
||||||
1 = dates
|
1 = dates
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -295,6 +295,7 @@ $iconRegistry->registerIcon(
|
|||||||
'ajax',
|
'ajax',
|
||||||
[
|
[
|
||||||
'AjaxSearch' => 'searchresult',
|
'AjaxSearch' => 'searchresult',
|
||||||
|
'AjaxFilterPanel' => 'options,search',
|
||||||
'AjaxDate' => 'dates',
|
'AjaxDate' => 'dates',
|
||||||
'AjaxContingent' => 'list,rooms',
|
'AjaxContingent' => 'list,rooms',
|
||||||
'AjaxTable' => 'datestable,pricetable,pricetableHtml,eventPricetable,daytripRooms',
|
'AjaxTable' => 'datestable,pricetable,pricetableHtml,eventPricetable,daytripRooms',
|
||||||
@@ -304,6 +305,7 @@ $iconRegistry->registerIcon(
|
|||||||
],
|
],
|
||||||
[
|
[
|
||||||
'AjaxSearch' => 'searchresult',
|
'AjaxSearch' => 'searchresult',
|
||||||
|
'AjaxFilterPanel' => 'options,search',
|
||||||
'AjaxDate' => 'dates',
|
'AjaxDate' => 'dates',
|
||||||
'AjaxContingent' => 'list,rooms',
|
'AjaxContingent' => 'list,rooms',
|
||||||
'AjaxTable' => 'datestable,pricetable,pricetableHtml,eventPricetable,daytripRooms',
|
'AjaxTable' => 'datestable,pricetable,pricetableHtml,eventPricetable,daytripRooms',
|
||||||
|
|||||||
@@ -1,18 +0,0 @@
|
|||||||
lib.searchBox = USER
|
|
||||||
lib.searchBox {
|
|
||||||
userFunc = TYPO3\CMS\Extbase\Core\Bootstrap->run
|
|
||||||
extensionName = EpProducts
|
|
||||||
pluginName = searchbox
|
|
||||||
vendorName = EP
|
|
||||||
controller = Search
|
|
||||||
action = searchbox
|
|
||||||
switchableControllerActions {
|
|
||||||
Search {
|
|
||||||
1 = searchbox
|
|
||||||
}
|
|
||||||
}
|
|
||||||
settings =< plugin.tx_epproducts.settings
|
|
||||||
settings.searchPageUid < plugin.tx_epproducts.settings.defaultSearchPageUid
|
|
||||||
persistence =< plugin.tx_epproducts.persistence
|
|
||||||
view =< plugin.tx_epproducts.view
|
|
||||||
}
|
|
||||||
-12
@@ -1,12 +0,0 @@
|
|||||||
import { Controller } from 'stimulus'
|
|
||||||
|
|
||||||
export default class extends Controller {
|
|
||||||
|
|
||||||
static targets = [ 'form', 'container' ]
|
|
||||||
|
|
||||||
static values = { loading: Boolean }
|
|
||||||
|
|
||||||
submit(e) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+89
@@ -0,0 +1,89 @@
|
|||||||
|
import { Controller } from 'stimulus'
|
||||||
|
import { useFetch} from '../mixins/use_fetch'
|
||||||
|
|
||||||
|
export default class extends Controller {
|
||||||
|
|
||||||
|
static targets = [
|
||||||
|
'form',
|
||||||
|
'container',
|
||||||
|
'loadingIndicator',
|
||||||
|
'dateFrom',
|
||||||
|
'dateTo',
|
||||||
|
]
|
||||||
|
|
||||||
|
static values = {
|
||||||
|
optionsUri: String,
|
||||||
|
searchUri: String,
|
||||||
|
loading: Boolean,
|
||||||
|
show: Boolean,
|
||||||
|
}
|
||||||
|
|
||||||
|
initialize() {
|
||||||
|
useFetch(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
open(e) {
|
||||||
|
if (e.detail === 'mobile-search') {
|
||||||
|
this.showValue = true
|
||||||
|
this.load()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
close() {
|
||||||
|
this.showValue = false
|
||||||
|
this.containerTarget.innerHTML = ''
|
||||||
|
}
|
||||||
|
|
||||||
|
filter() {
|
||||||
|
this.load({
|
||||||
|
method: 'POST',
|
||||||
|
body: new FormData(this.formTarget)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
reset() {
|
||||||
|
this.load({ method: 'POST' })
|
||||||
|
}
|
||||||
|
|
||||||
|
load(options) {
|
||||||
|
this.loadingValue = true
|
||||||
|
fetch(this.optionsUriValue, options)
|
||||||
|
.then(this.checkStatus)
|
||||||
|
.then(this.parseHTML)
|
||||||
|
.then(html => {
|
||||||
|
this.containerTarget.innerHTML = html
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.loadingValue = false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
search() {
|
||||||
|
const options = {
|
||||||
|
method: 'POST',
|
||||||
|
body: new FormData(this.formTarget)
|
||||||
|
}
|
||||||
|
this.loadingValue = true
|
||||||
|
fetch(this.searchUriValue, options)
|
||||||
|
.then(this.checkStatus)
|
||||||
|
.then(this.parseJSON)
|
||||||
|
.then(uri => {
|
||||||
|
window.location = uri
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
selectDateRange(e) {
|
||||||
|
this.dateFromTarget.value = e.detail.from
|
||||||
|
this.dateToTarget.value = e.detail.to
|
||||||
|
this.filter()
|
||||||
|
}
|
||||||
|
|
||||||
|
showValueChanged() {
|
||||||
|
this.element.classList.toggle('hidden', false === this.showValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
loadingValueChanged() {
|
||||||
|
this.containerTarget.classList.toggle('opacity-25', this.loadingValue === true)
|
||||||
|
this.loadingIndicatorTarget.classList.toggle('hidden', this.loadingValue === false)
|
||||||
|
}
|
||||||
|
}
|
||||||
+2
-2
@@ -49,7 +49,7 @@ export default class extends Controller {
|
|||||||
this.busIconTargets.forEach(icon => {
|
this.busIconTargets.forEach(icon => {
|
||||||
let busPrice = parseInt(icon.dataset.busPrice)
|
let busPrice = parseInt(icon.dataset.busPrice)
|
||||||
let busIncluded = !!icon.dataset.busIncluded
|
let busIncluded = !!icon.dataset.busIncluded
|
||||||
icon.classList.toggle('hidden', this.hideBusIcon(busPrice, busIncluded))
|
icon.classList.toggle('hidden', this.isHideBusIcon(busPrice, busIncluded))
|
||||||
})
|
})
|
||||||
if (this.hasSurchargeToggleLabelTarget) {
|
if (this.hasSurchargeToggleLabelTarget) {
|
||||||
let labelDefault = this.surchargeToggleLabelTarget.dataset.labelDefault
|
let labelDefault = this.surchargeToggleLabelTarget.dataset.labelDefault
|
||||||
@@ -86,7 +86,7 @@ export default class extends Controller {
|
|||||||
return minPrice
|
return minPrice
|
||||||
}
|
}
|
||||||
|
|
||||||
hideBusIcon(busPrice, busIncluded) {
|
isHideBusIcon(busPrice, busIncluded) {
|
||||||
return (
|
return (
|
||||||
busPrice && this.modeValue !== 'surcharge' ||
|
busPrice && this.modeValue !== 'surcharge' ||
|
||||||
busIncluded && this.modeValue === 'discount'
|
busIncluded && this.modeValue === 'discount'
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
<f:render partial="ContactBar" arguments="{_all}"/>
|
<f:render partial="ContactBar" arguments="{_all}"/>
|
||||||
<f:render partial="Topnav" arguments="{_all}"/>
|
<f:render partial="Topnav" arguments="{_all}"/>
|
||||||
<f:render partial="Mobilenav" section="Main" arguments="{_all}"/>
|
<f:render partial="Mobilenav" section="Main" arguments="{_all}"/>
|
||||||
<f:cObject typoscriptObjectPath="lib.searchBox"/>
|
<f:render partial="Search/MobileSearch" arguments="{_all}"/>
|
||||||
<f:render partial="Config" arguments="{_all}" />
|
<f:render partial="Config" arguments="{_all}" />
|
||||||
<f:render partial="Icons" arguments="{_all}"/>
|
<f:render partial="Icons" arguments="{_all}"/>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
<f:render partial="ContactBar" arguments="{_all}"/>
|
<f:render partial="ContactBar" arguments="{_all}"/>
|
||||||
<f:render partial="Topnav" arguments="{_all}"/>
|
<f:render partial="Topnav" arguments="{_all}"/>
|
||||||
<f:render partial="Mobilenav" section="Main" arguments="{_all}"/>
|
<f:render partial="Mobilenav" section="Main" arguments="{_all}"/>
|
||||||
|
<f:render partial="Search/MobileSearch" arguments="{_all}"/>
|
||||||
<f:render partial="Config" arguments="{_all}" />
|
<f:render partial="Config" arguments="{_all}" />
|
||||||
<f:render partial="Icons" arguments="{_all}"/>
|
<f:render partial="Icons" arguments="{_all}"/>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
<f:render partial="ContactBar" arguments="{_all}"/>
|
<f:render partial="ContactBar" arguments="{_all}"/>
|
||||||
<f:render partial="Topnav" arguments="{_all}"/>
|
<f:render partial="Topnav" arguments="{_all}"/>
|
||||||
<f:render partial="Mobilenav" section="Main" arguments="{_all}"/>
|
<f:render partial="Mobilenav" section="Main" arguments="{_all}"/>
|
||||||
|
<f:render partial="Search/MobileSearch" arguments="{_all}"/>
|
||||||
<f:render partial="Config" arguments="{_all}" />
|
<f:render partial="Config" arguments="{_all}" />
|
||||||
<f:render partial="Icons" arguments="{_all}"/>
|
<f:render partial="Icons" arguments="{_all}"/>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
<f:render partial="ContactBar" arguments="{_all}"/>
|
<f:render partial="ContactBar" arguments="{_all}"/>
|
||||||
<f:render partial="Topnav" arguments="{_all}"/>
|
<f:render partial="Topnav" arguments="{_all}"/>
|
||||||
<f:render partial="Mobilenav" section="Main" arguments="{_all}"/>
|
<f:render partial="Mobilenav" section="Main" arguments="{_all}"/>
|
||||||
|
<f:render partial="Search/MobileSearch" arguments="{_all}"/>
|
||||||
<f:render partial="Config" arguments="{_all}" />
|
<f:render partial="Config" arguments="{_all}" />
|
||||||
<f:render partial="Icons" arguments="{_all}"/>
|
<f:render partial="Icons" arguments="{_all}"/>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -16,19 +16,15 @@
|
|||||||
<f:render section="FirstLevel" arguments="{_all}"/>
|
<f:render section="FirstLevel" arguments="{_all}"/>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex lg:hidden items-center space-x-4">
|
<div class="flex lg:hidden items-center space-x-4">
|
||||||
<f:if condition="{data.tx_eptheme_hide_searchbar}">
|
<button type="button"
|
||||||
<f:else>
|
class="focus:outline-none text-gray-800"
|
||||||
<button type="button"
|
data-controller="overlay-toggle"
|
||||||
class="focus:outline-none text-gray-800"
|
data-overlay-toggle-id-value="mobile-search"
|
||||||
data-controller="overlay-toggle"
|
data-action="overlay-toggle#invokeToggle">
|
||||||
data-overlay-toggle-id-value="search"
|
<svg class="w-8 h-8 text-gray-800">
|
||||||
data-action="overlay-toggle#invokeToggle">
|
<use href="#icon-search"></use>
|
||||||
<svg class="w-8 h-8 text-gray-800">
|
</svg>
|
||||||
<use href="#icon-search"></use>
|
</button>
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
</f:else>
|
|
||||||
</f:if>
|
|
||||||
<button type="button"
|
<button type="button"
|
||||||
class="focus:outline-none text-gray-800"
|
class="focus:outline-none text-gray-800"
|
||||||
data-controller="overlay-toggle"
|
data-controller="overlay-toggle"
|
||||||
|
|||||||
+343
-350
@@ -3,118 +3,201 @@
|
|||||||
xmlns:ep="http://typo3.org/ns/EP/EpTheme/ViewHelpers"
|
xmlns:ep="http://typo3.org/ns/EP/EpTheme/ViewHelpers"
|
||||||
xmlns:f="http://typo3.org/ns/fluid/ViewHelpers">
|
xmlns:f="http://typo3.org/ns/fluid/ViewHelpers">
|
||||||
|
|
||||||
<f:form object="{filterSettings}"
|
<div class="mb-4 p-4 bg-ep-primary text-white"
|
||||||
name="filterSettings"
|
data-controller="collapse"
|
||||||
pluginName="Ajax"
|
data-collapse-collapsed-value="{f:if(condition: '{filterSettings.dateFrom} || {filterSettings.dateTo}', then: 'false', else: 'true')}">
|
||||||
data="{'search-target': 'form'}">
|
<button type="button"
|
||||||
|
data-action="click->collapse#toggle"
|
||||||
|
class="flex items-center justify-between w-full">
|
||||||
|
<span class="uppercase font-bold">
|
||||||
|
Reisezeitraum
|
||||||
|
</span>
|
||||||
|
<svg class="w-6 h-6 text-white transform"
|
||||||
|
data-collapse-target="icon">
|
||||||
|
<use href="#icon-arrow-right"></use>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<div data-collapse-target="container">
|
||||||
|
<f:form.hidden property="dateFrom"
|
||||||
|
data="{'search-target': 'dateFrom', 'mobile-search-target': 'dateFrom'}"/>
|
||||||
|
<f:form.hidden property="dateTo"
|
||||||
|
data="{'search-target': 'dateTo', 'mobile-search-target': 'dateTo'}"/>
|
||||||
|
|
||||||
<div class="mb-4 p-4 bg-ep-primary text-white"
|
<div data-controller="collapse datepicker"
|
||||||
data-controller="collapse"
|
data-datepicker-date-from-value="{filterSettings.dateFrom}"
|
||||||
data-collapse-collapsed-value="{f:if(condition: '{filterSettings.dateFrom} || {filterSettings.dateTo}', then: 'false', else: 'true')}">
|
data-datepicker-date-to-value="{filterSettings.dateTo}"
|
||||||
<button type="button"
|
data-datepicker-min-date-value="{f:format.date(date: 'now', format: 'Y-m-d')}"
|
||||||
data-action="click->collapse#toggle"
|
data-action="collapse:click:outside->collapse#close searchbar:input@window->collapse#close"
|
||||||
class="flex items-center justify-between w-full">
|
data-collapse-collapsed-value="true">
|
||||||
<span class="uppercase font-bold">
|
<div class="relative">
|
||||||
Reisezeitraum
|
<input type="text"
|
||||||
</span>
|
data-action="click->collapse#toggle"
|
||||||
<svg class="w-6 h-6 text-white transform"
|
class="w-full px-0 bg-transparent border-0 ring-0 focus:ring-0 text-white uppercase cursor-pointer placeholder-white"
|
||||||
data-collapse-target="icon">
|
placeholder="Zeitraum"
|
||||||
<use href="#icon-arrow-right"></use>
|
value="{ep:dateRange(dateFrom: filterSettings.dateFrom, dateTo: filterSettings.dateTo, includeLabel: 0)}"
|
||||||
</svg>
|
data-searchbar-target="dateRangeLabel"/>
|
||||||
</button>
|
<svg class="w-6 h-6 text-white absolute right-0 top-0 mt-2 cursor-pointer"
|
||||||
<div data-collapse-target="container">
|
data-action="click->collapse#toggle">
|
||||||
<f:form.hidden property="dateFrom"
|
<use href="#icon-calendar"></use>
|
||||||
data="{'search-target': 'dateFrom'}"/>
|
</svg>
|
||||||
<f:form.hidden property="dateTo"
|
<div class="hidden absolute z-20 top-100 mt-2 left-0 min-w-full bg-white p-4 shadow-md rounded"
|
||||||
data="{'search-target': 'dateTo'}"/>
|
data-collapse-target="container">
|
||||||
|
<div class="flex justify-between divide-x divide-gray-200">
|
||||||
<div data-controller="collapse datepicker"
|
<div class="pr-2">
|
||||||
data-datepicker-date-from-value="{filterSettings.dateFrom}"
|
<input type="hidden"
|
||||||
data-datepicker-date-to-value="{filterSettings.dateTo}"
|
data-datepicker-target="field">
|
||||||
data-datepicker-min-date-value="{f:format.date(date: 'now', format: 'Y-m-d')}"
|
</div>
|
||||||
data-action="collapse:click:outside->collapse#close searchbar:input@window->collapse#close"
|
<div class="flex-1 flex flex-col justify-between pl-2">
|
||||||
data-collapse-collapsed-value="true">
|
<f:if condition="{settings.datePickerPresets}">
|
||||||
<div class="relative">
|
|
||||||
<input type="text"
|
|
||||||
data-action="click->collapse#toggle"
|
|
||||||
class="w-full px-0 bg-transparent border-0 ring-0 focus:ring-0 text-white uppercase cursor-pointer placeholder-white"
|
|
||||||
placeholder="Zeitraum"
|
|
||||||
value="{ep:dateRange(dateFrom: filterSettings.dateFrom, dateTo: filterSettings.dateTo, includeLabel: 0)}"
|
|
||||||
data-searchbar-target="dateRangeLabel"/>
|
|
||||||
<svg class="w-6 h-6 text-white absolute right-0 top-0 mt-2 cursor-pointer"
|
|
||||||
data-action="click->collapse#toggle">
|
|
||||||
<use href="#icon-calendar"></use>
|
|
||||||
</svg>
|
|
||||||
<div class="hidden absolute z-20 top-100 mt-2 left-0 min-w-full bg-white p-4 shadow-md rounded"
|
|
||||||
data-collapse-target="container">
|
|
||||||
<div class="flex justify-between divide-x divide-gray-200">
|
|
||||||
<div class="pr-2">
|
|
||||||
<input type="hidden"
|
|
||||||
data-datepicker-target="field">
|
|
||||||
</div>
|
|
||||||
<div class="flex-1 flex flex-col justify-between pl-2">
|
|
||||||
<f:if condition="{settings.datePickerPresets}">
|
|
||||||
<div class="flex flex-col space-y-4">
|
|
||||||
<f:for each="{settings.datePickerPresets}" as="preset">
|
|
||||||
<button type="button"
|
|
||||||
class="button button--small button--light w-full"
|
|
||||||
data-preset='{preset -> f:format.json() -> f:format.raw()}'
|
|
||||||
data-action="datepicker#selectPreset">
|
|
||||||
<span>
|
|
||||||
{preset.label}
|
|
||||||
</span>
|
|
||||||
</button>
|
|
||||||
</f:for>
|
|
||||||
</div>
|
|
||||||
</f:if>
|
|
||||||
<div class="flex flex-col space-y-4">
|
<div class="flex flex-col space-y-4">
|
||||||
<button type="button"
|
<f:for each="{settings.datePickerPresets}" as="preset">
|
||||||
class="button button--small button--light w-full"
|
<button type="button"
|
||||||
data-action="collapse#close">
|
class="button button--small button--light w-full"
|
||||||
schließen
|
data-preset='{preset -> f:format.json() -> f:format.raw()}'
|
||||||
</button>
|
data-action="datepicker#selectPreset">
|
||||||
<button type="button"
|
<span>
|
||||||
class="button button--small button--light w-full"
|
{preset.label}
|
||||||
data-action="datepicker#reset">
|
</span>
|
||||||
zurücksetzen
|
</button>
|
||||||
</button>
|
</f:for>
|
||||||
</div>
|
</div>
|
||||||
|
</f:if>
|
||||||
|
<div class="flex flex-col space-y-4">
|
||||||
|
<button type="button"
|
||||||
|
class="button button--small button--light w-full"
|
||||||
|
data-action="collapse#close">
|
||||||
|
schließen
|
||||||
|
</button>
|
||||||
|
<button type="button"
|
||||||
|
class="button button--small button--light w-full"
|
||||||
|
data-action="datepicker#reset">
|
||||||
|
zurücksetzen
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="mb-4 p-4 bg-ep-primary text-white"
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-4 p-4 bg-ep-primary text-white"
|
||||||
|
data-controller="collapse"
|
||||||
|
data-collapse-collapsed-value="{f:if(condition: '{filterSettings.conceptUids}', then: 'false', else: 'true')}">
|
||||||
|
<button type="button"
|
||||||
|
data-action="click->collapse#toggle"
|
||||||
|
class="flex items-center justify-between w-full">
|
||||||
|
<span class="uppercase font-bold">
|
||||||
|
Reisekonzepte
|
||||||
|
</span>
|
||||||
|
<svg class="w-6 h-6 text-white transform"
|
||||||
|
data-collapse-target="icon">
|
||||||
|
<use href="#icon-arrow-right"></use>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<div data-collapse-target="container"
|
||||||
|
class="pt-2">
|
||||||
|
<ul class="mb-0 p-0 space-y-2">
|
||||||
|
<f:for each="{filterOptions.concepts}" as="concept">
|
||||||
|
<li>
|
||||||
|
<label>
|
||||||
|
<f:form.checkbox class="mr-2 rounded-full w-5 h-5 border-white ring-0 bg-transparent focus:ring-0 focus:border-none text-ep-primary"
|
||||||
|
property="conceptUids"
|
||||||
|
data="{action: 'search#filter mobile-search#filter'}"
|
||||||
|
value="{concept.uid}"/>
|
||||||
|
<span class="inline-block py-1 px-2 bg-concept-{concept.code} text-white">
|
||||||
|
{concept.name}
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
</f:for>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="px-4 divide-y">
|
||||||
|
|
||||||
|
<div class="py-2"
|
||||||
data-controller="collapse"
|
data-controller="collapse"
|
||||||
data-collapse-collapsed-value="{f:if(condition: '{filterSettings.conceptUids}', then: 'false', else: 'true')}">
|
data-collapse-collapsed-value="{f:if(condition: '{filterSettings.countryUids} || {filterSettings.regionUids}', then: 'false', else: 'true')}">
|
||||||
<button type="button"
|
<button type="button"
|
||||||
data-action="click->collapse#toggle"
|
data-action="click->collapse#toggle"
|
||||||
class="flex items-center justify-between w-full">
|
class="flex items-center justify-between w-full">
|
||||||
<span class="uppercase font-bold">
|
<span class="uppercase font-bold">
|
||||||
Reisekonzepte
|
Reiseziel
|
||||||
</span>
|
</span>
|
||||||
<svg class="w-6 h-6 text-white transform"
|
<svg class="w-6 h-6 transform"
|
||||||
data-collapse-target="icon">
|
data-collapse-target="icon">
|
||||||
<use href="#icon-arrow-right"></use>
|
<use href="#icon-arrow-right"></use>
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
<div data-collapse-target="container"
|
<div data-collapse-target="container">
|
||||||
class="pt-2">
|
<ul class="mb-0 p-0 pt-2">
|
||||||
<ul class="mb-0 p-0 space-y-2">
|
<f:for each="{filterOptions.destinations}" as="destination">
|
||||||
<f:for each="{filterOptions.concepts}" as="concept">
|
<li class="relative border-b last:border-0 mb-2">
|
||||||
|
<label class="flex items-start">
|
||||||
|
<f:form.checkbox class="w-5 h-5 border-ep-primary ring-0 bg-transparent focus:ring-0 focus:border-none text-ep-primary"
|
||||||
|
property="countryUids"
|
||||||
|
data="{action: 'search#filter mobile-search#filter'}"
|
||||||
|
value="{destination.country.uid}"/>
|
||||||
|
<span class="pl-2 leading-none">
|
||||||
|
<strong>{destination.country.label}</strong>
|
||||||
|
</span>
|
||||||
|
<svg class="absolute top-0 right-0 w-8 h-6">
|
||||||
|
<use href="#icon-flag-{destination.country.code -> f:format.case(mode: 'lower')}"/>
|
||||||
|
</svg>
|
||||||
|
</label>
|
||||||
|
<f:if condition="{destination.regions}">
|
||||||
|
<ul class="py-2 space-y-1">
|
||||||
|
<f:for each="{destination.regions}" as="region">
|
||||||
|
<li>
|
||||||
|
<label class="flex items-start">
|
||||||
|
<f:form.checkbox class="w-5 h-5 border-ep-primary ring-0 bg-transparent focus:ring-0 focus:border-none text-ep-primary"
|
||||||
|
property="regionUids"
|
||||||
|
data="{action: 'search#filter mobile-search#filter'}"
|
||||||
|
value="{region.uid}"/>
|
||||||
|
<span class="leading-none pl-2">
|
||||||
|
{region.label}
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
</f:for>
|
||||||
|
</ul>
|
||||||
|
</f:if>
|
||||||
|
</li>
|
||||||
|
</f:for>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="py-2"
|
||||||
|
data-controller="collapse"
|
||||||
|
data-collapse-collapsed-value="{f:if(condition: '{filterSettings.priceRanges}', then: 'false', else: 'true')}">
|
||||||
|
<button type="button"
|
||||||
|
data-action="click->collapse#toggle"
|
||||||
|
class="flex items-center justify-between w-full">
|
||||||
|
<span class="uppercase font-bold">
|
||||||
|
Preis
|
||||||
|
</span>
|
||||||
|
<svg class="w-6 h-6 transform"
|
||||||
|
data-collapse-target="icon">
|
||||||
|
<use href="#icon-arrow-right"></use>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<div data-collapse-target="container">
|
||||||
|
<ul class="mb-0 p-0 pt-2 space-y-1">
|
||||||
|
<f:for each="{filterOptions.priceRanges}" as="range">
|
||||||
<li>
|
<li>
|
||||||
<label>
|
<label class="flex items-start">
|
||||||
<f:form.checkbox class="mr-2 rounded-full w-5 h-5 border-white ring-0 bg-transparent focus:ring-0 focus:border-none text-ep-primary"
|
<f:form.checkbox class="w-5 h-5 border-ep-primary ring-0 bg-transparent focus:ring-0 focus:border-none text-ep-primary"
|
||||||
property="conceptUids"
|
property="priceRanges"
|
||||||
data="{action: 'search#filter'}"
|
data="{action: 'search#filter mobile-search#filter'}"
|
||||||
value="{concept.uid}"/>
|
value="{range.uid}"/>
|
||||||
<span class="inline-block py-1 px-2 bg-concept-{concept.code} text-white">
|
<span class="leading-none pl-2">
|
||||||
{concept.name}
|
{ep:priceRange(min: range.min, max: range.max)}
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
</li>
|
</li>
|
||||||
@@ -123,267 +206,177 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="px-4 divide-y">
|
<div class="py-2"
|
||||||
|
data-controller="collapse"
|
||||||
<div class="py-2"
|
data-collapse-collapsed-value="{f:if(condition: '{filterSettings.pax} > 1', then: 'false', else: 'true')}">
|
||||||
data-controller="collapse"
|
<button type="button"
|
||||||
data-collapse-collapsed-value="{f:if(condition: '{filterSettings.countryUids} || {filterSettings.regionUids}', then: 'false', else: 'true')}">
|
data-action="click->collapse#toggle"
|
||||||
<button type="button"
|
class="flex items-center justify-between w-full">
|
||||||
data-action="click->collapse#toggle"
|
<span class="uppercase font-bold">
|
||||||
class="flex items-center justify-between w-full">
|
Personen
|
||||||
<span class="uppercase font-bold">
|
</span>
|
||||||
Reiseziel
|
<svg class="w-6 h-6 transform"
|
||||||
</span>
|
data-collapse-target="icon">
|
||||||
<svg class="w-6 h-6 transform"
|
<use href="#icon-arrow-right"></use>
|
||||||
data-collapse-target="icon">
|
</svg>
|
||||||
<use href="#icon-arrow-right"></use>
|
</button>
|
||||||
</svg>
|
<div data-collapse-target="container">
|
||||||
</button>
|
<f:form.select class="w-full border-0 focus:ring-0 bg-right mt-2 p-0"
|
||||||
<div data-collapse-target="container">
|
property="pax"
|
||||||
<ul class="mb-0 p-0 pt-2">
|
options="{filterOptions.pax}"
|
||||||
<f:for each="{filterOptions.destinations}" as="destination">
|
data="{action: 'search#filter mobile-search#filter'}"/>
|
||||||
<li class="relative border-b last:border-0 mb-2">
|
|
||||||
<label class="flex items-start">
|
|
||||||
<f:form.checkbox class="w-5 h-5 border-ep-primary ring-0 bg-transparent focus:ring-0 focus:border-none text-ep-primary"
|
|
||||||
property="countryUids"
|
|
||||||
data="{action: 'search#filter'}"
|
|
||||||
value="{destination.country.uid}"/>
|
|
||||||
<span class="pl-2 leading-none">
|
|
||||||
<strong>{destination.country.label}</strong>
|
|
||||||
</span>
|
|
||||||
<svg class="absolute top-0 right-0 w-8 h-6">
|
|
||||||
<use href="#icon-flag-{destination.country.code -> f:format.case(mode: 'lower')}"/>
|
|
||||||
</svg>
|
|
||||||
</label>
|
|
||||||
<f:if condition="{destination.regions}">
|
|
||||||
<ul class="py-2 space-y-1">
|
|
||||||
<f:for each="{destination.regions}" as="region">
|
|
||||||
<li>
|
|
||||||
<label class="flex items-start">
|
|
||||||
<f:form.checkbox class="w-5 h-5 border-ep-primary ring-0 bg-transparent focus:ring-0 focus:border-none text-ep-primary"
|
|
||||||
property="regionUids"
|
|
||||||
data="{action: 'search#filter'}"
|
|
||||||
value="{region.uid}"/>
|
|
||||||
<span class="leading-none pl-2">
|
|
||||||
{region.label}
|
|
||||||
</span>
|
|
||||||
</label>
|
|
||||||
</li>
|
|
||||||
</f:for>
|
|
||||||
</ul>
|
|
||||||
</f:if>
|
|
||||||
</li>
|
|
||||||
</f:for>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="py-2"
|
|
||||||
data-controller="collapse"
|
|
||||||
data-collapse-collapsed-value="{f:if(condition: '{filterSettings.priceRanges}', then: 'false', else: 'true')}">
|
|
||||||
<button type="button"
|
|
||||||
data-action="click->collapse#toggle"
|
|
||||||
class="flex items-center justify-between w-full">
|
|
||||||
<span class="uppercase font-bold">
|
|
||||||
Preis
|
|
||||||
</span>
|
|
||||||
<svg class="w-6 h-6 transform"
|
|
||||||
data-collapse-target="icon">
|
|
||||||
<use href="#icon-arrow-right"></use>
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
<div data-collapse-target="container">
|
|
||||||
<ul class="mb-0 p-0 pt-2 space-y-1">
|
|
||||||
<f:for each="{filterOptions.priceRanges}" as="range">
|
|
||||||
<li>
|
|
||||||
<label class="flex items-start">
|
|
||||||
<f:form.checkbox class="w-5 h-5 border-ep-primary ring-0 bg-transparent focus:ring-0 focus:border-none text-ep-primary"
|
|
||||||
property="priceRanges"
|
|
||||||
data="{action: 'search#filter'}"
|
|
||||||
value="{range.uid}"/>
|
|
||||||
<span class="leading-none pl-2">
|
|
||||||
{ep:priceRange(min: range.min, max: range.max)}
|
|
||||||
</span>
|
|
||||||
</label>
|
|
||||||
</li>
|
|
||||||
</f:for>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="py-2"
|
|
||||||
data-controller="collapse"
|
|
||||||
data-collapse-collapsed-value="{f:if(condition: '{filterSettings.pax} > 1', then: 'false', else: 'true')}">
|
|
||||||
<button type="button"
|
|
||||||
data-action="click->collapse#toggle"
|
|
||||||
class="flex items-center justify-between w-full">
|
|
||||||
<span class="uppercase font-bold">
|
|
||||||
Personen
|
|
||||||
</span>
|
|
||||||
<svg class="w-6 h-6 transform"
|
|
||||||
data-collapse-target="icon">
|
|
||||||
<use href="#icon-arrow-right"></use>
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
<div data-collapse-target="container">
|
|
||||||
<f:form.select class="w-full border-0 focus:ring-0 bg-right mt-2 p-0"
|
|
||||||
property="pax"
|
|
||||||
options="{filterOptions.pax}"
|
|
||||||
data="{action: 'search#filter'}"/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<f:variable name="hotelTypes" value="{
|
|
||||||
1: 'Ferienwohnung',
|
|
||||||
2: 'Sportclub',
|
|
||||||
3: 'Appartment',
|
|
||||||
4: 'Gästehaus',
|
|
||||||
5: 'Pension'
|
|
||||||
}"/>
|
|
||||||
<div class="py-2"
|
|
||||||
data-controller="collapse"
|
|
||||||
data-collapse-collapsed-value="{f:if(condition: '{filterSettings.hotelTypes}', then: 'false', else: 'true')}">
|
|
||||||
<button type="button"
|
|
||||||
data-action="click->collapse#toggle"
|
|
||||||
class="flex items-center justify-between w-full">
|
|
||||||
<span class="uppercase font-bold">
|
|
||||||
Unterkunft
|
|
||||||
</span>
|
|
||||||
<svg class="w-6 h-6 transform"
|
|
||||||
data-collapse-target="icon">
|
|
||||||
<use href="#icon-arrow-right"></use>
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
<div data-collapse-target="container">
|
|
||||||
<ul class="mb-0 p-0 pt-2 space-y-1">
|
|
||||||
<f:for each="{filterOptions.hotelTypes}" as="type">
|
|
||||||
<li>
|
|
||||||
<label class="flex items-start">
|
|
||||||
<f:form.checkbox class="w-5 h-5 border-ep-primary ring-0 bg-transparent focus:ring-0 focus:border-none text-ep-primary"
|
|
||||||
property="hotelTypes"
|
|
||||||
data="{action: 'search#filter'}"
|
|
||||||
value="{type}"/>
|
|
||||||
<span class="leading-none pl-2">
|
|
||||||
{hotelTypes.{type}}
|
|
||||||
</span>
|
|
||||||
</label>
|
|
||||||
</li>
|
|
||||||
</f:for>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="py-2"
|
|
||||||
data-controller="collapse"
|
|
||||||
data-collapse-collapsed-value="{f:if(condition: '{filterSettings.boardTypes}', then: 'false', else: 'true')}">
|
|
||||||
<button type="button"
|
|
||||||
data-action="click->collapse#toggle"
|
|
||||||
class="flex items-center justify-between w-full">
|
|
||||||
<span class="uppercase font-bold">
|
|
||||||
Verpflegung
|
|
||||||
</span>
|
|
||||||
<svg class="w-6 h-6 transform"
|
|
||||||
data-collapse-target="icon">
|
|
||||||
<use href="#icon-arrow-right"></use>
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
<div data-collapse-target="container">
|
|
||||||
<ul class="mb-0 p-0 pt-2 space-y-1">
|
|
||||||
<f:for each="{filterOptions.boardTypes}" as="type">
|
|
||||||
<f:if condition="{type.label}">
|
|
||||||
<li>
|
|
||||||
<label class="flex items-start">
|
|
||||||
<f:form.checkbox class="w-5 h-5 border-ep-primary ring-0 bg-transparent focus:ring-0 focus:border-none text-ep-primary"
|
|
||||||
property="boardTypes"
|
|
||||||
data="{action: 'search#filter'}"
|
|
||||||
value="{type.uid}"/>
|
|
||||||
<span class="pl-2 leading-none">
|
|
||||||
{type.label}
|
|
||||||
</span>
|
|
||||||
</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="py-2"
|
|
||||||
data-controller="collapse"
|
|
||||||
data-collapse-collapsed-value="{f:if(condition: '{filterSettings.roomTypes}', then: 'false', else: 'true')}">
|
|
||||||
<button type="button"
|
|
||||||
data-action="click->collapse#toggle"
|
|
||||||
class="flex items-center justify-between w-full">
|
|
||||||
<span class="uppercase font-bold">
|
|
||||||
Zimmerarten/Apart.
|
|
||||||
</span>
|
|
||||||
<svg class="w-6 h-6 transform"
|
|
||||||
data-collapse-target="icon">
|
|
||||||
<use href="#icon-arrow-right"></use>
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
<div data-collapse-target="container">
|
|
||||||
<ul class="mb-0 p-0 p-0 pt-2 space-y-1">
|
|
||||||
<f:for each="{filterOptions.roomTypes}" as="type">
|
|
||||||
<li>
|
|
||||||
<label class="flex items-start">
|
|
||||||
<f:form.checkbox class="w-5 h-5 border-ep-primary ring-0 bg-transparent focus:ring-0 focus:border-none text-ep-primary"
|
|
||||||
property="roomTypes"
|
|
||||||
data="{action: 'search#filter'}"
|
|
||||||
value="{type}"/>
|
|
||||||
<span class="leading-none pl-2">
|
|
||||||
{roomTypes.{type}}
|
|
||||||
</span>
|
|
||||||
</label>
|
|
||||||
</li>
|
|
||||||
</f:for>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<f:if condition="{filterOptions.busAvailable}">
|
|
||||||
<div class="py-2"
|
|
||||||
data-controller="collapse"
|
|
||||||
data-collapse-collapsed-value="{f:if(condition: filterSettings.bus, then: 'false', else: 'true')}">
|
|
||||||
<button type="button"
|
|
||||||
data-action="click->collapse#toggle"
|
|
||||||
class="flex items-center justify-between w-full">
|
|
||||||
<span class="uppercase font-bold">
|
|
||||||
Anreise
|
|
||||||
</span>
|
|
||||||
<svg class="w-6 h-6 transform"
|
|
||||||
data-collapse-target="icon">
|
|
||||||
<use href="#icon-arrow-right"></use>
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
<div data-collapse-target="container">
|
|
||||||
<ul class="mb-0 p-0 pt-2 space-y-1">
|
|
||||||
<li>
|
|
||||||
<label class="flex items-start">
|
|
||||||
<f:form.checkbox class="w-5 h-5 border-ep-primary ring-0 bg-transparent focus:ring-0 focus:border-none text-ep-primary"
|
|
||||||
property="bus"
|
|
||||||
data="{action: 'search#filter'}"
|
|
||||||
value="1"/>
|
|
||||||
<span class="leading-none pl-2">
|
|
||||||
Busanreise
|
|
||||||
</span>
|
|
||||||
</label>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</f:if>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</f:form>
|
<f:variable name="hotelTypes" value="{
|
||||||
|
1: 'Ferienwohnung',
|
||||||
|
2: 'Sportclub',
|
||||||
|
3: 'Appartment',
|
||||||
|
4: 'Gästehaus',
|
||||||
|
5: 'Pension'
|
||||||
|
}"/>
|
||||||
|
<div class="py-2"
|
||||||
|
data-controller="collapse"
|
||||||
|
data-collapse-collapsed-value="{f:if(condition: '{filterSettings.hotelTypes}', then: 'false', else: 'true')}">
|
||||||
|
<button type="button"
|
||||||
|
data-action="click->collapse#toggle"
|
||||||
|
class="flex items-center justify-between w-full">
|
||||||
|
<span class="uppercase font-bold">
|
||||||
|
Unterkunft
|
||||||
|
</span>
|
||||||
|
<svg class="w-6 h-6 transform"
|
||||||
|
data-collapse-target="icon">
|
||||||
|
<use href="#icon-arrow-right"></use>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<div data-collapse-target="container">
|
||||||
|
<ul class="mb-0 p-0 pt-2 space-y-1">
|
||||||
|
<f:for each="{filterOptions.hotelTypes}" as="type">
|
||||||
|
<li>
|
||||||
|
<label class="flex items-start">
|
||||||
|
<f:form.checkbox class="w-5 h-5 border-ep-primary ring-0 bg-transparent focus:ring-0 focus:border-none text-ep-primary"
|
||||||
|
property="hotelTypes"
|
||||||
|
data="{action: 'search#filter mobile-search#filter'}"
|
||||||
|
value="{type}"/>
|
||||||
|
<span class="leading-none pl-2">
|
||||||
|
{hotelTypes.{type}}
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
</f:for>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="py-2"
|
||||||
|
data-controller="collapse"
|
||||||
|
data-collapse-collapsed-value="{f:if(condition: '{filterSettings.boardTypes}', then: 'false', else: 'true')}">
|
||||||
|
<button type="button"
|
||||||
|
data-action="click->collapse#toggle"
|
||||||
|
class="flex items-center justify-between w-full">
|
||||||
|
<span class="uppercase font-bold">
|
||||||
|
Verpflegung
|
||||||
|
</span>
|
||||||
|
<svg class="w-6 h-6 transform"
|
||||||
|
data-collapse-target="icon">
|
||||||
|
<use href="#icon-arrow-right"></use>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<div data-collapse-target="container">
|
||||||
|
<ul class="mb-0 p-0 pt-2 space-y-1">
|
||||||
|
<f:for each="{filterOptions.boardTypes}" as="type">
|
||||||
|
<f:if condition="{type.label}">
|
||||||
|
<li>
|
||||||
|
<label class="flex items-start">
|
||||||
|
<f:form.checkbox class="w-5 h-5 border-ep-primary ring-0 bg-transparent focus:ring-0 focus:border-none text-ep-primary"
|
||||||
|
property="boardTypes"
|
||||||
|
data="{action: 'search#filter mobile-search#filter'}"
|
||||||
|
value="{type.uid}"/>
|
||||||
|
<span class="pl-2 leading-none">
|
||||||
|
{type.label}
|
||||||
|
</span>
|
||||||
|
</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="py-2"
|
||||||
|
data-controller="collapse"
|
||||||
|
data-collapse-collapsed-value="{f:if(condition: '{filterSettings.roomTypes}', then: 'false', else: 'true')}">
|
||||||
|
<button type="button"
|
||||||
|
data-action="click->collapse#toggle"
|
||||||
|
class="flex items-center justify-between w-full">
|
||||||
|
<span class="uppercase font-bold">
|
||||||
|
Zimmerarten/Apart.
|
||||||
|
</span>
|
||||||
|
<svg class="w-6 h-6 transform"
|
||||||
|
data-collapse-target="icon">
|
||||||
|
<use href="#icon-arrow-right"></use>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<div data-collapse-target="container">
|
||||||
|
<ul class="mb-0 p-0 p-0 pt-2 space-y-1">
|
||||||
|
<f:for each="{filterOptions.roomTypes}" as="type">
|
||||||
|
<li>
|
||||||
|
<label class="flex items-start">
|
||||||
|
<f:form.checkbox class="w-5 h-5 border-ep-primary ring-0 bg-transparent focus:ring-0 focus:border-none text-ep-primary"
|
||||||
|
property="roomTypes"
|
||||||
|
data="{action: 'search#filter mobile-search#filter'}"
|
||||||
|
value="{type}"/>
|
||||||
|
<span class="leading-none pl-2">
|
||||||
|
{roomTypes.{type}}
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
</f:for>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<f:if condition="{filterOptions.busAvailable}">
|
||||||
|
<div class="py-2"
|
||||||
|
data-controller="collapse"
|
||||||
|
data-collapse-collapsed-value="{f:if(condition: filterSettings.bus, then: 'false', else: 'true')}">
|
||||||
|
<button type="button"
|
||||||
|
data-action="click->collapse#toggle"
|
||||||
|
class="flex items-center justify-between w-full">
|
||||||
|
<span class="uppercase font-bold">
|
||||||
|
Anreise
|
||||||
|
</span>
|
||||||
|
<svg class="w-6 h-6 transform"
|
||||||
|
data-collapse-target="icon">
|
||||||
|
<use href="#icon-arrow-right"></use>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<div data-collapse-target="container">
|
||||||
|
<ul class="mb-0 p-0 pt-2 space-y-1">
|
||||||
|
<li>
|
||||||
|
<label class="flex items-start">
|
||||||
|
<f:form.checkbox class="w-5 h-5 border-ep-primary ring-0 bg-transparent focus:ring-0 focus:border-none text-ep-primary"
|
||||||
|
property="bus"
|
||||||
|
data="{action: 'search#filter mobile-search#filter'}"
|
||||||
|
value="1"/>
|
||||||
|
<span class="leading-none pl-2">
|
||||||
|
Busanreise
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</f:if>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -3,15 +3,17 @@
|
|||||||
xmlns:f="http://typo3.org/ns/fluid/ViewHelpers">
|
xmlns:f="http://typo3.org/ns/fluid/ViewHelpers">
|
||||||
|
|
||||||
<div class="grid grid-cols-3 gap-8">
|
<div class="grid grid-cols-3 gap-8">
|
||||||
<div class="col-span-3 lg:col-span-1 relative"
|
<div class="col-span-3 lg:col-span-1 relative">
|
||||||
data-controller="collapse"
|
<div class="hidden lg:block bg-white p-4">
|
||||||
data-collapse-until-value="1024">
|
|
||||||
<div class="lg:block bg-white p-4"
|
|
||||||
data-collapse-target="container">
|
|
||||||
<h3 class="headline headline--underlined mb-4">
|
<h3 class="headline headline--underlined mb-4">
|
||||||
Filter
|
Filter
|
||||||
</h3>
|
</h3>
|
||||||
<f:render partial="Search/FilterPanel" arguments="{_all}"/>
|
<f:form object="{filterSettings}"
|
||||||
|
name="filterSettings"
|
||||||
|
pluginName="Ajax"
|
||||||
|
data="{'search-target': 'form'}">
|
||||||
|
<f:render partial="Search/FilterPanel" arguments="{_all}"/>
|
||||||
|
</f:form>
|
||||||
<div class="mt-4">
|
<div class="mt-4">
|
||||||
<button type="button"
|
<button type="button"
|
||||||
class="button button--secondary w-full"
|
class="button button--secondary w-full"
|
||||||
@@ -20,6 +22,38 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="fixed lg:hidden top-0 left-0 inset-0 w-screen h-screen pt-14 pb-10 z-50 bg-gray-700 hidden"
|
||||||
|
data-controller="mobile-search"
|
||||||
|
data-mobile-search-options-uri-value="{ep:uri.ajax(controller: 'AjaxFilterPanel', action: 'options', pageUid: settings.defaultAjaxUid, arguments: '{filterSettings: filterSettings}', format: 'html')}"
|
||||||
|
data-action="overlay-toggle:toggle@window->mobile-search#open">
|
||||||
|
<div class="fixed top-0 left-0 z-100 inset-x-0 px-4 py-2 flex justify-between bg-white shadow-md">
|
||||||
|
<a href="{f:uri.typolink(parameter: settings.defaultHomeUid)}"
|
||||||
|
class="block lg:pb-4"
|
||||||
|
title="{settings.defaultTitle}">
|
||||||
|
<img class="block h-10 lg:h-12 w-auto" src="{f:uri.image(src: settings.logoImage)}" alt="{settings.defaultTitle}">
|
||||||
|
</a>
|
||||||
|
<button type="button"
|
||||||
|
class="focus:outline-none" data-action="mobile-search#close">
|
||||||
|
<svg class="w-8 h-8">
|
||||||
|
<use href="#icon-close"></use>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div data-mobile-search-target="container"
|
||||||
|
class="h-full w-full overflow-y-scroll p-4 bg-white">
|
||||||
|
</div>
|
||||||
|
<div class="fixed top-0 left-0 z-20 w-full h-full hidden"
|
||||||
|
data-mobile-search-target="loadingIndicator">
|
||||||
|
<div class="absolute top-1/2 left-1/2 transform -translate-xy-1/2 flex items-center space-x-4 bg-ep-secondary text-white text-lg p-4 rounded">
|
||||||
|
<svg class="w-6 h-6">
|
||||||
|
<use href="#icon-spinner"></use>
|
||||||
|
</svg>
|
||||||
|
<span>Suche wird geladen...</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col-span-3 lg:col-span-2 relative">
|
<div class="col-span-3 lg:col-span-2 relative">
|
||||||
<f:render partial="Search/Result" arguments="{_all}"/>
|
<f:render partial="Search/Result" arguments="{_all}"/>
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
<html xmlns="http://www.w3.org/1999/xhtml" lang="en"
|
||||||
|
xmlns:f="http://typo3.org/ns/fluid/ViewHelpers"
|
||||||
|
xmlns:ep="http://typo3.org/ns/EP/EpTheme/ViewHelpers">
|
||||||
|
|
||||||
|
<div class="fixed lg:hidden top-0 left-0 inset-0 w-screen h-screen pt-14 pb-10 z-50 bg-gray-700 hidden"
|
||||||
|
data-controller="mobile-search"
|
||||||
|
data-mobile-search-options-uri-value="{ep:uri.ajax(controller: 'AjaxFilterPanel', action: 'options', pageUid: settings.defaultAjaxUid, format: 'html')}"
|
||||||
|
data-mobile-search-search-uri-value="{ep:uri.ajax(controller: 'AjaxFilterPanel', action: 'search', pageUid: settings.defaultAjaxUid, format: 'json')}"
|
||||||
|
data-action="overlay-toggle:toggle@window->mobile-search#open">
|
||||||
|
<div class="fixed top-0 left-0 z-100 inset-x-0 px-4 py-2 flex justify-between bg-white shadow-md">
|
||||||
|
<a href="{f:uri.typolink(parameter: settings.defaultHomeUid)}"
|
||||||
|
class="block lg:pb-4"
|
||||||
|
title="{settings.defaultTitle}">
|
||||||
|
<img class="block h-10 lg:h-12 w-auto" src="{f:uri.image(src: settings.logoImage)}" alt="{settings.defaultTitle}">
|
||||||
|
</a>
|
||||||
|
<button type="button"
|
||||||
|
class="focus:outline-none" data-action="mobile-search#close">
|
||||||
|
<svg class="w-8 h-8">
|
||||||
|
<use href="#icon-close"></use>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div data-mobile-search-target="container"
|
||||||
|
class="h-full w-full overflow-y-scroll p-4 bg-white">
|
||||||
|
</div>
|
||||||
|
<div class="fixed top-0 left-0 z-20 w-full h-full hidden"
|
||||||
|
data-mobile-search-target="loadingIndicator">
|
||||||
|
<div class="absolute top-1/2 left-1/2 transform -translate-xy-1/2 flex items-center space-x-4 bg-ep-secondary text-white text-lg p-4 rounded">
|
||||||
|
<svg class="w-6 h-6">
|
||||||
|
<use href="#icon-spinner"></use>
|
||||||
|
</svg>
|
||||||
|
<span>Suche wird geladen...</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</html>
|
||||||
+23
-1
@@ -5,6 +5,28 @@
|
|||||||
|
|
||||||
<f:layout name="Default"/>
|
<f:layout name="Default"/>
|
||||||
|
|
||||||
<f:render partial="Search/FilterPanel" arguments="{_all}"/>
|
<f:section name="Main">
|
||||||
|
<f:form object="{filterSettings}"
|
||||||
|
name="filterSettings"
|
||||||
|
pluginName="Ajax"
|
||||||
|
action=""
|
||||||
|
data="{'mobile-search-target': 'form'}">
|
||||||
|
<f:render partial="Search/FilterPanel" arguments="{_all}"/>
|
||||||
|
</f:form>
|
||||||
|
<div class="mt-4">
|
||||||
|
<button type="button"
|
||||||
|
class="button button--primary w-full"
|
||||||
|
data-action="mobile-search#search">
|
||||||
|
Ergebnis anzeigen
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="mt-4">
|
||||||
|
<button type="button"
|
||||||
|
class="button button--secondary w-full"
|
||||||
|
data-action="mobile-search#reset">
|
||||||
|
Filter zurücksetzen
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</f:section>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -1,20 +0,0 @@
|
|||||||
<div xmlns="http://www.w3.org/1999/xhtml" lang="en"
|
|
||||||
xmlns:f="http://typo3.org/ns/fluid/ViewHelpers"
|
|
||||||
xmlns:ep="http://typo3.org/ns/EP/EpTheme/ViewHelpers">
|
|
||||||
|
|
||||||
<f:layout name="Form/Default"/>
|
|
||||||
|
|
||||||
<f:section name="Main">
|
|
||||||
<div class="relative form form--border"
|
|
||||||
data-controller="contactform">
|
|
||||||
<div data-contactform-target="container">
|
|
||||||
<f:render partial="ContactForm/Simple" arguments="{_all}"/>
|
|
||||||
</div>
|
|
||||||
<div class="hidden form__overlay"
|
|
||||||
data-contactform-target="loadingIndicator">
|
|
||||||
<img src="{f:uri.resource(path: 'images/ajax-loader-white.gif', extensionName: 'ep_theme')}" alt="Processing...">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</f:section>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="en"
|
|
||||||
xmlns:f="http://typo3.org/ns/fluid/ViewHelpers"
|
|
||||||
xmlns:ep="http://typo3.org/ns/EP/EpTheme/ViewHelpers">
|
|
||||||
|
|
||||||
<f:layout name="Default"/>
|
|
||||||
|
|
||||||
<f:section name="Main">
|
|
||||||
<div class="fixed lg:hidden top-0 left-0 inset-0 w-screen h-screen pt-14 pb-10 z-50 bg-gray-700 hidden"
|
|
||||||
data-controller="overlay-toggle"
|
|
||||||
data-overlay-toggle-id-value="search"
|
|
||||||
data-overlay-toggle-target="overlay"
|
|
||||||
data-action="overlay-toggle:toggle@window->overlay-toggle#toggle">
|
|
||||||
<div class="fixed top-0 left-0 z-100 inset-x-0 px-4 py-2 flex justify-between bg-white shadow-md">
|
|
||||||
<a href="{f:uri.typolink(parameter: settings.defaultHomeUid)}"
|
|
||||||
class="block lg:pb-4"
|
|
||||||
title="{settings.defaultTitle}">
|
|
||||||
<img class="block h-10 lg:h-12 w-auto" src="{f:uri.image(src: settings.logoImage)}" alt="{settings.defaultTitle}">
|
|
||||||
</a>
|
|
||||||
<button type="button"
|
|
||||||
class="focus:outline-none" data-action="overlay-toggle#invokeToggle">
|
|
||||||
<svg class="w-8 h-8">
|
|
||||||
<use href="#icon-close"></use>
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div class="h-full w-full overflow-y-scroll p-4">
|
|
||||||
<f:form action="processSearch" controller="Search" method="post" name="searchParams"
|
|
||||||
object="{searchParams}" pluginName="searchresult" extensionName="epproducts"
|
|
||||||
pageUid="{settings.defaultSearchPageUid}">
|
|
||||||
<f:form.hidden property="dateFrom" data="{'searchbar-target': 'dateFrom'}"/>
|
|
||||||
<f:form.hidden property="dateTo" data="{'searchbar-target': 'dateTo'}"/>
|
|
||||||
<f:form.hidden property="pax" data="{'searchbar-target': 'pax'}"/>
|
|
||||||
<f:form.hidden property="destinationUid" data="{'searchbar-target': 'destinationUid'}"/>
|
|
||||||
<f:form.hidden property="destinationType" data="{'searchbar-target': 'destinationType'}"/>
|
|
||||||
<f:form.hidden property="priceRange" data="{'searchbar-target': 'priceRange'}"/>
|
|
||||||
|
|
||||||
<label>Früheste Anreise</label>
|
|
||||||
<input
|
|
||||||
type="date"
|
|
||||||
class="border-gray-400 focus:border-gray-800">
|
|
||||||
|
|
||||||
<label>Späteste Abreise</label>
|
|
||||||
<input
|
|
||||||
type="date"
|
|
||||||
class="border-gray-400 focus:border-gray-800">
|
|
||||||
|
|
||||||
<label>Personen</label>
|
|
||||||
<input
|
|
||||||
type="number"
|
|
||||||
min="1"
|
|
||||||
max="20"
|
|
||||||
class="border-gray-400 focus:border-gray-800">
|
|
||||||
|
|
||||||
<div class="grid grid-cols-2 gap-4">
|
|
||||||
<button type="submit"
|
|
||||||
class="button">
|
|
||||||
Suchen
|
|
||||||
</button>
|
|
||||||
<button type="submit"
|
|
||||||
class="button button--secondary">
|
|
||||||
Detailsuche
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</f:form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</f:section>
|
|
||||||
|
|
||||||
</html>
|
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
<f:layout name="Default"/>
|
<f:layout name="Default"/>
|
||||||
|
|
||||||
<f:section name="Main">
|
<f:section name="Main">
|
||||||
<div class="py-8 bg-ep-primary-bg">
|
<div class="pb-8 md:py-8 bg-ep-primary-bg">
|
||||||
<div class="container"
|
<div class="container"
|
||||||
data-controller="search"
|
data-controller="search"
|
||||||
data-search-uri-value="{ep:uri.ajax(controller: 'AjaxSearch', action: 'searchresult', pageUid: settings.defaultAjaxUid, format: 'html')}"
|
data-search-uri-value="{ep:uri.ajax(controller: 'AjaxSearch', action: 'searchresult', pageUid: settings.defaultAjaxUid, format: 'html')}"
|
||||||
|
|||||||
Reference in New Issue
Block a user