Add booking system with calendar and email notifications (v0.3.0)
All checks were successful
Create Release Package / build-release (push) Successful in 1m5s

- Booking Custom Post Type with full management features
- Room and guest relationship tracking
- Check-in/check-out date management with validation
- Booking status workflow (pending, confirmed, checked_in, checked_out, cancelled)
- Automatic price calculation using existing Calculator
- Availability system with real-time conflict detection
- AJAX endpoint for instant availability validation
- Calendar admin page with monthly view and room/building filters
- Color-coded booking status display with legend
- Email notifications for new bookings, confirmations, and cancellations
- HTML email templates with placeholder-based system
- Auto-generated booking references (BNB-YYYY-NNNNN)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-31 14:37:48 +01:00
parent dabfe1e826
commit 0c601df568
11 changed files with 3419 additions and 28 deletions

View File

@@ -9,8 +9,12 @@ declare( strict_types=1 );
namespace Magdev\WpBnb;
use Magdev\WpBnb\Admin\Calendar as CalendarAdmin;
use Magdev\WpBnb\Admin\Seasons as SeasonsAdmin;
use Magdev\WpBnb\Booking\Availability;
use Magdev\WpBnb\Booking\EmailNotifier;
use Magdev\WpBnb\License\Manager as LicenseManager;
use Magdev\WpBnb\PostTypes\Booking;
use Magdev\WpBnb\PostTypes\Building;
use Magdev\WpBnb\PostTypes\Room;
use Magdev\WpBnb\Pricing\Season;
@@ -87,6 +91,7 @@ final class Plugin {
private function register_post_types(): void {
Building::init();
Room::init();
Booking::init();
}
/**
@@ -132,6 +137,15 @@ final class Plugin {
// Initialize seasons admin page.
SeasonsAdmin::init();
// Initialize calendar admin page.
CalendarAdmin::init();
// Initialize email notifier.
EmailNotifier::init();
// Register AJAX handlers.
add_action( 'wp_ajax_wp_bnb_check_availability', array( $this, 'ajax_check_availability' ) );
}
/**
@@ -167,7 +181,7 @@ final class Plugin {
// Check if we're on plugin pages or editing our custom post types.
$is_plugin_page = strpos( $hook_suffix, 'wp-bnb' ) !== false;
$is_our_post_type = in_array( $post_type, array( Building::POST_TYPE, Room::POST_TYPE ), true );
$is_our_post_type = in_array( $post_type, array( Building::POST_TYPE, Room::POST_TYPE, Booking::POST_TYPE ), true );
$is_edit_screen = in_array( $hook_suffix, array( 'post.php', 'post-new.php' ), true );
if ( ! $is_plugin_page && ! ( $is_our_post_type && $is_edit_screen ) ) {
@@ -205,15 +219,22 @@ final class Plugin {
'nonce' => wp_create_nonce( 'wp_bnb_admin_nonce' ),
'postType' => $post_type,
'i18n' => array(
'validating' => __( 'Validating...', 'wp-bnb' ),
'activating' => __( 'Activating...', 'wp-bnb' ),
'error' => __( 'An error occurred. Please try again.', 'wp-bnb' ),
'selectImages' => __( 'Select Images', 'wp-bnb' ),
'addToGallery' => __( 'Add to Gallery', 'wp-bnb' ),
'confirmRemove' => __( 'Are you sure you want to remove this image?', 'wp-bnb' ),
'increase' => __( 'increase', 'wp-bnb' ),
'discount' => __( 'discount', 'wp-bnb' ),
'normalPrice' => __( 'Normal price', 'wp-bnb' ),
'validating' => __( 'Validating...', 'wp-bnb' ),
'activating' => __( 'Activating...', 'wp-bnb' ),
'error' => __( 'An error occurred. Please try again.', 'wp-bnb' ),
'selectImages' => __( 'Select Images', 'wp-bnb' ),
'addToGallery' => __( 'Add to Gallery', 'wp-bnb' ),
'confirmRemove' => __( 'Are you sure you want to remove this image?', 'wp-bnb' ),
'increase' => __( 'increase', 'wp-bnb' ),
'discount' => __( 'discount', 'wp-bnb' ),
'normalPrice' => __( 'Normal price', 'wp-bnb' ),
'checking' => __( 'Checking availability...', 'wp-bnb' ),
'available' => __( 'Available', 'wp-bnb' ),
'notAvailable' => __( 'Not available - conflicts with existing booking', 'wp-bnb' ),
'selectRoomAndDates' => __( 'Select room and dates to check availability', 'wp-bnb' ),
'nights' => __( 'nights', 'wp-bnb' ),
'night' => __( 'night', 'wp-bnb' ),
'calculating' => __( 'Calculating price...', 'wp-bnb' ),
),
)
);
@@ -817,6 +838,43 @@ final class Plugin {
settings_errors( 'wp_bnb_settings' );
}
/**
* AJAX handler for checking room availability.
*
* @return void
*/
public function ajax_check_availability(): void {
check_ajax_referer( 'wp_bnb_admin_nonce', 'nonce' );
if ( ! current_user_can( 'edit_posts' ) ) {
wp_send_json_error(
array( 'message' => __( 'You do not have permission to perform this action.', 'wp-bnb' ) )
);
}
$room_id = isset( $_POST['room_id'] ) ? absint( $_POST['room_id'] ) : 0;
$check_in = isset( $_POST['check_in'] ) ? sanitize_text_field( wp_unslash( $_POST['check_in'] ) ) : '';
$check_out = isset( $_POST['check_out'] ) ? sanitize_text_field( wp_unslash( $_POST['check_out'] ) ) : '';
$exclude = isset( $_POST['exclude_booking'] ) ? absint( $_POST['exclude_booking'] ) : null;
if ( ! $room_id || ! $check_in || ! $check_out ) {
wp_send_json_error(
array( 'message' => __( 'Missing required parameters.', 'wp-bnb' ) )
);
}
// Validate dates.
if ( strtotime( $check_out ) <= strtotime( $check_in ) ) {
wp_send_json_error(
array( 'message' => __( 'Check-out date must be after check-in date.', 'wp-bnb' ) )
);
}
$result = Availability::check_availability_with_price( $room_id, $check_in, $check_out, $exclude );
wp_send_json_success( $result );
}
/**
* Get Twig environment.
*