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:
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
/**
|
||||
* Silence is golden.
|
||||
*
|
||||
* @package Redux Framework
|
||||
*/
|
||||
|
||||
echo null;
|
||||
@@ -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 } ?>
|
||||
@@ -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"> </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;"> </div>
|
||||
</div> <!-- redux main -->
|
||||
<div class="clear"></div>
|
||||
@@ -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;"> </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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
/**
|
||||
* Silence is golden.
|
||||
*
|
||||
* @package Redux Framework
|
||||
*/
|
||||
|
||||
echo null;
|
||||
@@ -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>
|
||||
Reference in New Issue
Block a user