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,102 @@
<?php
/**
* Redux Search Extension Class
*
* @package Redux
* @author Dovy Paukstys (dovy)
* @class Redux_Extension_Search
* @version 3.4.5
*/
defined( 'ABSPATH' ) || exit;
if ( ! class_exists( 'Redux_Extension_Search' ) ) {
/**
* Class Redux_Extension_Search
*/
class Redux_Extension_Search extends Redux_Extension_Abstract {
/**
* Extension version.
*
* @var string
*/
public static $version = '3.4.5';
/**
* Extension friendly name.
*
* @var string
*/
public $extension_name = 'Search';
/**
* Redux_Extension_Search constructor.
*
* @param object $redux ReduxFramework object pointer.
*/
public function __construct( $redux ) {
if ( false === $redux->args['search'] ) {
return;
}
parent::__construct( $redux, __FILE__ );
$this->add_field( 'search' );
// Allow users to extend if they want.
// phpcs:ignore WordPress.NamingConventions.ValidHookName
do_action( 'redux/search/' . $redux->args['opt_name'] . '/construct' );
if ( isset( $_GET['page'] ) && sanitize_text_field( wp_unslash( $_GET['page'] === $this->parent->args['page_slug'] ) ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue' ), 0 );
}
add_action( "redux/metaboxes/{$this->parent->args[ 'opt_name' ]}/enqueue", array( $this, 'enqueue' ), 10 );
}
/**
* Support file enqueue.
*/
public function enqueue() {
$min = Redux_Functions::is_min();
/**
* Redux search CSS
* filter 'redux/page/{opt_name}/enqueue/redux-extension-search-css'
*/
if ( $this->parent->args['dev_mode'] ) {
wp_enqueue_style(
'redux-extension-search',
// phpcs:ignore WordPress.NamingConventions.ValidHookName
apply_filters( "redux/search/{$this->parent->args[ 'opt_name' ]}/enqueue/redux-extension-search-css", $this->extension_url . 'redux-extension-search.css' ),
array(),
self::$version
);
}
/**
* Redux search JS
* filter 'redux/page/{opt_name}/enqueue/redux-extension-search-js
*/
wp_enqueue_script(
'redux-extension-search',
// phpcs:ignore WordPress.NamingConventions.ValidHookName
apply_filters( "redux/search/{$this->parent->args[ 'opt_name' ]}/enqueue/redux-extension-search-js", $this->extension_url . 'redux-extension-search' . $min . '.js' ),
'',
self::$version,
true
);
// Values used by the javascript.
wp_localize_script(
'redux-extension-search',
'reduxSearch',
array(
'search' => esc_html__( 'Search for field(s)', 'redux-framework' ),
)
);
}
}
}

View File

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

View File

@@ -0,0 +1,21 @@
.redux_field_search { position: absolute; width: 250px !important; right: 20px; padding: 4px 7px; top: 6px; }
.redux-has-sections .redux_field_search { right: 10px; }
.redux-main.redux-search .redux-section-field, .redux-main.redux-search .redux-info-field, .redux-main.redux-search .redux-notice-field, .redux-main.redux-search .redux-container-group, .redux-main.redux-search .redux-container-raw, .redux-main.redux-search .redux-section-desc, .redux-main.redux-search .redux-group-tab h3, .redux-main.redux-search .hr, .redux-main.redux-search .redux-field-info, .redux-main.redux-search tr { display: none; }
.redux-main.redux-search #import_export_default_section_group, .redux-main.redux-search #dev_mode_default_section_group { display: none !important; }
.redux-main.redux-search .redux-group-tab { margin-bottom: 0; }
.redux-main.redux-search .redux-group-tab .form-table-section-indented { margin-left: 0 !important; width: 100%; }
.redux-main.redux-search .redux-group-tab .form-table-section-indented .redux-group-tab .form-table-section tr:first-of-type th:first-of-type { padding: inherit !important; }
.redux-main.redux-search .redux-group-tab .form-table-section-indented .redux-group-tab h3 { margin-top: inherit !important; }
.redux-metabox .redux-has-sections .redux_field_search { top: 8px; }
/*# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVkdXgtZXh0ZW5zaW9uLXNlYXJjaC5jc3MiLCJzb3VyY2VzIjpbInJlZHV4LWV4dGVuc2lvbi1zZWFyY2guc2NzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxBQUFBLG1CQUFtQixDQUFDLEVBQ2hCLFFBQVEsRUFBRSxRQUFRLEVBQ2xCLEtBQUssRUFBRSxnQkFBZ0IsRUFDdkIsS0FBSyxFQUFFLElBQUksRUFDWCxPQUFPLEVBQUUsT0FBTyxFQUNoQixHQUFHLEVBQUMsR0FBRyxHQUNWOztBQUVELEFBQ0ksbUJBRGUsQ0FDZixtQkFBbUIsQ0FBQyxFQUNoQixLQUFLLEVBQUUsSUFBSSxHQUNkOztBQUVMLEFBQ0ksV0FETyxBQUFBLGFBQWEsQ0FDcEIsb0JBQW9CLEVBRHhCLFdBQVcsQUFBQSxhQUFhLENBRXBCLGlCQUFpQixFQUZyQixXQUFXLEFBQUEsYUFBYSxDQUdwQixtQkFBbUIsRUFIdkIsV0FBVyxBQUFBLGFBQWEsQ0FJcEIsc0JBQXNCLEVBSjFCLFdBQVcsQUFBQSxhQUFhLENBS3BCLG9CQUFvQixFQUx4QixXQUFXLEFBQUEsYUFBYSxDQU1wQixtQkFBbUIsRUFOdkIsV0FBVyxBQUFBLGFBQWEsQ0FPcEIsZ0JBQWdCLENBQUMsRUFBRSxFQVB2QixXQUFXLEFBQUEsYUFBYSxDQVFwQixHQUFHLEVBUlAsV0FBVyxBQUFBLGFBQWEsQ0FTcEIsaUJBQWlCLEVBVHJCLFdBQVcsQUFBQSxhQUFhLENBVXBCLEVBQUUsQ0FBQyxFQUNDLE9BQU8sRUFBRSxJQUFJLEdBQ2hCOztBQVpMLEFBY0ksV0FkTyxBQUFBLGFBQWEsQ0FjcEIsb0NBQW9DLEVBZHhDLFdBQVcsQUFBQSxhQUFhLENBZXBCLCtCQUErQixDQUFDLEVBQzVCLE9BQU8sRUFBQyxlQUFlLEdBQzFCOztBQWpCTCxBQW1CSSxXQW5CTyxBQUFBLGFBQWEsQ0FtQnBCLGdCQUFnQixDQUFDLEVBQ2IsYUFBYSxFQUFFLENBQUMsR0FnQm5COztBQXBDTCxBQXNCUSxXQXRCRyxBQUFBLGFBQWEsQ0FtQnBCLGdCQUFnQixDQUdaLDRCQUE0QixDQUFDLEVBQ3pCLFdBQVcsRUFBRSxZQUFZLEVBQ3pCLEtBQUssRUFBRSxJQUFJLEdBV2Q7O0FBbkNULEFBMkJnQixXQTNCTCxBQUFBLGFBQWEsQ0FtQnBCLGdCQUFnQixDQUdaLDRCQUE0QixDQUl4QixnQkFBZ0IsQ0FDWixtQkFBbUIsQ0FBQyxFQUFFLEFBQUEsY0FBYyxDQUFDLEVBQUUsQUFBQSxjQUFjLENBQUMsRUFDcEQsT0FBTyxFQUFFLGtCQUFrQixHQUM1Qjs7QUE3QmpCLEFBK0JnQixXQS9CTCxBQUFBLGFBQWEsQ0FtQnBCLGdCQUFnQixDQUdaLDRCQUE0QixDQUl4QixnQkFBZ0IsQ0FLWixFQUFFLENBQUMsRUFDRCxVQUFVLEVBQUUsa0JBQWtCLEdBQy9COztBQU1qQixBQUFBLGNBQWMsQ0FBQyxtQkFBbUIsQ0FBQyxtQkFBbUIsQ0FBQyxFQUNuRCxHQUFHLEVBQUMsR0FDUixHQUFDIn0= */
/*# sourceMappingURL=redux-extension-search.css.map */

View File

@@ -0,0 +1 @@
{"version":3,"sources":["redux-extension-search.scss","redux-extension-search.css"],"names":[],"mappings":"AAAA,sBCCI,kBAAkB,EDOtB,uBACI,ECNA,WAAW,EDUf,gBAAW,ECRP,QAAO,EAAA;;ADQX,0CAAA,WAAW,EAAA;;ACAX,6aAWQ,aAAa,EAAA;;AAXrB,0HAgBQ,wBAAuB,EAAA;;AAhB/B,4CAoBQ,gBAAgB,EAAA;;AApBxB,yEAuBY,yBAAyB,EACzB,WAAW,EAAA;;AAxBvB,gJA4BkB,2BAA2B,EAAA;;AA5B7C,6FAgCkB,8BAA8B,EAAA;;AAOhD,yDACI,QACJ,EAAA;;AApCA,6xDAA6xD","file":"redux-extension-search.css","sourcesContent":[".redux_field_search {\r\n position: absolute;\r\n width: 250px !important;\r\n right: 20px;\r\n padding: 4px 7px;\r\n top:6px;\r\n}\r\n\r\n.redux-has-sections {\r\n .redux_field_search {\r\n right: 10px;\r\n }\r\n}\r\n.redux-main.redux-search {\r\n .redux-section-field,\r\n .redux-info-field,\r\n .redux-notice-field,\r\n .redux-container-group,\r\n .redux-container-raw,\r\n .redux-section-desc,\r\n .redux-group-tab h3,\r\n .hr,\r\n .redux-field-info,\r\n tr {\r\n display: none;\r\n }\r\n\r\n #import_export_default_section_group,\r\n #dev_mode_default_section_group {\r\n display:none !important;\r\n }\r\n\r\n .redux-group-tab {\r\n margin-bottom: 0;\r\n\r\n .form-table-section-indented {\r\n margin-left: 0 !important;\r\n width: 100%;\r\n\r\n .redux-group-tab {\r\n .form-table-section tr:first-of-type th:first-of-type {\r\n padding: inherit !important;\r\n }\r\n\r\n h3 {\r\n margin-top: inherit !important;\r\n }\r\n }\r\n }\r\n }\r\n}\r\n\r\n.redux-metabox .redux-has-sections .redux_field_search {\r\n top:8px\r\n}",".redux_field_search { position: absolute; width: 250px !important; right: 20px; padding: 4px 7px; top: 6px; }\n\n.redux-has-sections .redux_field_search { right: 10px; }\n\n.redux-main.redux-search .redux-section-field, .redux-main.redux-search .redux-info-field, .redux-main.redux-search .redux-notice-field, .redux-main.redux-search .redux-container-group, .redux-main.redux-search .redux-container-raw, .redux-main.redux-search .redux-section-desc, .redux-main.redux-search .redux-group-tab h3, .redux-main.redux-search .hr, .redux-main.redux-search .redux-field-info, .redux-main.redux-search tr { display: none; }\n\n.redux-main.redux-search #import_export_default_section_group, .redux-main.redux-search #dev_mode_default_section_group { display: none !important; }\n\n.redux-main.redux-search .redux-group-tab { margin-bottom: 0; }\n\n.redux-main.redux-search .redux-group-tab .form-table-section-indented { margin-left: 0 !important; width: 100%; }\n\n.redux-main.redux-search .redux-group-tab .form-table-section-indented .redux-group-tab .form-table-section tr:first-of-type th:first-of-type { padding: inherit !important; }\n\n.redux-main.redux-search .redux-group-tab .form-table-section-indented .redux-group-tab h3 { margin-top: inherit !important; }\n\n.redux-metabox .redux-has-sections .redux_field_search { top: 8px; }\n\n/*# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVkdXgtZXh0ZW5zaW9uLXNlYXJjaC5jc3MiLCJzb3VyY2VzIjpbInJlZHV4LWV4dGVuc2lvbi1zZWFyY2guc2NzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxBQUFBLG1CQUFtQixDQUFDLEVBQ2hCLFFBQVEsRUFBRSxRQUFRLEVBQ2xCLEtBQUssRUFBRSxnQkFBZ0IsRUFDdkIsS0FBSyxFQUFFLElBQUksRUFDWCxPQUFPLEVBQUUsT0FBTyxFQUNoQixHQUFHLEVBQUMsR0FBRyxHQUNWOztBQUVELEFBQ0ksbUJBRGUsQ0FDZixtQkFBbUIsQ0FBQyxFQUNoQixLQUFLLEVBQUUsSUFBSSxHQUNkOztBQUVMLEFBQ0ksV0FETyxBQUFBLGFBQWEsQ0FDcEIsb0JBQW9CLEVBRHhCLFdBQVcsQUFBQSxhQUFhLENBRXBCLGlCQUFpQixFQUZyQixXQUFXLEFBQUEsYUFBYSxDQUdwQixtQkFBbUIsRUFIdkIsV0FBVyxBQUFBLGFBQWEsQ0FJcEIsc0JBQXNCLEVBSjFCLFdBQVcsQUFBQSxhQUFhLENBS3BCLG9CQUFvQixFQUx4QixXQUFXLEFBQUEsYUFBYSxDQU1wQixtQkFBbUIsRUFOdkIsV0FBVyxBQUFBLGFBQWEsQ0FPcEIsZ0JBQWdCLENBQUMsRUFBRSxFQVB2QixXQUFXLEFBQUEsYUFBYSxDQVFwQixHQUFHLEVBUlAsV0FBVyxBQUFBLGFBQWEsQ0FTcEIsaUJBQWlCLEVBVHJCLFdBQVcsQUFBQSxhQUFhLENBVXBCLEVBQUUsQ0FBQyxFQUNDLE9BQU8sRUFBRSxJQUFJLEdBQ2hCOztBQVpMLEFBY0ksV0FkTyxBQUFBLGFBQWEsQ0FjcEIsb0NBQW9DLEVBZHhDLFdBQVcsQUFBQSxhQUFhLENBZXBCLCtCQUErQixDQUFDLEVBQzVCLE9BQU8sRUFBQyxlQUFlLEdBQzFCOztBQWpCTCxBQW1CSSxXQW5CTyxBQUFBLGFBQWEsQ0FtQnBCLGdCQUFnQixDQUFDLEVBQ2IsYUFBYSxFQUFFLENBQUMsR0FnQm5COztBQXBDTCxBQXNCUSxXQXRCRyxBQUFBLGFBQWEsQ0FtQnBCLGdCQUFnQixDQUdaLDRCQUE0QixDQUFDLEVBQ3pCLFdBQVcsRUFBRSxZQUFZLEVBQ3pCLEtBQUssRUFBRSxJQUFJLEdBV2Q7O0FBbkNULEFBMkJnQixXQTNCTCxBQUFBLGFBQWEsQ0FtQnBCLGdCQUFnQixDQUdaLDRCQUE0QixDQUl4QixnQkFBZ0IsQ0FDWixtQkFBbUIsQ0FBQyxFQUFFLEFBQUEsY0FBYyxDQUFDLEVBQUUsQUFBQSxjQUFjLENBQUMsRUFDcEQsT0FBTyxFQUFFLGtCQUFrQixHQUM1Qjs7QUE3QmpCLEFBK0JnQixXQS9CTCxBQUFBLGFBQWEsQ0FtQnBCLGdCQUFnQixDQUdaLDRCQUE0QixDQUl4QixnQkFBZ0IsQ0FLWixFQUFFLENBQUMsRUFDRCxVQUFVLEVBQUUsa0JBQWtCLEdBQy9COztBQU1qQixBQUFBLGNBQWMsQ0FBQyxtQkFBbUIsQ0FBQyxtQkFBbUIsQ0FBQyxFQUNuRCxHQUFHLEVBQUMsR0FDUixHQUFDIn0= */\n\n/*# sourceMappingURL=redux-extension-search.css.map */\n"]}

View File

@@ -0,0 +1,94 @@
/* global jQuery, reduxSearch */
(function( $ ) {
$( document ).ready(
function() {
$( '.redux-container' ).each(
function( ) {
if ( ! $( this ).hasClass( 'redux-no-sections' ) ) {
$( this ).find( '.redux-main' ).prepend( '<input class="redux_field_search" id="redux_field_search" type="text" placeholder="' + reduxSearch.search + '"/>' );
}
}
);
$( '.redux_field_search' ).on(
'keypress',
function( evt ) {
// Determine where our character code is coming from within the event.
var charCode = evt.charCode || evt.keyCode;
if ( 13 === charCode ) { // Enter key's keycode.
return false;
}
}
).typeWatch(
{
callback: function( searchString ) {
var searchArray;
var parent;
var expanded_options;
searchString = searchString.toLowerCase();
searchArray = searchString.split( ' ' );
parent = $( this ).parents( '.redux-container:first' );
expanded_options = parent.find( '.expand_options' );
if ( '' !== searchString ) {
if ( ! expanded_options.hasClass( 'expanded' ) ) {
expanded_options.trigger( 'click' );
parent.find( '.redux-main' ).addClass( 'redux-search' );
}
} else {
if ( expanded_options.hasClass( 'expanded' ) ) {
expanded_options.trigger( 'click' );
parent.find( '.redux-main' ).removeClass( 'redux-search' );
}
parent.find( '.redux-section-field, .redux-info-field, .redux-notice-field, .redux-container-group, .redux-section-desc, .redux-group-tab h3' ).show();
}
parent.find( '.redux-field-container' ).each(
function() {
if ( '' !== searchString ) {
$( this ).parents( 'tr:first' ).hide();
} else {
$( this ).parents( 'tr:first' ).show();
}
}
);
parent.find( '.form-table tr' ).filter(
function() {
var isMatch = true, text = $( this ).find( '.redux_field_th' ).text().toLowerCase();
if ( ! text || '' === text ) {
return false;
}
$.each(
searchArray,
function( i, searchStr ) {
if ( -1 === text.indexOf( searchStr ) ) {
isMatch = false;
}
}
);
if ( isMatch ) {
$( this ).show();
}
return isMatch;
}
).show();
},
wait: 400,
highlight: false,
captureLength: 0
}
);
}
);
} )( jQuery );

View File

@@ -0,0 +1 @@
.redux_field_search{position:absolute;width:250px !important;right:20px;padding:4px 7px;top:6px}.redux-has-sections .redux_field_search{right:10px}.redux-main.redux-search .redux-section-field,.redux-main.redux-search .redux-info-field,.redux-main.redux-search .redux-notice-field,.redux-main.redux-search .redux-container-group,.redux-main.redux-search .redux-container-raw,.redux-main.redux-search .redux-section-desc,.redux-main.redux-search .redux-group-tab h3,.redux-main.redux-search .hr,.redux-main.redux-search .redux-field-info,.redux-main.redux-search tr{display:none}.redux-main.redux-search #import_export_default_section_group,.redux-main.redux-search #dev_mode_default_section_group{display:none !important}.redux-main.redux-search .redux-group-tab{margin-bottom:0}.redux-main.redux-search .redux-group-tab .form-table-section-indented{margin-left:0 !important;width:100%}.redux-main.redux-search .redux-group-tab .form-table-section-indented .redux-group-tab .form-table-section tr:first-of-type th:first-of-type{padding:inherit !important}.redux-main.redux-search .redux-group-tab .form-table-section-indented .redux-group-tab h3{margin-top:inherit !important}.redux-metabox .redux-has-sections .redux_field_search{top:8px}

View File

@@ -0,0 +1 @@
!function(n){n(document).ready(function(){n(".redux-container").each(function(){n(this).hasClass("redux-no-sections")||n(this).find(".redux-main").prepend('<input class="redux_field_search" id="redux_field_search" type="text" placeholder="'+reduxSearch.search+'"/>')}),n(".redux_field_search").on("keypress",function(e){if(13===(e.charCode||e.keyCode))return!1}).typeWatch({callback:function(e){var r,i,t;e=e.toLowerCase(),r=e.split(" "),t=(i=n(this).parents(".redux-container:first")).find(".expand_options"),""!==e?t.hasClass("expanded")||(t.trigger("click"),i.find(".redux-main").addClass("redux-search")):(t.hasClass("expanded")&&(t.trigger("click"),i.find(".redux-main").removeClass("redux-search")),i.find(".redux-section-field, .redux-info-field, .redux-notice-field, .redux-container-group, .redux-section-desc, .redux-group-tab h3").show()),i.find(".redux-field-container").each(function(){""!==e?n(this).parents("tr:first").hide():n(this).parents("tr:first").show()}),i.find(".form-table tr").filter(function(){var i=!0,t=n(this).find(".redux_field_th").text().toLowerCase();return!(!t||""===t)&&(n.each(r,function(e,r){-1===t.indexOf(r)&&(i=!1)}),i&&n(this).show(),i)}).show()},wait:400,highlight:!1,captureLength:0})})}(jQuery);

View File

@@ -0,0 +1,55 @@
.redux_field_search {
position: absolute;
width: 250px !important;
right: 20px;
padding: 4px 7px;
top:6px;
}
.redux-has-sections {
.redux_field_search {
right: 10px;
}
}
.redux-main.redux-search {
.redux-section-field,
.redux-info-field,
.redux-notice-field,
.redux-container-group,
.redux-container-raw,
.redux-section-desc,
.redux-group-tab h3,
.hr,
.redux-field-info,
tr {
display: none;
}
#import_export_default_section_group,
#dev_mode_default_section_group {
display:none !important;
}
.redux-group-tab {
margin-bottom: 0;
.form-table-section-indented {
margin-left: 0 !important;
width: 100%;
.redux-group-tab {
.form-table-section tr:first-of-type th:first-of-type {
padding: inherit !important;
}
h3 {
margin-top: inherit !important;
}
}
}
}
}
.redux-metabox .redux-has-sections .redux_field_search {
top:8px
}