# Conflicts: # .DS_Store # src/client/app/tmpl/home-appointment-item.htmlbeta
| @@ -2,7 +2,7 @@ | |||
| require_once __DIR__ . '/../../server/server/config/boot_global.php'; | |||
| require_once __DIR__ . '/../../server/server/config/boot_local.php'; | |||
| $version = time();//Francis_Utils_Config::get( 'version' ); | |||
| $version = 1;//time();//Francis_Utils_Config::get( 'version' ); | |||
| ?> | |||
| <!DOCTYPE html> | |||
| <html lang="en"> | |||
| @@ -176,6 +176,10 @@ app.core.Controller = (function(){ | |||
| { | |||
| app.core.StateManager.switchTo( new app.state.ConfigurationProfileEdit(), r.params ); | |||
| }); | |||
| rlite.add( 'configuration/subprofile/edit', function( r ) | |||
| { | |||
| app.core.StateManager.switchTo( new app.state.ConfigurationSubProfileEdit(), r.params ); | |||
| }); | |||
| rlite.add( 'configuration/profile/delete', function( r ) | |||
| { | |||
| app.core.StateManager.switchTo( new app.state.ConfigurationProfileDelete(), r.params ); | |||
| @@ -269,14 +269,14 @@ app.model.Appointment = function( appData, attendees, attendeeProfiles ) | |||
| * @param profileId | |||
| * @returns {boolean} | |||
| */ | |||
| this.hasProfileIdAccepted = function( profileId ) | |||
| this.hasProfileIdAccepted = function( profileId, profileChildId = null ) | |||
| { | |||
| return ( "accepted" === this.getAttendeeStatusForProfileId( profileId ) ); | |||
| return ( "accepted" === this.getAttendeeStatusForProfileId( profileId, profileChildId ) ); | |||
| }; | |||
| this.hasProfileIdAttended = function( profileId ) | |||
| this.hasProfileIdAttended = function( profileId, profileChildId = null ) | |||
| { | |||
| return ( "attended" === this.getAttendeeHasAttendedValueForProfileId( profileId ) ); | |||
| return ( "attended" === this.getAttendeeHasAttendedValueForProfileId( profileId, profileChildId ) ); | |||
| }; | |||
| /** | |||
| @@ -290,7 +290,8 @@ app.model.Appointment = function( appData, attendees, attendeeProfiles ) | |||
| for ( var ai = 0; ai < attendees.length; ai++ ) | |||
| { | |||
| if ( attendees[ ai ].profile_id == profileId && attendees[ ai ].status.length > 0 ) | |||
| if ( attendees[ ai ].profile_id == profileId && | |||
| attendees[ ai ].status.length > 0 ) | |||
| { | |||
| attendee = this.getProfileById( profileId ); | |||
| break; | |||
| @@ -300,6 +301,24 @@ app.model.Appointment = function( appData, attendees, attendeeProfiles ) | |||
| return attendee; | |||
| }; | |||
| this.findAttendeeStatusByProfileIdAndChildId = function( profileId, childId = null ) | |||
| { | |||
| let as = null; | |||
| for ( var ai = 0; ai < attendees.length; ai++ ) | |||
| { | |||
| if ( attendees[ ai ].profile_id == profileId && | |||
| attendees[ ai ].profile_child_id == childId && | |||
| attendees[ ai ].status.length > 0 ) | |||
| { | |||
| as = attendees[ ai ]; | |||
| break; | |||
| } | |||
| } | |||
| return as; | |||
| }; | |||
| this.hasContractAttendances = function() | |||
| { | |||
| var r = false; | |||
| @@ -321,6 +340,76 @@ app.model.Appointment = function( appData, attendees, attendeeProfiles ) | |||
| return attendees; | |||
| }; | |||
| this.getAttendeeDataByStatus = function( status ) | |||
| { | |||
| let ad = []; | |||
| for ( let ai = 0; ai < attendees.length; ai++ ) | |||
| { | |||
| if ( attendees[ ai ].status == status ) | |||
| { | |||
| ad.push( attendees[ ai ] ); | |||
| } | |||
| } | |||
| return ad; | |||
| }; | |||
| this.getAttendeeProfilesByStatus = function( status ) | |||
| { | |||
| let ad = this.getAttendeeDataByStatus( status ), | |||
| ap = [], | |||
| p = null; | |||
| for ( let ai = 0; ai < ad.length; ai++ ) | |||
| { | |||
| p = this.getProfileById( ad[ ai ].profile_id ); | |||
| if ( p ) | |||
| { | |||
| ap.push( | |||
| { | |||
| "profile" : p, | |||
| "profileChildId" : ad[ ai ].profile_child_id | |||
| } | |||
| ); | |||
| } | |||
| } | |||
| return ap; | |||
| }; | |||
| this.hasProfileIdStatus = function( profileId, status ) | |||
| { | |||
| var has = false; | |||
| for ( var ai = 0; ai < attendees.length; ai++ ) | |||
| { | |||
| if ( attendees[ ai ].status == status && attendees[ ai ].profile_id == profileId ) | |||
| { | |||
| has = true; | |||
| break; | |||
| } | |||
| } | |||
| return has; | |||
| }; | |||
| this.hasProfileAndChildIdStatus = function( profileId, childId, status ) | |||
| { | |||
| var has = false; | |||
| for ( var ai = 0; ai < attendees.length; ai++ ) | |||
| { | |||
| if ( attendees[ ai ].status == status && | |||
| attendees[ ai ].profile_id == profileId && | |||
| attendees[ ai ].profile_child_id == childId ) | |||
| { | |||
| has = true; | |||
| break; | |||
| } | |||
| } | |||
| return has; | |||
| }; | |||
| this.getAttendeesAccepted = function() | |||
| { | |||
| var attendeesAccepted = []; | |||
| @@ -329,7 +418,8 @@ app.model.Appointment = function( appData, attendees, attendeeProfiles ) | |||
| { | |||
| if ( attendees[ ai ].status == "accepted" ) | |||
| { | |||
| attendeesAccepted.push( this.getProfileById( attendees[ ai ].profile_id ) ); | |||
| //attendeesAccepted.push( this.getProfileById( attendees[ ai ].profile_id ) ); | |||
| attendeesAccepted.push( attendees[ ai ] ); | |||
| } | |||
| } | |||
| @@ -359,7 +449,8 @@ app.model.Appointment = function( appData, attendees, attendeeProfiles ) | |||
| { | |||
| if ( attendees[ ai ].status == "declined" ) | |||
| { | |||
| attendeesDeclined.push( this.getProfileById( attendees[ ai ].profile_id ) ); | |||
| //attendeesDeclined.push( this.getProfileById( attendees[ ai ].profile_id ) ); | |||
| attendeesDeclined.push( attendees[ ai ] ); | |||
| } | |||
| } | |||
| @@ -389,7 +480,8 @@ app.model.Appointment = function( appData, attendees, attendeeProfiles ) | |||
| { | |||
| if ( attendees[ ai ].status == "waiting" ) | |||
| { | |||
| attendeesWaiting.push( this.getProfileById( attendees[ ai ].profile_id ) ); | |||
| //attendeesWaiting.push( this.getProfileById( attendees[ ai ].profile_id ) ); | |||
| attendeesWaiting.push( attendees[ ai ] ); | |||
| } | |||
| } | |||
| @@ -428,7 +520,8 @@ app.model.Appointment = function( appData, attendees, attendeeProfiles ) | |||
| { | |||
| if ( attendees[ ai ].has_attended == "attended" ) | |||
| { | |||
| attendeesAttended.push( this.getProfileById( attendees[ ai ].profile_id ) ); | |||
| //attendeesAttended.push( this.getProfileById( attendees[ ai ].profile_id ) ); | |||
| attendeesAttended.push( attendees[ ai ].profile_id ); | |||
| } | |||
| } | |||
| @@ -444,7 +537,8 @@ app.model.Appointment = function( appData, attendees, attendeeProfiles ) | |||
| if ( attendees[ ai ].status == "accepted" && | |||
| attendees[ ai ].has_attended == "declined" ) | |||
| { | |||
| attendeesNotAttended.push( this.getProfileById( attendees[ ai ].profile_id ) ); | |||
| //attendeesNotAttended.push( this.getProfileById( attendees[ ai ].profile_id ) ); | |||
| attendeesNotAttended.push( attendees[ ai ].profile_id ); | |||
| } | |||
| } | |||
| @@ -565,13 +659,13 @@ app.model.Appointment = function( appData, attendees, attendeeProfiles ) | |||
| * @param profileId | |||
| * @returns {*} | |||
| */ | |||
| this.getAttendeeStatusForProfileId = function( profileId ) | |||
| this.getAttendeeStatusForProfileId = function( profileId, profileChildId = null ) | |||
| { | |||
| var status = null; | |||
| for ( var ai = 0; ai < attendees.length; ai++ ) | |||
| { | |||
| if ( attendees[ ai ].profile_id == profileId ) | |||
| if ( attendees[ ai ].profile_id == profileId && profileChildId == attendees[ ai ].profile_child_id ) | |||
| { | |||
| status = attendees[ ai ].status; | |||
| break; | |||
| @@ -581,11 +675,11 @@ app.model.Appointment = function( appData, attendees, attendeeProfiles ) | |||
| return status; | |||
| }; | |||
| this.setAttendeeStatusForProfileId = function( profileId, status ) | |||
| this.setAttendeeStatusForProfileId = function( profileId, status, profileChildId = null ) | |||
| { | |||
| for ( var ai = 0; ai < attendees.length; ai++ ) | |||
| { | |||
| if ( attendees[ ai ].profile_id == profileId ) | |||
| if ( attendees[ ai ].profile_id == profileId && attendees[ ai ].profile_child_id == profileChildId ) | |||
| { | |||
| attendees[ ai ].status = status; | |||
| break; | |||
| @@ -31,6 +31,7 @@ app.model.Profile = function( data, groupsData ) | |||
| groups = [], | |||
| teamProps = data.team_prop_js || {}, | |||
| teamCategoryIds = data.team_category_ids_js || [], | |||
| childProfiles = data.child_profile_js || [], | |||
| createdDt = data.created_dt, | |||
| // Note: Emails are optional | |||
| email = null; | |||
| @@ -393,7 +394,7 @@ app.model.Profile = function( data, groupsData ) | |||
| return lastName; | |||
| }; | |||
| this.getName = function( groupId ) | |||
| this.getName = function( groupId, childId = null ) | |||
| { | |||
| var name = ''; | |||
| @@ -434,6 +435,12 @@ app.model.Profile = function( data, groupsData ) | |||
| } | |||
| } | |||
| if ( name && name.length > 0 && childId ) | |||
| { | |||
| let child = this.getChildProfileById( childId ); | |||
| } | |||
| if ( name.length === 0 ) | |||
| { | |||
| return _lc( 'UNKNOWN_NAME' ); | |||
| @@ -573,5 +580,120 @@ app.model.Profile = function( data, groupsData ) | |||
| } | |||
| } | |||
| return cn; | |||
| }; | |||
| this.hasMultipleChilds = function() | |||
| { | |||
| return ( this.getChildProfiles().length > 0 ); | |||
| }; | |||
| this.getChildProfiles = function() | |||
| { | |||
| let cp = []; | |||
| for ( let cpi = 0; cpi < childProfiles.length; cpi++ ) | |||
| { | |||
| if ( false === childProfiles[ cpi ].deleted ) | |||
| { | |||
| cp.push( childProfiles[ cpi ] ); | |||
| } | |||
| } | |||
| return cp; | |||
| }; | |||
| this.getChildProfileById = function( id ) | |||
| { | |||
| let cp = null; | |||
| for ( let cpi = 0; cpi < childProfiles.length; cpi++ ) | |||
| { | |||
| if ( id == childProfiles[ cpi ].id ) | |||
| { | |||
| cp = childProfiles[ cpi ]; | |||
| break; | |||
| } | |||
| } | |||
| return cp; | |||
| }; | |||
| this.getChildProfileHtmlTagById = function ( id ) | |||
| { | |||
| let html = '', | |||
| cp = this.getChildProfileById( id ); | |||
| if ( cp ) | |||
| { | |||
| html += '<i class="' + this.getChildProfileIconByType( cp.type ) + '"></i> ' + cp.name; | |||
| } | |||
| return html; | |||
| }; | |||
| this.getChildProfileNameByType = function( type ) | |||
| { | |||
| let typeName = ''; | |||
| switch( type ) | |||
| { | |||
| case 'child': | |||
| typeName = 'Kind' | |||
| break; | |||
| case 'person': | |||
| typeName = 'Person' | |||
| break; | |||
| case 'cat': | |||
| typeName = 'Katze' | |||
| break; | |||
| case 'horse': | |||
| typeName = 'Pferd' | |||
| break; | |||
| case 'dog': | |||
| typeName = 'Hund' | |||
| break; | |||
| default: | |||
| case 'other': | |||
| typeName = 'keine Angabe' | |||
| break; | |||
| } | |||
| return typeName; | |||
| }; | |||
| this.getChildProfileIconByType = function( type ) | |||
| { | |||
| let iconCss = ''; | |||
| switch( type ) | |||
| { | |||
| case 'child': | |||
| iconCss = 'fas fa-child'; | |||
| break; | |||
| case 'person': | |||
| iconCss = 'fas fa-user'; | |||
| break; | |||
| case 'cat': | |||
| iconCss = 'fas fa-cat'; | |||
| break; | |||
| case 'horse': | |||
| iconCss = 'fas fa-horse'; | |||
| break; | |||
| case 'dog': | |||
| iconCss = 'fas fa-dog'; | |||
| break; | |||
| default: | |||
| case 'other': | |||
| iconCss = 'fas fa-question-circle'; | |||
| break; | |||
| } | |||
| return iconCss; | |||
| } | |||
| }; | |||
| @@ -55,6 +55,10 @@ app.model.SessionUser = (function() | |||
| } | |||
| } | |||
| }, | |||
| udpateUserProfile : function( ud ) | |||
| { | |||
| userProfile = new app.model.Profile( ud ); | |||
| }, | |||
| setUserProfile : function( newProfile ) | |||
| { | |||
| userProfile = newProfile; | |||
| @@ -28,19 +28,50 @@ app.state.AppointmentEditAttendee = function() | |||
| function( res ) | |||
| { | |||
| appointment = new app.model.Appointment( res.appointment, res.attendee_data, res.attendee_profiles ); | |||
| app.core.Rpc.call( | |||
| 'Team', | |||
| 'getMembers', | |||
| { teamId : appointment.getTeamId() }, | |||
| function( res2 ) | |||
| { | |||
| let childs, m, notDecided = []; | |||
| for ( var tmi = 0; tmi < res2.members.length; tmi++ ) | |||
| { | |||
| m = new app.model.Profile( res2.members[ tmi ] ); | |||
| if ( null === appointment.findAttendeeStatusByProfileIdAndChildId( m.getId() ) ) | |||
| { | |||
| notDecided.push( | |||
| { | |||
| profile : m, | |||
| child : null | |||
| } | |||
| ); | |||
| } | |||
| childs = m.getChildProfiles(); | |||
| if ( childs && childs.length > 0 ) | |||
| { | |||
| for ( let ci = 0; ci < childs.length; ci++ ) | |||
| { | |||
| if ( null === appointment.findAttendeeStatusByProfileIdAndChildId( m.getId(), childs[ ci ].id ) ) | |||
| { | |||
| notDecided.push( | |||
| { | |||
| profile: m, | |||
| child : m.getChildProfileById( childs[ ci ].id ) | |||
| } | |||
| ); | |||
| } | |||
| } | |||
| } | |||
| /* | |||
| if ( null == appointment.getAttendeeByProfileId( res2.members[ tmi ].id ) ) | |||
| { | |||
| notDecidedMember.push( new app.model.Profile( res2.members[ tmi ] )); | |||
| } | |||
| */ | |||
| } | |||
| app.core.View.setContent( | |||
| @@ -48,7 +79,7 @@ app.state.AppointmentEditAttendee = function() | |||
| 'appointment-edit-attendee', | |||
| { | |||
| a: appointment, | |||
| members : notDecidedMember | |||
| notDecided : notDecided | |||
| } | |||
| ) | |||
| ); | |||
| @@ -90,6 +121,7 @@ app.state.AppointmentEditAttendee = function() | |||
| statusChanges.push({ | |||
| appointmentId : appointmentId, | |||
| profileId : $checkbox.attr( 'data-profile-id' ), | |||
| profileChildId : $checkbox.attr( 'data-child-profile-id' ), | |||
| status : 'accepted', | |||
| isLastInBatch : false | |||
| }); | |||
| @@ -100,6 +132,7 @@ app.state.AppointmentEditAttendee = function() | |||
| statusChanges.push({ | |||
| appointmentId : appointmentId, | |||
| profileId : $checkbox.attr( 'data-profile-id' ), | |||
| profileChildId : $checkbox.attr( 'data-child-profile-id' ), | |||
| status : 'declined', | |||
| isLastInBatch : false | |||
| }); | |||
| @@ -119,6 +152,7 @@ app.state.AppointmentEditAttendee = function() | |||
| appointmentId : appointmentId, | |||
| processSerial : isSerial, | |||
| profileId : $select.attr( 'data-profile-id' ), | |||
| profileChildId : $select.attr( 'data-child-profile-id' ), | |||
| status : $select.val(), | |||
| isLastInBatch : false | |||
| }); | |||
| @@ -22,7 +22,6 @@ app.state.ConfigurationContract = function() | |||
| null, | |||
| function( res ) | |||
| { | |||
| console.log( res ); | |||
| if ( res && res.hasOwnProperty( 'contractData' ) ) | |||
| { | |||
| for ( let ci = 0; ci < res.contractData.length; ci++ ) | |||
| @@ -48,21 +48,6 @@ app.state.ConfigurationProfileEdit = function() | |||
| birthday = $form.find( '[data-id="input-birthday"]' ).first().val(); | |||
| } | |||
| // Special group properties | |||
| if ( profile.isInGroupCategory( 'DOGSCHOOL' ) ) | |||
| { | |||
| if ( null === teamProps ) | |||
| { | |||
| teamProps = {}; | |||
| } | |||
| if ( !teamProps.hasOwnProperty( 'DOGSCHOOL' ) ) | |||
| { | |||
| teamProps[ 'DOGSCHOOL' ] = {}; | |||
| } | |||
| teamProps[ 'DOGSCHOOL' ][ 'dogname'] = $form.find( '[data-id="input-dogschool-dogname"]' ).first().val(); | |||
| } | |||
| app.core.Rpc.call( | |||
| 'Profile', | |||
| 'update', | |||
| @@ -0,0 +1,205 @@ | |||
| /** | |||
| * (c) by aheadware.com | |||
| */ | |||
| var app = app || {}; | |||
| app.state = app.state || {}; | |||
| app.state.ConfigurationSubProfileEdit = function() | |||
| { | |||
| var state = app.core.StateManager.createState( 'configuration-subprofile-edit' ); | |||
| state.onEnter = function( p ) | |||
| { | |||
| let $content = app.core.View.getContent(); | |||
| app.gui.PageLoader.show(); | |||
| app.core.Rpc.call( | |||
| 'Account', | |||
| 'getAccountRelatedData', | |||
| null, | |||
| function( res ) | |||
| { | |||
| var profile = new app.model.Profile( res.profile, res.own_teams ); | |||
| app.core.View.setContent( | |||
| app.core.View.getTemplate( | |||
| 'configuration-subprofile-edit', | |||
| { | |||
| p : profile | |||
| } | |||
| ) | |||
| ); | |||
| $content.find( '[data-id="btn-add-subprofile"]' ).click( function() | |||
| { | |||
| var fnAddSubProfile = function() | |||
| { | |||
| var $modalContent = app.core.View.getModalContent(), | |||
| $form = $modalContent.find( '[data-id="form-subprofile"]' ).first(), | |||
| isValid = app.util.Form.bootstrapValidate( $form ); | |||
| if ( isValid ) | |||
| { | |||
| app.core.View.closeModal(); | |||
| app.gui.PageLoader.show(); | |||
| app.core.Rpc.call( | |||
| 'Profile', | |||
| 'addSubProfile', | |||
| { | |||
| subProfileName : $form.find( '[data-id="input-subprofile-name"]' ).first().val(), | |||
| subProfileType : $form.find( '[data-id="select-subprofile-type"]' ).first().val() | |||
| }, | |||
| function( res ) | |||
| { | |||
| if ( res && res.hasOwnProperty( 'profile' ) ) | |||
| { | |||
| app.model.SessionUser.udpateUserProfile( res.profile ); | |||
| } | |||
| app.core.View.toastSuccess( 'Unterprofil erfolgreich erstellt.' ); | |||
| app.core.Controller.reload(); | |||
| } | |||
| ); | |||
| } | |||
| }.bind( this ); | |||
| app.core.View.showModal( | |||
| { | |||
| 'title' : 'Neues Unterprofil hinzufügen', | |||
| 'body' : app.core.View.getTemplate( 'configuration-subprofile-modal-form', { sp : null } ), | |||
| 'okButtonText' : "Speichern", | |||
| 'onConfirm' : fnAddSubProfile | |||
| } | |||
| ); | |||
| }); | |||
| $content.find( '[data-type="editSubProfile"]' ).click( function() | |||
| { | |||
| const childProfileId = $(this).attr( 'data-subprofile-id' ), | |||
| childProfile = profile.getChildProfileById( childProfileId ); | |||
| var fnUpdateSubprofile = function() | |||
| { | |||
| var $modalContent = app.core.View.getModalContent(), | |||
| $form = $modalContent.find( '[data-id="form-subprofile"]' ).first(), | |||
| isValid = app.util.Form.bootstrapValidate( $form ); | |||
| if ( isValid ) | |||
| { | |||
| app.core.View.closeModal(); | |||
| app.gui.PageLoader.show(); | |||
| app.core.Rpc.call( | |||
| 'Profile', | |||
| 'updateSubProfile', | |||
| { | |||
| subProfileId : childProfileId, | |||
| subProfileName : $form.find( '[data-id="input-subprofile-name"]' ).first().val(), | |||
| subProfileType : $form.find( '[data-id="select-subprofile-type"]' ).first().val() | |||
| }, | |||
| function( res ) | |||
| { | |||
| if ( res && res.hasOwnProperty( 'profile' ) ) | |||
| { | |||
| app.model.SessionUser.udpateUserProfile( res.profile ); | |||
| } | |||
| app.core.View.toastSuccess( 'Unterprofil erfolgreich aktualisiert.' ); | |||
| app.core.Controller.reload(); | |||
| } | |||
| ); | |||
| } | |||
| }.bind( this ); | |||
| app.core.View.showModal( | |||
| { | |||
| 'title' : 'Unterprofil bearbeiten', | |||
| 'body' : app.core.View.getTemplate( 'configuration-subprofile-modal-form', { sp : childProfile } ), | |||
| 'okButtonText' : "Speichern", | |||
| 'onConfirm' : fnUpdateSubprofile | |||
| } | |||
| ); | |||
| }); | |||
| $content.find( '[data-type="deleteSubProfile"]' ).click( function() | |||
| { | |||
| const subProfileId = $( this ).attr( 'data-subprofile-id' ); | |||
| app.core.View.confirm( | |||
| "Soll dieses Unterprofil wirklich gelöscht werden? Alle Profildaten inkl. der Terminzusagen werden unwiderrufbar gelöscht.", | |||
| function() | |||
| { | |||
| app.gui.PageLoader.show(); | |||
| app.core.Rpc.call( | |||
| 'Profile', | |||
| 'deleteSubProfile', | |||
| { | |||
| subProfileId : subProfileId | |||
| }, | |||
| function( res ) | |||
| { | |||
| app.core.View.toastSuccess( 'Unterprofile erfolgreich gelöscht' ); | |||
| app.core.Controller.reload(); | |||
| } | |||
| ); | |||
| }, | |||
| "Ja, löschen" | |||
| ); | |||
| return false; | |||
| }); | |||
| $content.find( '[data-id="btn-save"]' ).click( function() | |||
| { | |||
| let $form = $content.find('[data-id="form-profile"]').first(), | |||
| birthday = null, | |||
| teamProps = profile.getTeamProp(), | |||
| isValid = app.util.Form.bootstrapValidate($form); | |||
| if (isValid) | |||
| { | |||
| app.gui.PageLoader.show(); | |||
| let newChildProfile = null, | |||
| newChildProfileName = $.trim( $form.find('[data-id="input-new-childprofile-name"]').first().val() ), | |||
| newChildProfileType = $form.find('[data-id="select-new-chiildprofile-type"]').first().val() | |||
| if ( newChildProfileName.length > 0 ) | |||
| { | |||
| newChildProfile = { | |||
| "name" : newChildProfileName, | |||
| "type" : newChildProfileType | |||
| }; | |||
| } | |||
| app.core.Rpc.call( | |||
| 'Profile', | |||
| 'update', | |||
| { | |||
| status : $form.find( '[data-id="input-status"]' ).first().val(), | |||
| firstName: $form.find('[data-id="input-firstname"]').first().val(), | |||
| lastName : $form.find('[data-id="input-lastname"]').first().val(), | |||
| birthday : birthday, | |||
| childProfiles : [], | |||
| newChildProfile : newChildProfile, | |||
| teamProps : teamProps | |||
| }, | |||
| function( res ) | |||
| { | |||
| app.gui.PageLoader.hide(); | |||
| app.core.View.toastSuccess( _lc( 'PROFILE_SUCCESSFULLY_UPDATED' ) ); | |||
| app.core.Controller.redirect( '#/configuration/profile' ); | |||
| } | |||
| ); | |||
| } | |||
| }); | |||
| app.gui.PageLoader.hide(); | |||
| } | |||
| ); | |||
| }; | |||
| return state; | |||
| }; | |||
| @@ -23,6 +23,28 @@ app.state.Home = function() | |||
| }; | |||
| }; | |||
| state.getMemberByGroupAndProfileId = function( groupId, profileId ) | |||
| { | |||
| let self = this, | |||
| profile = null; | |||
| if ( false === self.teamMembers.hasOwnProperty( groupId ) ) | |||
| { | |||
| return profile; | |||
| } | |||
| for( let pi = 0; pi < self.teamMembers[ groupId ].length; pi++ ) | |||
| { | |||
| if ( self.teamMembers[ groupId ][ pi ].getId() == profileId ) | |||
| { | |||
| profile = self.teamMembers[ groupId][ pi ]; | |||
| break; | |||
| } | |||
| } | |||
| return profile; | |||
| }; | |||
| state.getMembersForAppointment = function( app, status ) | |||
| { | |||
| let self = this, | |||
| @@ -60,6 +82,141 @@ app.state.Home = function() | |||
| return appMembers; | |||
| }; | |||
| state.onSetAttendanceStatusResult = function( res ) | |||
| { | |||
| if ( false === res.hasOwnProperty( 'err' ) ) | |||
| { | |||
| app.core.View.toastSuccess( _lc( 'SAVED' ) ); | |||
| renderAppointmentItem( new app.model.Appointment( res.appointment, res.attendee_data ) ); | |||
| } | |||
| else | |||
| { | |||
| if ( res.err == 'max_reached' ) | |||
| { | |||
| $rsvpContainer.find( '[data-type="section-rsvp-icon-loading"]' ).first().hide(); | |||
| $rsvpContainer.find( '[data-type="section-rsvp-icon-unchecked"]' ).first().show(); | |||
| app.core.View.confirm( | |||
| _lc( 'MAX_REACHED_DO_YOU_WANT_ON_BE_ADDED_TO_THE_WAITLIST' ), | |||
| function() { | |||
| $rsvpContainer.find( '[data-type="section-rsvp-icon-unchecked"]' ).first().hide(); | |||
| $rsvpContainer.find( '[data-type="section-rsvp-icon-loading"]' ).first().show(); | |||
| app.core.Rpc.call( | |||
| 'Appointment', | |||
| 'setAttendanceStatus', | |||
| { | |||
| appointmentId : appId, | |||
| status : 'waiting' | |||
| }, | |||
| function( res ) | |||
| { | |||
| var newAppointment = new app.model.Appointment( res.appointment, res.attendee_data ); | |||
| app.core.View.toastWarning( | |||
| _lc( | |||
| 'SUCCESSFULLY_ADDED_TO_WAITING_LIST', | |||
| [ | |||
| newAppointment.getWaitingPositionForProfileId( app.model.SessionUser.getUserProfile().getId() ) | |||
| ] | |||
| ) | |||
| ); | |||
| renderAppointmentItem( newAppointment ); | |||
| } | |||
| ); | |||
| }, | |||
| _lc( 'BTN_OK' ), | |||
| ); | |||
| } | |||
| else if ( "deadline_over" === res.err ) | |||
| { | |||
| app.core.View.toastError( _lc( 'DEADLINE_IS_OVER' ) ); | |||
| renderAppointmentItem( getAppointment( appId ) ); | |||
| } | |||
| else | |||
| { | |||
| app.core.View.toastError( _lc( 'GENERAL_SERVER_ERROR' ) ); | |||
| renderAppointmentItem( getAppointment( appId ) ); | |||
| } | |||
| } | |||
| }; | |||
| state.callSetAttendanceStatus = function( appId, status, profileChildId = null ) | |||
| { | |||
| app.core.Rpc.call( | |||
| 'Appointment', | |||
| 'setAttendanceStatus', | |||
| { | |||
| appointmentId : appId, | |||
| status : status, | |||
| profileChildId : profileChildId | |||
| }, | |||
| function( res ) | |||
| { | |||
| if ( false === res.hasOwnProperty( 'err' ) ) | |||
| { | |||
| app.core.View.toastSuccess( _lc( 'SAVED' ) ); | |||
| renderAppointmentItem( new app.model.Appointment( res.appointment, res.attendee_data ) ); | |||
| } | |||
| else | |||
| { | |||
| if ( res.err == 'max_reached' ) | |||
| { | |||
| $rsvpContainer.find( '[data-type="section-rsvp-icon-loading"]' ).first().hide(); | |||
| $rsvpContainer.find( '[data-type="section-rsvp-icon-unchecked"]' ).first().show(); | |||
| app.core.View.confirm( | |||
| _lc( 'MAX_REACHED_DO_YOU_WANT_ON_BE_ADDED_TO_THE_WAITLIST' ), | |||
| function() { | |||
| $rsvpContainer.find( '[data-type="section-rsvp-icon-unchecked"]' ).first().hide(); | |||
| $rsvpContainer.find( '[data-type="section-rsvp-icon-loading"]' ).first().show(); | |||
| app.core.Rpc.call( | |||
| 'Appointment', | |||
| 'setAttendanceStatus', | |||
| { | |||
| appointmentId : appId, | |||
| status : 'waiting' | |||
| }, | |||
| function( res ) | |||
| { | |||
| var newAppointment = new app.model.Appointment( res.appointment, res.attendee_data ); | |||
| app.core.View.toastWarning( | |||
| _lc( | |||
| 'SUCCESSFULLY_ADDED_TO_WAITING_LIST', | |||
| [ | |||
| newAppointment.getWaitingPositionForProfileId( app.model.SessionUser.getUserProfile().getId() ) | |||
| ] | |||
| ) | |||
| ); | |||
| renderAppointmentItem( newAppointment ); | |||
| } | |||
| ); | |||
| }, | |||
| _lc( 'BTN_OK' ), | |||
| ); | |||
| } | |||
| else if ( "deadline_over" === res.err ) | |||
| { | |||
| app.core.View.toastError( _lc( 'DEADLINE_IS_OVER' ) ); | |||
| renderAppointmentItem( getAppointment( appId ) ); | |||
| } | |||
| else | |||
| { | |||
| app.core.View.toastError( _lc( 'GENERAL_SERVER_ERROR' ) ); | |||
| renderAppointmentItem( getAppointment( appId ) ); | |||
| } | |||
| } | |||
| }, | |||
| function( res ) | |||
| { | |||
| renderAppointmentItem( getAppointment( appId ) ); | |||
| } | |||
| ); | |||
| }; | |||
| state.onEnter = function( p ) | |||
| { | |||
| var $content = app.core.View.getContent(), | |||
| @@ -127,6 +284,88 @@ app.state.Home = function() | |||
| filter.isModified = false; | |||
| } | |||
| function callSetAttendanceStatus( appId, status, profileChildId = null ) | |||
| { | |||
| app.core.Rpc.call( | |||
| 'Appointment', | |||
| 'setAttendanceStatus', | |||
| { | |||
| appointmentId : appId, | |||
| status : status, | |||
| profileChildId : profileChildId | |||
| }, | |||
| function( res ) | |||
| { | |||
| if ( false === res.hasOwnProperty( 'err' ) ) | |||
| { | |||
| app.core.View.toastSuccess( _lc( 'SAVED' ) ); | |||
| renderAppointmentItem( new app.model.Appointment( res.appointment, res.attendee_data ) ); | |||
| } | |||
| else | |||
| { | |||
| if ( res.err == 'max_reached' ) | |||
| { | |||
| $rsvpContainer.find( '[data-type="section-rsvp-icon-loading"]' ).first().hide(); | |||
| $rsvpContainer.find( '[data-type="section-rsvp-icon-unchecked"]' ).first().show(); | |||
| app.core.View.confirm( | |||
| _lc( 'MAX_REACHED_DO_YOU_WANT_ON_BE_ADDED_TO_THE_WAITLIST' ), | |||
| function() { | |||
| $rsvpContainer.find( '[data-type="section-rsvp-icon-unchecked"]' ).first().hide(); | |||
| $rsvpContainer.find( '[data-type="section-rsvp-icon-loading"]' ).first().show(); | |||
| app.core.Rpc.call( | |||
| 'Appointment', | |||
| 'setAttendanceStatus', | |||
| { | |||
| appointmentId : appId, | |||
| status : 'waiting' | |||
| }, | |||
| function( res ) | |||
| { | |||
| var newAppointment = new app.model.Appointment( res.appointment, res.attendee_data ); | |||
| app.core.View.toastWarning( | |||
| _lc( | |||
| 'SUCCESSFULLY_ADDED_TO_WAITING_LIST', | |||
| [ | |||
| newAppointment.getWaitingPositionForProfileId( app.model.SessionUser.getUserProfile().getId() ) | |||
| ] | |||
| ) | |||
| ); | |||
| renderAppointmentItem( newAppointment ); | |||
| } | |||
| ); | |||
| }, | |||
| _lc( 'BTN_OK' ), | |||
| ); | |||
| } | |||
| else if ( "deadline_over" === res.err ) | |||
| { | |||
| app.core.View.toastError( _lc( 'DEADLINE_IS_OVER' ) ); | |||
| renderAppointmentItem( getAppointment( appId ) ); | |||
| } | |||
| else if ( "deadline_reject_over" === res.err ) | |||
| { | |||
| app.core.View.toastError( 'Die Absagefrist ist verstrichen. Bitte nehme direkten Kontakt auf.' ); | |||
| renderAppointmentItem( getAppointment( appId ) ); | |||
| } | |||
| else | |||
| { | |||
| app.core.View.toastError( _lc( 'GENERAL_SERVER_ERROR' ) ); | |||
| renderAppointmentItem( getAppointment( appId ) ); | |||
| } | |||
| } | |||
| }, | |||
| function( res ) | |||
| { | |||
| renderAppointmentItem( getAppointment( appId ) ); | |||
| } | |||
| ); | |||
| }; | |||
| function renderAppointmentItem( appointment ) | |||
| { | |||
| updateAppointment( appointment ); | |||
| @@ -371,7 +610,7 @@ app.state.Home = function() | |||
| ); | |||
| }); | |||
| $content.on( 'click', '[data-type="rsvp-button-accept"]', function() | |||
| $content.on( 'click', '[data-type="rsvp-button-accept-multiple"], [data-type="rsvp-button-recall-multiple"]', function() | |||
| { | |||
| var $btn = $(this), | |||
| appId = $btn.attr('data-appointment-id'), | |||
| @@ -379,87 +618,66 @@ app.state.Home = function() | |||
| appointment = getAppointment(appId), | |||
| profileStatus = appointment.getAttendeeStatusForProfileId( app.model.SessionUser.getUserProfile().getId() ); | |||
| if ( "accepted" === profileStatus ) | |||
| { | |||
| return false; | |||
| } | |||
| $rsvpContainer.find( '[data-type="section-rsvp-icon-accepted"]' ).first().hide(); | |||
| $rsvpContainer.find( '[data-type="section-rsvp-icon-unchecked"]' ).first().hide(); | |||
| $rsvpContainer.find( '[data-type="section-rsvp-icon-loading"]' ).first().show(); | |||
| app.core.Rpc.call( | |||
| 'Appointment', | |||
| 'setAttendanceStatus', | |||
| { | |||
| appointmentId : appId, | |||
| status : "accepted" | |||
| }, | |||
| function( res ) | |||
| app.core.View.showModal( | |||
| { | |||
| if ( false === res.hasOwnProperty( 'err' ) ) | |||
| { | |||
| app.core.View.toastSuccess( _lc( 'SAVED' ) ); | |||
| renderAppointmentItem( new app.model.Appointment( res.appointment, res.attendee_data ) ); | |||
| } | |||
| else | |||
| 'title' : appointment.getSubject() + ', am ' + appointment.getMomentStart().format( 'DD.MM.' ) + ' um ' + appointment.getMomentStart().format( 'HH:mm' ) + 'Uhr', | |||
| 'body' : app.core.View.getTemplate( 'home-modal-appointment-subprofile', { a : appointment, currentProfile: app.model.SessionUser.getUserProfile() } ), | |||
| 'cancelButtonText' : null, | |||
| 'okButtonText' : 'Schließen', | |||
| 'onShow' : function() | |||
| { | |||
| if ( res.err == 'max_reached' ) | |||
| const $modalRoot = app.core.View.getModalContent(); | |||
| $modalRoot.on( 'click', '[data-type="rsvp-button-accept"]', function() | |||
| { | |||
| $rsvpContainer.find( '[data-type="section-rsvp-icon-loading"]' ).first().hide(); | |||
| $rsvpContainer.find( '[data-type="section-rsvp-icon-unchecked"]' ).first().show(); | |||
| app.core.View.confirm( | |||
| _lc( 'MAX_REACHED_DO_YOU_WANT_ON_BE_ADDED_TO_THE_WAITLIST' ), | |||
| function() { | |||
| callSetAttendanceStatus( appId, "accepted", $(this).attr( 'data-child-profile-id' ) ); | |||
| app.core.View.closeModal(); | |||
| }); | |||
| $rsvpContainer.find( '[data-type="section-rsvp-icon-unchecked"]' ).first().hide(); | |||
| $rsvpContainer.find( '[data-type="section-rsvp-icon-loading"]' ).first().show(); | |||
| app.core.Rpc.call( | |||
| 'Appointment', | |||
| 'setAttendanceStatus', | |||
| { | |||
| appointmentId : appId, | |||
| status : 'waiting' | |||
| }, | |||
| function( res ) | |||
| { | |||
| var newAppointment = new app.model.Appointment( res.appointment, res.attendee_data ); | |||
| app.core.View.toastWarning( | |||
| _lc( | |||
| 'SUCCESSFULLY_ADDED_TO_WAITING_LIST', | |||
| [ | |||
| newAppointment.getWaitingPositionForProfileId( app.model.SessionUser.getUserProfile().getId() ) | |||
| ] | |||
| ) | |||
| ); | |||
| renderAppointmentItem( newAppointment ); | |||
| } | |||
| ); | |||
| }, | |||
| _lc( 'BTN_OK' ), | |||
| ); | |||
| } | |||
| else if ( "deadline_over" === res.err ) | |||
| $modalRoot.on( 'click', '[data-type="rsvp-button-recall"]', function() | |||
| { | |||
| app.core.View.toastError( _lc( 'DEADLINE_IS_OVER' ) ); | |||
| renderAppointmentItem( getAppointment( appId ) ); | |||
| } | |||
| else | |||
| { | |||
| app.core.View.toastError( _lc( 'GENERAL_SERVER_ERROR' ) ); | |||
| renderAppointmentItem( getAppointment( appId ) ); | |||
| } | |||
| callSetAttendanceStatus( appId, "declined", $(this).attr( 'data-child-profile-id' ) ); | |||
| app.core.View.closeModal(); | |||
| }); | |||
| }, | |||
| 'onHide' : function() | |||
| { | |||
| const $modalRoot = app.core.View.getModalContent(); | |||
| $modalRoot.off( 'click', '[data-type="rsvp-button-accept"]' ); | |||
| }, | |||
| 'onConfirm' : function() | |||
| { | |||
| app.core.View.closeModal(); | |||
| renderAppointmentItem( appointment ); | |||
| } | |||
| }, | |||
| function( res ) | |||
| { | |||
| renderAppointmentItem( getAppointment( appId ) ); | |||
| } | |||
| ); | |||
| }); | |||
| $content.on( 'click', '[data-type="rsvp-button-accept"]', function() | |||
| { | |||
| var $btn = $(this), | |||
| appId = $btn.attr('data-appointment-id'), | |||
| $rsvpContainer = $content.find( '[data-type="appointment-rsvp-container"][data-appointment-id="' + appId + '"]' ).first(), | |||
| appointment = getAppointment(appId), | |||
| profileStatus = appointment.getAttendeeStatusForProfileId( app.model.SessionUser.getUserProfile().getId() ); | |||
| if ( "accepted" === profileStatus ) | |||
| { | |||
| return false; | |||
| } | |||
| $rsvpContainer.find( '[data-type="section-rsvp-icon-unchecked"]' ).first().hide(); | |||
| $rsvpContainer.find( '[data-type="section-rsvp-icon-loading"]' ).first().show(); | |||
| callSetAttendanceStatus( appId, 'accepted', null ); | |||
| }); | |||
| $content.on( 'click', '[data-type="btn-appointment-edit"]', function() | |||
| { | |||
| var appToEdit = getAppointment( $(this).attr( 'data-appointment-id' ) ); | |||
| @@ -6,15 +6,13 @@ | |||
| src="<%= at.getProfileImg( a.getTeamId() ) %>"> | |||
| </td> | |||
| <td class="align-middle"> | |||
| <div> | |||
| <%=raw at.getName( a.getTeamId() ) %> | |||
| <% if ( childProfile ) { %> | |||
| <small>[<%=raw at.getChildProfileHtmlTagById( childProfile.id ) %>]</small> | |||
| <% } %> | |||
| </div> | |||
| <% if ( a.hasStarted() ) { %> | |||
| <div> | |||
| <%=raw at.getName( a.getTeamId() ) %> | |||
| <% if ( g.getCategory() === "DOGSCHOOL" ) { %> | |||
| <%= at.getCustomGroupProperty( 'DOGSCHOOL', 'dogname' ) %> | |||
| <% } %> | |||
| </div> | |||
| <div class="appointment-original-status"> | |||
| <small> | |||
| <%= _lc( 'ATTENDANCE' ) %> | |||
| @@ -26,17 +24,8 @@ | |||
| </small> | |||
| </div> | |||
| <% } else { %> | |||
| <div> | |||
| <%=raw at.getName( a.getTeamId() ) %> | |||
| </div> | |||
| <div class="appointment-original-status"> | |||
| <small> | |||
| <% if ( g.getCategory() === "DOGSCHOOL" ) { %> | |||
| <i class="fas fa-paw"></i> <%= at.getCustomGroupProperty( 'DOGSCHOOL', 'dogname' ) %> | |||
| <% } %> | |||
| </small> | |||
| </div> | |||
| <% } %> | |||
| </td> | |||
| <td class="align-middle"> | |||
| @@ -2,6 +2,7 @@ | |||
| <% mStart = a.getMomentStart(); %> | |||
| <% mEnd = a.getMomentEnd(); %> | |||
| <% mDeadline = a.getMomentDeadline(); %> | |||
| <% var prfl; %> | |||
| <div class="row"> | |||
| <div class="col-sm-12"> | |||
| <div class="card"> | |||
| @@ -19,7 +20,8 @@ | |||
| <table class="table table-profiles"> | |||
| <tbody> | |||
| <% for ( var aai = 0; aai < attendeesAttended.length; aai++ ) { %> | |||
| <%=raw app.core.View.getTemplate( 'appointment-detail-attendee-row', { a: a, at : attendeesAttended[ aai ], g : g } ) %> | |||
| <% prfl = a.getProfileById( attendeesAttended[ aai ].profile_id ); %> | |||
| <%=raw app.core.View.getTemplate( 'appointment-detail-attendee-row', { a: a, at :prfl, g : g, childProfile : prfl.getChildProfileById( attendeesAttended[ aai ].profile_child_id ) } ) %> | |||
| <% } %> | |||
| </tbody> | |||
| </table> | |||
| @@ -44,7 +46,8 @@ | |||
| <table class="table table-profiles"> | |||
| <tbody> | |||
| <% for ( var aai = 0; aai < attendeesAccepted.length; aai++ ) { %> | |||
| <%=raw app.core.View.getTemplate( 'appointment-detail-attendee-row', { a: a, at : attendeesAccepted[ aai ], g : g } ) %> | |||
| <% prfl = a.getProfileById( attendeesAccepted[ aai ].profile_id ); %> | |||
| <%=raw app.core.View.getTemplate( 'appointment-detail-attendee-row', { a: a, at : prfl, g : g, childProfile : prfl.getChildProfileById( attendeesAccepted[ aai ].profile_child_id ) } ) %> | |||
| <% } %> | |||
| </tbody> | |||
| </table> | |||
| @@ -69,7 +72,8 @@ | |||
| <table class="table table-profiles"> | |||
| <tbody> | |||
| <% for ( var awi = 0; awi < attendeesWaiting.length; awi++ ) { %> | |||
| <%=raw app.core.View.getTemplate( 'appointment-detail-attendee-waiting-row', { a: a, at : attendeesWaiting[ awi ], g : g, waitingPos : (awi + 1) } ) %> | |||
| <% prfl = a.getProfileById( attendeesWaiting[ awi ].profile_id ); %> | |||
| <%=raw app.core.View.getTemplate( 'appointment-detail-attendee-waiting-row', { a: a, at : prfl, g : g, waitingPos : (awi + 1), childProfile : prfl.getChildProfileById( attendeesWaiting[ awi ].profile_child_id ) } ) %> | |||
| <% } %> | |||
| </tbody> | |||
| </table> | |||
| @@ -91,7 +95,8 @@ | |||
| <table class="table table-profiles"> | |||
| <tbody> | |||
| <% for ( var adi = 0; adi < attendeesDeclined.length; adi++ ) { %> | |||
| <%=raw app.core.View.getTemplate( 'appointment-detail-attendee-row', { a: a, at : attendeesDeclined[ adi ], g : g } ) %> | |||
| <% prfl = a.getProfileById( attendeesDeclined[ adi ].profile_id ); %> | |||
| <%=raw app.core.View.getTemplate( 'appointment-detail-attendee-row', { a: a, at : prfl, g : g, childProfile : prfl.getChildProfileById( attendeesDeclined[ adi ].profile_child_id ) } ) %> | |||
| <% } %> | |||
| </tbody> | |||
| </table> | |||
| @@ -1,6 +1,9 @@ | |||
| <tr> | |||
| <td> | |||
| <%=raw attendee.getName() %> | |||
| <% if ( childProfile ) { %> | |||
| <small>[<%=raw attendee.getChildProfileHtmlTagById( childProfile.id ) %>]</small> | |||
| <% } %> | |||
| <% if ( attendee.getContractInGroup( a.getTeamId() ) ) { %> | |||
| <br /><small>Vetrag: <%= attendee.getContractInGroup( a.getTeamId() ) %></small> | |||
| <% } %> | |||
| @@ -19,9 +22,10 @@ | |||
| <% if ( false === a.hasStarted() ) { %> | |||
| <td class="text-center"> | |||
| <select class="form-control form-control-sm" | |||
| data-type="select-attendee-status" | |||
| a-type="select-attendee-status" | |||
| data-appointment-id="<%= a.getId() %>" | |||
| data-profile-id="<%= attendee.getId() %>" | |||
| data-child-profile-id="<%= childProfile ? childProfile.id : '0' %>" | |||
| data-orig-status="<%= currentStatus %>"> | |||
| <option value="no-change"> | |||
| <%= _lc( 'STATUS_NO_CHANGE' ) %> | |||
| @@ -46,6 +50,7 @@ | |||
| data-type="checkbox-attendee-final-status" | |||
| data-appointment-id="<%= a.getId() %>" | |||
| data-profile-id="<%= attendee.getId() %>" | |||
| data-child-profile-id="<%= childProfile ? childProfile.id : '0' %>" | |||
| data-orig-status="<%= a.hasProfileIdAttended( attendee.getId() ) ? 'checked' : 'not-checked' %>" | |||
| class="custom-control-input" | |||
| <%= a.hasProfileIdAttended( attendee.getId() ) ? 'checked="checked"' : '' %> | |||
| @@ -21,20 +21,23 @@ | |||
| </tr> | |||
| </thead> | |||
| <tbody> | |||
| <% var aa = a.getAttendeesAccepted(); %> | |||
| <% var aa = a.getAttendeesAccepted(), prfl; %> | |||
| <% for ( var aai = 0; aai < aa.length; aai++ ) { %> | |||
| <%=raw app.core.View.getTemplate( 'appointment-edit-attendee-row', { attendee : aa[ aai ], a: a, currentStatus : 'accepted' } ) %> | |||
| <% prfl = a.getProfileById( aa[ aai ].profile_id ); %> | |||
| <%=raw app.core.View.getTemplate( 'appointment-edit-attendee-row', { attendee : prfl, a: a, currentStatus : 'accepted', childProfile : prfl.getChildProfileById( aa[ aai ].profile_child_id ) } ) %> | |||
| <% } %> | |||
| <% var aw = a.getAttendeesWaiting(); %> | |||
| <% for ( var awi = 0; awi < aw.length; awi++ ) { %> | |||
| <%=raw app.core.View.getTemplate( 'appointment-edit-attendee-row', { attendee : aw[ awi ], a: a, currentStatus : 'waiting' } ) %> | |||
| <% prfl = a.getProfileById( aw[ awi ].profile_id ); %> | |||
| <%=raw app.core.View.getTemplate( 'appointment-edit-attendee-row', { attendee : prfl, a: a, currentStatus : 'waiting', childProfile : prfl.getChildProfileById( aw[ awi ].profile_child_id ) } ) %> | |||
| <% } %> | |||
| <% var ad = a.getAttendeesDeclined(); %> | |||
| <% for ( var adi = 0; adi < ad.length; adi++ ) { %> | |||
| <%=raw app.core.View.getTemplate( 'appointment-edit-attendee-row', { attendee : ad[ adi ], a: a, currentStatus : 'declined' } ) %> | |||
| <% prfl = a.getProfileById( ad[ adi ].profile_id ); %> | |||
| <%=raw app.core.View.getTemplate( 'appointment-edit-attendee-row', { attendee : prfl, a: a, currentStatus : 'declined', childProfile : prfl.getChildProfileById( ad[ adi ].profile_child_id ) } ) %> | |||
| <% } %> | |||
| <% for ( var ndmi = 0; ndmi < members.length; ndmi++ ) { %> | |||
| <%=raw app.core.View.getTemplate( 'appointment-edit-attendee-row', { attendee : members[ ndmi ], a: a, currentStatus : 'no-reaction' } ) %> | |||
| <% for ( var ndmi = 0; ndmi < notDecided.length; ndmi++ ) { %> | |||
| <%=raw app.core.View.getTemplate( 'appointment-edit-attendee-row', { attendee : notDecided[ ndmi ].profile, a: a, currentStatus : 'no-reaction', childProfile : notDecided[ ndmi ].child } ) %> | |||
| <% } %> | |||
| </tbody> | |||
| </table> | |||
| @@ -58,21 +58,6 @@ | |||
| </div> | |||
| </div> | |||
| </div> | |||
| <% if ( p.isInGroupCategory( 'DOGSCHOOL' ) ) { %> | |||
| <div class="form-group"> | |||
| <label for="input-dogschool-dogname"> | |||
| <%= _lc( 'PROFILE_DOGNAME' ) %> <small>- <%= _lc( 'PROFILE_DOGNAME_USAGE' ) %></small> | |||
| </label> | |||
| <input type="text" | |||
| maxlength="32" | |||
| name="dogschool-dogname" | |||
| data-id="input-dogschool-dogname" | |||
| id="input-dogschool-dogname" | |||
| class="form-control" | |||
| value="<%= p.getCustomGroupProperty( 'DOGSCHOOL', 'dogname' ) ? p.getCustomGroupProperty( 'DOGSCHOOL', 'dogname' ) : '' %>" | |||
| /> | |||
| </div> | |||
| <% } %> | |||
| <div class="form-group"> | |||
| <div class="form-row"> | |||
| <div class="col"> | |||
| @@ -16,14 +16,6 @@ | |||
| <div style="font-size: 1.4rem"> | |||
| <%=raw p.getName() %> | |||
| </div> | |||
| <% if ( p.isInGroupCategory( 'DOGSCHOOL' ) ) { %> | |||
| <div class="profile-header"> | |||
| <%= _lc( 'PROFILE_DOGNAME' ) %> | |||
| </div> | |||
| <div class="profile-content"> | |||
| <%= p.getCustomGroupProperty( 'DOGSCHOOL', 'dogname' ) ? p.getCustomGroupProperty( 'DOGSCHOOL', 'dogname' ) : '---' %> | |||
| </div> | |||
| <% } %> | |||
| <div class="profile-header"> | |||
| <%= _lc( 'PROFILE_STATUS' ) %> | |||
| </div> | |||
| @@ -36,6 +28,21 @@ | |||
| <div class="profile-content"> | |||
| <%= ( null != p.getMomentBirthday() ) ? p.getMomentBirthday().format( 'DD.MM.YYYY' ) : '---' %> | |||
| </div> | |||
| <div class="profile-header"> | |||
| Unterprofile | |||
| </div> | |||
| <div class="profile-content"> | |||
| <% let cp = p.getChildProfiles(); %> | |||
| <% if ( !cp || 0 === cp.length ) { %> | |||
| - keine - | |||
| <% } else { %> | |||
| <% for ( let cpi = 0; cpi < cp.length; cpi++ ) { %> | |||
| <% if ( false === cp[ cpi ].deleted ) { %> | |||
| <i class="<%= p.getChildProfileIconByType( cp[ cpi ].type ) %>"></i> <%= cp[ cpi ].name %><br /> | |||
| <% } %> | |||
| <% } %> | |||
| <% } %> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| @@ -49,6 +56,9 @@ | |||
| class="btn btn-sm btn-primary"> | |||
| <%= _lc( 'BTN_UPDATE_PROFILE_IMG' ) %> | |||
| </button> | |||
| <a href="#/configuration/subprofile/edit" class="btn btn-sm btn-primary"> | |||
| Unterprofile bearbeiten | |||
| </a> | |||
| <a href="#/configuration/profile/delete" class="float-right btn btn-sm btn-danger"> | |||
| <%= _lc( 'BTN_DELETE_PROFILE' ) %> | |||
| </a> | |||
| @@ -0,0 +1,82 @@ | |||
| <h4><a href="#/configuration/profile"><i class="fas fa-chevron-left"></i></a> Unterprofile</h4> | |||
| <% var mBirthday = p.getMomentBirthday(); %> | |||
| <div class="row"> | |||
| <div class="col-sm-12"> | |||
| <div class="card"> | |||
| <form data-id="form-profile" | |||
| class="needs-validation" | |||
| novalidate> | |||
| <div class="card-body"> | |||
| <div class="form-group"> | |||
| <p> | |||
| <strong>Unterprofile</strong><br /> | |||
| <small><i class="fa fa-info-circle"></i> Du kannst beliebig viele Unterprofile errichten. Unterprofile sind beispielsweise für Personen mit Kindern oder mehreren Haustieren nützlich.<br /><u>Beispiel:</u> Du verwendest <strong>Pro</strong>Buddy mit deiner Hundeschule und hast zwei Hunde. Dann kannst du mit deinem Account für jeden Hund individuell zu- bzw. absagen.</small> | |||
| </p> | |||
| <label>Deine derzeitigen Unterprofile</label> | |||
| <% let cp = p.getChildProfiles(); %> | |||
| <% if ( 0 === cp.length ) { %> | |||
| <p> | |||
| <i>- keine -</i> | |||
| </p> | |||
| <% } else { %> | |||
| <div class="table-responsive"> | |||
| <table class="table table-striped"> | |||
| <thead> | |||
| <tr> | |||
| <th class="text-center">ID</th> | |||
| <th>Name</th> | |||
| <th>Typ</th> | |||
| <th class="text-center"> </th> | |||
| </tr> | |||
| </thead> | |||
| <tbody> | |||
| <% for ( let cpi = 0; cpi < cp.length; cpi++ ) { %> | |||
| <tr> | |||
| <td class="text-center" | |||
| style="vertical-align: middle"> | |||
| <%= cp[ cpi ].id %> | |||
| </td> | |||
| <td style="vertical-align: middle"> | |||
| <%= cp[ cpi ].name %> | |||
| </td> | |||
| <td style="vertical-align: middle"> | |||
| <i class="<%= p.getChildProfileIconByType( cp[ cpi ].type ) %>"></i> <%= p.getChildProfileNameByType( cp[ cpi ].type ) %> | |||
| </td> | |||
| <td class="text-right"> | |||
| <button type="button" | |||
| data-subprofile-id="<%= cp[ cpi ].id %>" | |||
| data-type="editSubProfile" | |||
| class="btn btn-primary btn-sm"> | |||
| <i class="fas fa-pencil-alt"></i> | |||
| </button> | |||
| <button type="button" | |||
| data-subprofile-id="<%= cp[ cpi ].id %>" | |||
| data-type="deleteSubProfile" | |||
| class="btn btn-danger btn-sm"> | |||
| <i class="far fa-trash-alt"></i> | |||
| </button> | |||
| </td> | |||
| </tr> | |||
| <% } %> | |||
| </tbody> | |||
| </table> | |||
| </div> | |||
| <% } %> | |||
| </div> | |||
| </div> | |||
| <div class="card-footer"> | |||
| <a href="#/configuration/profile" | |||
| class="btn btn-sm btn-secondary"> | |||
| <%= _lc( 'BTN_CANCEL' ) %> | |||
| </a> | |||
| <button type="button" | |||
| data-id="btn-add-subprofile" | |||
| class="btn btn-sm btn-primary"> | |||
| Neues Unterprofil anlegen | |||
| </button> | |||
| </div> | |||
| </form> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| @@ -0,0 +1,46 @@ | |||
| <form data-id="form-subprofile" | |||
| class="needs-validation" | |||
| novalidate> | |||
| <div class="form-group"> | |||
| <label for="input-subprofile-name"> | |||
| Name | |||
| </label> | |||
| <input type="text" | |||
| minlength="3" | |||
| maxlength="32" | |||
| data-id="input-subprofile-name" | |||
| id="input-subprofile-name" | |||
| class="form-control" | |||
| value="<%= sp ? sp.name : '' %>" | |||
| placeholder="Name Unterprofile" | |||
| required /> | |||
| <div class="invalid-feedback"> | |||
| <%= _lc( 'VALIDATION_INPUT_REQUIRED' ) %> | |||
| </div> | |||
| </div> | |||
| <div class="form-group"> | |||
| <label for="input-subprofile-name"> | |||
| Typ | |||
| </label> | |||
| <select class="form-control" | |||
| name="new-subprofile-type" | |||
| data-id="select-subprofile-type" | |||
| id="select-subprofile-type"> | |||
| <option value="person" | |||
| <%= ( sp && sp.type === 'person' ) ? 'selected="selected"' : '' %>>Person</option> | |||
| <option value="child" | |||
| <%= ( sp && sp.type === 'child' ) ? 'selected="selected"' : '' %>>Kind</option> | |||
| <option value="dog" | |||
| <%= ( sp && sp.type === 'dog' ) ? 'selected="selected"' : '' %>>Hund</option> | |||
| <option value="cat" | |||
| <%= ( sp && sp.type === 'cat' ) ? 'selected="selected"' : '' %>>Katze</option> | |||
| <option value="horse" | |||
| <%= ( sp && sp.type === 'horse' ) ? 'selected="selected"' : '' %>>Pferd</option> | |||
| <option value="other" | |||
| <%= ( sp && sp.type === 'other' ) ? 'selected="selected"' : '' %>>Anderes</option> | |||
| </select> | |||
| <div class="invalid-feedback"> | |||
| <%= _lc( 'VALIDATION_INPUT_REQUIRED' ) %> | |||
| </div> | |||
| </div> | |||
| </form> | |||
| @@ -9,6 +9,7 @@ | |||
| <% var group = app.model.SessionUser.getGroupById( a.getTeamId() ); %> | |||
| <% var categoryNames = a.getCategoryNames(); %> | |||
| <% var homeState = app.core.StateManager.getCurrentState(); %> | |||
| <% var multiple = ( true === currentProfile.hasMultipleChilds() ) ? '-multiple' : '' %> | |||
| <div class="appointment-item"> | |||
| <div data-type="appointment-short-info" | |||
| data-appointment-id="<%= a.getId() %>" | |||
| @@ -77,9 +78,9 @@ | |||
| <% } else { %> | |||
| <section data-type="section-rsvp-icon-unchecked" | |||
| style="display: <%= ( a.hasProfileIdAccepted( currentProfile.getId() ) || a.isProfileIdWaiting( currentProfile.getId() ) ) ? 'none' : 'block' %>"> | |||
| style="display: <%= ( a.hasProfileIdStatus( currentProfile.getId(), "accepted" ) || a.hasProfileIdStatus( currentProfile.getId(), "waiting" ) ) ? 'none' : 'block' %>"> | |||
| <button type="button" | |||
| data-type="rsvp-button-accept" | |||
| data-type="rsvp-button-accept<%= multiple %>" | |||
| data-appointment-id="<%= a.getId() %>" | |||
| class="btn btn-rsvp-not-selected btn-circle btn-xl"> | |||
| <i class="fas fa-thumbs-up"></i> | |||
| @@ -94,9 +95,9 @@ | |||
| </section> | |||
| <section data-type="section-rsvp-icon-accepted" | |||
| style="display: <%= a.hasProfileIdAccepted( currentProfile.getId() ) ? 'block' : 'none' %>"> | |||
| style="display: <%= a.hasProfileIdStatus( currentProfile.getId(), "accepted" ) ? 'block' : 'none' %>"> | |||
| <div style="position:relative; width:52px; height:40px;"> | |||
| <div data-type="rsvp-button-recall" | |||
| <div data-type="rsvp-button-recall<%= multiple %>" | |||
| data-appointment-id="<%= a.getId() %>" | |||
| style="position: absolute;width:40px; height:40px;top:0;right:0"> | |||
| <svg class="rsvp-checkmark" | |||
| @@ -110,9 +111,9 @@ | |||
| </section> | |||
| <section data-type="section-rsvp-icon-waiting" | |||
| style="display: <%= a.isProfileIdWaiting( currentProfile.getId() ) ? 'block' : 'none' %>"> | |||
| style="display: <%= a.hasProfileIdStatus( currentProfile.getId(), "waiting" ) ? 'block' : 'none' %>"> | |||
| <div style="position:relative; width:52px; height:40px;"> | |||
| <div data-type="rsvp-button-recall" | |||
| <div data-type="rsvp-button-recall<%= multiple %>" | |||
| data-appointment-id="<%= a.getId() %>" | |||
| style="position: absolute;width:40px; height:40px;top:0;right:0"> | |||
| <svg class="rsvp-checkmark rsvp-chcekmark-waiting" | |||
| @@ -208,16 +209,24 @@ | |||
| <td> | |||
| <%= _lc( 'ACCEPTANCE' ) %> (<%= a.getNumAttendeesAccepted() %>) | |||
| </td> | |||
| <% let ma; %> | |||
| <% ma = homeState.getMembersForAppointment( a, 'accepted' ); %> | |||
| <% let ad, m, cp; %> | |||
| <% ad = a.getAttendeeDataByStatus( "accepted" ); %> | |||
| <td> | |||
| <% if ( ma.length > 0 ) { %> | |||
| <% for ( let mi = 0; mi < ma.length; mi++ ) { %> | |||
| <%= mi > 0 ? ' - ' : '' %> | |||
| <%=raw ma[ mi ].getName( a.getTeamId() ) %> | |||
| <% if ( ad.length > 0 ) { %> | |||
| <% for ( let ai = 0; ai < ad.length; ai++ ) { %> | |||
| <%= ai > 0 ? ' - ' : '' %> | |||
| <% m = homeState.getMemberByGroupAndProfileId( a.getTeamId(), ad[ ai ].profile_id ); %> | |||
| <% cp = m ? m.getChildProfileById( ad[ ai ].profile_child_id ) : null; %> | |||
| <% if ( m ) { %> | |||
| <%= m.getName( a.getTeamId() ) %> | |||
| <% if ( cp ) { %> | |||
| [<%=raw m.getChildProfileHtmlTagById( cp.id ) %>] | |||
| <% } %> | |||
| <% } else { %> | |||
| <i>Gelöscht</i> | |||
| <% } %> | |||
| <% } %> | |||
| <% } %> | |||
| @@ -227,15 +236,22 @@ | |||
| <td> | |||
| <%= _lc( 'WAITINGLIST' ) %> (<%= a.hasWaitingList() ? a.getNumAttendeesWaiting() : '0' %>) | |||
| </td> | |||
| <% ma = homeState.getMembersForAppointment( a, 'waiting' ); %> | |||
| <% ad = a.getAttendeeDataByStatus( "waiting" ); %> | |||
| <td> | |||
| <% if ( ma.length > 0 ) { %> | |||
| <% for ( let mi = 0; mi < ma.length; mi++ ) { %> | |||
| <%= mi > 0 ? ' - ' : '' %> | |||
| <%= ma[ mi ].getName( a.getTeamId() ) %> | |||
| <% if ( ad.length > 0 ) { %> | |||
| <% for ( let ai = 0; ai < ad.length; ai++ ) { %> | |||
| <%= ai > 0 ? ' - ' : '' %> | |||
| <% m = homeState.getMemberByGroupAndProfileId( a.getTeamId(), ad[ ai ].profile_id ); %> | |||
| <% cp = m ? m.getChildProfileById( ad[ ai ].profile_child_id ) : null; %> | |||
| <% if ( m ) { %> | |||
| <%= m.getName( a.getTeamId() ) %> | |||
| <% if ( cp ) { %> | |||
| [<%=raw m.getChildProfileHtmlTagById( cp.id ) %>] | |||
| <% } %> | |||
| <% } else { %> | |||
| <i>Gelöscht</i> | |||
| <% } %> | |||
| <% } %> | |||
| <% } %> | |||
| @@ -245,15 +261,21 @@ | |||
| <td> | |||
| Absagen (<%= a.getProfileIdsDeclined().length %>) | |||
| </td> | |||
| <% ma = homeState.getMembersForAppointment( a, 'declined' ); %> | |||
| <% ad = a.getAttendeeDataByStatus( "declined" ); %> | |||
| <td> | |||
| <% if ( ma.length > 0 ) { %> | |||
| <% for ( let mi = 0; mi < ma.length; mi++ ) { %> | |||
| <%= mi > 0 ? ' - ' : '' %> | |||
| <%= ma[ mi ].getName( a.getTeamId() ) %> | |||
| <% if ( ad.length > 0 ) { %> | |||
| <% for ( let ai = 0; ai < ad.length; ai++ ) { %> | |||
| <%= ai > 0 ? ' - ' : '' %> | |||
| <% m = homeState.getMemberByGroupAndProfileId( a.getTeamId(), ad[ ai ].profile_id ); %> | |||
| <% cp = m ? m.getChildProfileById( ad[ ai ].profile_child_id ) : null; %> | |||
| <% if ( m ) { %> | |||
| <%= m.getName( a.getTeamId() ) %> | |||
| <% if ( cp ) { %> | |||
| [<%=raw m.getChildProfileHtmlTagById( cp.id ) %>] | |||
| <% } %> | |||
| <% } else { %> | |||
| <i>Gelöscht</i> | |||
| <% } %> | |||
| <% } %> | |||
| <% } %> | |||
| @@ -0,0 +1,131 @@ | |||
| <% let childProfiles = currentProfile.getChildProfiles(); %> | |||
| <div class="row"> | |||
| <div class="col" style="line-height: 68px"> | |||
| <%= currentProfile.getName() %> | |||
| </div> | |||
| <div data-type="appointment-rsvp-container" | |||
| data-appointment-id="<%= a.getId() %>" | |||
| class="col-appointment-response"> | |||
| <div class="container-rsvp-icon"> | |||
| <section data-type="section-rsvp-icon-unchecked" | |||
| style="display: <%= ( a.hasProfileIdAccepted( currentProfile.getId() ) || a.isProfileIdWaiting( currentProfile.getId() ) ) ? 'none' : 'block' %>"> | |||
| <button type="button" | |||
| data-type="rsvp-button-accept" | |||
| data-appointment-id="<%= a.getId() %>" | |||
| class="btn btn-rsvp-not-selected btn-circle btn-xl"> | |||
| <i class="fas fa-thumbs-up"></i> | |||
| </button> | |||
| </section> | |||
| <section data-type="section-rsvp-icon-loading" | |||
| style="display: none"> | |||
| <div class="rsvp-loading-icon"> | |||
| <i class="fas fa-circle-notch fa-spin"></i> | |||
| </div> | |||
| </section> | |||
| <section data-type="section-rsvp-icon-accepted" | |||
| style="display: <%= a.hasProfileIdAccepted( currentProfile.getId() ) ? 'block' : 'none' %>"> | |||
| <div style="position:relative; width:52px; height:40px;"> | |||
| <div data-type="rsvp-button-recall" | |||
| data-appointment-id="<%= a.getId() %>" | |||
| style="position: absolute;width:40px; height:40px;top:0;right:0"> | |||
| <svg class="rsvp-checkmark" | |||
| xmlns="http://www.w3.org/2000/svg" | |||
| viewBox="0 0 52 52"> | |||
| <circle class="rsvp-checkmark__circle" cx="26" cy="26" r="25" fill="none"/> | |||
| <path class="rsvp-checkmark__check" fill="none" d="M14.1 27.2l7.1 7.2 16.7-16.8"/> | |||
| </svg> | |||
| </div> | |||
| </div> | |||
| </section> | |||
| <section data-type="section-rsvp-icon-waiting" | |||
| style="display: <%= a.isProfileIdWaiting( currentProfile.getId() ) ? 'block' : 'none' %>"> | |||
| <div style="position:relative; width:52px; height:40px;"> | |||
| <div data-type="rsvp-button-recall" | |||
| data-appointment-id="<%= a.getId() %>" | |||
| style="position: absolute;width:40px; height:40px;top:0;right:0"> | |||
| <svg class="rsvp-checkmark rsvp-chcekmark-waiting" | |||
| xmlns="http://www.w3.org/2000/svg" | |||
| viewBox="0 0 52 52"> | |||
| <circle class="rsvp-checkmark__circle rsvp-checkmark__circle-waiting" cx="26" cy="26" r="25" fill="none"/> | |||
| <path class="rsvp-checkmark__check" fill="none" d="M14.1 27.2l7.1 7.2 16.7-16.8"/> | |||
| </svg> | |||
| </div> | |||
| </div> | |||
| </section> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| <% for ( let ci = 0; ci < childProfiles.length; ci++ ) { %> | |||
| <hr style="margin-top: 0; margin-bottom: 0" /> | |||
| <div class="row"> | |||
| <div class="col" style="line-height: 68px"> | |||
| <i class="<%= currentProfile.getChildProfileIconByType(childProfiles[ ci ].type ) %>"></i> <%= childProfiles[ ci ].name %> | |||
| </div> | |||
| <div data-type="appointment-rsvp-container" | |||
| data-appointment-id="<%= a.getId() %>" | |||
| class="col-appointment-response"> | |||
| <div class="container-rsvp-icon"> | |||
| <section data-type="section-rsvp-icon-unchecked" | |||
| style="display: <%= ( a.hasProfileIdAccepted( currentProfile.getId(), childProfiles[ ci ].id ) || a.isProfileIdWaiting( currentProfile.getId(), childProfiles[ ci ].id ) ) ? 'none' : 'block' %>"> | |||
| <button type="button" | |||
| data-type="rsvp-button-accept" | |||
| data-appointment-id="<%= a.getId() %>" | |||
| data-child-profile-id="<%= childProfiles[ ci ].id %>" | |||
| class="btn btn-rsvp-not-selected btn-circle btn-xl"> | |||
| <i class="fas fa-thumbs-up"></i> | |||
| </button> | |||
| </section> | |||
| <section data-type="section-rsvp-icon-loading" | |||
| style="display: none"> | |||
| <div class="rsvp-loading-icon"> | |||
| <i class="fas fa-circle-notch fa-spin"></i> | |||
| </div> | |||
| </section> | |||
| <section data-type="section-rsvp-icon-accepted" | |||
| style="display: <%= a.hasProfileIdAccepted( currentProfile.getId(), childProfiles[ ci ].id ) ? 'block' : 'none' %>"> | |||
| <div style="position:relative; width:52px; height:40px;"> | |||
| <div data-type="rsvp-button-recall" | |||
| data-appointment-id="<%= a.getId() %>" | |||
| data-child-profile-id="<%= childProfiles[ ci ].id %>" | |||
| style="position: absolute;width:40px; height:40px;top:0;right:0"> | |||
| <svg class="rsvp-checkmark" | |||
| xmlns="http://www.w3.org/2000/svg" | |||
| viewBox="0 0 52 52"> | |||
| <circle class="rsvp-checkmark__circle" cx="26" cy="26" r="25" fill="none"/> | |||
| <path class="rsvp-checkmark__check" fill="none" d="M14.1 27.2l7.1 7.2 16.7-16.8"/> | |||
| </svg> | |||
| </div> | |||
| </div> | |||
| </section> | |||
| <section data-type="section-rsvp-icon-waiting" | |||
| style="display: <%= a.isProfileIdWaiting( currentProfile.getId(), childProfiles[ ci ].id ) ? 'block' : 'none' %>"> | |||
| <div style="position:relative; width:52px; height:40px;"> | |||
| <div data-type="rsvp-button-recall" | |||
| data-appointment-id="<%= a.getId() %>" | |||
| style="position: absolute;width:40px; height:40px;top:0;right:0"> | |||
| <svg class="rsvp-checkmark rsvp-chcekmark-waiting" | |||
| xmlns="http://www.w3.org/2000/svg" | |||
| viewBox="0 0 52 52"> | |||
| <circle class="rsvp-checkmark__circle rsvp-checkmark__circle-waiting" cx="26" cy="26" r="25" fill="none"/> | |||
| <path class="rsvp-checkmark__check" fill="none" d="M14.1 27.2l7.1 7.2 16.7-16.8"/> | |||
| </svg> | |||
| </div> | |||
| </div> | |||
| </section> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| <% } %> | |||
| @@ -7,10 +7,10 @@ body { | |||
| .pb_icon-gradient:before { | |||
| background: #2B2D42; | |||
| background: -moz-linear-gradient(45deg, #2B2D42 0%, #D2D2D2 100%); | |||
| background: -webkit-linear-gradient(45deg, #2B2D42 0%, #D2D2D2 100%); | |||
| background: -o-linear-gradient(45deg, #2B2D42 0%, #D2D2D2 100%); | |||
| background: linear-gradient(45deg, #2B2D42 0%, #D2D2D2 100%); | |||
| background: -moz-linear-gradient(90deg, #2b2d42 25%, #ffffff 100%); | |||
| background: -webkit-linear-gradient(90deg, #2b2d42 25%, #ffffff 100%); | |||
| background: -o-linear-gradient(90deg, #2b2d42 25%, #ffffff 100%); | |||
| background: linear-gradient(90deg, #2b2d42 25%, #ffffff 100%); | |||
| /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */ | |||
| -webkit-background-clip: text; | |||
| -webkit-text-fill-color: transparent; } | |||
| @@ -319,11 +319,13 @@ | |||
| .pb_md_py_cover .heading, | |||
| .pb_lg_py_cover .heading, | |||
| .pb_xl_py_cover .heading { | |||
| font-size: 62px; | |||
| font-size: 80px; | |||
| color: white; | |||
| font-weight: 300; | |||
| font-weight: 800; | |||
| margin-top: 20px; | |||
| margin-bottom: 0px; } | |||
| margin-bottom: 0px; | |||
| text-shadow: #393939 0.01em 0.01em 0.01em; | |||
| font-family: arial black; } | |||
| @media (max-width: 767px) { | |||
| .pb_sm_py_cover .heading, | |||
| .pb_md_py_cover .heading, | |||
| @@ -334,7 +336,7 @@ | |||
| .pb_md_py_cover .sub-heading, | |||
| .pb_lg_py_cover .sub-heading, | |||
| .pb_xl_py_cover .sub-heading { | |||
| font-size: 20px; | |||
| font-size: 24px; | |||
| color: rgba(255, 255, 255, 0.8); | |||
| max-width: 600px; | |||
| float: left; } | |||
| @@ -490,11 +492,13 @@ | |||
| .pb_cover_v2 .heading, | |||
| .pb_cover_v3 .heading, | |||
| .pb_cover_v4 .heading { | |||
| font-size: 62px; | |||
| font-size: 80px; | |||
| color: white; | |||
| font-weight: 300; | |||
| font-weight: 800; | |||
| margin-top: 20px; | |||
| margin-bottom: 0px; } | |||
| margin-bottom: 0px; | |||
| text-shadow: #393939 0.01em 0.01em 0.01em; | |||
| font-family: arial black;} | |||
| @media (max-width: 767px) { | |||
| .pb_cover .heading, | |||
| .pb_cover_v1 .heading, | |||
| @@ -507,7 +511,7 @@ | |||
| .pb_cover_v2 .sub-heading, | |||
| .pb_cover_v3 .sub-heading, | |||
| .pb_cover_v4 .sub-heading { | |||
| font-size: 20px; | |||
| font-size: 28px; | |||
| color: rgba(255, 255, 255, 0.8); | |||
| max-width: 600px; | |||
| float: left; } | |||
| @@ -0,0 +1,16 @@ | |||
| <?php | |||
| /******************************************************************************** | |||
| * (c)1337 aheadware.com - All rights reserved | |||
| ********************************************************************************/ | |||
| require_once __DIR__ . '/../../server/server/config/boot_global.php'; | |||
| require_once __DIR__ . '/../../server/server/config/boot_local.php'; | |||
| try | |||
| { | |||
| $app = new TB_Server_Core_App(); | |||
| $app->run(); | |||
| } | |||
| catch ( Exception $e ) | |||
| { | |||
| TB_Server_Utils_Log::get()->log( $e ); | |||
| } | |||
| @@ -0,0 +1,92 @@ | |||
| body { | |||
| overflow-x: hidden; } | |||
| .bg-light { | |||
| background-color: #f2f4f9 !important; } | |||
| .pb_icon-gradient:before { | |||
| background: #2B2D42; | |||
| background: -moz-linear-gradient(45deg, #2B2D42 0%, #D2D2D2 100%); | |||
| background: -webkit-linear-gradient(45deg, #2B2D42 0%, #D2D2D2 100%); | |||
| background: -o-linear-gradient(45deg, #2B2D42 0%, #D2D2D2 100%); | |||
| background: linear-gradient(45deg, #2B2D42 0%, #D2D2D2 100%); | |||
| /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */ | |||
| -webkit-background-clip: text; | |||
| -webkit-text-fill-color: transparent; } | |||
| .pb_slant-light, | |||
| .pb_slant-white { | |||
| position: relative; } | |||
| .pb_slant-light:after, | |||
| .pb_slant-white:after { | |||
| content: ""; | |||
| position: absolute; | |||
| bottom: -100px; | |||
| left: -50px; | |||
| height: 200px; | |||
| width: 130%; | |||
| background-color: #f2f4f9; | |||
| -webkit-transform: rotate(-4deg); | |||
| -ms-transform: rotate(-4deg); | |||
| transform: rotate(-4deg); | |||
| z-index: 10; } | |||
| .pb_slant-light.pb_slant-reverse:after, | |||
| .pb_slant-white.pb_slant-reverse:after { | |||
| -webkit-transform: rotate(4deg); | |||
| -ms-transform: rotate(4deg); | |||
| transform: rotate(4deg); | |||
| left: -100px; | |||
| bottom: -140px; } | |||
| .pb_slant-white:after { | |||
| background-color: #fff; } | |||
| .pb_section { | |||
| padding: 10em 0; } | |||
| .pb_cover_v3 a, .pb_xl_py_cover a { | |||
| color: rgba(255, 255, 255, 0.5); | |||
| border-bottom: 2px solid transparent; } | |||
| .pb_cover_v3 a:hover, .pb_xl_py_cover a:hover { | |||
| color: white; | |||
| border-bottom: 2px solid white; } | |||
| .pb_cover_v3 .btn, .pb_xl_py_cover .btn { | |||
| color: white; } | |||
| .pb_accordion .item > a[aria-expanded="true"] { | |||
| color: #2B2D42; | |||
| border-bottom: 1px solid transparent; | |||
| } | |||
| a { | |||
| color: #2B2D42; | |||
| } | |||
| .pb_navbar.scrolled.pb_scrolled-light ul li a.active { | |||
| color: #1d82ff !important; | |||
| } | |||
| .pb_navbar.scrolled.pb_scrolled-light ul li.cta-btn > a > span { | |||
| border: none; | |||
| background: #87AD71; | |||
| color: #fff; | |||
| } | |||
| .pb_navbar.awake a.navbar-brand > img.logo-dark { | |||
| display: block; | |||
| } | |||
| .pb_navbar.awake a.navbar-brand > img.logo-white { | |||
| display: none; | |||
| } | |||
| .pb_navbar a.navbar-brand > img.logo-dark { | |||
| display: none; | |||
| } | |||
| .pb_navbar a.navbar-brand > img.logo-white { | |||
| display: block; | |||
| } | |||
| @@ -0,0 +1,77 @@ | |||
| @charset "UTF-8"; | |||
| /* Slider */ | |||
| .slick-loading .slick-list { | |||
| background: #fff url("./ajax-loader.gif") center center no-repeat; } | |||
| /* Icons */ | |||
| @font-face { | |||
| font-family: "slick"; | |||
| src: url("../fonts/slick/slick.eot"); | |||
| src: url("../fonts/slick/slick.eot?#iefix") format("embedded-opentype"), url("../fonts/slick/slick.woff") format("woff"), url("../fonts/slick/slick.ttf") format("truetype"), url("../fonts/slick/slick.svg#slick") format("svg"); | |||
| font-weight: normal; | |||
| font-style: normal; } | |||
| /* Arrows */ | |||
| .slick-prev, | |||
| .slick-next { | |||
| border: 1px solid red !important; | |||
| position: absolute; | |||
| display: block; | |||
| height: 20px; | |||
| width: 20px; | |||
| line-height: 0px; | |||
| font-size: 0px; | |||
| cursor: pointer; | |||
| background: transparent; | |||
| color: transparent; | |||
| top: 50%; | |||
| -webkit-transform: translate(0, -50%); | |||
| -ms-transform: translate(0, -50%); | |||
| transform: translate(0, -50%); | |||
| padding: 0; | |||
| border: none; | |||
| outline: none; } | |||
| .slick-prev:hover, .slick-prev:focus, | |||
| .slick-next:hover, | |||
| .slick-next:focus { | |||
| outline: none; | |||
| background: transparent; | |||
| color: transparent; } | |||
| .slick-prev:hover:before, .slick-prev:focus:before, | |||
| .slick-next:hover:before, | |||
| .slick-next:focus:before { | |||
| opacity: 1; } | |||
| .slick-prev.slick-disabled:before, | |||
| .slick-next.slick-disabled:before { | |||
| opacity: 0.25; } | |||
| .slick-prev:before, | |||
| .slick-next:before { | |||
| font-family: "slick"; | |||
| font-size: 20px; | |||
| line-height: 1; | |||
| color: white; | |||
| opacity: 0.75; | |||
| -webkit-font-smoothing: antialiased; | |||
| -moz-osx-font-smoothing: grayscale; } | |||
| .slick-prev { | |||
| left: -25px; } | |||
| [dir="rtl"] .slick-prev { | |||
| left: auto; | |||
| right: -25px; } | |||
| .slick-prev:before { | |||
| content: "←"; } | |||
| [dir="rtl"] .slick-prev:before { | |||
| content: "→"; } | |||
| .slick-next { | |||
| right: -25px; } | |||
| [dir="rtl"] .slick-next { | |||
| left: -25px; | |||
| right: auto; } | |||
| .slick-next:before { | |||
| content: "→"; } | |||
| [dir="rtl"] .slick-next:before { | |||
| content: "←"; } | |||
| /* Dots */ | |||
| @@ -0,0 +1,84 @@ | |||
| /* Slider */ | |||
| .slick-slider { | |||
| position: relative; | |||
| display: block; | |||
| -webkit-box-sizing: border-box; | |||
| box-sizing: border-box; | |||
| -webkit-touch-callout: text; | |||
| -webkit-user-select: text; | |||
| -khtml-user-select: text; | |||
| -moz-user-select: text; | |||
| -ms-user-select: text; | |||
| user-select: text; | |||
| -ms-touch-action: pan-y; | |||
| touch-action: pan-y; | |||
| -webkit-tap-highlight-color: transparent; } | |||
| .slick-list { | |||
| position: relative; | |||
| overflow: hidden; | |||
| display: block; | |||
| margin: 0; | |||
| padding: 0; } | |||
| .slick-list:focus { | |||
| outline: none; } | |||
| .slick-list.dragging { | |||
| cursor: pointer; | |||
| cursor: hand; } | |||
| .slick-slider .slick-track, | |||
| .slick-slider .slick-list { | |||
| -webkit-transform: translate3d(0, 0, 0); | |||
| -moz-transform: translate3d(0, 0, 0); | |||
| -ms-transform: translate3d(0, 0, 0); | |||
| -o-transform: translate3d(0, 0, 0); | |||
| transform: translate3d(0, 0, 0); } | |||
| .slick-track { | |||
| position: relative; | |||
| left: 0; | |||
| top: 0; | |||
| display: block; | |||
| margin-left: auto; | |||
| margin-right: auto; } | |||
| .slick-track:before, .slick-track:after { | |||
| content: ""; | |||
| display: table; } | |||
| .slick-track:after { | |||
| clear: both; } | |||
| .slick-loading .slick-track { | |||
| visibility: hidden; } | |||
| .slick-slide { | |||
| float: left; | |||
| height: 100%; | |||
| min-height: 1px; | |||
| display: none; } | |||
| .slick-slide:focus { | |||
| outline: none; } | |||
| [dir="rtl"] .slick-slide { | |||
| float: right; } | |||
| .slick-slide img { | |||
| display: block; } | |||
| .slick-slide.slick-loading img { | |||
| display: none; } | |||
| .slick-slide.dragging img { | |||
| pointer-events: none; } | |||
| .slick-initialized .slick-slide { | |||
| display: block; } | |||
| .slick-loading .slick-slide { | |||
| visibility: hidden; } | |||
| .slick-vertical .slick-slide { | |||
| display: block; | |||
| height: auto; | |||
| border: 1px solid transparent; } | |||
| .slick-arrow.slick-hidden { | |||
| display: none; } | |||
| .slick-list.draggable { | |||
| -webkit-user-select: none; | |||
| -khtml-user-select: none; | |||
| -moz-user-select: none; | |||
| -ms-user-select: none; | |||
| user-select: none; } | |||
| @@ -0,0 +1,14 @@ | |||
| <?xml version="1.0" standalone="no"?> | |||
| <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> | |||
| <svg xmlns="http://www.w3.org/2000/svg"> | |||
| <metadata>Generated by Fontastic.me</metadata> | |||
| <defs> | |||
| <font id="slick" horiz-adv-x="512"> | |||
| <font-face font-family="slick" units-per-em="512" ascent="480" descent="-32"/> | |||
| <missing-glyph horiz-adv-x="512" /> | |||
| <glyph unicode="→" d="M241 113l130 130c4 4 6 8 6 13 0 5-2 9-6 13l-130 130c-3 3-7 5-12 5-5 0-10-2-13-5l-29-30c-4-3-6-7-6-12 0-5 2-10 6-13l87-88-87-88c-4-3-6-8-6-13 0-5 2-9 6-12l29-30c3-3 8-5 13-5 5 0 9 2 12 5z m234 143c0-40-9-77-29-110-20-34-46-60-80-80-33-20-70-29-110-29-40 0-77 9-110 29-34 20-60 46-80 80-20 33-29 70-29 110 0 40 9 77 29 110 20 34 46 60 80 80 33 20 70 29 110 29 40 0 77-9 110-29 34-20 60-46 80-80 20-33 29-70 29-110z"/> | |||
| <glyph unicode="←" d="M296 113l29 30c4 3 6 7 6 12 0 5-2 10-6 13l-87 88 87 88c4 3 6 8 6 13 0 5-2 9-6 12l-29 30c-3 3-8 5-13 5-5 0-9-2-12-5l-130-130c-4-4-6-8-6-13 0-5 2-9 6-13l130-130c3-3 7-5 12-5 5 0 10 2 13 5z m179 143c0-40-9-77-29-110-20-34-46-60-80-80-33-20-70-29-110-29-40 0-77 9-110 29-34 20-60 46-80 80-20 33-29 70-29 110 0 40 9 77 29 110 20 34 46 60 80 80 33 20 70 29 110 29 40 0 77-9 110-29 34-20 60-46 80-80 20-33 29-70 29-110z"/> | |||
| <glyph unicode="•" d="M475 256c0-40-9-77-29-110-20-34-46-60-80-80-33-20-70-29-110-29-40 0-77 9-110 29-34 20-60 46-80 80-20 33-29 70-29 110 0 40 9 77 29 110 20 34 46 60 80 80 33 20 70 29 110 29 40 0 77-9 110-29 34-20 60-46 80-80 20-33 29-70 29-110z"/> | |||
| <glyph unicode="a" d="M475 439l0-128c0-5-1-9-5-13-4-4-8-5-13-5l-128 0c-8 0-13 3-17 11-3 7-2 14 4 20l40 39c-28 26-62 39-100 39-20 0-39-4-57-11-18-8-33-18-46-32-14-13-24-28-32-46-7-18-11-37-11-57 0-20 4-39 11-57 8-18 18-33 32-46 13-14 28-24 46-32 18-7 37-11 57-11 23 0 44 5 64 15 20 9 38 23 51 42 2 1 4 3 7 3 3 0 5-1 7-3l39-39c2-2 3-3 3-6 0-2-1-4-2-6-21-25-46-45-76-59-29-14-60-20-93-20-30 0-58 5-85 17-27 12-51 27-70 47-20 19-35 43-47 70-12 27-17 55-17 85 0 30 5 58 17 85 12 27 27 51 47 70 19 20 43 35 70 47 27 12 55 17 85 17 28 0 55-5 81-15 26-11 50-26 70-45l37 37c6 6 12 7 20 4 8-4 11-9 11-17z"/> | |||
| </font></defs></svg> | |||
| @@ -0,0 +1 @@ | |||
| <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" width="64" height="64"><title>yoga</title><g class="nc-icon-wrapper" stroke-linecap="square" stroke-linejoin="miter" stroke-width="2" fill="#111111" stroke="#111111"><circle cx="32" cy="9" r="6" fill="none" stroke="#111111" stroke-miterlimit="10"/> <line data-color="color-2" x1="2" y1="59" x2="62" y2="59" fill="none" stroke-miterlimit="10"/> <path d="M20,50.92,16.813,49.9A4.046,4.046,0,0,1,14,46.046h0A4.047,4.047,0,0,1,18.046,42H24V28l-6.007,5.242a3,3,0,0,1-3.657.254L8.05,29.305a2.655,2.655,0,0,1-.737-3.683h0a2.657,2.657,0,0,1,3.393-.905l5.031,2.5,7.27-6.461A3,3,0,0,1,25,20H39a3,3,0,0,1,1.993.758l7.27,6.461,5.031-2.5a2.657,2.657,0,0,1,3.393.905h0a2.655,2.655,0,0,1-.737,3.683L49.664,33.5a3,3,0,0,1-3.657-.254L40,28V42h6.051A3.949,3.949,0,0,1,50,45.949h0a3.948,3.948,0,0,1-2.952,3.821L30.015,54.214a3.33,3.33,0,0,1-4-2.17h0a3.33,3.33,0,0,1,1.99-4.171L33,46" fill="none" stroke="#111111" stroke-miterlimit="10"/></g></svg> | |||
| @@ -0,0 +1,49 @@ | |||
| var google; | |||
| function init() { | |||
| // Basic options for a simple Google Map | |||
| // For more options see: https://developers.google.com/maps/documentation/javascript/reference#MapOptions | |||
| // var myLatlng = new google.maps.LatLng(40.71751, -73.990922); | |||
| var myLatlng = new google.maps.LatLng(40.69847032728747, -73.9514422416687); | |||
| // 39.399872 | |||
| // -8.224454 | |||
| var mapOptions = { | |||
| // How zoomed in you want the map to start at (always required) | |||
| zoom: 7, | |||
| // The latitude and longitude to center the map (always required) | |||
| center: myLatlng, | |||
| // How you would like to style the map. | |||
| scrollwheel: false, | |||
| styles: [{"featureType": "all","elementType": "geometry.fill","stylers": [{"weight": "2.00"}]},{"featureType": "all","elementType": "geometry.stroke","stylers": [{"color": "#9c9c9c"}]},{"featureType": "all","elementType": "labels.text","stylers": [{"visibility": "on"}]},{"featureType": "landscape","elementType": "all","stylers": [{"color": "#f2f2f2"}]},{"featureType": "landscape","elementType": "geometry.fill","stylers": [{"color": "#ffffff"}]},{"featureType": "landscape.man_made","elementType": "geometry.fill","stylers": [{"color": "#ffffff"}]},{"featureType": "poi","elementType": "all","stylers": [{"visibility": "off"}]},{"featureType": "road","elementType": "all","stylers": [{"saturation": -100},{"lightness": 45}]},{"featureType": "road","elementType": "geometry.fill","stylers": [{"color": "#eeeeee"}]},{"featureType": "road","elementType": "labels.text.fill","stylers": [{"color": "#7b7b7b"}]},{"featureType": "road","elementType": "labels.text.stroke","stylers": [{"color": "#ffffff"}]},{"featureType": "road.highway","elementType": "all","stylers": [{"visibility": "simplified"}]},{"featureType": "road.arterial","elementType": "labels.icon","stylers": [{"visibility": "off"}]},{"featureType": "transit","elementType": "all","stylers": [{"visibility": "off"}]},{"featureType": "water","elementType": "all","stylers": [{"color": "#46bcec"},{"visibility": "on"}]},{"featureType": "water","elementType": "geometry.fill","stylers": [{"color": "#c8d7d4"}]},{"featureType": "water","elementType": "labels.text.fill","stylers": [{"color": "#070707"}]},{"featureType": "water","elementType": "labels.text.stroke","stylers": [{"color": "#ffffff"}]}] | |||
| }; | |||
| // Get the HTML DOM element that will contain your map | |||
| // We are using a div with id="map" seen below in the <body> | |||
| var mapElement = document.getElementById('map'); | |||
| // Create the Google Map using out element and options defined above | |||
| var map = new google.maps.Map(mapElement, mapOptions); | |||
| var addresses = ['New York']; | |||
| for (var x = 0; x < addresses.length; x++) { | |||
| $.getJSON('http://maps.googleapis.com/maps/api/geocode/json?address='+addresses[x]+'&sensor=false', null, function (data) { | |||
| var p = data.results[0].geometry.location | |||
| var latlng = new google.maps.LatLng(p.lat, p.lng); | |||
| new google.maps.Marker({ | |||
| position: latlng, | |||
| map: map, | |||
| icon: 'img/loc.png' | |||
| }); | |||
| }); | |||
| } | |||
| } | |||
| google.maps.event.addDomListener(window, 'load', init); | |||
| @@ -0,0 +1,205 @@ | |||
| /* | |||
| * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/ | |||
| * | |||
| * Uses the built in easing capabilities added In jQuery 1.1 | |||
| * to offer multiple easing options | |||
| * | |||
| * TERMS OF USE - jQuery Easing | |||
| * | |||
| * Open source under the BSD License. | |||
| * | |||
| * Copyright © 2008 George McGinley Smith | |||
| * All rights reserved. | |||
| * | |||
| * Redistribution and use in source and binary forms, with or without modification, | |||
| * are permitted provided that the following conditions are met: | |||
| * | |||
| * Redistributions of source code must retain the above copyright notice, this list of | |||
| * conditions and the following disclaimer. | |||
| * Redistributions in binary form must reproduce the above copyright notice, this list | |||
| * of conditions and the following disclaimer in the documentation and/or other materials | |||
| * provided with the distribution. | |||
| * | |||
| * Neither the name of the author nor the names of contributors may be used to endorse | |||
| * or promote products derived from this software without specific prior written permission. | |||
| * | |||
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY | |||
| * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | |||
| * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | |||
| * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |||
| * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE | |||
| * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | |||
| * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |||
| * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | |||
| * OF THE POSSIBILITY OF SUCH DAMAGE. | |||
| * | |||
| */ | |||
| // t: current time, b: begInnIng value, c: change In value, d: duration | |||
| jQuery.easing['jswing'] = jQuery.easing['swing']; | |||
| jQuery.extend( jQuery.easing, | |||
| { | |||
| def: 'easeOutQuad', | |||
| swing: function (x, t, b, c, d) { | |||
| //alert(jQuery.easing.default); | |||
| return jQuery.easing[jQuery.easing.def](x, t, b, c, d); | |||
| }, | |||
| easeInQuad: function (x, t, b, c, d) { | |||
| return c*(t/=d)*t + b; | |||
| }, | |||
| easeOutQuad: function (x, t, b, c, d) { | |||
| return -c *(t/=d)*(t-2) + b; | |||
| }, | |||
| easeInOutQuad: function (x, t, b, c, d) { | |||
| if ((t/=d/2) < 1) return c/2*t*t + b; | |||
| return -c/2 * ((--t)*(t-2) - 1) + b; | |||
| }, | |||
| easeInCubic: function (x, t, b, c, d) { | |||
| return c*(t/=d)*t*t + b; | |||
| }, | |||
| easeOutCubic: function (x, t, b, c, d) { | |||
| return c*((t=t/d-1)*t*t + 1) + b; | |||
| }, | |||
| easeInOutCubic: function (x, t, b, c, d) { | |||
| if ((t/=d/2) < 1) return c/2*t*t*t + b; | |||
| return c/2*((t-=2)*t*t + 2) + b; | |||
| }, | |||
| easeInQuart: function (x, t, b, c, d) { | |||
| return c*(t/=d)*t*t*t + b; | |||
| }, | |||
| easeOutQuart: function (x, t, b, c, d) { | |||
| return -c * ((t=t/d-1)*t*t*t - 1) + b; | |||
| }, | |||
| easeInOutQuart: function (x, t, b, c, d) { | |||
| if ((t/=d/2) < 1) return c/2*t*t*t*t + b; | |||
| return -c/2 * ((t-=2)*t*t*t - 2) + b; | |||
| }, | |||
| easeInQuint: function (x, t, b, c, d) { | |||
| return c*(t/=d)*t*t*t*t + b; | |||
| }, | |||
| easeOutQuint: function (x, t, b, c, d) { | |||
| return c*((t=t/d-1)*t*t*t*t + 1) + b; | |||
| }, | |||
| easeInOutQuint: function (x, t, b, c, d) { | |||
| if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b; | |||
| return c/2*((t-=2)*t*t*t*t + 2) + b; | |||
| }, | |||
| easeInSine: function (x, t, b, c, d) { | |||
| return -c * Math.cos(t/d * (Math.PI/2)) + c + b; | |||
| }, | |||
| easeOutSine: function (x, t, b, c, d) { | |||
| return c * Math.sin(t/d * (Math.PI/2)) + b; | |||
| }, | |||
| easeInOutSine: function (x, t, b, c, d) { | |||
| return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b; | |||
| }, | |||
| easeInExpo: function (x, t, b, c, d) { | |||
| return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b; | |||
| }, | |||
| easeOutExpo: function (x, t, b, c, d) { | |||
| return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b; | |||
| }, | |||
| easeInOutExpo: function (x, t, b, c, d) { | |||
| if (t==0) return b; | |||
| if (t==d) return b+c; | |||
| if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b; | |||
| return c/2 * (-Math.pow(2, -10 * --t) + 2) + b; | |||
| }, | |||
| easeInCirc: function (x, t, b, c, d) { | |||
| return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b; | |||
| }, | |||
| easeOutCirc: function (x, t, b, c, d) { | |||
| return c * Math.sqrt(1 - (t=t/d-1)*t) + b; | |||
| }, | |||
| easeInOutCirc: function (x, t, b, c, d) { | |||
| if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b; | |||
| return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b; | |||
| }, | |||
| easeInElastic: function (x, t, b, c, d) { | |||
| var s=1.70158;var p=0;var a=c; | |||
| if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3; | |||
| if (a < Math.abs(c)) { a=c; var s=p/4; } | |||
| else var s = p/(2*Math.PI) * Math.asin (c/a); | |||
| return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b; | |||
| }, | |||
| easeOutElastic: function (x, t, b, c, d) { | |||
| var s=1.70158;var p=0;var a=c; | |||
| if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3; | |||
| if (a < Math.abs(c)) { a=c; var s=p/4; } | |||
| else var s = p/(2*Math.PI) * Math.asin (c/a); | |||
| return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b; | |||
| }, | |||
| easeInOutElastic: function (x, t, b, c, d) { | |||
| var s=1.70158;var p=0;var a=c; | |||
| if (t==0) return b; if ((t/=d/2)==2) return b+c; if (!p) p=d*(.3*1.5); | |||
| if (a < Math.abs(c)) { a=c; var s=p/4; } | |||
| else var s = p/(2*Math.PI) * Math.asin (c/a); | |||
| if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b; | |||
| return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b; | |||
| }, | |||
| easeInBack: function (x, t, b, c, d, s) { | |||
| if (s == undefined) s = 1.70158; | |||
| return c*(t/=d)*t*((s+1)*t - s) + b; | |||
| }, | |||
| easeOutBack: function (x, t, b, c, d, s) { | |||
| if (s == undefined) s = 1.70158; | |||
| return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b; | |||
| }, | |||
| easeInOutBack: function (x, t, b, c, d, s) { | |||
| if (s == undefined) s = 1.70158; | |||
| if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b; | |||
| return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b; | |||
| }, | |||
| easeInBounce: function (x, t, b, c, d) { | |||
| return c - jQuery.easing.easeOutBounce (x, d-t, 0, c, d) + b; | |||
| }, | |||
| easeOutBounce: function (x, t, b, c, d) { | |||
| if ((t/=d) < (1/2.75)) { | |||
| return c*(7.5625*t*t) + b; | |||
| } else if (t < (2/2.75)) { | |||
| return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b; | |||
| } else if (t < (2.5/2.75)) { | |||
| return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b; | |||
| } else { | |||
| return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b; | |||
| } | |||
| }, | |||
| easeInOutBounce: function (x, t, b, c, d) { | |||
| if (t < d/2) return jQuery.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b; | |||
| return jQuery.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b; | |||
| } | |||
| }); | |||
| /* | |||
| * | |||
| * TERMS OF USE - EASING EQUATIONS | |||
| * | |||
| * Open source under the BSD License. | |||
| * | |||
| * Copyright © 2001 Robert Penner | |||
| * All rights reserved. | |||
| * | |||
| * Redistribution and use in source and binary forms, with or without modification, | |||
| * are permitted provided that the following conditions are met: | |||
| * | |||
| * Redistributions of source code must retain the above copyright notice, this list of | |||
| * conditions and the following disclaimer. | |||
| * Redistributions in binary form must reproduce the above copyright notice, this list | |||
| * of conditions and the following disclaimer in the documentation and/or other materials | |||
| * provided with the distribution. | |||
| * | |||
| * Neither the name of the author nor the names of contributors may be used to endorse | |||
| * or promote products derived from this software without specific prior written permission. | |||
| * | |||
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY | |||
| * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | |||
| * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | |||
| * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |||
| * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE | |||
| * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | |||
| * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |||
| * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | |||
| * OF THE POSSIBILITY OF SUCH DAMAGE. | |||
| * | |||
| */ | |||
| @@ -0,0 +1,230 @@ | |||
| $(document).ready(function($) { | |||
| "use strict"; | |||
| var loader = function() { | |||
| setTimeout(function() { | |||
| if($('#pb_loader').length > 0) { | |||
| $('#pb_loader').removeClass('show'); | |||
| } | |||
| }, 2400); | |||
| }; | |||
| loader(); | |||
| // scroll | |||
| var scrollWindow = function() { | |||
| $(window).scroll(function(){ | |||
| var $w = $(this), | |||
| st = $w.scrollTop(), | |||
| navbar = $('.pb_navbar'), | |||
| sd = $('.js-scroll-wrap'); | |||
| if (st > 150) { | |||
| if ( !navbar.hasClass('scrolled') ) { | |||
| navbar.addClass('scrolled'); | |||
| } | |||
| } | |||
| if (st < 150) { | |||
| if ( navbar.hasClass('scrolled') ) { | |||
| navbar.removeClass('scrolled sleep'); | |||
| } | |||
| } | |||
| if ( st > 350 ) { | |||
| if ( !navbar.hasClass('awake') ) { | |||
| navbar.addClass('awake'); | |||
| } | |||
| if(sd.length > 0) { | |||
| sd.addClass('sleep'); | |||
| } | |||
| } | |||
| if ( st < 350 ) { | |||
| if ( navbar.hasClass('awake') ) { | |||
| navbar.removeClass('awake'); | |||
| navbar.addClass('sleep'); | |||
| } | |||
| if(sd.length > 0) { | |||
| sd.removeClass('sleep'); | |||
| } | |||
| } | |||
| }); | |||
| }; | |||
| scrollWindow(); | |||
| // slick sliders | |||
| var slickSliders = function() { | |||
| $('.single-item').slick({ | |||
| slidesToShow: 1, | |||
| slidesToScroll: 1, | |||
| dots: true, | |||
| infinite: true, | |||
| autoplay: false, | |||
| autoplaySpeed: 2000, | |||
| nextArrow: '<span class="next"><i class="ion-ios-arrow-right"></i></span>', | |||
| prevArrow: '<span class="prev"><i class="ion-ios-arrow-left"></i></span>', | |||
| arrows: true, | |||
| draggable: false, | |||
| adaptiveHeight: true | |||
| }); | |||
| $('.single-item-no-arrow').slick({ | |||
| slidesToShow: 1, | |||
| slidesToScroll: 1, | |||
| dots: true, | |||
| infinite: true, | |||
| autoplay: true, | |||
| autoplaySpeed: 2000, | |||
| nextArrow: '<span class="next"><i class="ion-ios-arrow-right"></i></span>', | |||
| prevArrow: '<span class="prev"><i class="ion-ios-arrow-left"></i></span>', | |||
| arrows: false, | |||
| draggable: false | |||
| }); | |||
| $('.multiple-items').slick({ | |||
| slidesToShow: 3, | |||
| slidesToScroll: 1, | |||
| dots: true, | |||
| infinite: true, | |||
| autoplay: true, | |||
| autoplaySpeed: 2000, | |||
| arrows: true, | |||
| nextArrow: '<span class="next"><i class="ion-ios-arrow-right"></i></span>', | |||
| prevArrow: '<span class="prev"><i class="ion-ios-arrow-left"></i></span>', | |||
| draggable: false, | |||
| responsive: [ | |||
| { | |||
| breakpoint: 1125, | |||
| settings: { | |||
| slidesToShow: 2, | |||
| slidesToScroll: 1, | |||
| infinite: true, | |||
| dots: true | |||
| } | |||
| }, | |||
| { | |||
| breakpoint: 900, | |||
| settings: { | |||
| slidesToShow: 2, | |||
| slidesToScroll: 2 | |||
| } | |||
| }, | |||
| { | |||
| breakpoint: 580, | |||
| settings: { | |||
| slidesToShow: 1, | |||
| slidesToScroll: 1 | |||
| } | |||
| } | |||
| ] | |||
| }); | |||
| $('.js-pb_slider_content').slick({ | |||
| slidesToShow: 1, | |||
| slidesToScroll: 1, | |||
| arrows: false, | |||
| fade: true, | |||
| asNavFor: '.js-pb_slider_nav', | |||
| adaptiveHeight: false | |||
| }); | |||
| $('.js-pb_slider_nav').slick({ | |||
| slidesToShow: 3, | |||
| slidesToScroll: 1, | |||
| asNavFor: '.js-pb_slider_content', | |||
| dots: false, | |||
| centerMode: true, | |||
| centerPadding: "0px", | |||
| focusOnSelect: true, | |||
| arrows: false | |||
| }); | |||
| $('.js-pb_slider_content2').slick({ | |||
| slidesToShow: 1, | |||
| slidesToScroll: 1, | |||
| arrows: false, | |||
| fade: true, | |||
| asNavFor: '.js-pb_slider_nav2', | |||
| adaptiveHeight: false | |||
| }); | |||
| $('.js-pb_slider_nav2').slick({ | |||
| slidesToShow: 3, | |||
| slidesToScroll: 1, | |||
| asNavFor: '.js-pb_slider_content2', | |||
| dots: false, | |||
| centerMode: true, | |||
| centerPadding: "0px", | |||
| focusOnSelect: true, | |||
| arrows: false | |||
| }); | |||
| }; | |||
| slickSliders(); | |||
| // navigation | |||
| var OnePageNav = function() { | |||
| var navToggler = $('.navbar-toggler'); | |||
| $(".smoothscroll[href^='#'], #probootstrap-navbar ul li a[href^='#']").on('click', function(e) { | |||
| $(this).blur(); | |||
| e.preventDefault(); | |||
| var hash = this.hash, | |||
| pos = ( hash === '#section-register' ) ? $(hash).offset().top - 200 : $(hash).offset().top; | |||
| $('html, body').animate({ | |||
| scrollTop: pos | |||
| }, 700, 'easeInOutExpo', function(){ | |||
| //window.location.hash = hash; | |||
| }); | |||
| }); | |||
| $("#probootstrap-navbar ul li a[href^='#']").on('click', function(e){ | |||
| if ( navToggler.is(':visible') ) { | |||
| navToggler.click(); | |||
| } | |||
| }); | |||
| $('body').on('activate.bs.scrollspy', function () { | |||
| console.log('nice'); | |||
| }) | |||
| }; | |||
| OnePageNav(); | |||
| var offCanvasNav = function() { | |||
| var toggleNav = $('.js-pb_nav-toggle'), | |||
| offcanvasNav = $('.js-pb_offcanvas-nav_v1'); | |||
| if( toggleNav.length > 0 ) { | |||
| toggleNav.click(function(e){ | |||
| $(this).toggleClass('active'); | |||
| offcanvasNav.addClass('active'); | |||
| e.preventDefault(); | |||
| }); | |||
| } | |||
| offcanvasNav.click(function(e){ | |||
| if (offcanvasNav.hasClass('active')) { | |||
| offcanvasNav.removeClass('active'); | |||
| toggleNav.removeClass('active'); | |||
| } | |||
| e.preventDefault(); | |||
| }); | |||
| }; | |||
| offCanvasNav(); | |||
| /* | |||
| var ytpPlayer = function() { | |||
| if ($('.ytp_player').length > 0) { | |||
| $('.ytp_player').mb_YTPlayer(); | |||
| } | |||
| } | |||
| ytpPlayer(); | |||
| */ | |||
| setTimeout( function() | |||
| { | |||
| pbInit(); | |||
| }, 250 ); | |||
| }); | |||
| @@ -0,0 +1,360 @@ | |||
| window.PB_CONFIG = null; | |||
| window.PB_USERPROFILE = null; | |||
| function pbRegister( data ) | |||
| { | |||
| var xhr = new XMLHttpRequest(), | |||
| request = { | |||
| auth : { | |||
| version : window.PB_CONFIG.version, | |||
| sessionToken : null | |||
| }, | |||
| c : 'Auth', | |||
| a: 'registerTrainer', | |||
| params : data | |||
| }; | |||
| xhr.onload = function() { | |||
| var response = xhr.responseText ? xhr.responseText : null; | |||
| if ( response ) | |||
| { | |||
| try | |||
| { | |||
| response = JSON.parse(response); | |||
| } | |||
| catch( err ) {} | |||
| if ( response && response.hasOwnProperty( 'data' ) && response.hasOwnProperty( 'code' ) ) | |||
| { | |||
| if ( response.code == 200 ) | |||
| { | |||
| $( '[data-type="register-section"]' ).hide(); | |||
| $( '[data-id="checkmark-container"]' ).first().html( | |||
| ' <div data-type="rsvp-button-recall">\n' + | |||
| ' <svg class="rsvp-checkmark"\n' + | |||
| ' xmlns="http://www.w3.org/2000/svg"\n' + | |||
| ' viewBox="0 0 52 52">\n' + | |||
| ' <circle class="rsvp-checkmark__circle" cx="26" cy="26" r="25" fill="none"/>\n' + | |||
| ' <path class="rsvp-checkmark__check" fill="none" d="M14.1 27.2l7.1 7.2 16.7-16.8"/>\n' + | |||
| ' </svg>\n' + | |||
| ' </div>' | |||
| ); | |||
| // Show next steps | |||
| if ( response.data.session === null ) | |||
| { | |||
| // Show validation info | |||
| $( '[data-id="registration-new-user"]' ).first().show(); | |||
| } | |||
| else | |||
| { | |||
| // Show login | |||
| $( '[data-id="registration-existing-user"]' ).first().show(); | |||
| } | |||
| } | |||
| else | |||
| { | |||
| $( '[data-id="error-general"]' ).first().show(); | |||
| } | |||
| } | |||
| $( '[data-id="btn-register"]' ).first().attr( 'disabled', false ); | |||
| } | |||
| }; | |||
| xhr.onabort = function() { | |||
| $( '[data-id="btn-register"]' ).first().enable(); | |||
| }; | |||
| xhr.onerror = function() { | |||
| $( '[data-id="btn-register"]' ).first().enable(); | |||
| }; | |||
| xhr.open( 'POST', 'api.php' ); | |||
| xhr.setRequestHeader( "Content-Type", "application/json" ); | |||
| xhr.send( JSON.stringify( request ) ); | |||
| } | |||
| function pbRegisterWizard( onOk, onErr ) | |||
| { | |||
| var xhr = new XMLHttpRequest(), | |||
| request = { | |||
| auth : { | |||
| version : window.PB_CONFIG.version, | |||
| sessionToken : null | |||
| }, | |||
| c : 'Auth', | |||
| a: 'registerTrainer', | |||
| params : window.WIZARD_DATA | |||
| }, | |||
| onSuccess = onOk || null, | |||
| onError = onErr || null; | |||
| xhr.onload = function() | |||
| { | |||
| var response = xhr.responseText ? xhr.responseText : null; | |||
| if ( response ) | |||
| { | |||
| try | |||
| { | |||
| response = JSON.parse(response); | |||
| } catch (err) {} | |||
| if ( response && response.hasOwnProperty( 'data' ) && response.hasOwnProperty( 'code' ) ) | |||
| { | |||
| if ( response.code == 200 ) | |||
| { | |||
| onSuccess && onSuccess( response ); | |||
| } | |||
| } | |||
| } | |||
| }; | |||
| xhr.onabort = function() { | |||
| onError && onError(); | |||
| }; | |||
| xhr.onerror = function() { | |||
| onError && onError(); | |||
| }; | |||
| xhr.open( 'POST', 'api.php' ); | |||
| xhr.setRequestHeader( "Content-Type", "application/json" ); | |||
| xhr.send( JSON.stringify( request ) ); | |||
| } | |||
| function pbInitWizard() | |||
| { | |||
| window.WIZARD_INDEX = 0; | |||
| window.WIZARD_DATA = {}; | |||
| window.WIZARD_DATA.industry = 'DOGSCHOOL'; | |||
| window.WIZARD_DATA.affiliateId = 'retrust'; | |||
| var $bWizard = $( '[data-id="wizard-carousel"]' ).first(), | |||
| $wizardProgress = $( '[data-id="wizard-progress"]' ).first(); | |||
| $wizardProgress.css( 'width', '0%' ); | |||
| $bWizard.carousel({ | |||
| interval: false, | |||
| keyboard : false, | |||
| touch: false | |||
| }); | |||
| $bWizard.on( 'slide.bs.carousel', function( e ) | |||
| { | |||
| var nextH = $(e.relatedTarget).height(); | |||
| $(this).find('.carousel-item.active').parent().animate({ | |||
| height: nextH | |||
| }, 500); | |||
| }); | |||
| } | |||
| function pbWizardUpdateProgress() | |||
| { | |||
| var $wizardProgress = $( '[data-id="wizard-progress"]' ).first(), | |||
| totalSteps = $( '[data-type="wizard-step"]' ).length, | |||
| progress = ~~( window.WIZARD_INDEX / totalSteps * 100); | |||
| $wizardProgress.css( 'width', progress + '%' ); | |||
| } | |||
| function pbWizardNext( step ) | |||
| { | |||
| window.WIZARD_INDEX++; | |||
| var $bWizard = $( '[data-id="wizard-carousel"]' ).first(); | |||
| switch ( step ) | |||
| { | |||
| case 'school': | |||
| var $form = $( '[data-id="wizardform-school"]' ).first(), | |||
| heightAdd = $form.hasClass( 'was-validated' ) ? 0 : 70; | |||
| $form.removeClass( 'was-validated' ); | |||
| var isValid = $form.get(0).checkValidity(); | |||
| $form.addClass( 'was-validated' ); | |||
| if ( false === isValid ) | |||
| { | |||
| if ( heightAdd > 0 ) | |||
| { | |||
| setTimeout( function() | |||
| { | |||
| $( '.carousel-inner' ).animate( { height: $( '.carousel-inner' ).innerHeight() + heightAdd }, 300 ); | |||
| }, 100 ); | |||
| } | |||
| return; | |||
| } | |||
| break; | |||
| case 'register': | |||
| var $form = $( '[data-id="wizardform-account"]' ).first(), | |||
| heightAdd = $form.hasClass( 'was-validated' ) ? 0 : 70; | |||
| $form.removeClass( 'was-validated' ); | |||
| var isValid = $form.get(0).checkValidity(); | |||
| $form.addClass( 'was-validated' ); | |||
| if ( false === isValid ) | |||
| { | |||
| if ( heightAdd > 0 ) | |||
| { | |||
| setTimeout( function() | |||
| { | |||
| $( '.carousel-inner' ).animate( { height: $( '.carousel-inner' ).innerHeight() + heightAdd }, 300 ); | |||
| }, 100 ); | |||
| } | |||
| return; | |||
| } | |||
| window.WIZARD_DATA.teamname = $.trim( $( '[data-id="input-register-teamname"]' ).first().val() ); | |||
| window.WIZARD_DATA.courseCategories = []; | |||
| $( '[data-type="checkbox-coursecategories"]' ).each( function() | |||
| { | |||
| if ( $(this).prop( 'checked' ) ) | |||
| { | |||
| window.WIZARD_DATA.courseCategories.push( $(this).attr( 'data-value' ) ); | |||
| } | |||
| }); | |||
| window.WIZARD_DATA.createDemoAppointments = $( '[data-id="register-demo-appointments"]' ).first().prop( 'checked' ) ? 1 : 0; | |||
| window.WIZARD_DATA.firstname = $.trim( $( '[data-id="input-register-firstname"]' ).first().val() ); | |||
| window.WIZARD_DATA.lastname = $.trim( $( '[data-id="input-register-lastname"]' ).first().val() ); | |||
| window.WIZARD_DATA.email = $.trim( $( '[data-id="input-register-email"]' ).first().val() ); | |||
| window.WIZARD_DATA.password = $.trim( $( '[data-id="input-register-password"]' ).first().val() ); | |||
| window.WIZARD_DATA.subscribedNews = $.trim( $( '[data-id="register-accept-newsletter"]' ).first().prop( 'checked' ) ? 1 : 0 ); | |||
| pbRegisterWizard( | |||
| // onSuccess | |||
| function( res ) | |||
| { | |||
| $( '[data-id="btnLaunchApp"]' ).first().attr( 'href', window.PB_CONFIG.url + '/#/auth/sso/' + res.data.session.token + '/dog' ); | |||
| $( '[data-id="register-container"]' ).first().html( | |||
| ' <div class="register-success">\n' + | |||
| ' <svg class="rsvp-checkmark"\n' + | |||
| ' xmlns="http://www.w3.org/2000/svg"\n' + | |||
| ' viewBox="0 0 52 52">\n' + | |||
| ' <circle class="rsvp-checkmark__circle" cx="26" cy="26" r="25" fill="none"/>\n' + | |||
| ' <path class="rsvp-checkmark__check" fill="none" d="M14.1 27.2l7.1 7.2 16.7-16.8"/>\n' + | |||
| ' </svg>\n' + | |||
| ' </div>' | |||
| ); | |||
| window.WIZARD_INDEX++; | |||
| pbWizardUpdateProgress(); | |||
| setTimeout( function() | |||
| { | |||
| pbWizardNext( 'done' ); | |||
| }, 1400 ); | |||
| }, | |||
| // onError | |||
| function() | |||
| { | |||
| $( '[data-id="section-wizard-form"]' ).hide(); | |||
| $( '[data-id="registration-error"]' ).show(); | |||
| } | |||
| ); | |||
| break; | |||
| } | |||
| pbWizardUpdateProgress(); | |||
| $bWizard.carousel( 'next' ); | |||
| $('html, body').animate({ | |||
| scrollTop: ( $( '#section-register' ).offset().top - 200 ) | |||
| }, 700, 'easeInOutExpo', function(){ | |||
| //window.location.hash = hash; | |||
| }); | |||
| } | |||
| function pbWizardPrev() | |||
| { | |||
| window.WIZARD_INDEX--; | |||
| var $bWizard = $( '[data-id="wizard-carousel"]' ).first(); | |||
| pbWizardUpdateProgress(); | |||
| $bWizard.carousel( 'prev' ); | |||
| } | |||
| function pbInit() | |||
| { | |||
| var xhr = new XMLHttpRequest(), | |||
| request = { | |||
| auth : { | |||
| version : 0, | |||
| sessionToken : null | |||
| }, | |||
| c : 'Auth', | |||
| a: 'getSession', | |||
| params : { includeConfig: true } | |||
| }; | |||
| xhr.onload = function() { | |||
| var response = xhr.responseText ? xhr.responseText : null; | |||
| if ( response ) | |||
| { | |||
| try | |||
| { | |||
| response = JSON.parse(response); | |||
| } | |||
| catch( err ) {} | |||
| if ( response.hasOwnProperty( 'data' ) ) | |||
| { | |||
| if ( response.data.hasOwnProperty( 'config' ) ) | |||
| { | |||
| window.PB_CONFIG = response.data.config; | |||
| } | |||
| if ( response.data.hasOwnProperty( 'userProfile' ) ) | |||
| { | |||
| window.PB_USERPROFILE = response.data.userProfile; | |||
| } | |||
| } | |||
| } | |||
| }; | |||
| xhr.onabort = function() {}; | |||
| xhr.onerror = function() {}; | |||
| xhr.open( 'POST', 'api.php' ); | |||
| xhr.setRequestHeader( "Content-Type", "application/json" ); | |||
| xhr.send( JSON.stringify( request ) ); | |||
| // Form | |||
| $( '[data-id="btn-register"]' ).first().click( function() | |||
| { | |||
| var $form = $( '[data-id="form-register"]' ).first(); | |||
| $form.removeClass( 'was-validated' ); | |||
| var isValid = $form.get(0).checkValidity(); | |||
| $form.addClass( 'was-validated' ); | |||
| $( '[data-id="error-email-exists"]' ).first().hide(); | |||
| $( '[data-id="error-general"]' ).first().hide(); | |||
| if ( isValid ) | |||
| { | |||
| $(this).attr( 'disabled', true ); | |||
| var data = {}; | |||
| data.teamname = $.trim( $( '[data-id="input-register-teamname"]' ).first().val() ); | |||
| data.teamCategory = $.trim( $( '[data-id="input-team-category"]' ).first().val() ); | |||
| data.affiliateId = $.trim( $( '[data-id="input-affiliate-id"]' ).first().val() ); | |||
| data.email = $.trim( $( '[data-id="input-register-email"]' ).first().val() ); | |||
| data.password = $.trim( $( '[data-id="input-register-password"]' ).first().val() ); | |||
| data.firstname = $.trim( $( '[data-id="input-register-firstname"]' ).first().val() ); | |||
| data.lastname = $.trim( $( '[data-id="input-register-lastname"]' ).first().val() ); | |||
| data.subscribedNews = $.trim( $( '[data-id="register-accept-newsletter"]' ).first().prop( 'checked' ) ? 1 : 0 ); | |||
| pbRegister( data ); | |||
| } | |||
| }); | |||
| pbInitWizard(); | |||
| } | |||
| @@ -0,0 +1,701 @@ | |||
| <!DOCTYPE html> | |||
| <html lang="en"> | |||
| <head> | |||
| <meta charset="utf-8"> | |||
| <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> | |||
| <title>ProBuddy © TBuddy UG (haftungsbeschränkt)</title> | |||
| <meta name="description" content="ProBuddy - Professionelle Kursverwaltung"> | |||
| <link href="https://fonts.googleapis.com/css?family=Crimson+Text:400,400i,600|Montserrat:200,300,400" rel="stylesheet"> | |||
| <link rel="stylesheet" href="assets/css/bootstrap/bootstrap.css"> | |||
| <link rel="stylesheet" href="assets/fonts/ionicons/css/ionicons.min.css"> | |||
| <link rel="stylesheet" href="assets/fonts/law-icons/font/flaticon.css"> | |||
| <link rel="stylesheet" href="assets/fonts/fontawesome/css/font-awesome.min.css"> | |||
| <link rel="stylesheet" href="assets/css/slick.css"> | |||
| <link rel="stylesheet" href="assets/css/slick-theme.css"> | |||
| <link rel="stylesheet" href="assets/css/helpers.css"> | |||
| <link rel="stylesheet" href="assets/css/style.css"> | |||
| <link rel="stylesheet" href="assets/css/landing-2.css"> | |||
| </head> | |||
| <body data-spy="scroll" data-target="#pb-navbar" data-offset="200"> | |||
| <nav class="navbar navbar-expand-lg navbar-dark pb_navbar pb_scrolled-light" id="pb-navbar"> | |||
| <div class="container"> | |||
| <a class="navbar-brand" href="#section-home"><strong>Pro</strong>Buddy</a> | |||
| <button class="navbar-toggler ml-auto" type="button" data-toggle="collapse" data-target="#probootstrap-navbar" aria-controls="probootstrap-navbar" aria-expanded="false" aria-label="Toggle navigation"> | |||
| <span><i class="ion-navicon"></i></span> | |||
| </button> | |||
| <div class="collapse navbar-collapse" id="probootstrap-navbar"> | |||
| <ul class="navbar-nav ml-auto"> | |||
| <li class="nav-item"><a class="nav-link" href="#section-home">Home</a></li> | |||
| <li class="nav-item"><a class="nav-link" href="#section-challenge">Herausforderung</a></li> | |||
| <li class="nav-item"><a class="nav-link" href="#section-features">Lösung</a></li> | |||
| <li class="nav-item"><a class="nav-link" href="#section-industry">Anwendungsfälle</a></li> | |||
| <li class="nav-item"><a class="nav-link" href="#section-reviews">Reviews</a></li> | |||
| <li class="nav-item"><a class="nav-link" href="#section-pricing">Preise</a></li> | |||
| <li class="nav-item"><a class="nav-link" href="#section-faq">FAQ</a></li> | |||
| <li class="nav-item cta-btn ml-xl-2 ml-lg-2 ml-md-0 ml-sm-0 ml-0"> | |||
| <a class="nav-link" | |||
| href="https://www.probuddy.de/#/auth/login"> | |||
| <span class="pb_rounded-4 px-4">Login</span> | |||
| </a> | |||
| </li> | |||
| </ul> | |||
| </div> | |||
| </div> | |||
| </nav> | |||
| <!-- END nav --> | |||
| <section class="pb_cover_v3 overflow-hidden cover-bg-indigo cover-bg-opacity-7 text-center pb_gradient_v1 pb_slant-light" | |||
| id="section-home" style="background-image:url(./assets/images/bckgrnd.jpeg);"> | |||
| <!--rawpixel-771284-unsplash.jpg);"--> | |||
| <div class="container"> | |||
| <div class="row align-items-center justify-content-center"> | |||
| <div class="col-md-6"> | |||
| <h2 class="sub-heading"><p class="mb-3">Lösung für Hunde-Schulen.</p></h2> | |||
| <h2 class="heading mb-3">Mehr Zeit <br>für "Hund und Herrchen".</h2> | |||
| <div class="sub-heading"> | |||
| <p class="mb-3">Organisieren Sie Ihre Hunde-Schule mit <strong>Pro</strong>Buddy und bauen Ihr Geschäft kundenfreundlich und effizient aus.</p> | |||
| </div> | |||
| </div> | |||
| <div class="col-md-1"> | |||
| </div> | |||
| <div class="col-md-5 relative align-self-center"> | |||
| <div class="bg-white rounded pb_form_v1"> | |||
| <h2 class="mb-4 mt-0 text-center">Jetzt kostenlos testen</h2> | |||
| <p> | |||
| Testen sie <strong>Pro</strong>Buddy jetzt 30 Tage kostenlos und unverbindlich. | |||
| </p> | |||
| <div class="form-group"> | |||
| <a href="https://www.probuddy.de/#/auth/register" class="btn btn-primary btn-lg btn-block pb_btn-pill btn-shadow-blue">Loslegen</a> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </section> | |||
| <!-- END section --> | |||
| <section class="pb_section bg-light pb_slant-white pb_pb-250" id="section-challenge"> | |||
| <div class="container"> | |||
| <div class="row justify-content-center mb-5"> | |||
| <div class="col-md-6 text-center mb-5"> | |||
| <h5 class="text-uppercase pb_font-15 mb-2 pb_color-dark-opacity-3 pb_letter-spacing-2"><strong>Herausforderungen im täglichen Betrieb</strong></h5> | |||
| <h2>Gehen wir Ihre Themen gemeinsam an.</h2> | |||
| <strong>Pro</strong>Buddy hilft Ihnen dabei, Ihr Angebot optimal zu präsentieren, "Zeitfresser" zu beseitigen und die Kommunikation miteinander zu verbessern. | |||
| </div> | |||
| </div> | |||
| <div class="row"> | |||
| <div class="col-lg-4 col-md- col-sm-6"> | |||
| <div class="media d-block pb_feature-v1 text-left"> | |||
| <div class="pb_icon"><i class="ion-ios-list-outline pb_icon-gradient"></i></div> | |||
| <div class="media-body"> | |||
| <h5 class="mt-0 mb-3 heading">Nicht optimale Kursauslastung</h5> | |||
| <p class="text-sans-serif">Zu- und Absagen, Verlässlichkeit der Teilnehmer, Warteliste.</p> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| <div class="col-lg-4 col-md- col-sm-6"> | |||
| <div class="media d-block pb_feature-v1 text-left"> | |||
| <div class="pb_icon"><i class="ion-ios-timer-outline pb_icon-gradient"></i></div> | |||
| <div class="media-body"> | |||
| <h5 class="mt-0 mb-3 heading">Mühsame Terminorganisation</h5> | |||
| <p class="text-sans-serif">Vor, während und nach dem Termin. Anwesenheit, u.a. für die Abrechnung.</p> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| <div class="col-lg-4 col-md- col-sm-6"> | |||
| <div class="media d-block pb_feature-v1 text-left"> | |||
| <div class="pb_icon"><i class=" ion-ios-color-wand-outline pb_icon-gradient"></i></div> | |||
| <div class="media-body"> | |||
| <h5 class="mt-0 mb-3 heading">Zu wenig digitale Unterstützung</h5> | |||
| <p class="text-sans-serif">Mail, SMS, Anruf, Wandkalender. Was erwarten Ihre Kunden heute?</p> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| <div class="col-lg-4 col-md- col-sm-6"> | |||
| <div class="media d-block pb_feature-v1 text-left"> | |||
| <div class="pb_icon"><i class=" ion-ios-calendar-outline pb_icon-gradient"></i></div> | |||
| <div class="media-body"> | |||
| <h5 class="mt-0 mb-3 heading">Starrer Kurs-Kalender</h5> | |||
| <p class="text-sans-serif">Flexibel und schnell Kalender erweitern, neue Themen probieren. </p> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| <div class="col-lg-4 col-md- col-sm-6"> | |||
| <div class="media d-block pb_feature-v1 text-left"> | |||
| <div class="pb_icon"><i class=" ion-ios-chatboxes-outline pb_icon-gradient"></i></div> | |||
| <div class="media-body"> | |||
| <h5 class="mt-0 mb-3 heading">Zu viele Kommunikationswege</h5> | |||
| <p class="text-sans-serif">Erinnerungen, News und Updates. Wie erreichen Sie die Kunden? </p> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| <div class="col-lg-4 col-md- col-sm-6"> | |||
| <div class="media d-block pb_feature-v1 text-left"> | |||
| <div class="pb_icon"><i class=" ion-ios-locked-outline pb_icon-gradient"></i></div> | |||
| <div class="media-body"> | |||
| <h5 class="mt-0 mb-3 heading">Datenschutz ist Pflicht</h5> | |||
| <p class="text-sans-serif">Gesetzliche Datenschutzrichtlinien (DSGVO)? Ohne IT keine Chance.</p> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </section> | |||
| <!-- END section --> | |||
| <section class="pb_section pb_slant-light" id="section-features"> | |||
| <div class="container"> | |||
| <div class="row"> | |||
| <div class="col-lg-4 order-2"> | |||
| <img src="assets/images/phone_3.png" alt="Image placeholder" class="img-fluid"> | |||
| </div> | |||
| <div class="col-lg-8 pl-md-5 pl-sm-0"> | |||
| <div class="row"> | |||
| <div class="col"> | |||
| <h2>Steigern sie ihre Produktivität.</h2> | |||
| <p class="pb_font-20"> | |||
| Mit <strong>Pro</strong>Buddy reduzieren Sie zeitintensive Aufgaben, verbessern gleichzeitig Ihre Kommunikation und schaffen Freiräume. | |||
| </p> | |||
| </div> | |||
| </div> | |||
| <div class="row"> | |||
| <div class="col-lg"> | |||
| <div class="media pb_feature-v2 text-left mb-1 mt-5"> | |||
| <div class="pb_icon d-flex mr-3 align-self-start pb_w-15"><i class="fa fa-flag-checkered pb_icon-gradient"></i></div> | |||
| <div class="media-body"> | |||
| <h3 class="mt-2 mb-2 heading">Schnelles Setup</h3> | |||
| <p class="text-sans-serif pb_font-16">In nur wenigen Schritten zum Erfolg. Registrieren. Kurse anlegen. Mitglieder einladen. Fertig!</p> | |||
| </div> | |||
| </div> | |||
| <div class="media pb_feature-v2 text-left mb-1 mt-5"> | |||
| <div class="pb_icon d-flex mr-3 align-self-start pb_w-15"><i class="fa fa-bell-o pb_icon-gradient"></i></div> | |||
| <div class="media-body"> | |||
| <h3 class="mt-2 mb-2 heading">Zu- und Absagen einfach organisieren</h3> | |||
| <p class="text-sans-serif pb_font-16">Maximale Teilnehmerzahl, Zusagefrist und Warteliste. Zusagen einfach per Klick, das kann jeder. </p> | |||
| </div> | |||
| </div> | |||
| <div class="media pb_feature-v2 text-left mb-1 mt-5"> | |||
| <div class="pb_icon d-flex mr-3 align-self-start pb_w-15"><i class="fa fa-bell-o pb_icon-gradient"></i></div> | |||
| <div class="media-body"> | |||
| <h3 class="mt-2 mb-2 heading">Integrierte Benachrichtigungen</h3> | |||
| <p class="text-sans-serif pb_font-16">Ein Kurs fällt aus oder ändert sich? Kein Problem. <strong>Pro</strong>Buddy informiert ihre Mitglieder automatisch.</p> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| <div class="col-lg"> | |||
| <div class="media pb_feature-v2 text-left mb-1 mt-5"> | |||
| <div class="pb_icon d-flex mr-3 align-self-start pb_w-15"><i class="fa fa-calendar-check-o pb_icon-gradient"></i></div> | |||
| <div class="media-body"> | |||
| <h3 class="mt-2 mb-2 heading">Zentraler Kurskalender</h3> | |||
| <p class="text-sans-serif pb_font-16">Alle Kursangebote sind in einem zentralen Kalender erreichbar - ob direkt über die App oder über Plugin auf ihrer Webseite.</p> | |||
| </div> | |||
| </div> | |||
| <div class="media pb_feature-v2 text-left mb-1 mt-5"> | |||
| <div class="pb_icon d-flex mr-3 align-self-start pb_w-15"><i class="fa fa-mobile-phone pb_icon-gradient"></i></div> | |||
| <div class="media-body"> | |||
| <h3 class="mt-2 mb-2 heading">Einfache Verwaltung - jederzeit und überall</h3> | |||
| <p class="text-sans-serif pb_font-16">Verwalten sie Kurse und Mitglieder effizient. Egal, ob am PC oder auf dem Smartphone unterwegs.</p> | |||
| </div> | |||
| </div> | |||
| <div class="media pb_feature-v2 text-left mb-1 mt-5"> | |||
| <div class="pb_icon d-flex mr-3 align-self-start pb_w-15"><i class="fa fa-mobile-phone pb_icon-gradient"></i></div> | |||
| <div class="media-body"> | |||
| <h3 class="mt-2 mb-2 heading">Datenschutz und Anonymität</h3> | |||
| <p class="text-sans-serif pb_font-16">Nutzen Sie eine DSGVO-konforme Plattform für Ihre Kunden, vermeiden Sie jegliche Risiken.</p> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </section> | |||
| <!-- END section --> | |||
| <section class="pb_section bg-light pb_slant-white pb_pb-250" id="section-vorteilKunde"> | |||
| <div class="container"> | |||
| <div class="row"> | |||
| <div class="col-lg-4 mb-5"> | |||
| <img src="assets/images/phone_3.png" alt="Image placeholder" class="img-fluid"> | |||
| </div> | |||
| <div class="col-lg-8 pr-md-5 pr-sm-0 order-1 mb-5"> | |||
| <div class="row"> | |||
| <div class="col"> | |||
| <h2>Sechs Gründe, warum Ihre Kunden Ihr Angebot noch mehr <u>lieben</u> werden.</h2> | |||
| <p class="pb_font-20"> | |||
| <strong>Pro</strong>Buddy unterstützt nicht nur Sie, sondern bietet auch Ihren Kunden viele Vorteile. | |||
| </p> | |||
| </div> | |||
| <div class="row"> | |||
| <div class="col-lg"> | |||
| <div class="media pb_feature-v2 text-left mb-1 mt-5"> | |||
| <div class="pb_icon d-flex mr-3 align-self-start pb_w-15"><i class="fa fa-mobile pb_icon-gradient"></i></div> | |||
| <div class="media-body"> | |||
| <h3 class="mt-2 mb-2 heading">Kurskalender immer dabei</h3> | |||
| <p class="text-sans-serif pb_font-16">Wann ist der nächste Kurs, ist noch was frei - kann ich reservieren?</p> | |||
| </div> | |||
| </div> | |||
| <div class="media pb_feature-v2 text-left mb-1 mt-5"> | |||
| <div class="pb_icon d-flex mr-3 align-self-start pb_w-15"><i class="fa fa-check-circle pb_icon-gradient"></i></div> | |||
| <div class="media-body"> | |||
| <h3 class="mt-2 mb-2 heading">Einfach Zu- und Absagen.</h3> | |||
| <p class="text-sans-serif pb_font-16">Mit nur einem Klick. In der App oder im Browser.</p> | |||
| </div> | |||
| </div> | |||
| <div class="media pb_feature-v2 text-left mb-1 mt-5"> | |||
| <div class="pb_icon d-flex mr-3 align-self-start pb_w-15"><i class="fa fa-calendar pb_icon-gradient"></i></div> | |||
| <div class="media-body"> | |||
| <h3 class="mt-2 mb-2 heading">Im eigenen Kalender</h3> | |||
| <p class="text-sans-serif pb_font-16">Termine abonniert im persönlichen Kalender - immer aktuell.</p> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| <div class="col-lg"> | |||
| <div class="media pb_feature-v2 text-left mb-1 mt-5"> | |||
| <div class="pb_icon d-flex mr-3 align-self-start pb_w-15"><i class="fa fa-bell pb_icon-gradient"></i></div> | |||
| <div class="media-body"> | |||
| <h3 class="mt-2 mb-2 heading">Mit Erinnerungsfunktion</h3> | |||
| <p class="text-sans-serif pb_font-16">Per Notification immer informiert - bin ich dabei, wann geht's los.</p> | |||
| </div> | |||
| </div> | |||
| <div class="media pb_feature-v2 text-left mb-1 mt-5"> | |||
| <div class="pb_icon d-flex mr-3 align-self-start pb_w-15"><i class="fa fa-lock pb_icon-gradient"></i></div> | |||
| <div class="media-body"> | |||
| <h3 class="mt-2 mb-2 heading">Intuitiv und sicher</h3> | |||
| <p class="text-sans-serif pb_font-16">Kunden schätzen eine professionelle, moderne Plattform.</p> | |||
| </div> | |||
| </div> | |||
| <div class="media pb_feature-v2 text-left mb-1 mt-5"> | |||
| <div class="pb_icon d-flex mr-3 align-self-start pb_w-15"><i class="fa fa-users pb_icon-gradient"></i></div> | |||
| <div class="media-body"> | |||
| <h3 class="mt-2 mb-2 heading">Chat zum Austausch</h3> | |||
| <p class="text-sans-serif pb_font-16">Fördern Sie den Austausch, schaffen Sie eine Community.</p> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </section> | |||
| <!-- END section --> | |||
| <section class="pb_section pb_slant-light" id="section-industry"> | |||
| <div class="container"> | |||
| <div class="row justify-content-center mb-5"> | |||
| <div class="col-md-6 text-center mb-5"> | |||
| <h5 class="text-uppercase pb_font-15 mb-2 pb_color-dark-opacity-3 pb_letter-spacing-2"><strong>Professionelle Branchenlösung</strong></h5> | |||
| <h2>ProBuddy im Einsatz</h2> | |||
| </div> | |||
| </div> | |||
| <div class="row"> | |||
| <div class="col-lg-4 col-md- col-sm-6"> | |||
| <div class="media d-block pb_feature-v1 text-left"> | |||
| <div class="media-img-container"> | |||
| <img src="./assets/images/geert-pieters-688278-unsplash.jpg" class="img-fluid rounded" /> | |||
| </div> | |||
| <div class="media-body"> | |||
| <h5 class="mt-0 mb-3 heading">Sport & Fitness</h5> | |||
| <p class="text-sans-serif">Ideal für Sport- & Fitnesscenter mit Kursangeboten. <strong>Pro</strong>Buddy bietet Transparenz in der Kursauslastung. Für sie und ihre Mitglieder.</p> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| <div class="col-lg-4 col-md- col-sm-6"> | |||
| <div class="media d-block pb_feature-v1 text-left"> | |||
| <div class="media-img-container"> | |||
| <img src="./assets/images/jesper-aggergaard-495757-unsplash.jpg" class="img-fluid rounded" /> | |||
| </div> | |||
| <div class="media-body"> | |||
| <h5 class="mt-0 mb-3 heading">Arztpraxen & Gesundheitsförderung</h5> | |||
| <p class="text-sans-serif">Artpraxen und Zentren für Gesundheitsförderung mit Kursprogrammen schwören auf <strong>Pro</strong>Buddy.</p> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| <div class="col-lg-4 col-md- col-sm-6"> | |||
| <div class="media d-block pb_feature-v1 text-left"> | |||
| <div class="media-img-container"> | |||
| <img src="./assets/images/rawpixel-771284-unsplash.jpg" class="img-fluid rounded" /> | |||
| </div> | |||
| <div class="media-body"> | |||
| <h5 class="mt-0 mb-3 heading">Yogaschulen</h5> | |||
| <p class="text-sans-serif">Nutzen sie <strong>Pro</strong>Buddy für ihre Yogaschule. Mitglieder- und Kursverwaltung war noch nie so einfach!</p> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| <div class="col-lg-4 col-md- col-sm-6"> | |||
| <div class="media d-block pb_feature-v1 text-left"> | |||
| <div class="media-img-container"> | |||
| <img src="./assets/images/bruce-mars-556415-unsplash.jpg" class="img-fluid rounded" /> | |||
| </div> | |||
| <div class="media-body"> | |||
| <h5 class="mt-0 mb-3 heading">Personal Training</h5> | |||
| <p class="text-sans-serif">Personal Trainer haben wenig Zeit und arbeiten oft mobil. Mit <strong>Pro</strong>Buddy haben sie ihr persönliches Office immer dabei!</p> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| <div class="col-lg-4 col-md- col-sm-6"> | |||
| <div class="media d-block pb_feature-v1 text-left"> | |||
| <div class="media-img-container"> | |||
| <img src="./assets/images/kevin-laminto-621654-unsplash.jpg" class="img-fluid rounded" /> | |||
| </div> | |||
| <div class="media-body"> | |||
| <h5 class="mt-0 mb-3 heading">Hundeschulen</h5> | |||
| <p class="text-sans-serif">Ob Welpen-, Junghund- oder Agilitykurse. Hundeschulen planen und organisieren sich und ihre Kurse mit <strong>Pro</strong>Buddy.</p> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| <div class="col-lg-4 col-md- col-sm-6"> | |||
| <div class="media d-block pb_feature-v1 text-left"> | |||
| <div class="media-img-container"> | |||
| <img src="./assets/images/alvaro-reyes-507651-unsplash.jpg" class="img-fluid rounded" /> | |||
| </div> | |||
| <div class="media-body"> | |||
| <h5 class="mt-0 mb-3 heading">Individuell einsetzbar</h5> | |||
| <p class="text-sans-serif"><strong>Pro</strong>Buddy ist eine offene Plattform mit der wir die verschiedensten Anwendungsfälle abbilden können. Sprechen sie uns an!</p> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </section> | |||
| <!-- END section --> | |||
| <section class="pb_section bg-light pb_slant-white pb_pb-250" id="section-reviews"> | |||
| <div class="container"> | |||
| <div class="row justify-content-center mb-1"> | |||
| <div class="col-md-6 text-center mb-5"> | |||
| <h5 class="text-uppercase pb_font-15 mb-2 pb_color-dark-opacity-3 pb_letter-spacing-2"><strong>Reviews</strong></h5> | |||
| <h2>Unsere Kunden sind die besten Referenzen</h2> | |||
| </div> | |||
| </div> | |||
| <div class="row"> | |||
| <div class="col-md"> | |||
| <div class="pb_slide_testimonial_sync_v1"> | |||
| <div class="pb_slider_content js-pb_slider_content2"> | |||
| <div> | |||
| <div class="media d-block text-center testimonial_v1 pb_quote_v2"> | |||
| <div class="media-body"> | |||
| <div class="quote">“</div> | |||
| <blockquote class="mb-5">Wir konnten unsere Auslastung stark ausbauen und bieten jetzt pro Woche sogar fünf Kurse mehr an. So konnten wir unseren Umsatz gleich doppelt steigern. </blockquote> | |||
| <p> | |||
| <i class="ion-ios-star text-warning"></i> | |||
| <i class="ion-ios-star text-warning"></i> | |||
| <i class="ion-ios-star text-warning"></i> | |||
| <i class="ion-ios-star text-warning"></i> | |||
| <i class="ion-ios-star text-warning"></i> | |||
| </p> | |||
| <h3 class="heading">Martina</h3> | |||
| <span class="subheading">Rosenheim</span> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| <div> | |||
| <div class="media d-block text-center testimonial_v1 pb_quote_v2"> | |||
| <div class="media-body"> | |||
| <div class="quote">“</div> | |||
| <blockquote class="mb-5">Die Räumlichkeiten unserer Yoga-Schule sind begrenzt, die Organisation der Teilnahmen war eine Herausforderung und zeitlich aufwendig. Mit ProBuddy haben wir eine innovative, faire Lösung gefunden, die von unseren über einhundert Kunden schnell angenommen wurde. Wir freuen uns auf die weiteren Ausbaustufen, wie z.B. die Abrechnung.</blockquote> | |||
| <p> | |||
| <i class="ion-ios-star text-warning"></i> | |||
| <i class="ion-ios-star text-warning"></i> | |||
| <i class="ion-ios-star text-warning"></i> | |||
| <i class="ion-ios-star text-warning"></i> | |||
| <i class="ion-ios-star-half text-warning"></i> | |||
| </p> | |||
| <h3 class="heading">Susanne</h3> | |||
| <span class="subheading">Stuttgart</span> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| <div> | |||
| <div class="media d-block text-center testimonial_v1 pb_quote_v2"> | |||
| <div class="media-body"> | |||
| <div class="quote">“</div> | |||
| <blockquote class="mb-5">Unsere Termine waren immer schnell ausgebucht, viele Kunden haben Termine geblockt, sind aber nicht erschienen. Mit der Zusagefrist und der Wartelistenfunktion von ProBuddy können wir nun besser steuern und kommunizieren. Die automatische Terminerinnerung wirkt Wunder. </blockquote> | |||
| <p> | |||
| <i class="ion-ios-star text-warning"></i> | |||
| <i class="ion-ios-star text-warning"></i> | |||
| <i class="ion-ios-star text-warning"></i> | |||
| <i class="ion-ios-star-half text-warning"></i> | |||
| <i class="ion-ios-star-outline text-warning"></i> | |||
| </p> | |||
| <h3 class="heading">Bernd</h3> | |||
| <span class="subheading">Flensburg</span> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| <div> | |||
| <div class="media d-block text-center testimonial_v1 pb_quote_v2"> | |||
| <div class="media-body"> | |||
| <div class="quote">“</div> | |||
| <blockquote class="mb-5">Unsere Stresspegel war extrem hoch. Terminzu- und absagen kamen per Mail, WhatsApp, Telefon - den Überblick zu behalten war enorm schwer. Mit ProBuddy gibt es jetzt einen zentralen Kalender, die Benachrichtigungen gehen automatisch raus. Unsere Kunden haben die moderne Lösung schnell akzeptiert. Und wir haben jetzt deutlich mehr Zeit für wichtigere Dinge. </blockquote> | |||
| <p> | |||
| <i class="ion-ios-star text-warning"></i> | |||
| <i class="ion-ios-star text-warning"></i> | |||
| <i class="ion-ios-star text-warning"></i> | |||
| <i class="ion-ios-star text-warning"></i> | |||
| <i class="ion-ios-star text-warning"></i> | |||
| </p> | |||
| <h3 class="heading">Marie</h3> | |||
| <span class="subheading">Düsseldorf</span> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| <div class="row"> | |||
| <div class="col-md-6 mx-auto"> | |||
| <div class="pb_slider_nav js-pb_slider_nav2"> | |||
| <div class="author"> | |||
| <img class="img-fluid rounded-circle" src="assets/images/person_1.jpg" alt="Generic placeholder image"> | |||
| </div> | |||
| <div class="author"> | |||
| <img class="img-fluid rounded-circle" src="assets/images/person_5.jpg" alt="Generic placeholder image"> | |||
| </div> | |||
| <div class="author"> | |||
| <img class="img-fluid rounded-circle" src="assets/images/person_2.jpg" alt="Generic placeholder image"> | |||
| </div> | |||
| <div class="author"> | |||
| <img class="img-fluid rounded-circle" src="assets/images/person_6.jpg" alt="Generic placeholder image"> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| <!-- END sync_v1 --> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </section> | |||
| <!-- END section --> | |||
| <section class="pb_section pb_slant-light pb_pb-250" id="section-pricing"> | |||
| <div class="container"> | |||
| <div class="row justify-content-center mb-5"> | |||
| <div class="col-md-6 text-center mb-5"> | |||
| <h5 class="text-uppercase pb_font-15 mb-2 pb_color-dark-opacity-3 pb_letter-spacing-2"><strong>Preise im Überblick </strong></h5> | |||
| <h2>Mit welcher Gruppengröße wollen Sie starten?</h2> | |||
| </div> | |||
| </div> | |||
| <div class="row"> | |||
| <div class="col-md"> | |||
| <div class="pb_pricing_v1 p-5 border text-center bg-white"> | |||
| <h3>SMALL</h3> | |||
| <span class="price">19,99<sup>€</sup><span>Monat</span></span> | |||
| <p class="pb_font-15">Für bis zu 50 Teilnehmer. <br>(0,40 EUR/Kunde)</p> | |||
| <p class="mb-0"><a href="#" role="button" class="btn btn-secondary">Kostenlos registrieren</a></p> | |||
| </div> | |||
| </div> | |||
| <div class="col-md"> | |||
| <div class="pb_pricing_v1 p-5 border border-primary text-center bg-white"> | |||
| <h3>MEDIUM</h3> | |||
| <span class="price">34,99<sup>€</sup><span>Monat</span></span> | |||
| <p class="pb_font-15">Für 51-100 Teilnehmer. <br>(0,35 EUR/Kunde)</p> | |||
| <p class="mb-0"><a href="#" role="button" class="btn btn-primary btn-shadow-blue">Kostenlos registrieren</a></p> | |||
| </div> | |||
| </div> | |||
| <div class="col-md"> | |||
| <div class="pb_pricing_v1 p-5 border text-center bg-white"> | |||
| <h3>LARGE</h3> | |||
| <span class="price">49,99<sup>€</sup><span>Monat</span></span> | |||
| <p class="pb_font-15">Für 101-200 Teilnehmer. <br>(0,20 EUR/Kunde)</p> | |||
| <p class="mb-0"><a href="#" role="button" class="btn btn-secondary">Kostenlos registrieren</a></p> | |||
| </div> | |||
| </div> | |||
| <!-- <div class="col-md"> | |||
| <div class="pb_pricing_v1 p-5 border text-center bg-white"> | |||
| <h3>XXL</h3> | |||
| <span class="price">69,99<sup>€</sup><span>Monat</span></span> | |||
| <p class="pb_font-15">Für bis 250-500 Teilnehmer.</p> | |||
| <p class="mb-0"><a href="#" role="button" class="btn btn-secondary">Get started</a></p> | |||
| </div> | |||
| </div> | |||
| <div class="col-md"> | |||
| <div class="pb_pricing_v1 p-5 border text-center bg-white"> | |||
| <h3>FLATRATE</h3> | |||
| <span class="price">99,99<sup>€</sup><span>Monat</span></span> | |||
| <p class="pb_font-15">Für über 300 Teilnehmer. </p> | |||
| <p class="mb-0"><a href="#" role="button" class="btn btn-secondary">Get started</a></p> | |||
| </div> | |||
| </div> --> | |||
| Die Paketpreise orientieren sich nur an der Teilnehmeranzahl. Funktional sind die Pakete 100% identisch. Risikolos können Sie 30 Tage ProBuddy testen, die Testphase ist unverbindlich. Erst wenn Sie von ProBuddy überzeugt sind, buchen Sie das passende Paket. Die minimale Vertragslaufzeit beträgt 6 Monate. Sie erhalten nach Beauftragung eine Rechnung per Mail, die Plattform ist sofort verfügbar. Das Zahlungsziel beträgt vierzehn Tage. Gern helfen wir Ihnen bei der Inbetriebnahme, melden Sie sich jederzeit gern über die Hilfefunktion in der App. | |||
| </div> | |||
| </div> | |||
| </section> | |||
| <!-- ENDs ection --> | |||
| <section class="pb_section bg-light pb_slant-light pb_pb-250" id="section-faq"> | |||
| <div class="container"> | |||
| <div class="row justify-content-center mb-5"> | |||
| <div class="col-md-6 text-center mb-5"> | |||
| <h5 class="text-uppercase pb_font-15 mb-2 pb_color-dark-opacity-3 pb_letter-spacing-2"><strong>FAQ</strong></h5> | |||
| <h2>Frequently Asked Questions</h2> | |||
| </div> | |||
| </div> | |||
| <div class="row"> | |||
| <div class="col-md"> | |||
| <div id="pb_faq" class="pb_accordion" data-children=".item"> | |||
| <div class="item"> | |||
| <a data-toggle="collapse" data-parent="#pb_faq" href="#pb_faq0" aria-expanded="true" aria-controls="pb_faq0" class="pb_font-22 py-4">Für wen ist <strong>Pro</strong>Buddy besonders sinnvoll?</a> | |||
| <div id="pb_faq0" class="collapse show" role="tabpanel"> | |||
| <div class="py-3"> | |||
| <p><strong>Pro</strong>Buddy ist für (semi-)professionelle Anbieter von Dienstleistungen und Services gedacht, die Einzel- oder Gruppentermine (Mitarbeiter, Kunden und Partner) regelmäßig pro Tag/Woche/Monat organisieren. Mit <strong>Pro</strong>Buddy ersetzen Sie WhatsApp-Gruppen oder sonstige Organisationshilfen und setzen auf eine professionelle, verlässliche Umgebung für Ihr Geschäft. </p> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| <div class="item"> | |||
| <a data-toggle="collapse" data-parent="#pb_faq" href="#pb_faq1" aria-expanded="false" aria-controls="pb_faq1" class="pb_font-22 py-4">Ab wann rechnet sich <strong>Pro</strong>Buddy?</a> | |||
| <div id="pb_faq1" class="collapse" role="tabpanel"> | |||
| <div class="py-3"> | |||
| <p>Allgemein ist festzustellen, dass Unternehmer <strong>Pro</strong>Buddy dann einsetzen, wenn sie merken, dass der zeitliche Aufwand für die Terminorganisation zu groß wird, die Unzufriedenheit auf Kundenseite steigt und die Umsetzung der Datenschutzbestimmungen nicht mehr aufgeschoben werden sollte.</p> | |||
| <p>Der typische Business Case für <strong>Pro</strong>Buddy errechnet sich aus der Anzahl Teilnehmer und der Anzahl Termine pro Monat. Beispiel: Wenn Sie 100 Kunden haben und wöchentlich 10 Termine (monatlich 40 Termine) anbieten, organisieren Sie pro Monat 4.000 Zu- und Absagen. Was kostet es Sie heute, die Termine optimal zu füllen? </p> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| <div class="item"> | |||
| <a data-toggle="collapse" data-parent="#pb_faq" href="#pb_faq2" aria-expanded="false" aria-controls="pb_faq2" class="pb_font-22 py-4">Können meine Kunden und ich <strong>Pro</strong>Buddy auch ohne modernes Smartphone nutzen?</a> | |||
| <div id="pb_faq2" class="collapse" role="tabpanel"> | |||
| <div class="py-3"> | |||
| <p><strong>Pro</strong>Buddy gibt es als native App im Apple Appstore und Google Playstore zum kostenlosen Download. Zudem kann man <strong>Pro</strong>Buddy auf jedem modernen Browser aufrufen. Egal ob auf dem Smartphone oder am PC. Die minimale Voraussetzung für die Nutzung ist somit eine Internetverbindung. </p> | |||
| <p>Alternativ kann der Betreiber die Lösung auch für den Kunden bedienen, z.B. durch eine Assistenz, und Zu- und Absagen eintragen. </p> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| <div class="item"> | |||
| <a data-toggle="collapse" data-parent="#pb_faq" href="#pb_faq3" aria-expanded="false" aria-controls="pb_faq3" class="pb_font-22 py-4">Wie sicher ist <strong>Pro</strong>Buddy? Was steckt dahinter?</a> | |||
| <div id="pb_faq3" class="collapse" role="tabpanel"> | |||
| <div class="py-3"> | |||
| <p>Die Plattform von <strong>Pro</strong>Buddy wird in deutschen Rechenzentren betrieben, die Daten sind durch die deutschen Datenschutzrichtlinien und vom Anbieter geschützt. Eine werbliche Verwendung der Daten ist ausgeschlossen.</p> | |||
| <p>Die Daten sind verschlüsselt in der Datenbank abgelegt. Jeder Teilnehmer kann sein Profil anonymisieren und jederzeit vollständig löschen. </p> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| <div class="item"> | |||
| <a data-toggle="collapse" data-parent="#pb_faq" href="#pb_faq4" aria-expanded="false" aria-controls="pb_faq4" class="pb_font-22 py-4">Können wir von TBuddy auf <strong>Pro</strong>Buddy upgraden? Können Anpassungen vorgenommen werden?</a> | |||
| <div id="pb_faq4" class="collapse" role="tabpanel"> | |||
| <div class="py-3"> | |||
| <p>Ja, TBuddy-Kunden können jederzeit auf <strong>Pro</strong>Buddy migrieren, unser Support-Team bietet hierfür einen Service an. Erweiterungen und Anpassungen an <strong>Pro</strong>Buddy können kostenpflichtig durchgeführt werden. Sprechen Sie unser deutsch- und englisch sprachiges Supportteam jederzeit gern an. Schicken sie einfach eine Mail an <a href="mailto://support@probuddy.de" target="_blank">support{at]probuddy.de</a>.</p> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| <div class="item"> | |||
| <a data-toggle="collapse" data-parent="#pb_faq" href="#pb_faq5" aria-expanded="false" aria-controls="pb_faq5" class="pb_font-22 py-4">Bietet <strong>Pro</strong>Buddy auch Hilfe bei der Inbetriebnahme an? </a> | |||
| <div id="pb_faq5" class="collapse" role="tabpanel"> | |||
| <div class="py-3"> | |||
| <p>Unser deutsch- und englisch sprachiges Supportteam steht ihnen rund um die Uhr zur Seite. Schicken sie einfach eine Mail an <a href="mailto://support@probuddy.de" target="_blank">support{at]probuddy.de</a>.</p> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </section> | |||
| <!-- END section --> | |||
| <section class="pb_xl_py_cover overflow-hidden pb_gradient_v1 cover-bg-opacity-8" | |||
| style="background-image: url(assets/images/1900x1200_img_5.jpg)"> | |||
| <div class="container"> | |||
| <div class="row align-items-center justify-content-center"> | |||
| <div class="col-md-5 justify-content-center"> | |||
| <h2 class="heading mb-5 pb_font-40">Jetzt kostenfrei bei <strong>Pro</strong>Buddy registrieren</h2> | |||
| <div class="sub-heading"> | |||
| <p class="mb-4"> | |||
| Investieren Sie 5 Minuten. Registrieren Sie sich, stellen ein paar Termine ein und laden ein paar Kollegen, Freunde oder Kunden ein. Testen Sie <strong>Pro</strong>Buddy 30 Tage kostenlos. | |||
| </p> | |||
| </div> | |||
| </div> | |||
| <div class="col-md-1"></div> | |||
| <div class="col-md-5 relative align-self-center"> | |||
| <div class="bg-white rounded pb_form_v1"> | |||
| <h2 class="mb-4 mt-0 text-center">30 Tage kostenfrei testen</h2> | |||
| <p> | |||
| Ihre Praxis kostenfrei registrieren, ProBuddy testen. Kein Vertragsrisiko. Dazu Support und Unterstützung durch unser Team. | |||
| </p> | |||
| <div class="form-group"> | |||
| <a href="https://www.probuddy.de/#/auth/register" class="btn btn-primary btn-lg btn-block pb_btn-pill btn-shadow-blue">Jetzt loslegen</a> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </section> | |||
| <!-- END section --> | |||
| <footer class="pb_footer bg-light" role="contentinfo"> | |||
| <div class="container"> | |||
| <div class="row text-center"> | |||
| <div class="col"> | |||
| <ul class="list-inline"> | |||
| <li class="list-inline-item"><a href="#" class="p-2"><i class="fa fa-facebook"></i></a></li> | |||
| <li class="list-inline-item"><a href="#" class="p-2"><i class="fa fa-twitter"></i></a></li> | |||
| <li class="list-inline-item"><a href="#" class="p-2"><i class="fa fa-linkedin"></i></a></li> | |||
| </ul> | |||
| </div> | |||
| </div> | |||
| <div class="row"> | |||
| <div class="col text-center"> | |||
| <p class="pb_font-14">© 2018 - 2019 <a href="https://uicookies.com/" target="_blank">TBuddy UG (haftungsbeschränkt)</a>. All Rights Reserved. <br /> | |||
| <small> | |||
| <a href="https://www.tbuddy.de/impressum/" target="_blank">Impressum</a> - <a href="https://www.tbuddy.de/datenschutz/" target="_blank">Datenschutzerklärung</a> - <a href="https://www.tbuddy.de/disclaimer/" target="_blank">Disclaimer</a> - <a href="https://www.tbuddy.de/agb/" target="_blank">AGB</a> | |||
| </small> | |||
| </p> | |||
| <p class="pb_font-14"> | |||
| <small> | |||
| Bildquelle: <a href="https://unsplash.com/" target="_blank" rel="nofollow">Unsplash</a> | |||
| </small> | |||
| </p> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </footer> | |||
| <!-- loader --> | |||
| <div id="pb_loader" class="show fullscreen"><svg class="circular" width="48px" height="48px"><circle class="path-bg" cx="24" cy="24" r="22" fill="none" stroke-width="4" stroke="#eeeeee"/><circle class="path" cx="24" cy="24" r="22" fill="none" stroke-width="4" stroke-miterlimit="10" stroke="#1d82ff"/></svg></div> | |||
| <script src="assets/js/jquery.min.js"></script> | |||
| <script src="assets/js/popper.min.js"></script> | |||
| <script src="assets/js/bootstrap.min.js"></script> | |||
| <script src="assets/js/slick.min.js"></script> | |||
| <script src="assets/js/jquery.mb.YTPlayer.min.js"></script> | |||
| <script src="assets/js/jquery.waypoints.min.js"></script> | |||
| <script src="assets/js/jquery.easing.1.3.js"></script> | |||
| <script src="assets/js/main.js"></script> | |||
| </body> | |||
| </html> | |||