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,90 @@
<?php
/**
* Redux Options Object Extension Class
*
* @class Redux_Core
* @version 4.0.0
* @package Redux Framework
*/
defined( 'ABSPATH' ) || exit;
// Don't duplicate me!
if ( ! class_exists( 'Redux_Extension_Options_Object', false ) ) {
/**
* Main ReduxFramework options_object extension class
*
* @since 3.1.6
*/
class Redux_Extension_Options_Object extends Redux_Extension_Abstract {
/**
* Ext version.
*
* @var string
*/
public static $version = '4.0.0';
/**
* Set the name of the field. Ideally, this will also be your extension's name.
* Please use underscores and NOT dashes.
*
* @var string
*/
private $field_name = 'options_object';
/**
* Is field bit.
*
* @var bool
*/
public $is_field = false;
/**
* Class Constructor. Defines the args for the extensions class
*
* @since 1.0.0
* @access public
*
* @param object $redux Redux object.
*
* @return void
*/
public function __construct( $redux ) {
parent::__construct( $redux, __FILE__ );
$this->add_field( $this->field_name );
$this->is_field = Redux_Helpers::is_field_in_use( $redux, $this->field_name );
if ( ! $this->is_field && $this->parent->args['dev_mode'] && $this->parent->args['show_options_object'] ) {
$this->add_section();
}
}
/**
* Add section to panel.
*/
public function add_section() {
$this->parent->sections[] = array(
'id' => 'options-object',
'title' => esc_html__( 'Options Object', 'redux-framework' ),
'heading' => '',
'icon' => 'el el-info-circle',
'customizer' => false,
'fields' => array(
array(
'id' => 'redux_options_object',
'type' => 'options_object',
'title' => '',
),
),
);
}
}
}
if ( ! class_exists( 'ReduxFramework_Extension_options_object' ) ) {
class_alias( 'Redux_Extension_Options_Object', 'ReduxFramework_Extension_options_object' );
}

View File

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

View File

@@ -0,0 +1,150 @@
<?php
/**
* Debug Options Object
*
* @package ReduxFramework
* @author Kevin Provance (kprovance)
* @version 3.5.4
*
* @noinspection ALL
*/
defined( 'ABSPATH' ) || exit;
// Don't duplicate me!
if ( ! class_exists( 'Redux_Options_Object', false ) ) {
/**
* Main Redux_options_object class
*
* @since 1.0.0
*/
class Redux_Options_Object extends Redux_Field {
public $is_field;
/**
* Redux_Options_Object constructor.
*
* @param array $field Field array.
* @param mixed $value Value array.
* @param object $parent ReduxFramework object.
*
* @throws ReflectionException .
*/
public function __construct( array $field, $value, $parent ) {
parent::__construct( $field, $value, $parent );
$this->is_field = $this->parent->extensions['options_object']->is_field;
}
/**
* Set field defaults.
*/
public function set_defaults() {
$defaults = array(
'options' => array(),
'stylesheet' => '',
'output' => true,
'enqueue' => true,
'enqueue_frontend' => true,
);
$this->field = wp_parse_args( $this->field, $defaults );
}
/**
* Field Render Function.
* Takes the vars and outputs the HTML for the field in the settings
*
* @since 1.0.0
* @access public
* @return void
*/
public function render() {
if ( version_compare( phpversion(), '5.3.0', '>=' ) ) {
$json = wp_json_encode( $this->parent->options, true );
} else {
$json = wp_json_encode( $this->parent->options );
}
$defaults = array(
'full_width' => true,
'overflow' => 'inherit',
);
$this->field = wp_parse_args( $this->field, $defaults );
if ( $this->is_field ) {
$full_width = $this->field['full_width'];
}
$do_close = false;
$id = $this->parent->args['opt_name'] . '-' . $this->field['id'];
if ( ! $this->is_field || ( $this->is_field && false === $full_width ) ) {
?>
<style>#<?php echo esc_html( $id ); ?>{padding: 0;}</style>
<?php // phpcs:ignore WordPress.CodeAnalysis.EmptyStatement ?>
<?php echo '</td></tr></table>'; ?>
<table id="<?php echo esc_attr( $id ); ?>" class="form-table no-border redux-group-table redux-raw-table" style=" overflow: <?php esc_attr( $this->field['overflow'] ); ?>;">
<tbody><tr><td>
<?php
$do_close = true;
}
?>
<fieldset
id="<?php echo esc_attr( $id ); ?>-fieldset"
class="redux-field redux-container-<?php echo esc_attr( $this->field['type'] ) . ' ' . esc_attr( $this->field['class'] ); ?>"
data-id="<?php echo esc_attr( $this->field['id'] ); ?>">
<h3><?php esc_html_e( 'Options Object', 'redux-framework' ); ?></h3>
<div id="redux-object-browser"></div>
<div id="redux-object-json" class="hide"><?php echo( $json ); // phpcs:ignore WordPress.Security.EscapeOutput ?></div>
<a
href="#" id="consolePrintObject"
class="button">
<?php esc_html_e( 'Show Object in Javascript Console Object', 'redux-framework' ); ?></a>
</fieldset>
<?php if ( true === $do_close ) { ?>
</td></tr></table>
<table class="form-table no-border" style="margin-top: 0;">
<tbody>
<tr style="border-bottom: 0;">
<th></th>
<td>
<?php } ?>
<?php
}
/**
* Enqueue Function.
* If this field requires any scripts, or css define this function and register/enqueue the scripts/css
*
* @since 1.0.0
* @access public
* @return void
*/
public function enqueue() {
wp_enqueue_script(
'redux-extension-options-object',
$this->url . 'redux-options-object' . Redux_Functions::is_min() . '.js',
array( 'jquery', 'redux-js' ),
Redux_Extension_Options_Object::$version,
true
);
if ( $this->parent->args['dev_mode'] ) {
wp_enqueue_style(
'redux-options-object',
$this->url . 'redux-options-object.css',
array(),
Redux_Extension_Options_Object::$version,
'all'
);
}
}
}
}

View File

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

View File

@@ -0,0 +1,5 @@
#redux-object-browser { overflow: auto; word-wrap: break-word; max-height: 600px; max-width: 100%; }
/*# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVkdXgtb3B0aW9ucy1vYmplY3QuY3NzIiwic291cmNlcyI6WyJyZWR1eC1vcHRpb25zLW9iamVjdC5zY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLEFBQUEscUJBQXFCLENBQUMsRUFDbEIsUUFBUSxFQUFFLElBQUksRUFDZCxTQUFTLEVBQUUsVUFBVSxFQUNyQixVQUFVLEVBQUUsS0FBSyxFQUNqQixTQUFTLEVBQUUsSUFBSSxHQUNsQiJ9 */
/*# sourceMappingURL=redux-options-object.css.map */

View File

@@ -0,0 +1 @@
{"version":3,"sources":["redux-options-object.scss","redux-options-object.css"],"names":[],"mappings":"AAAA,wBCCI,cAAc,EACd,qBAAqB,EACrB,iBAAiB,EACjB,eAAe,EAAA;;AAFnB,yWAAyW","file":"redux-options-object.css","sourcesContent":["#redux-object-browser {\r\n overflow: auto;\r\n word-wrap: break-word;\r\n max-height: 600px;\r\n max-width: 100%;\r\n}\r\n\r\n","#redux-object-browser { overflow: auto; word-wrap: break-word; max-height: 600px; max-width: 100%; }\n\n/*# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVkdXgtb3B0aW9ucy1vYmplY3QuY3NzIiwic291cmNlcyI6WyJyZWR1eC1vcHRpb25zLW9iamVjdC5zY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLEFBQUEscUJBQXFCLENBQUMsRUFDbEIsUUFBUSxFQUFFLElBQUksRUFDZCxTQUFTLEVBQUUsVUFBVSxFQUNyQixVQUFVLEVBQUUsS0FBSyxFQUNqQixTQUFTLEVBQUUsSUFBSSxHQUNsQiJ9 */\n\n/*# sourceMappingURL=redux-options-object.css.map */\n"]}

View File

@@ -0,0 +1,36 @@
/*global redux, jsonView */
(function( $ ) {
redux.field_objects = redux.field_objects || {};
redux.field_objects.options_object = redux.field_objects.options_object || {};
redux.field_objects.options_object.init = function( selector ) {
var parent;
selector = $.redux.getSelector( selector, 'options_object' );
parent = selector;
if ( ! selector.hasClass( 'redux-field-container' ) ) {
parent = selector.parents( '.redux-field-container:first' );
}
if ( parent.hasClass( 'redux-field-init' ) ) {
parent.removeClass( 'redux-field-init' );
} else {
return;
}
$( '#consolePrintObject' ).on(
'click',
function( e ) {
e.preventDefault();
console.log( JSON.parse( $( '#redux-object-json' ).html() ) );
}
);
if ( 'function' === typeof jsonView ) {
jsonView( '#redux-object-json', '#redux-object-browser' );
}
};
})( jQuery );

View File

@@ -0,0 +1 @@
!function(t){redux.field_objects=redux.field_objects||{},redux.field_objects.options_object=redux.field_objects.options_object||{},redux.field_objects.options_object.init=function(e){var o;(o=(o=e=t.redux.getSelector(e,"options_object")).hasClass("redux-field-container")?o:e.parents(".redux-field-container:first")).hasClass("redux-field-init")&&(o.removeClass("redux-field-init"),t("#consolePrintObject").on("click",function(e){e.preventDefault(),console.log(JSON.parse(t("#redux-object-json").html()))}),"function"==typeof jsonView)&&jsonView("#redux-object-json","#redux-object-browser")}}(jQuery);

View File

@@ -0,0 +1,7 @@
#redux-object-browser {
overflow: auto;
word-wrap: break-word;
max-height: 600px;
max-width: 100%;
}