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,55 @@
<?php
/**
* The template for the main panel container.
* Override this template by specifying the path where it is stored (templates_path) in your Redux config.
*
* @author Redux Framework
* @package ReduxFramework/Templates
* @version: 4.4.4
*/
$expanded = ( $this->parent->args['open_expanded'] ) ? ' fully-expanded' : ( ! empty( $this->parent->args['class'] ) ? ' ' . esc_attr( $this->parent->args['class'] ) : '' );
$nonce = wp_create_nonce( 'redux_ajax_nonce' . $this->parent->args['opt_name'] );
$actionn = ( 'network' === $this->parent->args['database'] && $this->parent->args['network_admin'] && is_network_admin() ? './edit.php?action=redux_' . $this->parent->args['opt_name'] : './options.php' );
// Last tab?
$this->parent->options['last_tab'] = ( isset( $_GET['tab'] ) && ! isset( $this->parent->transients['last_save_mode'] ) ) ? sanitize_text_field( wp_unslash( $_GET['tab'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification
?>
<div
class="redux-container<?php echo esc_attr( $expanded ); ?>">
<form
method="post"
action="<?php echo esc_attr( $actionn ); ?>"
data-nonce="<?php echo esc_attr( $nonce ); ?>"
enctype="multipart/form-data"
class="redux-form-wrapper"
id="redux-form-wrapper"
data-opt-name="<?php echo esc_attr( $this->parent->args['opt_name'] ); ?>">
<input
type="hidden" id="redux-compiler-hook"
name="<?php echo esc_attr( $this->parent->args['opt_name'] ); ?>[compiler]"
value=""/>
<input
type="hidden" id="currentSection"
name="<?php echo esc_attr( $this->parent->args['opt_name'] ); ?>[redux-section]"
value=""/>
<?php if ( ! empty( $this->parent->options_class->no_panel ) ) { ?>
<input
type="hidden"
name="<?php echo esc_attr( $this->parent->args['opt_name'] ); ?>[redux-no_panel]"
value="<?php echo esc_attr( implode( '|', $this->parent->options_class->no_panel ) ); ?>"/>
<?php } ?>
<?php $this->init_settings_fields(); // Must run or the page won't redirect properly. ?>
<input
type="hidden" id="last_tab"
name="<?php echo esc_attr( $this->parent->args['opt_name'] ); ?>[last_tab]"
value="<?php echo esc_attr( $this->parent->options['last_tab'] ); ?>"/>
<?php $this->get_template( 'content.tpl.php' ); ?>
</form>
</div>
<?php if ( isset( $this->parent->args['footer_text'] ) ) { ?>
<div id="redux-sub-footer"><?php echo wp_kses_post( $this->parent->args['footer_text'] ); ?></div>
<?php } ?>

View File

@@ -0,0 +1,92 @@
<?php
/**
* The template for the main content of the panel.
* Override this template by specifying the path where it is stored (templates_path) in your Redux config.
*
* @author Redux Framework
* @package ReduxFramework/Templates
* @version: 4.0.0
*/
?>
<!-- Header Block -->
<?php $this->get_template( 'header.tpl.php' ); ?>
<!-- Intro Text -->
<?php if ( isset( $this->parent->args['intro_text'] ) ) { ?>
<div id="redux-intro-text"><?php echo wp_kses_post( $this->parent->args['intro_text'] ); ?></div>
<?php } ?>
<?php $this->get_template( 'menu-container.tpl.php' ); ?>
<div class="redux-main">
<!-- Stickybar -->
<?php $this->get_template( 'header-stickybar.tpl.php' ); ?>
<div id="redux_ajax_overlay">&nbsp;</div>
<?php foreach ( $this->parent->sections as $k => $section ) { ?>
<?php if ( isset( $section['customizer_only'] ) && true === $section['customizer_only'] ) { ?>
<?php continue; ?>
<?php } // phpcs:ignore Squiz.PHP.NonExecutableCode.Unreachable ?>
<?php $section['class'] = isset( $section['class'] ) ? ' ' . $section['class'] : ''; ?>
<?php $disabled = ''; ?>
<?php if ( isset( $section['disabled'] ) && $section['disabled'] ) { ?>
<?php $disabled = 'disabled '; ?>
<?php } ?>
<div
id="<?php echo esc_attr( $k ); ?>_section_group"
class="redux-group-tab <?php echo esc_attr( $disabled ); ?><?php echo esc_attr( $section['class'] ); ?>"
data-rel="<?php echo esc_attr( $k ); ?>">
<?php $display = true; ?>
<?php if ( isset( $_GET['page'] ) && $this->parent->args['page_slug'] === $_GET['page'] ) { // phpcs:ignore WordPress.Security.NonceVerification ?>
<?php if ( isset( $section['panel'] ) && false === $section['panel'] ) { ?>
<?php $display = false; ?>
<?php } ?>
<?php } ?>
<?php
if ( $display ) {
/**
* Action 'redux/page/{opt_name}/section/before'
*
* @param object $this ReduxFramework
*/
// phpcs:ignore WordPress.NamingConventions.ValidHookName
do_action( "redux/page/{$this->parent->args['opt_name']}/section/before", $section );
$this->output_section( $k );
/**
* Action 'redux/page/{opt_name}/section/after'
*
* @param object $this ReduxFramework
*/
// phpcs:ignore WordPress.NamingConventions.ValidHookName
do_action( "redux/page/{$this->parent->args['opt_name']}/section/after", $section );
}
?>
</div> <!-- section group -->
<?php } ?>
<?php
/**
* Action 'redux/page/{opt_name}/sections/after'
*
* @param object $this ReduxFramework
*/
// phpcs:ignore WordPress.NamingConventions.ValidHookName
do_action( "redux/page/{$this->parent->args['opt_name']}/sections/after", $this );
?>
<div class="clear"></div>
<!-- Footer Block -->
<?php $this->get_template( 'footer.tpl.php' ); ?>
<div id="redux-sticky-padder" style="display: none;">&nbsp;</div>
</div> <!-- redux main -->
<div class="clear"></div>

View File

@@ -0,0 +1,69 @@
<?php
/**
* The template for the panel footer area.
* Override this template by specifying the path where it is stored (templates_path) in your Redux config.
*
* @author Redux Framework
* @package ReduxFramework/Templates
* @version: 4.4.2
*/
// Exit if accessed directly.
defined( 'ABSPATH' ) || exit;
?>
<div id="redux-sticky-padder" style="display: none;">&nbsp;</div>
<div id="redux-footer-sticky">
<div id="redux-footer">
<?php
if ( isset( $this->parent->args['share_icons'] ) ) {
$skip_icons = false;
if ( ! $this->parent->args['dev_mode'] && $this->parent->args_class->omit_icons ) {
$skip_icons = true;
}
?>
<div id="redux-share">
<?php
foreach ( $this->parent->args['share_icons'] as $links ) {
if ( $skip_icons ) {
continue;
}
// SHIM, use URL now.
if ( isset( $links['link'] ) && ! empty( $links['link'] ) ) {
$links['url'] = $links['link'];
unset( $links['link'] );
}
if ( isset( $links['icon'] ) && ! empty( $links['icon'] ) ) {
if ( strpos( $links['icon'], 'el-icon' ) !== false && strpos( $links['icon'], 'el ' ) === false ) {
$links['icon'] = 'el ' . $links['icon'];
}
}
?>
<a href="<?php echo esc_url( $links['url'] ); ?>" title="<?php echo esc_attr( $links['title'] ); ?>" target="_blank">
<?php if ( isset( $links['icon'] ) && ! empty( $links['icon'] ) ) { ?>
<i class="<?php echo esc_attr( $links['icon'] ); ?>"></i>
<?php } else { ?>
<img alt="<?php echo esc_url( $links['img'] ); ?>" src="<?php echo esc_url( $links['img'] ); ?>"/>
<?php } ?>
</a>
<?php } ?>
</div>
<?php } ?>
<div class="redux-action_bar">
<span class="spinner"></span>
<?php
if ( false === $this->parent->args['hide_save'] ) {
submit_button( esc_html__( 'Save Changes', 'redux-framework' ), 'primary', 'redux_save', false, array( 'id' => 'redux_bottom_save' ) );
}
if ( false === $this->parent->args['hide_reset'] ) {
submit_button( esc_html__( 'Reset Section', 'redux-framework' ), 'secondary', $this->parent->args['opt_name'] . '[defaults-section]', false, array( 'id' => 'redux-defaults-section-bottom' ) );
submit_button( esc_html__( 'Reset All', 'redux-framework' ), 'secondary', $this->parent->args['opt_name'] . '[defaults]', false, array( 'id' => 'redux-defaults-bottom' ) );
}
?>
</div>
<div class="clear"></div>
</div>
</div>

View File

@@ -0,0 +1,38 @@
<?php
/**
* The template for the header sticky bar.
* Override this template by specifying the path where it is stored (templates_path) in your Redux config.
*
* @author Redux Framework
* @package ReduxFramework/Templates
* @version: 4.4.2
*/
?>
<div id="redux-sticky">
<div id="info_bar">
<a href="javascript:void(0);"
class="expand_options<?php echo esc_attr( ( $this->parent->args['open_expanded'] ) ? ' expanded' : '' ); ?>"<?php echo( true === $this->parent->args['hide_expand'] ? ' style="display: none;"' : '' ); ?>>
<?php esc_attr_e( 'Expand', 'redux-framework' ); ?>
</a>
<div class="redux-action_bar">
<span class="spinner"></span>
<?php
if ( false === $this->parent->args['hide_save'] ) {
submit_button( esc_attr__( 'Save Changes', 'redux-framework' ), 'primary', 'redux_save', false, array( 'id' => 'redux_top_save' ) );
}
if ( false === $this->parent->args['hide_reset'] ) {
submit_button( esc_attr__( 'Reset Section', 'redux-framework' ), 'secondary', $this->parent->args['opt_name'] . '[defaults-section]', false, array( 'id' => 'redux-defaults-section-top' ) );
submit_button( esc_attr__( 'Reset All', 'redux-framework' ), 'secondary', $this->parent->args['opt_name'] . '[defaults]', false, array( 'id' => 'redux-defaults-top' ) );
}
?>
</div>
<div class="clear"></div>
</div>
<!-- Notification bar -->
<div id="redux_notification_bar">
<?php $this->notification_bar(); ?>
</div>
</div>

View File

@@ -0,0 +1,58 @@
<?php
/**
* The template for the panel header area.
* Override this template by specifying the path where it is stored (templates_path) in your Redux config.
*
* @author Redux Framework
* @package ReduxFramework/Templates
* @version: 4.0.0
*/
$tip_title = esc_html__( 'Developer Mode Enabled', 'redux-framework' );
if ( $this->parent->args_class->dev_mode_forced ) {
$is_debug = false;
$is_localhost = false;
$debug_bit = '';
if ( Redux_Helpers::is_wp_debug() ) {
$is_debug = true;
$debug_bit = esc_html__( 'WP_DEBUG is enabled', 'redux-framework' );
}
$localhost_bit = '';
if ( Redux_Helpers::is_local_host() ) {
$is_localhost = true;
$localhost_bit = esc_html__( 'you are working in a localhost environment', 'redux-framework' );
}
$conjunction_bit = '';
if ( $is_localhost && $is_debug ) {
$conjunction_bit = ' ' . esc_html__( 'and', 'redux-framework' ) . ' ';
}
$tip_msg = esc_html__( 'This has been automatically enabled because', 'redux-framework' ) . ' ' . $debug_bit . $conjunction_bit . $localhost_bit . '.';
} else {
$tip_msg = esc_html__( 'If you are not a developer, your theme/plugin author shipped with developer mode enabled. Contact them directly to fix it.', 'redux-framework' );
}
?>
<div id="redux-header">
<?php if ( ! empty( $this->parent->args['display_name'] ) ) { ?>
<div class="display_header">
<?php if ( isset( $this->parent->args['dev_mode'] ) && $this->parent->args['dev_mode'] ) { ?>
<div
class="redux-dev-mode-notice-container redux-dev-qtip"
qtip-title="<?php echo esc_attr( $tip_title ); ?>"
qtip-content="<?php echo esc_attr( $tip_msg ); ?>">
<span class="redux-dev-mode-notice"><?php esc_html_e( 'Developer Mode Enabled', 'redux-framework' ); ?></span>
</div>
<?php } ?>
<h2><?php echo wp_kses_post( $this->parent->args['display_name'] ); ?></h2>
<?php if ( ! empty( $this->parent->args['display_version'] ) ) { ?>
<span><?php echo wp_kses_post( $this->parent->args['display_version'] ); ?></span>
<?php } ?>
</div>
<?php } ?>
<div class="clear"></div>
</div>

View File

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

View File

@@ -0,0 +1,42 @@
<?php
/**
* The template for the menu container of the panel.
* Override this template by specifying the path where it is stored (templates_path) in your Redux config.
*
* @author Redux Framework
* @package ReduxFramework/Templates
* @version: 4.3.11
*/
?>
<div class="redux-sidebar">
<ul class="redux-group-menu">
<?php
foreach ( $this->parent->sections as $k => $section ) {
$the_title = $section['title'] ?? '';
$skip_sec = false;
foreach ( $this->parent->options_class->hidden_perm_sections as $num => $section_title ) {
if ( $section_title === $the_title ) {
$skip_sec = true;
}
}
if ( isset( $section['customizer_only'] ) && true === $section['customizer_only'] ) {
continue;
}
if ( false === $skip_sec ) {
echo( $this->parent->render_class->section_menu( $k, $section ) ); // phpcs:ignore WordPress.Security.EscapeOutput
$skip_sec = false;
}
}
/**
* Action 'redux/page/{opt_name}/menu/after'
*
* @param object $this ReduxFramework
*/
do_action( "redux/page/{$this->parent->args['opt_name']}/menu/after", $this ); // phpcs:ignore WordPress.NamingConventions.ValidHookName
?>
</ul>
</div>