Hotel Raxa - Advanced Booking System Implementation

🏨 Hotel Booking Enhancements:
- Implemented Eagle Booking Advanced Pricing add-on
- Added Booking.com-style rate management system
- Created professional calendar interface for pricing
- Integrated deals and discounts functionality

💰 Advanced Pricing Features:
- Dynamic pricing models (per room, per person, per adult)
- Base rates, adult rates, and child rates management
- Length of stay discounts and early bird deals
- Mobile rates and secret deals implementation
- Seasonal promotions and flash sales

📅 Availability Management:
- Real-time availability tracking
- Stop sell and restriction controls
- Closed to arrival/departure functionality
- Minimum/maximum stay requirements
- Automatic sold-out management

💳 Payment Integration:
- Maintained Redsys payment gateway integration
- Seamless integration with existing Eagle Booking
- No modifications to core Eagle Booking plugin

🛠️ Technical Implementation:
- Custom database tables for advanced pricing
- WordPress hooks and filters integration
- AJAX-powered admin interface
- Data migration from existing Eagle Booking
- Professional calendar view for revenue management

📊 Admin Interface:
- Booking.com-style management dashboard
- Visual rate and availability calendar
- Bulk operations for date ranges
- Statistics and analytics dashboard
- Modal dialogs for quick editing

🔧 Code Quality:
- WordPress coding standards compliance
- Secure database operations with prepared statements
- Proper input validation and sanitization
- Error handling and logging
- Responsive admin interface

🤖 Generated with Claude Code (https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Hotel Raxa Dev
2025-07-11 07:43:22 +02:00
commit 5b1e2453c7
9816 changed files with 2784509 additions and 0 deletions

View File

@@ -0,0 +1,76 @@
<?php
/**
* Switch Field
*
* @package Redux Framework
* @author Dovy Paukstys & Kevin Provance (kprovance)
* @version 4.0.0
*/
defined( 'ABSPATH' ) || exit;
if ( ! class_exists( 'Redux_Switch', false ) ) {
/**
* Class Redux_Switch
*/
class Redux_Switch extends Redux_Field {
/**
* Field Render Function.
* Takes the vars and outputs the HTML for the field in the settings
*
* @since ReduxFramework 0.0.4
*/
public function render() {
$cb_enabled = '';
$cb_disabled = '';
// Get selected.
if ( 1 === (int) $this->value ) {
$cb_enabled = ' selected';
} else {
$cb_disabled = ' selected';
}
// Label ON.
$this->field['on'] = $this->field['on'] ?? esc_html__( 'On', 'redux-framework' );
// Label OFF.
$this->field['off'] = $this->field['off'] ?? esc_html__( 'Off', 'redux-framework' );
echo '<div class="switch-options">';
echo '<div class="cb-enable label' . esc_attr( $cb_enabled ) . '" data-id="' . esc_attr( $this->field['id'] ) . '"><span>' . esc_html( $this->field['on'] ) . '</span></div>';
echo '<div class="cb-disable label' . esc_attr( $cb_disabled ) . '" data-id="' . esc_attr( $this->field['id'] ) . '"><span>' . esc_html( $this->field['off'] ) . '</span></div>';
echo '<input type="hidden" class="checkbox checkbox-input ' . esc_attr( $this->field['class'] ) . '" id="' . esc_attr( $this->field['id'] ) . '" name="' . esc_attr( $this->field['name'] . $this->field['name_suffix'] ) . '" value="' . esc_attr( $this->value ) . '" />';
echo '</div>';
}
/**
* Enqueue Function.
* If this field requires any scripts, or css define this function and register/enqueue the scripts/css
*
* @since ReduxFramework 0.0.4
*/
public function enqueue() {
wp_enqueue_script(
'redux-field-switch',
Redux_Core::$url . 'inc/fields/switch/redux-switch' . Redux_Functions::is_min() . '.js',
array( 'jquery', 'redux-js' ),
$this->timestamp,
true
);
if ( $this->parent->args['dev_mode'] ) {
wp_enqueue_style(
'redux-field-switch',
Redux_Core::$url . 'inc/fields/switch/redux-switch.css',
array(),
$this->timestamp
);
}
}
}
}
class_alias( 'Redux_Switch', 'ReduxFramework_Switch' );

View File

@@ -0,0 +1,8 @@
<?php
/**
* Silence is golden.
*
* @package Redux Framework
*/
_deprecated_file( 'field_spinner.php', '4.3', 'class-redux-spinner.php', 'This file has been renamed and is no longer used in Redux 4. Please change any references to it as it will be removed in future versions of Redux.' );

View File

@@ -0,0 +1,8 @@
<?php
/**
* Silence is golden.
*
* @package Redux Framework
*/
echo null;

View File

@@ -0,0 +1,23 @@
.redux-container-switch .switch-options { min-height: 30px; margin-right: 10px; }
.redux-container-switch .switch-options .label { cursor: pointer; }
.redux-container-switch .switch-options input { display: none; }
.redux-container-switch .cb-enable, .redux-container-switch .cb-disable { padding: 0 10px; border-width: 1px; border-style: solid; -webkit-appearance: none; white-space: nowrap; -webkit-box-sizing: border-box; box-sizing: border-box; }
.redux-container-switch .cb-enable span, .redux-container-switch .cb-disable span { line-height: 30px; display: block; font-weight: 700; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; }
.redux-container-switch .cb-enable, .redux-container-switch .cb-disable, .redux-container-switch .cb-enable span, .redux-container-switch .cb-disable span { display: block; float: left; }
.redux-container-switch .cb-enable { border-right: 0; border-radius: 3px 0 0 3px; -moz-border-radius: 3px 0 0 3px; -webkit-border-radius: 3px 0 0 3px; }
.redux-container-switch .cb-enable.selected { color: #fff; }
.redux-container-switch .cb-disable { border-left: 0; border-radius: 0 3px 3px 0; -moz-border-radius: 0 3px 3px 0; -webkit-border-radius: 0 3px 3px 0; }
.redux-container-switch .cb-disable.selected { color: #fff; }
/*# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVkdXgtc3dpdGNoLmNzcyIsInNvdXJjZXMiOlsicmVkdXgtc3dpdGNoLnNjc3MiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsQUFDSSx1QkFEbUIsQ0FDbkIsZUFBZSxDQUFDLEVBQ1osVUFBVSxFQUFFLElBQUksRUFDaEIsWUFBWSxFQUFFLElBQUksR0FTckI7O0FBWkwsQUFLUSx1QkFMZSxDQUNuQixlQUFlLENBSVgsTUFBTSxDQUFDLEVBQ0gsTUFBTSxFQUFFLE9BQU8sR0FDbEI7O0FBUFQsQUFTUSx1QkFUZSxDQUNuQixlQUFlLENBUVgsS0FBSyxDQUFDLEVBQ0YsT0FBTyxFQUFFLElBQUksR0FDaEI7O0FBWFQsQUFjSSx1QkFkbUIsQ0FjbkIsVUFBVSxFQWRkLHVCQUF1QixDQWVuQixXQUFXLENBQUMsRUFDUixPQUFPLEVBQUUsTUFBTSxFQUNmLFlBQVksRUFBRSxHQUFHLEVBQ2pCLFlBQVksRUFBRSxLQUFLLEVBQ25CLGtCQUFrQixFQUFFLElBQUksRUFDeEIsV0FBVyxFQUFFLE1BQU0sRUFDbkIsVUFBVSxFQUFFLFVBQVUsR0FXekI7O0FBaENMLEFBdUJRLHVCQXZCZSxDQWNuQixVQUFVLENBU04sSUFBSSxFQXZCWix1QkFBdUIsQ0FlbkIsV0FBVyxDQVFQLElBQUksQ0FBQyxFQUNELFdBQVcsRUFBRSxJQUFJLEVBQ2pCLE9BQU8sRUFBRSxLQUFLLEVBQ2QsV0FBVyxFQUFFLEdBQUcsRUFDaEIsbUJBQW1CLEVBQUUsSUFBSSxFQUN6QixnQkFBZ0IsRUFBRSxJQUFJLEVBQ3RCLGVBQWUsRUFBRSxJQUFJLEVBQ3JCLFdBQVcsRUFBRSxJQUFJLEdBQ3BCOztBQS9CVCxBQWtDSSx1QkFsQ21CLENBa0NuQixVQUFVLEVBbENkLHVCQUF1QixDQW1DbkIsV0FBVyxFQW5DZix1QkFBdUIsQ0FvQ25CLFVBQVUsQ0FBQyxJQUFJLEVBcENuQix1QkFBdUIsQ0FxQ25CLFdBQVcsQ0FBQyxJQUFJLENBQUMsRUFDYixPQUFPLEVBQUUsS0FBSyxFQUNkLEtBQUssRUFBRSxJQUFJLEdBQ2Q7O0FBeENMLEFBMENJLHVCQTFDbUIsQ0EwQ25CLFVBQVUsQ0FBQyxFQUNQLFlBQVksRUFBRSxDQUFDLEVBQ2YsYUFBYSxFQUFFLFdBQVcsRUFDMUIsa0JBQWtCLEVBQUUsV0FBVyxFQUMvQixxQkFBcUIsRUFBRSxXQUFXLEdBS3JDOztBQW5ETCxBQWdEUSx1QkFoRGUsQ0EwQ25CLFVBQVUsQUFNTCxTQUFTLENBQUMsRUFDUCxLQUFLLEVBQUUsSUFBSSxHQUNkOztBQWxEVCxBQXFESSx1QkFyRG1CLENBcURuQixXQUFXLENBQUMsRUFDUixXQUFXLEVBQUUsQ0FBQyxFQUNkLGFBQWEsRUFBRSxXQUFXLEVBQzFCLGtCQUFrQixFQUFFLFdBQVcsRUFDL0IscUJBQXFCLEVBQUUsV0FBVyxHQUtyQzs7QUE5REwsQUEyRFEsdUJBM0RlLENBcURuQixXQUFXLEFBTU4sU0FBUyxDQUFDLEVBQ1AsS0FBSyxFQUFFLElBQUksR0FDZCJ9 */
/*# sourceMappingURL=redux-switch.css.map */

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,96 @@
/*global redux_change, redux*/
/**
* Switch
* Dependencies : jquery
* Feature added by : Smartik - http://smartik.ws/
* Date : 03.17.2013
*/
(function( $ ) {
'use strict';
redux.field_objects = redux.field_objects || {};
redux.field_objects.switch = redux.field_objects.switch || {};
redux.field_objects.switch.init = function( selector ) {
selector = $.redux.getSelector( selector, 'switch' );
$( selector ).each(
function() {
var el = $( this );
var parent = el;
if ( ! el.hasClass( 'redux-field-container' ) ) {
parent = el.parents( '.redux-field-container:first' );
}
if ( parent.is( ':hidden' ) ) {
return;
}
if ( parent.hasClass( 'redux-field-init' ) ) {
parent.removeClass( 'redux-field-init' );
} else {
return;
}
el.find( '.cb-enable' ).on(
'click',
function() {
var parent;
var obj;
var $fold;
if ( $( this ).hasClass( 'selected' ) ) {
return;
}
parent = $( this ).parents( '.switch-options' );
$( '.cb-disable', parent ).removeClass( 'selected' );
$( this ).addClass( 'selected' );
$( '.checkbox-input', parent ).val( 1 ).trigger( 'change' );
redux_change( $( '.checkbox-input', parent ) );
// Fold/unfold related options.
obj = $( this );
$fold = '.f_' + obj.data( 'id' );
el.find( $fold ).slideDown( 'normal', 'swing' );
}
);
el.find( '.cb-disable' ).on(
'click',
function() {
var parent;
var obj;
var $fold;
if ( $( this ).hasClass( 'selected' ) ) {
return;
}
parent = $( this ).parents( '.switch-options' );
$( '.cb-enable', parent ).removeClass( 'selected' );
$( this ).addClass( 'selected' );
$( '.checkbox-input', parent ).val( 0 ).trigger( 'change' );
redux_change( $( '.checkbox-input', parent ) );
// Fold/unfold related options.
obj = $( this );
$fold = '.f_' + obj.data( 'id' );
el.find( $fold ).slideUp( 'normal', 'swing' );
}
);
el.find( '.cb-enable span, .cb-disable span' ).find().attr( 'unselectable', 'on' );
}
);
};
})( jQuery );

View File

@@ -0,0 +1 @@
!function(i){"use strict";redux.field_objects=redux.field_objects||{},redux.field_objects.switch=redux.field_objects.switch||{},redux.field_objects.switch.init=function(e){e=i.redux.getSelector(e,"switch"),i(e).each(function(){var s=i(this),e=s;(e=s.hasClass("redux-field-container")?e:s.parents(".redux-field-container:first")).is(":hidden")||e.hasClass("redux-field-init")&&(e.removeClass("redux-field-init"),s.find(".cb-enable").on("click",function(){var e;i(this).hasClass("selected")||(e=i(this).parents(".switch-options"),i(".cb-disable",e).removeClass("selected"),i(this).addClass("selected"),i(".checkbox-input",e).val(1).trigger("change"),redux_change(i(".checkbox-input",e)),e=".f_"+i(this).data("id"),s.find(e).slideDown("normal","swing"))}),s.find(".cb-disable").on("click",function(){var e;i(this).hasClass("selected")||(e=i(this).parents(".switch-options"),i(".cb-enable",e).removeClass("selected"),i(this).addClass("selected"),i(".checkbox-input",e).val(0).trigger("change"),redux_change(i(".checkbox-input",e)),e=".f_"+i(this).data("id"),s.find(e).slideUp("normal","swing"))}),s.find(".cb-enable span, .cb-disable span").find().attr("unselectable","on"))})}}(jQuery);

View File

@@ -0,0 +1,64 @@
.redux-container-switch {
.switch-options {
min-height: 30px;
margin-right: 10px;
.label {
cursor: pointer;
}
input {
display: none;
}
}
.cb-enable,
.cb-disable {
padding: 0 10px;
border-width: 1px;
border-style: solid;
-webkit-appearance: none;
white-space: nowrap;
box-sizing: border-box;
span {
line-height: 30px;
display: block;
font-weight: 700;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
}
.cb-enable,
.cb-disable,
.cb-enable span,
.cb-disable span {
display: block;
float: left;
}
.cb-enable {
border-right: 0;
border-radius: 3px 0 0 3px;
-moz-border-radius: 3px 0 0 3px;
-webkit-border-radius: 3px 0 0 3px;
&.selected {
color: #fff;
}
}
.cb-disable {
border-left: 0;
border-radius: 0 3px 3px 0;
-moz-border-radius: 0 3px 3px 0;
-webkit-border-radius: 0 3px 3px 0;
&.selected {
color: #fff;
}
}
}