Finalize new teaser layout

This commit is contained in:
Björn Fromme
2021-09-03 16:47:56 +02:00
parent f64da4a8f5
commit 4442b03dd9
7 changed files with 125 additions and 350 deletions
@@ -3,10 +3,22 @@
xmlns:f="http://typo3.org/ns/fluid/ViewHelpers">
<f:section name="Teaser">
<div class="relative">
<div class="absolute top-0 left-0 z-10 inset-x-0 flex justify-between items-center bg-ep-primary-80">
<div class="w-2/3 flex items-center">
<div class="bg-ep-primary p-2 mr-4 text-white">
<div class="flex flex-col h-full bg-white group{f:if(condition: landscape, then: ' sm:flex-row sm:h-auto')}">
<f:render section="TeaserImage" arguments="{_all}"/>
<f:render section="TeaserContent" arguments="{_all}"/>
</div>
</f:section>
<f:section name="TeaserImage">
<div class="relative{f:if(condition: landscape, then: ' sm:w-2/5')}">
<img class="block w-full h-full object-cover lazyload"
src="{f:uri.image(src: 'EXT:ep_theme/Resources/Public/images/lazy.png')}"
data-src="{f:uri.image(image: productImage, width: '640c', height: '480c')}"
alt="{product.name}"
width="640" height="480" />
<div class="absolute top-0 left-0 z-10 inset-x-0 flex justify-between items-center {f:if(condition: concept, then: 'bg-concept-{concept.code}', else: 'bg-ep-primary-80')}">
<div class="flex items-center">
<div class="p-2 mr-4 text-white {f:if(condition: concept, else: 'bg-ep-primary-80')}">
<f:alias map="{ icons: { bik: 'Mountainbike', akt: 'Walking', prg: 'Sportclub' } }">
<svg class="product-teaser__icon text-white">
<use href="#icon-{icons.{concept.code} -> f:format.case(mode: 'lower')}"></use>
@@ -29,25 +41,13 @@
<svg class="w-6 h-6 text-white" data-watchlist-toggle-target="icon" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z"></path></svg>
</button>
</div>
<a href="{ep:uri.product(forceHotelUid: forceHotelUid, product: product, hotel: hotel, dateFrom: dateFrom, dateTo: dateTo)}"
title="{region.name} {product.name} Details und Buchen"
class="flex flex-col h-full bg-white">
<f:render section="TeaserImage" arguments="{_all}"/>
<f:render section="TeaserContent" arguments="{_all}"/>
</a>
</div>
</f:section>
<f:section name="TeaserImage">
<img class="block w-full h-auto lazyload"
src="{f:uri.image(src: 'EXT:ep_theme/Resources/Public/images/lazy.png')}"
data-src="{f:uri.image(image: productImage, width: '640c', height: '480c')}"
alt="{product.name}"
width="640" height="480" />
</f:section>
<f:section name="TeaserContent">
<div class="flex-1 flex flex-col space-y-1 px-2 py-4 md:p-4">
<a href="{ep:uri.product(forceHotelUid: forceHotelUid, product: product, hotel: hotel, dateFrom: dateFrom, dateTo: dateTo)}"
title="{region.name} {product.name} Details und Buchen"
class="flex-1 flex flex-col space-y-1 px-2 py-4 md:p-4">
<div class="text-gray-800 leading-none pl-8 md:pl-10">
{product.name}
</div>
@@ -91,7 +91,7 @@
</f:if>
</ul>
<div class="pt-8 pl-8 md:pl-10">
<div class="bg-ep-primary text-white font-bold px-4 py-1">
<div class="bg-ep-primary text-white font-bold px-4 py-1 group-hover:bg-ep-secondary transition-colors">
<div class="lg:inline-block">
ab <span class="text-xl md:text-3xl mx-1">{minPrice} €</span>
</div>
@@ -100,7 +100,7 @@
</div>
</div>
</div>
</div>
</a>
</f:section>
</html>
@@ -1,131 +0,0 @@
<html data-namespace-typo3-fluid="true" lang="en"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:v="http://typo3.org/ns/FluidTYPO3/Vhs/ViewHelpers"
xmlns:ep="http://typo3.org/ns/EP/EpTheme/ViewHelpers"
xmlns:f="http://typo3.org/ns/fluid/ViewHelpers">
<f:section name="Teaser">
{ep:uri.product(forceHotelUid: teaser.forceHotelUid, product: teaser.product, hotel: teaser.hotel, dateFrom: dateFrom, dateTo: dateTo, slug: slug) -> f:variable(name: 'teaserUrl')}
<f:render section="Inner" arguments="{_all}"/>
</f:section>
<f:section name="Inner">
<div class="teaserbox teaserbox--landscape teaserbox--product col-xs-12">
<div class="teaserbox__image">
<img class="teaserbox__flag"
src="{teaser.country.flag}"
alt="{teaser.country.name}"/>
<a href="{teaserUrl}" title="{teaser.product.name}">
<f:render section="Image" arguments="{_all}"/>
</a>
<f:if condition="{teaser.concept.code}">
<div class="concept-badge concept-badge--{teaser.concept.code}">{teaser.concept.name}</div>
</f:if>
</div>
<div class="teaserbox__main">
<div class="teaserbox__header">
<span class="subline searchresult-item__headline">
{teaser.region.name}<f:if condition="{teaser.concept.code} == 'evt'"><strong> | {teaser.product.name}</strong></f:if>
</span>
<f:if condition="{teaser.hotelCount} == 1">
<span class="searchresult-item__subline">{teaser.hotel.name}</span>
<f:if condition="{teaser.hotel.category}">
<span class="searchresult-item__category">Kategorie {teaser.hotel.category}</span>
</f:if>
</f:if>
<f:if condition="{teaser.hotelCount} > 1">
<span class="searchresult-item__subline">Verschiedene Unterkünfte</span>
<span class="searchresult-item__category"><strong>Kategorie</strong> {ep:hotelCategories(categories: teaser.hotelCategories)}</span>
</f:if>
</div>
<ul class="check-list searchresult-item__checklist">
<f:if condition="{teaser.hotelCount} == 1">
<f:if condition="{teaser.hotel.fact}">
<li>{teaser.hotel.fact}</li>
</f:if>
</f:if>
<f:if condition="{teaser.product.fact}">
<li>{teaser.product.fact}</li>
</f:if>
<f:if condition="{teaser.region.feature}">
<f:then>
<li>{teaser.region.feature}</li>
</f:then>
<f:else>
<f:if condition="{teaser.region.fact}">
<li>{teaser.region.fact}</li>
</f:if>
</f:else>
</f:if>
</ul>
<ul class="check-list check-list--inverted searchresult-item__featurelist">
<li>{f:if(condition: '{teaser.season} == "s"', then: 'Bergbahnticket', else: 'Skipass')}</li>
<f:if condition="{teaser.board}">
<li>{teaser.board}</li>
</f:if>
<f:if condition="{teaser.product.feature}">
<li>{teaser.product.feature}</li>
</f:if>
</ul>
</div>
<div class="teaserbox__aside">
<div class="teaserbox__aside__top">
<span class="searchresult-item__label">{f:if(condition: '{teaser.dates -> f:count()} > 1', then: 'Zeitraum', else: 'Termin')}</span>
<span class="searchresult-item__daterange">{ep:dateRange(dateFrom: teaser.minDateStart, dateTo: teaser.maxDateEnd, includeLabel: 0)}</span>
<f:if condition="{teaser.dates -> f:count()} > 1 && !{teaser.daytrip}">
<a href="{teaserUrl}" title="Alle Termine {teaser.product.name}">
<span class="searchresult-item__daterange">
<i class="fa fa-arrow-circle-right"></i> {teaser.dates -> f:count()} Termin{f:if(condition: '{teaser.dates -> f:count()} > 1', then: 'e')}
</span>
</a>
</f:if>
<hr>
<span class="searchresult-item__label">{ep:nightsOptions(options: teaser.nights, daytrip: teaser.daytrip)}</span>
</div>
<div class="teaserbox__aside__bottom">
<span class="searchresult-item__price">ab {teaser.minPrice} €{f:if(condition: teaser.pseudoPrice, then: ' <s class="searchresult-item__pseudo-price">{teaser.pseudoPrice} €</s>')}</span>
<a href="{teaserUrl}" title="{teaser.product.name}" class="button button--full searchresult-item__button">
<f:if condition="{teaser.hideBookingButton}">
<f:then>{f:translate(key: 'tx_eptheme.label.teaserbutton.product_no_booking', extensionName: 'ep_theme')}</f:then>
<f:else>{f:translate(key: 'tx_eptheme.label.teaserbutton.product', extensionName: 'ep_theme')}</f:else>
</f:if>
</a>
</div>
</div>
<button type="button"
class="px-2"
data-controller="watchlist-toggle"
data-watchlist-toggle-key-value="{teaser.hotel.uid}:{teaser.product.uid}"
data-watchlist-toggle-target="ariaLabel"
data-action="watchlist-toggle#toggle"
data-cooltipz-dir="top-right"
aria-label="auf die Merkliste setzen"
role="tooltip">
<svg class="w-6 h-6 text-white" data-watchlist-toggle-target="icon" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z"></path></svg>
</button>
</div>
</f:section>
<f:section name="Image">
<f:if condition="{teaser.hotelCount} > 1">
<f:then>
<f:render section="PictureTag" arguments="{image: teaser.product.images.original.0}"/>
</f:then>
<f:else>
<f:render section="PictureTag" arguments="{image: teaser.hotel.images.original.0}"/>
</f:else>
</f:if>
</f:section>
<f:section name="PictureTag">
<f:if condition="{image}">
<picture class="searchresult-item__image">
<img class="scale lazyload" title="{image.title}" alt="{image.alternative}"
src="{f:uri.image(src: 'EXT:ep_theme/Resources/Public/images/lazy.png', width: '640')}"
data-src="{f:uri.image(image: image, width: '640')}"
>
</picture>
</f:if>
</f:section>
</html>
@@ -19,139 +19,38 @@
</f:else>
</f:if>
</div>
<div class="searchresult__content">
<f:if condition="{referringPageUri}">
<f:variable name="referrer" value="{referringPageUri}"/>
</f:if>
<f:for each="{searchResult}" as="section">
<div id="concept-{section.concept.uid}">
<h2 class="headline headline--secondary headline--underlined">
{section.concept.name}
</h2>
<div class="searchresult-section searchresult-section--{section.concept.code}">
<f:for each="{section.items}" as="item">
<div class="teaserbox teaserbox--landscape teaserbox--searchresult searchresult-item">
<div class="teaserbox__image">
<img src="{item.country.flag}" class="teaserbox__flag" alt="{item.country.name}"/>
<f:link.action action="detail" controller="Product" extensionName="epproducts" pluginName="product_detail"
arguments="{product: item.product.uid, hotel: item.hotel.uid}"
additionalParams="{ref: referrer}"
pageUid="{item.product.detailPage}" absolute="1"
rel="nofollow" title="Details &amp; Buchen">
<picture class="searchresult-item__image">
<source media="(min-width: 1201px)" data-srcset="{item.hotel.images.resized.m.0.url} 260w"/>
<source media="(max-width: 1200px)" data-srcset="{item.hotel.images.resized.l.0.url} 280w"/>
<source media="(max-width: 768px)" data-srcset="{item.hotel.images.resized.s.0.url} 220w"/>
<img class="scale lazyload" data-src="{item.hotel.images.resized.s[0].url}"
title="{item.hotel.images.resized.s.0.title}"
alt="{item.hotel.images.resized.s.0.alt}">
</picture>
</f:link.action>
<div class="concept-badge concept-badge--{section.concept.code}"
id="{section.concept.code}">
{section.concept.name}
</div>
</div>
<div class="teaserbox__main">
<div class="teaserbox__header">
<span class="searchresult-item__headline">
{item.region.name}
<f:if condition="{section.concept.code} == 'evt'">
<strong>
<span class="block">
{item.product.name}
</span>
</strong>
</f:if>
</span>
<span class="searchresult-item__subline">
{item.hotel.name}
</span>
<f:if condition="{item.hotel.category}">
<span class="searchresult-item__category">
Kategorie {item.hotel.category}
</span>
</f:if>
</div>
<ul class="check-list searchresult-item__checklist">
<f:if condition="{item.hotel.fact}">
<li>{item.hotel.fact}</li>
</f:if>
<f:if condition="{item.product.fact}">
<li>{item.product.fact}</li>
</f:if>
<f:if condition="{item.region.feature}">
<f:then>
<li>{item.region.feature}</li>
</f:then>
<f:else>
<f:if condition="{item.region.fact}">
<li>{item.region.fact}</li>
</f:if>
</f:else>
</f:if>
</ul>
<ul class="check-list check-list--inverted searchresult-item__featurelist">
<li>Skipass</li>
<f:if condition="{item.board}">
<li>{item.board}</li>
</f:if>
<f:if condition="{item.product.feature}">
<li>{item.product.feature}</li>
</f:if>
</ul>
</div>
<div class="teaserbox__aside">
<div class="teaserbox__aside__top">
<span class="searchresult-item__label">
{f:if(condition: '{item.dates -> f:count()} > 1', then: 'Zeitraum', else: 'Termin')}
</span>
<span class="searchresult-item__daterange">
{ep:dateRange(dateFrom: item.minDateStart, dateTo: item.maxDateEnd, includeLabel: 0)}
</span>
<f:if condition="{item.dates -> f:count()} > 0">
<f:if condition="{item.daytrip}">
<f:else>
<f:link.action action="detail" controller="Product" extensionName="epproducts" pluginName="product_detail"
arguments="{product: item.product.uid, hotel: item.hotel.uid}"
additionalParams="{ref: referrer}"
pageUid="{item.product.detailPage}" absolute="1"
rel="nofollow" title="Details &amp; Buchen">
<span class="searchresult-item__daterange">
<i class="fa fa-arrow-circle-right"></i> {item.dates -> f:count()} {f:if(condition: '{item.dates -> f:count()} > 1', then: 'Termine', else: 'Termin')}
</span>
</f:link.action>
</f:else>
</f:if>
</f:if>
<hr>
<span class="searchresult-item__label">
{f:if(condition: item.daytrip, then: 'Tageweise buchbar', else: '{ep:nightsOptions(options: item.nights, daytrip: item.daytrip)}')}
</span>
</div>
<div class="teaserbox__aside__bottom">
<span class="searchresult-item__price">ab {item.minPrice} €</span>
<f:link.action action="detail" controller="Product" extensionName="epproducts" pluginName="product_detail"
arguments="{product: item.product.uid, hotel: item.hotel.uid}"
additionalParams="{ref: referrer}"
pageUid="{item.product.detailPage}" absolute="1"
rel="nofollow" title="Details &amp; Buchen"
class="button w-full">
Details{f:if(condition: item.hideBookingButton, else: ' &amp; Buchen')}
</f:link.action>
</div>
</div>
<button class="teaserbox-watchlist"
data-controller="watchlist-toggle"
data-watchlist-toggle-key-value="{item.key}"
data-action="watchlist-toggle#toggle">
<svg class="w-5 h-5 text-ep-secondary" data-watchlist-toggle-target="icon" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z"></path></svg>
</button>
</div>
</f:for>
</div>
<f:if condition="{referringPageUri}">
<f:variable name="referrer" value="{referringPageUri}"/>
</f:if>
<f:for each="{searchResult}" as="section">
<div id="concept-{section.concept.uid}">
<h2 class="headline headline--secondary headline--underlined">
{section.concept.name}
</h2>
<div class="flex flex-col space-y-4 md:space-y-8 mb-8">
<f:for each="{section.items}" as="item">
<f:render partial="Product/Teaser" section="Teaser" arguments="{
concept: section.concept,
hotel: item.hotel,
product: item.product,
country: item.country,
region: item.region,
productImage: item.hotel.images.original.0,
nights: item.nights,
board: item.board,
minPrice: item.minPrice,
daytrip: product.daytrip,
season: product.season,
dateFrom: item.minDateStart,
dateTo: item.maxDateEnd,
forceHotelUid: 1,
landscape: 1
}"/>
</f:for>
</div>
</f:for>
</div>
</div>
</f:for>
</html>
@@ -8,10 +8,10 @@
<f:if condition="{teaser.dates}">
<f:switch expression="{data.layout}">
<f:case value="2">
{f:variable(name: 'partial', value: 'Product/TeaserWide')}
{f:variable(name: 'partial', value: 'Product/TeaserLandscape')}
</f:case>
<f:case value="3">
{f:variable(name: 'partial', value: 'Product/TeaserWide')}
{f:variable(name: 'partial', value: 'Product/TeaserLandscape')}
</f:case>
<f:defaultCase>
{f:variable(name: 'partial', value: 'Product/Teaser')}
@@ -10,10 +10,10 @@
<f:if condition="{teaser.dates}">
<f:switch expression="{data.layout}">
<f:case value="2">
{v:variable.set(name: 'partial', value: 'Product/TeaserWide')}
{v:variable.set(name: 'partial', value: 'Product/TeaserLandscape')}
</f:case>
<f:case value="3">
{v:variable.set(name: 'partial', value: 'Product/TeaserWide')}
{v:variable.set(name: 'partial', value: 'Product/TeaserLandscape')}
</f:case>
<f:defaultCase>
{v:variable.set(name: 'partial', value: 'Product/Teaser')}
@@ -6,58 +6,63 @@
<f:section name="Main">
<f:render partial="Product/HeaderDetail" arguments="{_all}"/>
<div class="container grid grid-cols-3 gap-8">
<div class="col-span-3 lg:col-span-2">
<div class="py-8 bg-ep-primary-10">
<div class="container">
<f:render partial="Header/Header" arguments="{layout: 8, subheader: product.name, header: product.headline}"/>
<div data-rte-content>
{product.teaserLong -> f:format.html()}
</div>
<div class="headerbar">
Wähle deine Unterkunft
</div>
<f:if condition="{hotels}">
<f:then>
<div class="grid grid-cols-2 gap-4 md:gap-8">
<f:for each="{hotels}" as="item">
<f:render partial="Product/Teaser" section="Teaser" arguments="{
concept: product.concept,
hotel: item.hotel,
product: product,
country: product.country,
region: product.region,
productImage: item.hotel.images.original.0,
nights: item.nights,
board: item.board,
minPrice: item.minPrice,
daytrip: product.daytrip,
season: product.season,
dateFrom: item.minDateStart,
dateTo: item.maxDateEnd,
forceHotelUid: 1
}"/>
</f:for>
</div>
</f:then>
<f:else>
<div class="alert alert-info">
Die von dir gewählte Reise ist aktuell nicht buchbar, aber wir helfen dir gerne dabei,
eine andere Reise zu finden. Ruf uns an unter <a href="tel:{settings.phoneNumber -> v:format.pregReplace(pattern: '/[\-\s]/', replacement: '')}" title="Service Telefon anrufen" rel="nofollow">{settings.phoneNumber}</a>
oder schreibe an <f:link.email email="[email protected]"/>.
</div>
</f:else>
</f:if>
</div>
<div class="col-span-3 lg:col-span-1">
<f:alias map="{region: product.region}">
<f:if condition="{region.winter}">
<f:render partial="Facts" arguments="{facts: region.facts, title: region.name}"/>
<f:render partial="Snowreport" arguments="{snowreport: region.snowreport}"/>
<f:render partial="Regioninfo" arguments="{region: region}"/>
<f:render partial="Region/Webcam" arguments="{region: region}"/>
<f:render partial="RegionMaps" arguments="{region: region}"/>
<f:render partial="RegionAward" arguments="{region: region}"/>
<div class="container grid grid-cols-3 gap-8">
<div class="col-span-3 lg:col-span-2">
<div data-rte-content>
{product.teaserLong -> f:format.html()}
</div>
<div class="headerbar">
Wähle deine Unterkunft
</div>
<f:if condition="{hotels}">
<f:then>
<div class="flex flex-col space-y-4 md:space-y-8">
<f:for each="{hotels}" as="item">
<f:render partial="Product/Teaser" section="Teaser" arguments="{
concept: product.concept,
hotel: item.hotel,
product: product,
country: product.country,
region: product.region,
productImage: item.hotel.images.original.0,
nights: item.nights,
board: item.board,
minPrice: item.minPrice,
daytrip: product.daytrip,
season: product.season,
dateFrom: item.minDateStart,
dateTo: item.maxDateEnd,
forceHotelUid: 1,
landscape: 1
}"/>
</f:for>
</div>
</f:then>
<f:else>
<div class="alert alert-info">
Die von dir gewählte Reise ist aktuell nicht buchbar, aber wir helfen dir gerne dabei,
eine andere Reise zu finden. Ruf uns an unter <a href="tel:{settings.phoneNumber -> v:format.pregReplace(pattern: '/[\-\s]/', replacement: '')}" title="Service Telefon anrufen" rel="nofollow">{settings.phoneNumber}</a>
oder schreibe an <f:link.email email="[email protected]"/>.
</div>
</f:else>
</f:if>
</f:alias>
</div>
<div class="col-span-3 lg:col-span-1">
<f:alias map="{region: product.region}">
<f:if condition="{region.winter}">
<f:render partial="Facts" arguments="{facts: region.facts, title: region.name}"/>
<f:render partial="Snowreport" arguments="{snowreport: region.snowreport}"/>
<f:render partial="Regioninfo" arguments="{region: region}"/>
<f:render partial="Region/Webcam" arguments="{region: region}"/>
<f:render partial="RegionMaps" arguments="{region: region}"/>
<f:render partial="RegionAward" arguments="{region: region}"/>
</f:if>
</f:alias>
</div>
</div>
</div>
</f:section>
@@ -6,18 +6,20 @@
<f:image src="{settings.searchPageHeaderImage}"
width="1366" height="160c+100"
class="block w-full h-auto -mt-16 mb-8"/>
<div class="container relative"
data-controller="search"
data-search-uri-value="{ep:uri.ajax(controller: 'AjaxSearch', action: 'searchresult', pageUid: settings.defaultAjaxUid, format: 'html')}"
data-action="datepicker:range-select->search#selectDateRange">
<div data-search-target="resultsContainer">
<f:render partial="Search/Main" arguments="{_all}"/>
</div>
<div class="absolute z-20 inset-0 w-full h-fill bg-overlay-white hidden"
data-search-target="loadingIndicator">
<div class="absolute mt-16 top-0 left-1/2 transform -translate-x-1/2 flex items-center space-x-4 alert alert-info">
<f:image src="EXT:ep_theme/Resources/Public/images/ajax-loader-white.gif" alt="Loading" />
<span>Suchergebnis wird geladen...</span>
<div class="py-8 bg-ep-primary-10">
<div class="container relative"
data-controller="search"
data-search-uri-value="{ep:uri.ajax(controller: 'AjaxSearch', action: 'searchresult', pageUid: settings.defaultAjaxUid, format: 'html')}"
data-action="datepicker:range-select->search#selectDateRange">
<div data-search-target="resultsContainer">
<f:render partial="Search/Main" arguments="{_all}"/>
</div>
<div class="absolute z-20 inset-0 w-full h-fill bg-overlay-white hidden"
data-search-target="loadingIndicator">
<div class="absolute mt-16 top-0 left-1/2 transform -translate-x-1/2 flex items-center space-x-4 alert alert-info">
<f:image src="EXT:ep_theme/Resources/Public/images/ajax-loader-white.gif" alt="Loading" />
<span>Suchergebnis wird geladen...</span>
</div>
</div>
</div>
</div>