Finalize integration of group bookings into myep spa

This commit is contained in:
Björn Fromme
2020-09-23 11:17:59 +02:00
parent 733fe11f89
commit c25efb717b
14 changed files with 255 additions and 119 deletions
@@ -134,7 +134,3 @@ page {
)
headerData.999.stdWrap.if.isTrue = {$plugin.tx_eptheme.settings.googleTagManagerId}
}
[applicationContext == "Development"]
page.includeCSS.main.disableCompression = 1
[END]
@@ -118,15 +118,8 @@ lib.stdheader.3.headerClass >
@import "EXT:ep_theme/Configuration/TypoScript/Page/Export.typoscript"
config {
doctype = html5
removeDefaultCSS = 1
removePageCss = 1
removeDefaultJS = 0
disablePrefixComment = 1
inlineStyle2TempFile = 0
absRefPrefix = /
compressJs = 0
compressCss = 0
compressJs = 1
compressCss = 1
typolinkCheckRootline = 1
typolinkEnableLinksAcrossDomains = 1
sendCacheHeaders = 1
@@ -1,6 +1,6 @@
<template>
<div class="form-wrapper form--border" id="myep-main" v-show="!loading">
<h1>Adressdaten</h1>
<p class="text-2xl">Adressdaten</p>
<form @submit.prevent="save()">
<div class="row">
<div class="col-xs-12 col-md-6">
@@ -1,41 +1,33 @@
<template>
<div id="myep" class="relative">
<nav class="navbar navbar-default" v-if="isLoggedIn">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed"
data-toggle="collapse" data-target="#myep-navbar" aria-expanded="false">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">My E&amp;P</a>
</div>
<div class="collapse navbar-collapse" id="myep-navbar">
<ul class="nav navbar-nav">
<router-link :to="{ name: 'address' }" tag="li" active-class="active" :class="{ disabled: loading }"><a>Adressdaten</a></router-link>
<router-link :to="{ name: 'newsletter' }" tag="li" active-class="active" :class="{ disabled: loading }"><a>Newsletter</a></router-link>
<router-link :to="{ name: 'profile' }" tag="li" active-class="active" :class="{ disabled: loading }"><a>Mein Profil</a></router-link>
<router-link :to="{ name: 'events' }" tag="li" active-class="active" :class="{ disabled: loading }"><a>Buchungen</a></router-link>
<router-link :to="{ name: 'teamer' }" tag="li" active-class="active" :class="{ disabled: loading }" v-if="isTeamer"><a>Teamer</a></router-link>
</ul>
<ul class="nav navbar-nav navbar-right">
<li :class="{ disabled: loading }"><a href="#" @click.prevent="logout()">Logout</a></li>
</ul>
<div id="myep" class="relative mb-16">
<nav class="w-full bg-gray-200 flex items-center justify-between mb-2 relative" v-if="isLoggedIn">
<span class="block text-2xl px-4">My E&P</span>
<div class="absolute z-10 top-100 left-0 w-full bg-gray-200 shadow lg:relative lg:top-auto lg:left-auto lg:w-auto lg:shadow-none lg:flex lg:space-x-4"
:class="{ 'hidden': !navVisible }">
<div class="lg:flex lg:items-center m-0">
<router-link :to="{ name: 'address' }" class="block p-4 text-black hover:bg-gray-400 hover:text-gray-800" active-class="bg-gray-400 text-gray-800">Adressdaten</router-link>
<router-link :to="{ name: 'newsletter' }" class="block p-4 text-black hover:bg-gray-400 hover:text-gray-800" active-class="bg-gray-400 text-gray-800">Newsletter</router-link>
<router-link :to="{ name: 'profile' }" class="block p-4 text-black hover:bg-gray-400 hover:text-gray-800" active-class="bg-gray-400 text-gray-800">Mein Profil</router-link>
<router-link :to="{ name: 'events' }" class="block p-4 text-black hover:bg-gray-400 hover:text-gray-800" active-class="bg-gray-400 text-gray-800">Buchungen</router-link>
<router-link :to="{ name: 'teamer' }" class="block p-4 text-black hover:bg-gray-400 hover:text-gray-800" active-class="bg-gray-400 text-gray-800" v-if="isTeamer">Teamer</router-link>
</div>
<a class="block px-4 py-4 text-black hover:bg-gray-400 hover:text-gray-800" href="#" @click.prevent="logout()">Logout</a>
</div>
<a href="#" class="lg:hidden p-4 transform text-black hover:text-gray-800" :class="{ 'rotate-90': navVisible }" @click.prevent="navVisible = !navVisible">
<svg class="w-8 h-8" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"></path></svg>
</a>
</nav>
<div class="row" v-if="alert.message">
<div class="col-xs-12">
<div class="alert alert-dismissable" :class="alert.class">
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
{{ alert.message }}
</div>
<div class="py-2" v-if="alert.message">
<div class="alert alert-dismissable" :class="alert.class">
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
{{ alert.message }}
</div>
</div>
<div class="absolute top-0 left-0 w-full h-full z-100 bg-overlay-white" v-show="loading">
<img :src="config.loaderUrl" alt="" class="absolute top-1/2 left-1/2 transform -translate-xy-1/2">
<div class="flex items-center space-x-2 h-8 mb-2" v-show="loading">
<img :src="config.loaderUrl" alt="" class="block w-4 h-4">
<span v-text="statusMessage"></span>
</div>
<router-view></router-view>
</div>
@@ -57,8 +49,13 @@
}).catch(error => {});
}
},
data () {
return {
navVisible: false
}
},
computed: {
...mapState(['config', 'loading', 'alert']),
...mapState(['config', 'loading', 'alert', 'statusMessage']),
...mapGetters(['isLoggedIn', 'isTeamer'])
},
mounted () {
@@ -31,10 +31,10 @@
</div>
</div>
<div class="py-4 lg:flex lg:justify-between space-y-1 lg:space-y-0" v-show="!loading">
<button class="btn btn-primary" :disabled="!dirty" @click.prevent="storeBookingData()" v-if="initialized">
<button class="button" :disabled="!dirty" @click.prevent="storeBookingData()" v-if="initialized">
Buchung aktualisieren
</button>
<router-link :to="{ name: 'events' }" class="btn btn-primary">
<router-link :to="{ name: 'events' }" class="button">
zur Übersicht
</router-link>
</div>
@@ -117,33 +117,19 @@
</collapsible-panel>
</div>
<div class="py-4 lg:flex lg:justify-between space-y-1 lg:space-y-0" v-show="!loading">
<button class="btn btn-primary" :disabled="!dirty" @click.prevent="storeBookingData()" v-if="initialized">
<button class="button" :disabled="!dirty" @click.prevent="storeBookingData()" v-if="initialized">
Buchung aktualisieren
</button>
<router-link :to="{ name: 'events' }" class="btn btn-primary">
<router-link :to="{ name: 'events' }" class="button">
zur Übersicht
</router-link>
</div>
<div class="py-4 text-center" v-show="statusMessage" v-text="statusMessage" />
<div class="modal fade" tabindex="-1" role="dialog" ref="modal">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">{{ modal.title }}</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<p v-html="modal.message"/>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import Vue from 'vue'
import VueScrollTo from 'vue-scrollto'
import AccommodationSelect from './components/AccommodationSelect'
import ContingentsOverview from './components/ContingentsOverview';
import MutableFields from './components/MutableFields';
@@ -157,9 +143,11 @@
import ServicesOverview from './components/ServicesOverview';
import TransportationSelect from './components/TransportationSelect';
import authenticatedClient from "../api";
import authenticatedClient from '../api';
import {mapMutations, mapState} from 'vuex';
Vue.use(VueScrollTo)
export default {
name: 'BookingEdit',
components: {
@@ -182,7 +170,6 @@
initialized: false,
dirty: false,
processing: false,
statusMessage: '',
bookingData: null,
participantData: null,
invalidParticipantData: {},
@@ -218,16 +205,8 @@
this.endLoading()
});
},
showModal (message, title = 'Hinweis') {
this.modal = {
message: message,
title: title
};
$(this.$refs.modal).modal('show');
},
loadBookingData () {
this.beginLoading()
this.statusMessage = 'Lade Reise- und Buchungsdaten';
this.beginLoading('Lade Reise- und Buchungsdaten...')
return authenticatedClient.get(`/api/booking/${this.bookingId}`)
.then(response => {
this.bookingData = response.data.bookingData;
@@ -238,13 +217,11 @@
throw new Error('Reise- und Buchungsdaten konnten nicht geladen werden.');
})
.finally(() => {
this.statusMessage = '';
this.endLoading()
})
},
loadEventData () {
this.beginLoading()
this.statusMessage = 'Lade Vorgangsdaten';
this.beginLoading('Lade Vorgangsdaten...')
return authenticatedClient.get(`/api/event/${this.bookingData.bookingNumber}`)
.then(response => {
this.eventData = response.data;
@@ -253,13 +230,11 @@
throw new Error(error.response.data.message);
})
.finally(() => {
this.statusMessage = '';
this.endLoading()
})
},
loadMutableFields () {
this.beginLoading()
this.statusMessage = 'Lade mögliche Änderungen';
this.beginLoading('Lade mögliche Änderungen...')
return authenticatedClient.get(`/api/mutable-fields/${this.travelData.busproId}`)
.then(response => {
this.mutableFields = response.data;
@@ -268,13 +243,11 @@
throw new Error('Mögliche Änderungen konnten nicht geladen werden.');
})
.finally(() => {
this.statusMessage = '';
this.endLoading()
})
},
loadContingents () {
this.beginLoading()
this.statusMessage = 'Lade Kontingente';
this.beginLoading('Lade Kontingente...')
return authenticatedClient.get(`/api/contingents/${this.travelData.busproId}`)
.then(response => {
this.contingents = response.data;
@@ -283,13 +256,11 @@
throw new Error('Kontingente konnten nicht geladen werden.');
})
.finally(() => {
this.statusMessage = '';
this.endLoading()
})
},
loadServices () {
this.beginLoading()
this.statusMessage = 'Lade Leistungen';
this.beginLoading('Lade Leistungen...')
return authenticatedClient.get(`/api/services/${this.travelData.busproId}`)
.then(response => {
this.services = response.data;
@@ -298,7 +269,6 @@
throw new Error('Leistungen konnten nicht geladen werden.');
})
.finally(() => {
this.statusMessage = '';
this.endLoading()
})
},
@@ -417,9 +387,13 @@
return messages
},
storeBookingData() {
this.$scrollTo('#myep')
let messages = this.validateInput();
if (false === this.dataValid) {
this.showModal(messages.join('<br>'), 'Daten unvollständig');
this.alert({
message: messages.join('<br>'),
class: 'alert-danger'
});
return;
}
this.beginLoading()
@@ -428,10 +402,16 @@
selectedTransportations: this.selectedTransportations,
remarks: this.bookingData.remarks
}).then(response => {
this.showModal(response.data.message);
this.alert({
message: response.data.message,
class: 'alert-info'
});
this.dirty = false;
}).catch(error => {
this.showModal(error.response.data.message)
this.alert({
message: error.response.data.message,
class: 'alert-danger'
})
}).finally(() => {
this.endLoading()
})
@@ -499,10 +479,12 @@
this.initialized = true;
})
.catch(error => {
this.showModal(error.message, 'Fehler');
this.alert({
message: error.message,
class: 'alert-danger'
});
})
.finally(() => {
this.statusMessage = '';
this.endLoading()
})
}
@@ -23,13 +23,13 @@
<td style="white-space: nowrap">{{ calculateBalance(event) }}</td>
<td>{{ status[event.status] }}</td>
<td class="flex space-x-1">
<a :href="getDownloadUrl(event, 'confirmation')" target="_blank" class="btn btn-primary btn-sm">
<a :href="getDownloadUrl(event, 'confirmation')" target="_blank" class="button button--small">
Bestätigung
</a>
<a :href="getDownloadUrl(event, 'documents')" target="_blank" class="btn btn-primary btn-sm" v-if="event.documents">
<a :href="getDownloadUrl(event, 'documents')" target="_blank" class="button button--small" v-if="event.documents">
Reiseinfos
</a>
<router-link :to="{ name: 'bookingEdit', params: { id: event.id } }" v-if="isGroupManager && event.editable" class="btn btn-primary btn-sm">
<router-link :to="{ name: 'bookingEdit', params: { id: event.id } }" v-if="isGroupManager && event.editable" class="button button--small">
bearbeiten
</router-link>
</td>
@@ -95,5 +95,8 @@ export default new VueRouter({
path: '*',
redirect: { name: 'login' }
}
]
],
scrollBehavior (to, from, savedPosition) {
return { selector: '#myep', offset: { x: 0 , y: 160 } }
}
});
@@ -26,6 +26,7 @@ export default new Vuex.Store({
state: {
config: {},
loading: false,
statusMessage: '',
authToken: null,
refreshToken: null,
userData: defaultUserData,
@@ -77,12 +78,14 @@ export default new Vuex.Store({
alert(state, payload) {
state.alert = payload;
},
beginLoading(state) {
state.loading = true;
state.alert = {message: '', class: ''};
beginLoading(state, statusMessage) {
state.loading = true
state.statusMessage = statusMessage
state.alert = {message: '', class: ''}
},
endLoading(state) {
state.loading = false;
state.loading = false
state.statusMessage = ''
},
setCountries(state, countries) {
state.countries = countries;
@@ -0,0 +1,54 @@
// vendor styles
$icon-font-path: "~bootstrap-sass/assets/fonts/bootstrap/";
// Core variables and mixins
@import "~bootstrap-sass/assets/stylesheets/bootstrap/variables";
@import "~bootstrap-sass/assets/stylesheets/bootstrap/mixins";
// Reset and dependencies
@import "~bootstrap-sass/assets/stylesheets/bootstrap/normalize";
@import "~bootstrap-sass/assets/stylesheets/bootstrap/print";
@import "~bootstrap-sass/assets/stylesheets/bootstrap/glyphicons";
// Core CSS
@import "~bootstrap-sass/assets/stylesheets/bootstrap/scaffolding";
@import "~bootstrap-sass/assets/stylesheets/bootstrap/type";
@import "~bootstrap-sass/assets/stylesheets/bootstrap/code";
@import "~bootstrap-sass/assets/stylesheets/bootstrap/grid";
@import "~bootstrap-sass/assets/stylesheets/bootstrap/tables";
@import "~bootstrap-sass/assets/stylesheets/bootstrap/forms";
@import "~bootstrap-sass/assets/stylesheets/bootstrap/buttons";
// Components
@import "~bootstrap-sass/assets/stylesheets/bootstrap/component-animations";
@import "~bootstrap-sass/assets/stylesheets/bootstrap/dropdowns";
@import "~bootstrap-sass/assets/stylesheets/bootstrap/button-groups";
@import "~bootstrap-sass/assets/stylesheets/bootstrap/input-groups";
@import "~bootstrap-sass/assets/stylesheets/bootstrap/navs";
@import "~bootstrap-sass/assets/stylesheets/bootstrap/navbar";
@import "~bootstrap-sass/assets/stylesheets/bootstrap/breadcrumbs";
@import "~bootstrap-sass/assets/stylesheets/bootstrap/pagination";
@import "~bootstrap-sass/assets/stylesheets/bootstrap/pager";
@import "~bootstrap-sass/assets/stylesheets/bootstrap/labels";
@import "~bootstrap-sass/assets/stylesheets/bootstrap/badges";
@import "~bootstrap-sass/assets/stylesheets/bootstrap/jumbotron";
@import "~bootstrap-sass/assets/stylesheets/bootstrap/thumbnails";
@import "~bootstrap-sass/assets/stylesheets/bootstrap/alerts";
@import "~bootstrap-sass/assets/stylesheets/bootstrap/progress-bars";
@import "~bootstrap-sass/assets/stylesheets/bootstrap/media";
@import "~bootstrap-sass/assets/stylesheets/bootstrap/list-group";
@import "~bootstrap-sass/assets/stylesheets/bootstrap/panels";
@import "~bootstrap-sass/assets/stylesheets/bootstrap/responsive-embed";
@import "~bootstrap-sass/assets/stylesheets/bootstrap/wells";
@import "~bootstrap-sass/assets/stylesheets/bootstrap/close";
// Components w/ JavaScript
@import "~bootstrap-sass/assets/stylesheets/bootstrap/modals";
@import "~bootstrap-sass/assets/stylesheets/bootstrap/tooltip";
@import "~bootstrap-sass/assets/stylesheets/bootstrap/popovers";
@import "~bootstrap-sass/assets/stylesheets/bootstrap/carousel";
// Utility classes
//@import "~bootstrap-sass/assets/stylesheets/bootstrap/utilities";
@import "bootstrap-overrides/utilities";
@import "~bootstrap-sass/assets/stylesheets/bootstrap/responsive-utilities";
@@ -0,0 +1,55 @@
//
// Utility classes
// --------------------------------------------------
// Floats
// -------------------------
.clearfix {
@include clearfix;
}
.center-block {
@include center-block;
}
.pull-right {
float: right !important;
}
.pull-left {
float: left !important;
}
// Toggling content
// -------------------------
// Note: Deprecated .hide in favor of .hidden or .sr-only (as appropriate) in v3.0.1
.hide {
display: none;
}
.show {
display: block;
}
.invisible {
visibility: hidden;
}
.text-hide {
@include text-hide;
}
// Hide from screenreaders and browsers
//
// Credit: HTML5 Boilerplate
.hidden {
display: none;
}
// For Affix plugin
// -------------------------
.affix {
position: fixed;
}
@@ -8,10 +8,7 @@
@import "remix/variables";
@import "remix/colors";
// vendor styles
$icon-font-path: "~bootstrap-sass/assets/fonts/bootstrap/";
@import "~bootstrap-sass/assets/stylesheets/bootstrap";
@import "bootstrap";
@import "mixins";
@@ -73,12 +70,6 @@
}
@layer utilities {
.top-1\/2 {
top: 50%;
}
.left-1\/2 {
left: 50%;
}
.-translate-xy-1\/2 {
transform: translate(-50%, -50%);
}