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,155 @@
<?php
/**
* Info Field.
*
* @package ReduxFramework/Fields
* @author Dovy Paukstys & Kevin Provance (kprovance)
* @version 4.0.0
*/
defined( 'ABSPATH' ) || exit;
// Don't duplicate me!
if ( ! class_exists( 'Redux_Info', false ) ) {
/**
* Main Redux_info class
*
* @since 1.0.0
*/
class Redux_Info extends Redux_Field {
/**
* Set field and value defaults.
*/
public function set_defaults() {
$defaults = array(
'title' => '',
'desc' => '',
'indent' => false,
'notice' => true,
'style' => '',
'color' => '',
);
$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() {
$styles = array(
'normal',
'info',
'warning',
'success',
'critical',
'custom',
);
if ( ! in_array( $this->field['style'], $styles, true ) ) {
$this->field['style'] = 'normal';
}
if ( 'custom' === $this->field['style'] ) {
if ( ! empty( $this->field['color'] ) ) {
$this->field['color'] = 'border-color:' . $this->field['color'] . ';';
} else {
$this->field['style'] = 'normal';
$this->field['color'] = '';
}
} else {
$this->field['color'] = '';
}
if ( empty( $this->field['desc'] ) && ! empty( $this->field['default'] ) ) {
$this->field['desc'] = $this->field['default'];
unset( $this->field['default'] );
}
if ( empty( $this->field['desc'] ) && ! empty( $this->field['subtitle'] ) ) {
$this->field['desc'] = $this->field['subtitle'];
unset( $this->field['subtitle'] );
}
if ( empty( $this->field['desc'] ) ) {
$this->field['desc'] = '';
}
if ( empty( $this->field['raw_html'] ) ) {
if ( true === $this->field['notice'] ) {
$this->field['class'] .= ' redux-notice-field';
} else {
$this->field['class'] .= ' redux-info-field';
}
$this->field['style'] = 'redux-' . $this->field['style'] . ' ';
}
// Old shim, deprecated arg.
if ( isset( $this->field['sectionIndent'] ) ) {
$this->field['indent'] = $this->field['sectionIndent'];
}
$indent = ( isset( $this->field['indent'] ) && $this->field['indent'] ) ? ' form-table-section-indented' : '';
echo '</td></tr></table>';
echo '<div
id="info-' . esc_attr( $this->field['id'] ) . '"
class="' . ( isset( $this->field['icon'] ) && ! empty( $this->field['icon'] ) && true !== $this->field['icon'] ? 'hasIcon ' : '' ) . esc_attr( $this->field['style'] ) . ' ' . esc_attr( $this->field['class'] ) . ' redux-field-' . esc_attr( $this->field['type'] ) . esc_attr( $indent ) . '"' . ( ! empty( $this->field['color'] ) ? ' style="' . esc_attr( $this->field['color'] ) . '"' : '' ) . '>';
if ( ! empty( $this->field['raw_html'] ) && $this->field['raw_html'] ) {
echo wp_kses_post( $this->field['desc'] );
} else {
if ( isset( $this->field['title'] ) && ! empty( $this->field['title'] ) ) {
$this->field['title'] = '<b>' . wp_kses_post( $this->field['title'] ) . '</b><br/>';
}
if ( isset( $this->field['icon'] ) && ! empty( $this->field['icon'] ) && true !== $this->field['icon'] ) {
echo '<p class="redux-info-icon"><i class="' . esc_attr( $this->field['icon'] ) . ' icon-large"></i></p>';
}
if ( isset( $this->field['raw'] ) && ! empty( $this->field['raw'] ) ) {
echo wp_kses_post( $this->field['raw'] );
}
if ( ! empty( $this->field['title'] ) || ! empty( $this->field['desc'] ) ) {
echo '<p class="redux-info-desc">' . wp_kses_post( $this->field['title'] ) . wp_kses_post( $this->field['desc'] ) . '</p>';
}
}
echo '</div>';
echo '<table class="form-table no-border" style="margin-top: 0;">';
echo '<tbody>';
echo '<tr style="border-bottom:0; display:none;">';
echo '<th style="padding-top:0;"></th>';
echo '<td style="padding-top:0;">';
}
/**
* 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() {
if ( $this->parent->args['dev_mode'] ) {
wp_enqueue_style(
'redux-field-info',
Redux_Core::$url . 'inc/fields/info/redux-info.css',
array(),
$this->timestamp
);
}
}
}
}
class_alias( 'Redux_Info', 'ReduxFramework_Info' );

View File

@@ -0,0 +1,8 @@
<?php
/**
* Silence is golden.
*
* @package Redux Framework
*/
_deprecated_file( 'field_info.php', '4.3', 'class-redux-info.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,63 @@
.redux-info-field { min-height: 20px; padding: 8px 19px; margin: 10px 0; border: 1px solid; border-radius: 4px; position: relative; }
.redux-info-field h1, .redux-info-field h2, .redux-info-field h3, .redux-info-field h4, .redux-info-field h5, .redux-info-field h6 { border-bottom: 0 !important; }
.redux-info-field h3 { color: #777; }
.redux-info-field .redux-info-icon { display: inline-block; margin-right: 15px; }
.redux-info-field .redux-info-icon i { font-size: 2em; }
.redux-info-field .redux-info-desc { display: inline-block; vertical-align: top; }
.redux-info-field.redux-normal { background-color: #eee; border-color: #ccc; color: #666; }
.redux-info-field.redux-normal i { color: #c5c5c5; }
.redux-info-field.redux-warning { background-color: #fbeba4; border-color: #d7c281; color: #958234; }
.redux-info-field.redux-warning i { color: #dcca81; }
.redux-info-field.redux-success { background-color: #c4ee91; border-color: #71af5d; color: #4d7615; }
.redux-info-field.redux-success i { color: #a0ca6c; }
.redux-info-field.redux-critical { background-color: #fba1a3; border-color: #b84f5b; color: #981225; }
.redux-info-field.redux-critical i { color: #dd767d; }
.redux-info-field.redux-info { background-color: #d3e4f4; border-color: #a9b6c2; color: #5c80a1; }
.redux-info-field.redux-info i { color: #afc6da; }
.redux-notice-field { margin: 15px 0 0; background-color: #fff; border: 0; border-left: 4px solid #f3f3f3; -webkit-box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.1); box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.1); padding: 1px 12px; }
.redux-notice-field h1, .redux-notice-field h2, .redux-notice-field h3, .redux-notice-field h4, .redux-notice-field h5, .redux-notice-field h6 { border-bottom: 0 !important; }
.redux-notice-field p { margin: 0.5em 0; padding: 2px; }
.redux-notice-field .redux-info-icon { display: inline-block; margin-right: 15px; }
.redux-notice-field .redux-info-icon i { font-size: 2em; }
.redux-notice-field .redux-info-desc { display: inline-block; vertical-align: top; }
.redux-notice-field.redux-info { border-left: 4px solid #0099d5; }
.redux-notice-field.redux-success { border-left: 4px solid #7ad03a; }
.redux-notice-field.redux-warning { border-left: 4px solid #fbeba4; }
.redux-notice-field.redux-critical { border-left: 4px solid #dd3d36; }
.redux-main .redux-field-container.redux-container-info { padding: 0; }
.wp-customizer .hasIcon.redux-notice-field .redux-info-desc, .wp-customizer .hasIcon.redux-info-field .redux-info-desc { display: block; margin-left: 43px; }
.wp-customizer .hasIcon.redux-notice-field .redux-info-icon, .wp-customizer .hasIcon.redux-info-field .redux-info-icon { float: left; }
.wp-customizer .redux-main .customize-control.customize-control-redux-info { border-bottom: 0; }
/*# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVkdXgtaW5mby5jc3MiLCJzb3VyY2VzIjpbInJlZHV4LWluZm8uc2NzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxBQUFBLGlCQUFpQixDQUFDLEVBQ2QsVUFBVSxFQUFFLElBQUksRUFDaEIsT0FBTyxFQUFFLFFBQVEsRUFDakIsTUFBTSxFQUFFLE1BQU0sRUFDZCxNQUFNLEVBQUUsU0FBUyxFQUNqQixhQUFhLEVBQUUsR0FBRyxFQUNsQixRQUFRLEVBQUUsUUFBUSxHQThFckI7O0FBcEZELEFBUUksaUJBUmEsQ0FRYixFQUFFLEVBUk4saUJBQWlCLENBU2IsRUFBRSxFQVROLGlCQUFpQixDQVViLEVBQUUsRUFWTixpQkFBaUIsQ0FXYixFQUFFLEVBWE4saUJBQWlCLENBWWIsRUFBRSxFQVpOLGlCQUFpQixDQWFiLEVBQUUsQ0FBQyxFQUNDLGFBQWEsRUFBRSxZQUFZLEdBQzlCOztBQWZMLEFBaUJJLGlCQWpCYSxDQWlCYixFQUFFLENBQUMsRUFDQyxLQUFLLEVBQUUsSUFBSSxHQUNkOztBQW5CTCxBQXFCSSxpQkFyQmEsQ0FxQmIsZ0JBQWdCLENBQUMsRUFDYixPQUFPLEVBQUUsWUFBWSxFQUNyQixZQUFZLEVBQUUsSUFBSSxHQUtyQjs7QUE1QkwsQUF5QlEsaUJBekJTLENBcUJiLGdCQUFnQixDQUlaLENBQUMsQ0FBQyxFQUNFLFNBQVMsRUFBRSxHQUFHLEdBQ2pCOztBQTNCVCxBQThCSSxpQkE5QmEsQ0E4QmIsZ0JBQWdCLENBQUMsRUFDYixPQUFPLEVBQUUsWUFBWSxFQUNyQixjQUFjLEVBQUUsR0FBRyxHQUN0Qjs7QUFqQ0wsQUFtQ0ksaUJBbkNhLEFBbUNaLGFBQWEsQ0FBQyxFQUNYLGdCQUFnQixFQUFFLElBQUksRUFDdEIsWUFBWSxFQUFFLElBQUksRUFDbEIsS0FBSyxFQUFFLElBQUksR0FLZDs7QUEzQ0wsQUF3Q1EsaUJBeENTLEFBbUNaLGFBQWEsQ0FLVixDQUFDLENBQUMsRUFDRSxLQUFLLEVBQUUsT0FBTyxHQUNqQjs7QUExQ1Qs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 */
/*# sourceMappingURL=redux-info.css.map */

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,160 @@
.redux-info-field {
min-height: 20px;
padding: 8px 19px;
margin: 10px 0;
border: 1px solid;
border-radius: 4px;
position: relative;
h1,
h2,
h3,
h4,
h5,
h6 {
border-bottom: 0 !important;
}
h3 {
color: #777;
}
.redux-info-icon {
display: inline-block;
margin-right: 15px;
i {
font-size: 2em;
}
}
.redux-info-desc {
display: inline-block;
vertical-align: top;
}
&.redux-normal {
background-color: #eee;
border-color: #ccc;
color: #666;
i {
color: #c5c5c5;
}
}
&.redux-warning {
background-color: #fbeba4;
border-color: #d7c281;
color: #958234;
i {
color: #dcca81;
}
}
&.redux-success {
background-color: #c4ee91;
border-color: #71af5d;
color: #4d7615;
i {
color: #a0ca6c;
}
}
&.redux-critical {
background-color: #fba1a3;
border-color: #b84f5b;
color: #981225;
i {
color: #dd767d;
}
}
&.redux-info {
background-color: #d3e4f4;
border-color: #a9b6c2;
color: #5c80a1;
i {
color: #afc6da;
}
}
}
.redux-notice-field {
margin: 15px 0 0;
background-color: #fff;
border: 0;
border-left: 4px solid #f3f3f3;
-webkit-box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.1);
box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.1);
padding: 1px 12px;
h1,
h2,
h3,
h4,
h5,
h6 {
border-bottom: 0 !important;
}
p {
margin: 0.5em 0;
padding: 2px;
}
.redux-info-icon {
display: inline-block;
margin-right: 15px;
i {
font-size: 2em;
}
}
.redux-info-desc {
display: inline-block;
vertical-align: top;
}
&.redux-info {
border-left: 4px solid #0099d5;
}
&.redux-success {
border-left: 4px solid #7ad03a;
}
&.redux-warning {
border-left: 4px solid #fbeba4;
}
&.redux-critical {
border-left: 4px solid #dd3d36;
}
}
.redux-main .redux-field-container.redux-container-info {
padding: 0;
}
.wp-customizer {
.hasIcon.redux-notice-field,
.hasIcon.redux-info-field {
.redux-info-desc {
display: block;
margin-left: 43px;
}
.redux-info-icon {
float: left;
}
}
.redux-main .customize-control.customize-control-redux-info {
border-bottom: 0;
}
}