Migrate groups price calculator
This commit is contained in:
@@ -9,7 +9,7 @@ page {
|
||||
bodyTagCObject = COA
|
||||
bodyTagCObject {
|
||||
10 = TEXT
|
||||
10.value = <body class="antialiased text-gray-800 font-sans pt-14 lg:pt-8
|
||||
10.value = <body class="antialiased text-gray-800 font-sans pt-14 lg:pt-8 bg-white
|
||||
20 = TEXT
|
||||
20 {
|
||||
field = tx_eptheme_bodyclass
|
||||
@@ -162,3 +162,9 @@ page {
|
||||
if.isTrue = {$plugin.tx_eptheme.settings.cookieFirstKey}
|
||||
}
|
||||
}
|
||||
|
||||
[page["backend_layout"] == 'pagets__popup']
|
||||
page.bodyTagCObject >
|
||||
page.bodyTagCObject = TEXT
|
||||
page.bodyTagCObject.value = <body class="antialiased text-gray-800 font-sans bg-white p-4">
|
||||
[end]
|
||||
|
||||
+171
-99
@@ -1,143 +1,209 @@
|
||||
<template>
|
||||
<div class="container relative">
|
||||
<div class="mb-4"
|
||||
<div class="relative">
|
||||
<div class="mb-8"
|
||||
v-show="!submitted">
|
||||
<label class="mb-2 font-bold">
|
||||
Zeitraum
|
||||
</label>
|
||||
<input type="text"
|
||||
class="border-gray-400 focus:border-gray-800 mt-1 w-full"
|
||||
class="form-field"
|
||||
placeholder="von... bis" ref="picker"/>
|
||||
</div>
|
||||
<div class="form-group" v-show="!submitted">
|
||||
<label>Personenzahl</label>
|
||||
<input type="number" class="form-control" v-model.number="selectedPax" @change="onPaxUpdated()"
|
||||
<div class="mb-8"
|
||||
v-show="!submitted">
|
||||
<label class="mb-2 font-bold">
|
||||
Personenzahl
|
||||
</label>
|
||||
<input type="number"
|
||||
class="form-field"
|
||||
v-model.number="selectedPax"
|
||||
@change="onPaxUpdated()"
|
||||
v-show="nightsCount > 0 && !includesBonusCard"/>
|
||||
<div class="flex space-x-4" v-show="nightsCount > 0 && includesBonusCard">
|
||||
<div class="w-1/3 flex flex-col space-y-1">
|
||||
<span>ab 15 Jahre</span>
|
||||
<input type="number" class="form-control" v-model.number="selectedPaxGroup3" @change="onPaxUpdated()"/>
|
||||
<input type="number"
|
||||
class="form-control"
|
||||
v-model.number="selectedPaxGroup3"
|
||||
@change="onPaxUpdated()"/>
|
||||
</div>
|
||||
<div class="w-1/3 flex flex-col space-y-1">
|
||||
<span>7-14 Jahre</span>
|
||||
<input type="number" class="form-control" v-model.number="selectedPaxGroup2" @change="onPaxUpdated()"/>
|
||||
<input type="number"
|
||||
class="form-control"
|
||||
v-model.number="selectedPaxGroup2"
|
||||
@change="onPaxUpdated()"/>
|
||||
</div>
|
||||
<div class="w-1/3 flex flex-col space-y-1">
|
||||
<span>4-6 Jahre</span>
|
||||
<input type="number" class="form-control" v-model.number="selectedPaxGroup1" @change="onPaxUpdated()"/>
|
||||
<input type="number"
|
||||
class="form-control"
|
||||
v-model.number="selectedPaxGroup1"
|
||||
@change="onPaxUpdated()"/>
|
||||
</div>
|
||||
</div>
|
||||
<p class="text-sm italic" v-show="nightsCount === 0">Bitte wählen Sie einen Zeitraum</p>
|
||||
<p class="text-sm italic"
|
||||
v-show="nightsCount === 0">
|
||||
Bitte zuerst einen Zeitraum wählen
|
||||
</p>
|
||||
</div>
|
||||
<div class="form-group" v-show="options.length > 0 && !submitted">
|
||||
<label>Optionale Zusatzleistungen</label>
|
||||
<div class="checkbox" v-for="option of options" :key="option.uid">
|
||||
<label>
|
||||
<input type="checkbox" v-model="selectedOptions" :value="option">
|
||||
<span class="cr"><i class="cr-icon glyphicon glyphicon-ok"></i></span>
|
||||
{{ option.title }}{{ formatOptionPriceType(option) }}
|
||||
</label>
|
||||
<div class="mb-8"
|
||||
v-show="options.length > 0 && !submitted">
|
||||
<div class="mb-2 font-bold">
|
||||
Optionale Zusatzleistungen
|
||||
</div>
|
||||
<ul class="mb-0 p-0 space-y-2">
|
||||
<li v-for="option of options" :key="option.uid">
|
||||
<label class="flex items-start">
|
||||
<input type="checkbox"
|
||||
class="w-5 h-5 border-ep-primary-light ring-0 bg-transparent focus:ring-0 focus:border-none text-ep-primary"
|
||||
v-model="selectedOptions"
|
||||
:value="option">
|
||||
<span class="pl-2 leading-none">{{ option.title }}{{ formatOptionPriceType(option) }}</span>
|
||||
</label>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="form-group" v-show="boards.length > 0 && !submitted">
|
||||
<label>Optionale Verpflegungsleistungen</label>
|
||||
<select class="form-control" v-model="selectedBoard" v-if="totalPax >= 30">
|
||||
<div class="mb-8"
|
||||
v-show="boards.length > 0 && !submitted">
|
||||
<label class="mb-2 font-bold">
|
||||
Optionale Verpflegungsleistungen
|
||||
</label>
|
||||
<select class="form-field"
|
||||
v-model="selectedBoard"
|
||||
v-if="totalPax >= 30">
|
||||
<option :value="null">Keine Auswahl</option>
|
||||
<option v-for="board of boards" :value="board" :key="board.uid">{{ board.title }}
|
||||
({{ formatCurrency(board.price) }} pro Person und Nacht)
|
||||
<option v-for="board of boards"
|
||||
:value="board"
|
||||
:key="board.uid">
|
||||
{{ board.title }} ({{ formatCurrency(board.price) }} pro Person und Nacht)
|
||||
</option>
|
||||
</select>
|
||||
<div v-show="totalPax < 30">
|
||||
<span class="label label-warning">Erst ab 30 Personen buchbar.</span>
|
||||
<span class="text-red-600">Erst ab 30 Personen buchbar.</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">Preise</div>
|
||||
<div class="panel-body">
|
||||
<table class="table table-striped" v-show="nightsCount > 0">
|
||||
<div class="mb-8">
|
||||
<div class="p-2 uppercase bg-ep-primary-dark text-white w-full">
|
||||
Preise
|
||||
</div>
|
||||
<div class="bg-gray-100 p-2">
|
||||
<table class="w-full" v-show="nightsCount > 0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>Zeitraum</th>
|
||||
<tr class="odd:bg-gray-100">
|
||||
<th class="text-left py-2">Zeitraum</th>
|
||||
<td>{{ rangeFormatted }}, {{ nightsCount }} Nächte</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Basispreis</th>
|
||||
<tr class="odd:bg-gray-100">
|
||||
<th class="text-left py-2">Basispreis</th>
|
||||
<td>{{ formatCurrency(pricePax.base) }}</td>
|
||||
</tr>
|
||||
<tr v-if="pricePax.additional > 0">
|
||||
<th>Aufpreis Personenzahl</th>
|
||||
<tr class="odd:bg-gray-100"
|
||||
v-if="pricePax.additional > 0">
|
||||
<th class="text-left py-2">Aufpreis Personenzahl</th>
|
||||
<td>{{ formatCurrency(pricePax.additional) }}</td>
|
||||
</tr>
|
||||
<tr v-if="priceShortTerm > 0">
|
||||
<th>Aufpreis Kurzzeit</th>
|
||||
<tr class="odd:bg-gray-100"
|
||||
v-if="priceShortTerm > 0">
|
||||
<th class="text-left py-2">Aufpreis Kurzzeit</th>
|
||||
<td>{{ formatCurrency(priceShortTerm) }}</td>
|
||||
</tr>
|
||||
<tr v-if="includesBonusCard">
|
||||
<th>Inklusivleistungen</th>
|
||||
<tr class="odd:bg-gray-100"
|
||||
v-if="includesBonusCard">
|
||||
<th class="text-left py-2">Inklusivleistungen</th>
|
||||
<td>
|
||||
<a href="https://www.saalbach.com/de/sommer/joker-card" target="_blank" class="uppercase">
|
||||
Joker Card
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-if="selectedOptions.length > 0">
|
||||
<th>Zusatzleistungen</th>
|
||||
<tr class="odd:bg-gray-100"
|
||||
v-if="selectedOptions.length > 0">
|
||||
<th class="text-left py-2">Zusatzleistungen</th>
|
||||
<td>{{ formatCurrency(priceOptions) }}</td>
|
||||
</tr>
|
||||
<tr v-if="priceBoard > 0">
|
||||
<th>Verpflegung</th>
|
||||
<tr class="odd:bg-gray-100"
|
||||
v-if="priceBoard > 0">
|
||||
<th class="text-left py-2">Verpflegung</th>
|
||||
<td>{{ formatCurrency(priceBoard) }}</td>
|
||||
</tr>
|
||||
<tr v-if="priceRunningCosts > 0">
|
||||
<th>Strom- und Abfallgebühren</th>
|
||||
<tr class="odd:bg-gray-100"
|
||||
v-if="priceRunningCosts > 0">
|
||||
<th class="text-left py-2">Strom- und Abfallgebühren</th>
|
||||
<td>{{ formatCurrency(priceRunningCosts) }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Gesamtpreis</th>
|
||||
<tr class="odd:bg-gray-100">
|
||||
<th class="text-left py-2">Gesamtpreis</th>
|
||||
<td><strong>{{ formatCurrency(priceTotal) }}</strong><br><small>zzgl. vor Ort zu entrichtender
|
||||
Ortstaxe</small></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div v-show="nightsCount === 0">
|
||||
<span class="label label-warning">Bitte wählen Sie einen Zeitraum</span>
|
||||
</div>
|
||||
<p class="text-sm italic"
|
||||
v-show="nightsCount === 0">
|
||||
Bitte zuerst einen Zeitraum wählen
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel panel-default" v-show="nightsCount > 0 && !submitted">
|
||||
<div class="panel-heading">Angebot anfordern</div>
|
||||
<div class="panel-body">
|
||||
<div class="form-group" :class="{ 'has-error': formErrors.name }">
|
||||
<label>Name*</label>
|
||||
<input type="text" class="form-control" v-model="name">
|
||||
<div class="help-block"
|
||||
v-show="formErrors.name" v-html="formErrors.name"></div>
|
||||
</div>
|
||||
<div class="form-group" :class="{ 'has-error': formErrors.email }">
|
||||
<label>E-Mail*</label>
|
||||
<input type="text" class="form-control" v-model="email">
|
||||
<div class="help-block"
|
||||
v-show="formErrors.email" v-html="formErrors.email"></div>
|
||||
</div>
|
||||
<div class="form-group" :class="{ 'has-error': formErrors.phone }">
|
||||
<label>Telefon*</label>
|
||||
<input type="text" class="form-control" v-model="phone">
|
||||
<div class="help-block"
|
||||
v-show="formErrors.phone" v-html="formErrors.phone"></div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Bemerkungen/Wünsche</label>
|
||||
<textarea class="form-control" cols="30" rows="3" v-model="remarks"/>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<button class="button" type="submit" @click.prevent="submitForm()">SENDEN</button>
|
||||
<div class="mb-8"
|
||||
v-show="nightsCount > 0 && !submitted">
|
||||
<div class="p-2 uppercase bg-ep-primary-dark text-white w-full">
|
||||
Angebot anfordern
|
||||
</div>
|
||||
<div class="bg-gray-100 p-2">
|
||||
<div class="grid md:grid-cols-2 gap-4 mb-4">
|
||||
<div :class="{ 'has-error': formErrors.name }">
|
||||
<label class="font-bold mb-2">
|
||||
Name*
|
||||
</label>
|
||||
<input type="text"
|
||||
class="form-field"
|
||||
v-model="name">
|
||||
<div class="text-sm text-red-600 mt-1"
|
||||
v-show="formErrors.name"
|
||||
v-html="formErrors.name"></div>
|
||||
</div>
|
||||
<div :class="{ 'has-error': formErrors.email }">
|
||||
<label class="font-bold mb-2">
|
||||
E-Mail*
|
||||
</label>
|
||||
<input type="text"
|
||||
class="form-field"
|
||||
v-model="email">
|
||||
<div class="text-sm text-red-600 mt-1"
|
||||
v-show="formErrors.email"
|
||||
v-html="formErrors.email"></div>
|
||||
</div>
|
||||
<div :class="{ 'has-error': formErrors.phone }">
|
||||
<label class="font-bold mb-2">
|
||||
Telefon*
|
||||
</label>
|
||||
<input type="text"
|
||||
class="form-field"
|
||||
v-model="phone">
|
||||
<div class="text-sm text-red-600 mt-1"
|
||||
v-show="formErrors.phone"
|
||||
v-html="formErrors.phone"></div>
|
||||
</div>
|
||||
<div>
|
||||
<label class="font-bold mb-2">
|
||||
Bemerkungen/Wünsche
|
||||
</label>
|
||||
<textarea class="form-field"
|
||||
cols="30"
|
||||
rows="3"
|
||||
v-model="remarks"/>
|
||||
</div>
|
||||
</div>
|
||||
<button class="button"
|
||||
type="submit"
|
||||
@click.prevent="submitForm()">
|
||||
Senden
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel panel-default form-success" v-show="submitted">
|
||||
<div class="panel-body">
|
||||
<strong>Vielen Dank für Ihre Anfrage. Wir werden diese schnellstmöglich bearbeiten.</strong>
|
||||
</div>
|
||||
<div class="py-8 text-xl text-center font-bold" v-show="submitted">
|
||||
Vielen Dank für Ihre Anfrage. Wir werden diese schnellstmöglich bearbeiten.
|
||||
</div>
|
||||
<div class="fixed top-0 left-0 inset-0 bg-overlay-white flex items-center justify-center" v-show="processing">
|
||||
<img :src="loaderUri" alt="Loading...">
|
||||
@@ -265,30 +331,37 @@ export default {
|
||||
}
|
||||
},
|
||||
submitForm() {
|
||||
let options = [];
|
||||
for (let option of this.selectedOptions) {
|
||||
options.push(option.uid);
|
||||
let formData = new URLSearchParams({
|
||||
'tx_epproducts_ajax[groupsPriceInquiry][name]': this.name ? this.name : '',
|
||||
'tx_epproducts_ajax[groupsPriceInquiry][email]': this.email? this.email : '',
|
||||
'tx_epproducts_ajax[groupsPriceInquiry][phone]': this.phone ? this.phone : '',
|
||||
'tx_epproducts_ajax[groupsPriceInquiry][remarks]': this.remarks,
|
||||
'tx_epproducts_ajax[groupsPriceInquiry][dateFrom]': this.selectedFrom.format('DD.MM.YYYY'),
|
||||
'tx_epproducts_ajax[groupsPriceInquiry][dateTo]': this.selectedTo.format('DD.MM.YYYY'),
|
||||
'tx_epproducts_ajax[groupsPriceInquiry][pax]': this.includesBonusCard ? '' : this.selectedPax,
|
||||
'tx_epproducts_ajax[groupsPriceInquiry][paxGroup1]': this.includesBonusCard ? this.selectedPaxGroup1 : '',
|
||||
'tx_epproducts_ajax[groupsPriceInquiry][paxGroup2]': this.includesBonusCard ? this.selectedPaxGroup2 : '',
|
||||
'tx_epproducts_ajax[groupsPriceInquiry][paxGroup3]': this.includesBonusCard ? this.selectedPaxGroup3 : '',
|
||||
'tx_epproducts_ajax[groupsPriceInquiry][summary][paxBase]': this.formatCurrency(this.pricePax.base),
|
||||
'tx_epproducts_ajax[groupsPriceInquiry][summary][paxAdditional]': this.formatCurrency(this.pricePax.additional),
|
||||
'tx_epproducts_ajax[groupsPriceInquiry][summary][shortTerm]': this.formatCurrency(this.priceShortTerm),
|
||||
'tx_epproducts_ajax[groupsPriceInquiry][summary][options]': this.priceOptions,
|
||||
'tx_epproducts_ajax[groupsPriceInquiry][summary][board]': this.formatCurrency(this.priceBoard),
|
||||
'tx_epproducts_ajax[groupsPriceInquiry][summary][priceRunningCosts]': this.formatCurrency(this.priceRunningCosts),
|
||||
'tx_epproducts_ajax[groupsPriceInquiry][summary][total]': this.formatCurrency(this.priceTotal),
|
||||
})
|
||||
if (this.selectedBoard) {
|
||||
formData.append('tx_epproducts_ajax[groupsPriceInquiry][board]', this.selectedBoard.uid)
|
||||
}
|
||||
let formData = new FormData()
|
||||
formData.set('tx_epproducts_ajax[groupsPriceInquiry][name]', this.name)
|
||||
formData.set('tx_epproducts_ajax[groupsPriceInquiry][email]', this.email)
|
||||
formData.set('tx_epproducts_ajax[groupsPriceInquiry][phone]', this.phone)
|
||||
formData.set('tx_epproducts_ajax[groupsPriceInquiry][remarks]', this.remarks)
|
||||
formData.set('tx_epproducts_ajax[groupsPriceInquiry][dateFrom]', this.selectedFrom.format('DD.MM.YYYY'))
|
||||
formData.set('tx_epproducts_ajax[groupsPriceInquiry][dateTo]', this.selectedTo.format('DD.MM.YYYY'))
|
||||
formData.set('tx_epproducts_ajax[groupsPriceInquiry][pax]', this.includesBonusCard ? '' : this.selectedPax)
|
||||
formData.set('tx_epproducts_ajax[groupsPriceInquiry][paxGroup1]', this.includesBonusCard ? this.selectedPaxGroup1 : '')
|
||||
formData.set('tx_epproducts_ajax[groupsPriceInquiry][paxGroup2]', this.includesBonusCard ? this.selectedPaxGroup2 : '')
|
||||
formData.set('tx_epproducts_ajax[groupsPriceInquiry][paxGroup3]', this.includesBonusCard ? this.selectedPaxGroup3 : '')
|
||||
formData.set('tx_epproducts_ajax[groupsPriceInquiry][board]', this.selectedBoard ? this.selectedBoard.uid : null)
|
||||
formData.set('tx_epproducts_ajax[groupsPriceInquiry][options]', options)
|
||||
formData.set('tx_epproducts_ajax[groupsPriceInquiry][summary]', this.priceSummary)
|
||||
this.selectedOptions.map(option => (
|
||||
formData.append('tx_epproducts_ajax[groupsPriceInquiry][options][]', option.uid)
|
||||
))
|
||||
this.processing = true;
|
||||
this.submitted = false;
|
||||
axios({
|
||||
url: this.endpoint,
|
||||
method: 'POST',
|
||||
data: formData
|
||||
data: formData,
|
||||
}).then(response => {
|
||||
if ('validation' === response.data.status) {
|
||||
this.formErrors = response.data.errors;
|
||||
@@ -424,7 +497,6 @@ export default {
|
||||
Vue.nextTick(() => {
|
||||
this.picker = flatpickr(this.$refs.picker, {
|
||||
mode: 'range',
|
||||
inline: true,
|
||||
dateFormat: 'd.m.Y',
|
||||
locale: German,
|
||||
onChange: selectedDates => {
|
||||
|
||||
+4
-1
@@ -5,12 +5,15 @@ export default class extends Controller {
|
||||
|
||||
static targets = [ 'thumb' ]
|
||||
|
||||
static values = { url: String }
|
||||
static values = { url: String, height: String }
|
||||
|
||||
connect() {
|
||||
let elements = []
|
||||
if (this.hasUrlValue) {
|
||||
let element = { href: this.urlValue }
|
||||
if (this.hasHeightValue) {
|
||||
element.height = this.heightValue
|
||||
}
|
||||
elements.push(element)
|
||||
} else if (this.element.hasAttribute('href')) {
|
||||
let element = { href: this.element.href }
|
||||
|
||||
@@ -3,17 +3,11 @@
|
||||
xmlns:encore="http://typo3.org/ns/Ssch/Typo3Encore/ViewHelpers"
|
||||
data-namespace-typo3-fluid="true">
|
||||
|
||||
<div class="container">
|
||||
<div class="page-header">
|
||||
<div class="media">
|
||||
<div class="media-left media-middle">
|
||||
<f:image class="media-object" width="128" src="EXT:ep_theme/Resources/Public/images/logo_wide.svg" alt=""/>
|
||||
</div>
|
||||
<div class="media-body">
|
||||
<h1 class="media-heading">Preisberechnung <small>{hotel.name}</small></h1>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="max-w-screen-lg mx-auto">
|
||||
<h1 class="headline--underlined headline--has-subline">
|
||||
<span class="subline">{hotel.name}</span>
|
||||
Preisberechnung
|
||||
</h1>
|
||||
<f:format.raw>
|
||||
<groups-price-calculator
|
||||
configs-json='{configs}'
|
||||
|
||||
@@ -281,6 +281,7 @@
|
||||
class="button w-full"
|
||||
data-controller="lightbox"
|
||||
data-lightbox-url-value="{f:uri.action(action: 'index', controller: 'GroupsPrice', arguments: '{hotel: hotel}', pageUid: settings.groupsPricePopupPageUid)}"
|
||||
data-lightbox-height-value="85vh"
|
||||
data-action="lightbox#open">
|
||||
Preisberechnung
|
||||
</button>
|
||||
|
||||
Reference in New Issue
Block a user