/home/crealab/cars.brainware.com.co/wp-content/plugins/jet-booking/assets/js/admin/bookings.js
(function () {
"use strict";
const eventHub = new Vue();
const { __, sprintf } = wp.i18n;
const buildQuery = function ( params ) {
return Object.keys( params ).map( function ( key ) {
return key + '=' + params[ key ];
} ).join( '&' );
}
window.jetBookingState = {
isActive: false
};
const getCurrentMode = function () {
let mode = window.location.hash ? window.location.hash.replace( '#', '' ) : false;
if ( ! mode ) {
return 'all';
}
return [ 'all', 'upcoming', 'past' ].includes( mode ) ? mode : 'all';
}
const statusMixin = {
computed: Vuex.mapState( ['statuses_schema'] ),
methods: {
isFinished: function ( status ) {
return ( 0 <= this.statuses_schema.finished.indexOf( status ) );
},
isInProgress: function ( status ) {
return ( 0 <= this.statuses_schema.in_progress.indexOf( status ) );
},
isInvalid: function ( status ) {
return ( 0 <= this.statuses_schema.invalid.indexOf( status ) );
},
statusClass: function ( status ) {
return {
'notice': true,
'notice-alt': true,
'notice-success': this.isFinished( status ),
'notice-warning': this.isInProgress( status ),
'notice-error': this.isInvalid( status )
}
},
}
};
const itemsMethods = {
computed: Vuex.mapState( [ 'bookings', 'bookings_units' ] ),
methods: {
getItemLabel: function ( item_id ) {
return this.bookings[ item_id ] || item_id;
},
getItemUnitLabel: function ( item_id, unit_id ) {
if ( this.bookings_units[ item_id ] && this.bookings_units[ item_id ][ unit_id] ) {
return this.bookings_units[ item_id ][ unit_id ] + ' (#' + unit_id + ')';
} else {
return unit_id;
}
},
getOrderLink: function ( orderID ) {
return window.JetABAFConfig.edit_link.replace( /\%id\%/, orderID );
}
},
}
// Mixin for handling booking fields.
const fieldsManager = {
computed: Vuex.mapState( {
bookingItem: 'bookingItem',
dateRangePickerConfig: 'dateRangePickerConfig',
isDisabled: 'isDisabled',
itemUnits: 'itemUnits',
bookingPrice: 'bookingPrice'
} ),
methods: {
initDateRangePicker: function () {
let self = this;
store.dispatch( 'getDateRangePickerConfig' ).then( function () {
jQuery( self.$refs.jetABAFDatePicker ).dateRangePicker( self.dateRangePickerConfig )
.bind( 'datepicker-first-date-selected', () => {
window.jetBookingState.isActive = true;
} ).bind( 'datepicker-change', () => {
window.jetBookingState.isActive = false;
} );
} );
},
getBookingPrice: function ( booking ) {
jQuery.ajax( {
url: window.JetABAFConfig.ajax_url,
type: 'POST',
dataType: 'json',
data: {
action: 'jet_booking_product_get_total_price',
booking: booking,
nonce: window?.JetABAFConfig?.nonce
},
} ).done( function ( response ) {
store.commit( 'setValue', {
key: 'bookingPrice',
value: response.data.price
} );
} ).fail( function ( _, _2, errorThrown ) {
alert( errorThrown );
} );
},
beVisible: function ( key ) {
switch ( key ) {
case 'booking_id':
case 'apartment_unit':
case 'order_id':
case 'user_id':
case 'import_id':
case 'status':
case 'apartment_id':
case 'check_in_date':
case 'check_in_date_timestamp':
case 'check_out_date':
case 'check_out_date_timestamp':
return false;
default:
return true;
}
},
onApartmentChange: function () {
this.initDateRangePicker();
},
}
};
const store = new Vuex.Store( {
state: {
...window.JetABAFConfig,
pageUrl: new URL( window.location.href ),
perPage: 15,
offset: 0,
pageNumber: 1,
totalItems: 0,
itemsList: [],
isLoading: true,
overlappingBookings: false,
bookingItem: {},
bookingPrice: 0,
dateRangePickerConfig: {},
isDisabled: false,
itemUnits: [],
currentFilters: {},
sortBy: {
orderby: 'booking_id',
order: 'DESC'
},
currentView: 'list',
views: {
list: {
label: __('List', 'jet-booking')
},
calendar: {
label: __('Calendar', 'jet-booking')
},
timeline: {
label: __('Timeline', 'jet-booking')
},
}
},
mutations: {
setValue ( state, varObject ) {
state[ varObject.key ] = varObject.value;
},
},
actions: {
getItems: function () {
store.commit( 'setValue', {
key: 'isLoading',
value: true
} );
wp.apiFetch( {
method: 'get',
path: window.JetABAFConfig.api.bookings_list + '?' + buildQuery( {
per_page: 'list' === store.state.currentView ? store.state.perPage : -1,
offset: 'list' === store.state.currentView ? store.state.offset : 0,
filters: JSON.stringify( store.state.currentFilters ),
sort: JSON.stringify( store.state.sortBy ),
mode: getCurrentMode(),
view: store.state.currentView
} ),
} ).then( function ( response ) {
store.commit( 'setValue', {
key: 'isLoading',
value: false
} );
if ( response.success ) {
store.commit( 'setValue', {
key: 'itemsList',
value: response.data
} );
store.commit( 'setValue', {
key: 'totalItems',
value: +response.total
} );
}
} ).catch( function ( e ) {
store.commit( 'setValue', {
key: 'isLoading',
value: false
} );
eventHub.$CXNotice.add( {
message: e.message,
type: 'error',
duration: 7000,
} );
} );
},
getDateRangePickerConfig: async function () {
store.commit( 'setValue', {
key: 'isDisabled',
value: true
} );
const bookingItem = store.state.bookingItem;
if ( ! bookingItem.check_in_date ) {
bookingItem.check_in_date = '';
}
if ( ! bookingItem.check_out_date ) {
bookingItem.check_out_date = '';
}
await wp.apiFetch( {
method: 'post',
path: window.JetABAFConfig.api.booked_dates,
data: { item: bookingItem }
} ).then( function ( response ) {
if ( ! response.success ) {
eventHub.$CXNotice.add( {
message: response.data,
type: 'error',
duration: 7000,
} );
} else {
const {
per_nights: perNights,
booked_dates: excludedDates,
booked_next: excludedNext,
disabled_days: disabledDays,
check_in_days: checkInDays,
checkout_only: checkoutOnly,
labels: labels,
start_day_offset: startDayOffset,
end_date: rangeEndDate,
min_days: minDays,
max_days: maxDays,
month_select: monthSelect,
year_select: yearSelect
} = response;
window.JetABAFConfig = { ...window.JetABAFConfig, ...response };
if ( bookingItem.check_in_date.length && bookingItem.check_out_date.length && 0 <= excludedDates.indexOf( bookingItem.check_in_date ) ) {
let deleteCount = moment( bookingItem.check_out_date ).diff( moment( bookingItem.check_in_date ), 'days' );
if ( ! perNights ) {
deleteCount++;
}
excludedDates.splice( excludedDates.indexOf( bookingItem.check_in_date ), deleteCount );
excludedDates.push( ...response.days_off )
}
let config = {
autoClose: true,
separator: ' - ',
startDate: new Date(),
startOfWeek: response.start_of_week,
getValue: function () {
if ( bookingItem.check_in_date && bookingItem.check_out_date ) {
return bookingItem.check_in_date + ' - ' + bookingItem.check_out_date;
} else {
return '';
}
},
setValue: function ( s, s1, s2 ) {
if ( s === s1 ) {
s2 = s1;
}
bookingItem.check_in_date = s1;
bookingItem.check_out_date = s2;
},
minDays: minDays.length && +minDays ? +minDays : '',
maxDays: maxDays.length && +maxDays ? +maxDays : '',
perNights: perNights,
container: '.jet-abaf-details__booking-dates',
beforeShowDay: function ( t ) {
const formatted = moment( t ).format('YYYY-MM-DD');
let valid = true,
_class = '',
_tooltip = '';
if ( disabledDays.length && 0 <= disabledDays.indexOf( t.getDay() ) ) {
const disabledNext = moment( t ).add( 1, 'd' ).format('YYYY-MM-DD');
if ( ! ( 0 <= excludedNext.indexOf( disabledNext ) ) ) {
excludedNext.push( disabledNext );
}
if ( ! ( 0 <= excludedDates.indexOf( formatted ) ) ) {
excludedDates.push( formatted );
}
valid = false;
}
if ( checkInDays.length && -1 === checkInDays.indexOf( t.getDay() ) ) {
valid = window.jetBookingState.isActive && -1 === disabledDays.indexOf( t.getDay() );
}
if ( excludedDates.length && 0 <= excludedDates.indexOf( formatted ) ) {
valid = false;
_tooltip = response.custom_labels ? labels.booked : __( 'Sold out', 'jet-booking' );
// Mark first day of booked period as checkout only
if ( checkoutOnly ) {
let next = moment( t ).add( 1, 'd' ).format('YYYY-MM-DD'),
prev = moment( t ).subtract( 1, 'd' ).format('YYYY-MM-DD');
if ( 0 <= excludedNext.indexOf( next ) || ( 0 <= excludedDates.indexOf( next ) && -1 === excludedDates.indexOf( prev ) ) ) {
if ( window.jetBookingState.isActive ) {
valid = true;
_tooltip = '';
} else {
_class = 'only-checkout';
_tooltip = response.custom_labels ? labels[ 'only-checkout' ] : __( 'Only checkout', 'jet-booking' );
}
}
}
}
// If is single night booking - exclude next day for checkout only days.
if ( checkoutOnly && window.jetBookingState.isActive && 0 <= excludedNext.indexOf( formatted ) ) {
valid = false;
_tooltip = response.custom_labels ? labels.booked : __( 'Sold out', 'jet-booking' );
}
return window.JetPlugins.hooks.applyFilters( 'jet-booking.date-range-picker.date-show-params', [ valid, _class, _tooltip ], t );
},
selectForward: true,
monthSelect: monthSelect,
yearSelect: yearSelect
};
if ( startDayOffset.length && +startDayOffset ) {
config.startDate = moment().add( +startDayOffset, 'd' );
}
if ( rangeEndDate ) {
config.endDate = moment( +rangeEndDate, 'X' ).format('YYYY-MM-DD');
}
if ( response.custom_labels ) {
jQuery.dateRangePickerLanguages[ 'custom' ] = labels;
config.language = 'custom';
}
if ( response.weekly_bookings && ! disabledDays.length ) {
config.batchMode = 'week';
config.showShortcuts = false;
if ( response.week_offset ) {
config.weekOffset = Number( response.week_offset );
}
} else if ( response.one_day_bookings ) {
config.singleDate = true;
}
store.commit( 'setValue', {
key: 'dateRangePickerConfig',
value: window.JetPlugins.hooks.applyFilters( 'jet-booking.input.config', config )
} );
store.commit( 'setValue', {
key: 'isDisabled',
value: false
} );
store.commit( 'setValue', {
key: 'itemUnits',
value: response.units.length ? response.units.map( unit => ({
value: unit.unit_id,
label: unit.unit_title
}) ) : []
} );
}
} ).catch( function( e ) {
eventHub.$CXNotice.add( {
message: e.message,
type: 'error',
duration: 7000,
} );
} );
}
}
} );
Vue.component( 'jet-abaf-bookings-list', {
template: '#jet-abaf-bookings-list',
mixins: [ statusMixin, itemsMethods ],
data: function () {
return {
currentSort: 'booking_id'
};
},
computed: {
...Vuex.mapState( {
pageUrl: 'pageUrl',
sortBy: 'sortBy',
itemsList: 'itemsList',
perPage: 'perPage',
offset: 'offset',
pageNumber: 'pageNumber',
totalItems: 'totalItems',
statuses: state => state.all_statuses
} )
},
watch: {
itemsList( value ) {
if ( this.pageUrl.searchParams.has( 'booking-details' ) ) {
const bookingItem = value.find( item => item.booking_id === this.pageUrl.searchParams.get( 'booking-details' ) ) || false;
if ( bookingItem ) {
eventHub.$emit( 'call-popup', {
item: bookingItem,
state: 'info',
} );
this.pageUrl.searchParams.delete( 'booking-details' );
window.history.pushState(null, '', this.pageUrl.toString());
}
}
}
},
methods: {
sortColumn: function ( column ) {
this.currentSort = column;
store.commit( 'setValue', {
key: 'sortBy',
value: {
orderby: column,
order: "DESC" === this.sortBy.order ? "ASC" : "DESC"
}
} );
store.dispatch( 'getItems' );
},
classColumn: function ( column ) {
return {
'jet-abaf-active-column': column === this.currentSort,
'jet-abaf-active-column-asc': column === this.currentSort && "DESC" === this.sortBy.order,
'jet-abaf-active-column-desc': column === this.currentSort && "ASC" === this.sortBy.order
};
},
changePage: function ( page ) {
store.commit( 'setValue', {
key: 'offset',
value: this.perPage * ( page - 1 )
} );
store.commit( 'setValue', {
key: 'pageNumber',
value: page
} );
store.dispatch( 'getItems' );
},
callPopup: function ( state = false, item = false ) {
eventHub.$emit( 'call-popup', {
item: item,
state: state
} );
}
},
} );
Vue.component( 'jet-abaf-bookings-filter', {
template: '#jet-abaf-bookings-filter',
mixins: [ fieldsManager ],
components: {
vuejsDatepicker: window.vuejsDatepicker,
},
data () {
return {
currentMode: 'all',
expandFilters: false,
dateFormat: 'dd/MM/yyyy',
showExportPopup: false,
exportType: 'all',
exportFormat: 'csv',
exportDataReturnType: 'id',
exportDateFormat: 'Y-m-d',
}
},
computed: {
...Vuex.mapState( [ 'filters', 'currentFilters', 'currentView', 'monday_first', 'export_nonce', 'export_url' ] ),
},
created: function () {
this.currentMode = getCurrentMode();
},
methods: {
setMode ( mode ) {
window.location.hash = '#' + mode;
this.currentMode = mode;
store.commit( 'setValue', {
key: 'offset',
value: 0
} );
store.commit( 'setValue', {
key: 'pageNumber',
value: 1
} );
store.dispatch( 'getItems' );
},
modeButtonStyle ( mode ) {
return this.currentMode === mode ? 'accent' : 'link-accent';
},
updateFilters: function ( value, name, type ) {
let filterValue = value.target ? value.target.value : value;
let currentFilter = {};
if ( 'date-picker' === type ) {
filterValue = value ? moment( filterValue ).format( 'MMMM DD YYYY' ) : '';
}
if ( filterValue.length ) {
currentFilter = { [ name ]: filterValue };
} else {
delete this.currentFilters[ name ];
}
store.commit( 'setValue', {
key: 'currentFilters',
value: Object.assign( {}, this.currentFilters, currentFilter )
} );
store.commit( 'setValue', {
key: 'offset',
value: 0
} );
store.commit( 'setValue', {
key: 'pageNumber',
value: 1
} );
store.dispatch( 'getItems' );
},
clearFilter: function () {
store.commit( 'setValue', {
key: 'currentFilters',
value: {}
} );
store.commit( 'setValue', {
key: 'offset',
value: 0
} );
store.commit( 'setValue', {
key: 'pageNumber',
value: 1
} );
store.dispatch( 'getItems' );
},
isVisible ( id, filter, type ) {
if ( type !== filter.type ) {
return false;
}
if ( 'select' === filter.type && ! Object.keys( filter.value ).length ) {
return false;
}
if ( 'date-picker' === filter.type && 'list' !== this.currentView ) {
return false;
}
return true;
},
prepareObjectForOptions: function ( input ) {
let result = [ {
'value': '',
'label': __( 'Select...', 'jet-booking' ),
} ];
for ( const value in input ) {
if ( input.hasOwnProperty( value ) ) {
result.push( {
'value': value,
'label': input[ value ],
} );
}
}
return result;
},
doExport () {
let urlParts = {
type: this.exportType,
format: this.exportFormat,
return: this.exportDataReturnType,
date_format: this.exportDateFormat,
nonce: this.export_nonce,
};
if ( 'filtered' === this.exportType ) {
urlParts = {
...urlParts,
...{
filters: JSON.stringify( store.state.currentFilters ),
sort: JSON.stringify( store.state.sortBy ),
per_page: 0,
mode: getCurrentMode(),
}
};
}
window.location = this.export_url + '&' + buildQuery( urlParts );
},
}
} );
Vue.component( 'jet-abaf-bookings-view', {
template: '#jet-abaf-bookings-view',
computed: { ...Vuex.mapState( [ 'pageUrl', 'currentFilters', 'currentView', 'views' ] ) },
methods: {
viewButtonStyle ( view ) {
return this.currentView === view ? 'accent' : 'link-accent';
},
updateView: function ( view ) {
store.commit( 'setValue', {
key: 'currentView',
value: view
} );
this.pageUrl.searchParams.set( 'view', view );
if ( 'all' !== getCurrentMode() ) {
this.pageUrl.hash = getCurrentMode();
}
window.history.pushState( null, '', this.pageUrl.toString() );
const newFilters = Object.assign( {}, this.currentFilters, { 'check_in_date': '', 'check_out_date': '', 'date': '' } );
store.commit( 'setValue', {
key: 'currentFilters',
value: newFilters
} );
store.dispatch( 'getItems' );
}
},
} );
Vue.component('jet-abaf-bookings-calendar', {
template: '#jet-abaf-bookings-calendar',
mixins: [ dateMethods, statusMixin, itemsMethods ],
data() {
return {
masks: { weekdays: 'WWW' },
maxItemInCell: 3
}
},
components: {
vCalendar: window.vCalendar,
},
computed: Vuex.mapState( {
currentFilters: state => state.currentFilters,
dayIndex: state => state.monday_first ? 2 : 1,
itemsList: function ( state ) {
const self = this;
return state.itemsList.map( function ( item ) {
return {
key: item.booking_id,
customData: { ...item },
dates: self.createRange( item.check_in_date_timestamp, item.check_out_date_timestamp )
}
} );
},
pageUrl: 'pageUrl'
} ),
methods: {
callPopup: function ( state = false, item = false ) {
eventHub.$emit( 'call-popup', {
item: item,
state: state
} );
},
createRange: function ( start, end, step = 86400 ) {
const range = [ this.timestampToDate( start, "MMM DD YYYY" ) ];
if ( this.timestampToDate( start, "MMM DD YYYY" ) === this.timestampToDate( end, "MMM DD YYYY" ) ) {
return range;
}
let newItem = +start;
while ( newItem < +end ) {
range.push( this.timestampToDate( newItem += step, "MMM DD YYYY" ) );
}
return range;
},
getRemainingItemCount: function ( attributes ) {
return attributes && attributes.length > this.maxItemInCell ? attributes.length - this.maxItemInCell : 0;
},
showMore: function ( day ) {
const date = this.objectTimeToTimestamp( new Date( day.year, day.month -1, day.day ) );
const newFilters = Object.assign( {}, this.currentFilters, { 'date': date } );
store.commit( 'setValue', {
key: 'currentFilters',
value: newFilters
} );
store.commit( 'setValue', {
key: 'currentView',
value: 'list'
} );
this.pageUrl.searchParams.set( 'view', 'list' );
window.history.pushState( null, '', this.pageUrl.toString() );
store.dispatch( 'getItems' );
},
mouseEnter: function ( event ) {
jQuery( '.jet-abaf-calendar-day-booking' ).each( function() {
if ( jQuery( event.target ).data( 'booking-id' ) === jQuery( this ).data( 'booking-id' ) ) {
jQuery( this ).find( '.jet-abaf-booking-data' ).addClass( 'active' );
}
} );
},
mouseLeave: function ( event ) {
jQuery( '.jet-abaf-calendar-day-booking' ).each( function() {
if ( jQuery( event.target ).data( 'booking-id' ) === jQuery( this ).data( 'booking-id' ) ) {
jQuery( this ).find( '.jet-abaf-booking-data' ).removeClass( 'active' );
}
} );
},
},
});
Vue.component('jet-abaf-bookings-timeline', {
template: '#jet-abaf-bookings-timeline',
mixins: [ itemsMethods, statusMixin ],
components: {
vuejsDatepicker: window.vuejsDatepicker,
},
data() {
return {
dateFormat: 'MMMM yyyy',
selectedDate: moment().format("MMMM YYYY")
}
},
computed: {
startTime: function () {
return moment( this.selectedDate, 'MMMM YYYY' ).startOf( 'month' ).format( 'YYYY-MM-DD' );
},
endTime: function () {
return moment( this.selectedDate, 'MMMM YYYY' ).endOf( 'month' ).format( 'YYYY-MM-DD' );
},
...Vuex.mapState( {
itemsList: function ( state ) {
const self = this;
let itemsList = [];
state.itemsList.map( function ( item ) {
let apartmentID = +item.apartment_id;
if ( ! itemsList[ apartmentID ] ) {
itemsList[ apartmentID ] = {
id: apartmentID,
instance: self.getItemLabel( apartmentID ),
gtArray: []
}
}
itemsList[ apartmentID ].gtArray.push( {
id: +item.booking_id,
start: moment( +item.check_in_date_timestamp, 'X' ).startOf( 'day' ).format( 'YYYY-MM-DD HH:mm:ss' ),
end: moment( +item.check_out_date_timestamp, 'X' ).endOf( 'day' ).format( 'YYYY-MM-DD HH:mm:ss' ),
customData:{ ...item }
} );
} );
itemsList = itemsList.filter( item => item );
return itemsList;
}
} )
},
watch: {
selectedDate() {
this.adjustHeight();
this.$refs.gantt.scrollToPostionHandle( { x:0, y:0 } )
}
},
updated: function () {
this.adjustHeight();
},
methods: {
adjustHeight: function () {
const leftBarItems = jQuery( '.gantt-leftbar-item:not( .gantt-block-top-space )' );
jQuery( '.gantt-block:not(.gantt-block-top-space)' ).each( function( index ) {
const ganttBlock = jQuery( this );
setTimeout( function() {
leftBarItems[ index ].style.setProperty( 'height', ganttBlock.outerHeight() - 1 + 'px', 'important' );
}, 0 );
} );
},
callPopup: function ( state = false, item = false ) {
eventHub.$emit( 'call-popup', {
item: item,
state: state
} );
}
},
});
Vue.component( 'jet-abaf-add-new-booking', {
template: '#jet-abaf-add-new-booking',
mixins: [ fieldsManager ],
data: function () {
return {
addDialog: false,
newItem: {
status: '',
apartment_id: '',
check_in_date: '',
check_out_date: '',
},
datePickerFormat: 'dd-MM-yyyy',
dateMomentFormat: 'DD-MM-YYYY',
createRelatedOrder: false,
bookingOrderStatus: 'draft',
wcOrderFirstName: '',
wcOrderLastName: '',
wcOrderEmail: '',
wcOrderPhone: '',
submitting: false
}
},
computed: {
...Vuex.mapState( {
bookingMode: state => state.booking_mode,
statuses: state => state.all_statuses,
bookingInstances: state => state.bookings,
orderPostType: state => state.order_post_type,
orderPostTypeStatuses: state => state.order_post_type_statuses,
wcIntegration: state => state.wc_integration,
overlappingBookings: 'overlappingBookings',
fields: function ( state ) {
return [ ...state.columns, ...state.additional_columns ];
}
} ),
computedNewItem: function () {
return Object.assign( {}, this.newItem );
}
},
watch: {
computedNewItem: {
handler: function ( value, oldValue ) {
if ( ! Object.keys( value ).length || ! Object.keys( oldValue ).length ) {
return;
}
if ( ! value.apartment_id.length || ! value?.check_in_date?.length || ! value?.check_out_date?.length ) {
return;
}
if (
value.apartment_id !== oldValue.apartment_id
|| value.check_in_date && ! moment( value.check_in_date ).isSame( oldValue.check_in_date, 'day' )
|| value.check_out_date && ! moment( value.check_out_date ).isSame( oldValue.check_out_date, 'day' )
) {
this.getBookingPrice( value );
}
},
deep: true,
},
},
methods: {
showAddDialog: function () {
this.addDialog = true;
store.commit( 'setValue', {
key: 'overlappingBookings',
value: false
} );
store.commit( 'setValue', {
key: 'isDisabled',
value: true
} );
store.commit( 'setValue', {
key: 'bookingPrice',
value: 0
} );
store.commit( 'setValue', {
key: 'bookingItem',
value: this.newItem
} );
if ( this.newItem.apartment_id.length ) {
this.initDateRangePicker();
this.getBookingPrice( this.newItem );
}
},
checkRequiredFields: function () {
let requiredFields = [ 'status', 'apartment_id', 'check_in_date', 'check_out_date' ],
emptyFields = [],
invalidFields = [],
message = '';
for ( let field of requiredFields ) {
if ( ! this.newItem[ field ].length ) {
switch ( field ) {
case 'status':
emptyFields.push( 'Status' );
break;
case 'apartment_id':
emptyFields.push( 'Booking item' );
break;
case 'check_in_date':
emptyFields.push( 'Check in/out' );
break;
}
}
}
if ( (this.wcIntegration && this.createRelatedOrder) || 'wc_based' === this.bookingMode ) {
if ( ! this.wcOrderFirstName.length ) {
emptyFields.push( 'First name' );
}
if ( ! this.wcOrderLastName.length ) {
emptyFields.push( 'Last name' );
}
if ( ! this.wcOrderEmail.length ) {
emptyFields.push( 'Email' );
} else {
if ( ! this.wcOrderEmail.match( /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/ ) ) {
invalidFields.push( 'Email' );
}
}
}
if ( ! emptyFields.length && ! invalidFields.length ) {
return true;
} else if ( emptyFields.length ) {
emptyFields = emptyFields.join( ', ' ).toLowerCase();
message = sprintf( __( 'Empty fields: %s.', 'jet-booking' ), emptyFields );
} else if ( invalidFields.length ) {
invalidFields = invalidFields.join( ', ' ).toLowerCase();
message = sprintf( __( 'Invalid value fields: %s.', 'jet-booking' ), invalidFields );
}
eventHub.$CXNotice.add( {
message: message,
type: 'error',
duration: 7000,
} );
return false;
},
handleAdd: function () {
let self = this;
self.addDialog = true;
if ( ! self.checkRequiredFields() ) {
return;
}
store.commit( 'setValue', {
key: 'overlappingBookings',
value: false
} );
const data = {
item: self.newItem
}
if ( (self.createRelatedOrder && self.wcIntegration) || 'wc_based' === this.bookingMode ) {
data.relatedOrder = {
firstName: self.wcOrderFirstName,
lastName: self.wcOrderLastName,
email: self.wcOrderEmail,
phone: self.wcOrderPhone,
}
} else if ( self.createRelatedOrder && self.orderPostType ) {
data.relatedOrder = {
orderStatus: self.bookingOrderStatus
};
}
self.submitting = true;
wp.apiFetch( {
method: 'post',
path: window.JetABAFConfig.api.add_booking,
data: data
} ).then( function ( response ) {
if ( ! response.success ) {
if ( response.overlapping_bookings ) {
eventHub.$CXNotice.add( {
message: response.data,
type: 'error',
duration: 7000,
} );
store.commit( 'setValue', {
key: 'overlappingBookings',
value: response.html
} );
self.initDateRangePicker();
self.submitting = false;
return;
} else {
eventHub.$CXNotice.add( {
message: response.data,
type: 'error',
duration: 7000,
} );
}
} else {
self.addDialog = false;
eventHub.$CXNotice.add( {
message: 'Done!',
type: 'success',
duration: 7000,
} );
store.dispatch( 'getItems' );
}
self.newItem = { status: '', apartment_id: '', check_in_date: '', check_out_date: '' };
self.createRelatedOrder = false;
self.bookingOrderStatus = 'draft';
self.wcOrderFirstName = '';
self.wcOrderLastName = '';
self.wcOrderEmail = '';
self.wcOrderPhone = '';
self.submitting = false;
} ).catch( function ( e ) {
eventHub.$CXNotice.add( {
message: e.message,
type: 'error',
duration: 7000,
} );
} );
}
}
} );
Vue.component( 'jet-abaf-popup', {
template: '#jet-abaf-popup',
mixins: [ fieldsManager, itemsMethods, statusMixin ],
data: function () {
return {
calculateTotals: false,
currentItem: false,
editDialog: false,
isShow: false,
popUpState: '',
recalculateTotals: false,
submitting: false
};
},
computed: {
...Vuex.mapState( {
overlappingBookings: 'overlappingBookings',
bookingInstances: state => state.bookings,
bookingMode: state => state.booking_mode,
statuses: state => state.all_statuses
} ),
computedCurrentItem: function () {
return Object.assign( {}, this.currentItem );
}
},
watch: {
computedCurrentItem: {
handler: function ( value, oldValue ) {
if ( ! Object.keys( value ).length || ! Object.keys( oldValue ).length ) {
return;
}
if (
value.apartment_id !== oldValue.apartment_id
|| value.check_in_date && ! moment( value.check_in_date ).isSame( +oldValue.check_in_date, 'day' )
|| value.check_out_date && ! moment( value.check_out_date ).isSame( +oldValue.check_out_date, 'day' )
) {
if ( 'wc_based' === this.bookingMode ) {
this.recalculateTotals = true;
}
this.getBookingPrice( value );
}
},
deep: true,
},
editDialog ( value ) {
if ( ! value ) {
this.currentItem = false;
this.recalculateTotals = false;
this.calculateTotals = false;
}
}
},
mounted: function () {
eventHub.$on( 'call-popup', this.callPopup );
eventHub.$on( 'cancel-popup', this.cancelPopup );
},
methods: {
callPopup: function ( { state, item } ) {
this.isShow = true;
this.popUpState = state;
this.currentItem = item;
if ( 'info' === state ) {
this.getBookingPrice( item );
} else if ( 'update' === state ) {
this.openUpdatePopup( item );
}
},
cancelPopup: function () {
this.isShow = false ;
this.popUpState = '';
this.currentItem = false;
},
updateDetailsItem: function ( item ) {
this.popUpState = 'update';
this.openUpdatePopup( item );
},
openUpdatePopup: function ( item ) {
this.editDialog = true;
store.commit( 'setValue', {
key: 'overlappingBookings',
value: false
} );
this.currentItem = JSON.parse( JSON.stringify( item ) );
this.currentItem.check_in_date = moment.unix( this.currentItem.check_in_date_timestamp ).utc().format( 'YYYY-MM-DD' );
this.currentItem.check_out_date = moment.unix( this.currentItem.check_out_date_timestamp ).utc().format( 'YYYY-MM-DD' );
store.commit( 'setValue', {
key: 'bookingPrice',
value: 0
} );
store.commit( 'setValue', {
key: 'bookingItem',
value: this.currentItem
} );
this.initDateRangePicker();
this.getBookingPrice( this.currentItem );
},
updateItem: function () {
let self = this;
self.editDialog = true;
if ( ! self.currentItem ) {
return;
}
store.commit( 'setValue', {
key: 'overlappingBookings',
value: false
} );
if ( ! self.itemUnits.length ) {
self.currentItem.apartment_unit = null;
}
const data = {
item: self.currentItem
}
if ( 'wc_based' === self.bookingMode ) {
data.calculateTotals = self.calculateTotals;
}
self.submitting = true;
wp.apiFetch( {
method: 'post',
path: window.JetABAFConfig.api.update_booking + self.currentItem.booking_id + '/',
data: data
} ).then( function ( response ) {
if ( ! response.success ) {
if ( response.overlapping_bookings ) {
self.$CXNotice.add( {
message: response.data,
type: 'error',
duration: 7000,
} );
store.commit( 'setValue', {
key: 'overlappingBookings',
value: response.html
} );
self.initDateRangePicker();
self.submitting = false;
return;
} else {
self.$CXNotice.add( {
message: response.data,
type: 'error',
duration: 7000,
} );
}
} else {
self.editDialog = false;
self.$CXNotice.add( {
message: 'Done!',
type: 'success',
duration: 7000,
} );
store.dispatch( 'getItems' );
}
self.recalculateTotals = false;
self.calculateTotals = false;
self.submitting = false;
self.cancelPopup();
} ).catch( function ( e ) {
self.$CXNotice.add( {
message: e.message,
type: 'error',
duration: 7000,
} );
self.recalculateTotals = false;
self.calculateTotals = false;
self.submitting = false;
self.cancelPopup();
} );
},
deleteDetailsItem: function () {
this.popUpState = 'delete';
},
deleteItem: function () {
const self = this;
if ( ! self.currentItem ) {
return;
}
self.submitting = true;
wp.apiFetch( {
method: 'delete',
path: window.JetABAFConfig.api.delete_booking + self.currentItem.booking_id + '/',
} ).then( function ( response ) {
if ( ! response.success ) {
self.$CXNotice.add( {
message: response.data,
type: 'error',
duration: 7000,
} );
}
store.commit( 'setValue', {
key: 'offset',
value: 0
} );
store.commit( 'setValue', {
key: 'pageNumber',
value: 1
} );
store.dispatch( 'getItems' );
self.submitting = false;
self.cancelPopup();
} ).catch( function ( e ) {
self.$CXNotice.add( {
message: e.message,
type: 'error',
duration: 7000,
} );
self.cancelPopup();
} );
},
},
} );
new Vue( {
el: '#jet-abaf-bookings-page',
template: '#jet-abaf-bookings',
store,
computed: Vuex.mapState( {
isSet: state => state.setup.is_set,
bookingsList: state => state.bookings_list,
currentView: state => `jet-abaf-bookings-${ state.currentView }`,
isLoading: 'isLoading',
pageUrl: 'pageUrl',
perPage: 'perPage',
} ),
created: function () {
if ( this.pageUrl.searchParams.has( 'booking-details' ) ) {
const index = this.bookingsList.reverse().findIndex( item => item.booking_id === this.pageUrl.searchParams.get( 'booking-details' ) );
const page = Math.ceil( ( index + 1 ) / this.perPage ) || 1;
store.commit( 'setValue', {
key: 'offset',
value: this.perPage * ( page - 1 )
} );
store.commit( 'setValue', {
key: 'pageNumber',
value: page
} );
}
if ( this.pageUrl.searchParams.has( 'view' ) ) {
const view = [ 'list', 'calendar', 'timeline' ].includes( this.pageUrl.searchParams.get( 'view' ) ) ? this.pageUrl.searchParams.get( 'view' ) : 'list';
store.commit( 'setValue', {
key: 'currentView',
value: view
} );
}
store.dispatch( 'getItems' );
},
} );
})();