Add frontend features with search, shortcodes, widgets, and blocks (v0.6.0)
All checks were successful
Create Release Package / build-release (push) Successful in 1m20s
All checks were successful
Create Release Package / build-release (push) Successful in 1m20s
- Room search with availability, capacity, room type, amenity, price range, and building filters - AJAX-powered search with pagination and load more - Shortcodes: [bnb_buildings], [bnb_rooms], [bnb_room_search], [bnb_building], [bnb_room] - Widgets: Similar Rooms, Building Rooms, Availability Calendar - Gutenberg blocks: Building, Room, Room Search, Buildings List, Rooms List - Frontend CSS with responsive design and CSS custom properties - Frontend JavaScript with SearchForm, CalendarWidget, AvailabilityForm, PriceCalculator Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
261
src/Frontend/Widgets/BuildingRooms.php
Normal file
261
src/Frontend/Widgets/BuildingRooms.php
Normal file
@@ -0,0 +1,261 @@
|
||||
<?php
|
||||
/**
|
||||
* Building Rooms widget.
|
||||
*
|
||||
* Displays all rooms in a specific building.
|
||||
*
|
||||
* @package Magdev\WpBnb\Frontend\Widgets
|
||||
*/
|
||||
|
||||
declare( strict_types=1 );
|
||||
|
||||
namespace Magdev\WpBnb\Frontend\Widgets;
|
||||
|
||||
use Magdev\WpBnb\Frontend\Search;
|
||||
use Magdev\WpBnb\PostTypes\Building;
|
||||
use Magdev\WpBnb\PostTypes\Room;
|
||||
|
||||
/**
|
||||
* Building Rooms widget class.
|
||||
*/
|
||||
class BuildingRooms extends \WP_Widget {
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
parent::__construct(
|
||||
'wp_bnb_building_rooms',
|
||||
__( 'WP BnB: Building Rooms', 'wp-bnb' ),
|
||||
array(
|
||||
'classname' => 'wp-bnb-widget-building-rooms',
|
||||
'description' => __( 'Display all rooms in a building.', 'wp-bnb' ),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Output the widget content.
|
||||
*
|
||||
* @param array $args Widget arguments.
|
||||
* @param array $instance Widget instance settings.
|
||||
* @return void
|
||||
*/
|
||||
public function widget( $args, $instance ): void {
|
||||
$title = ! empty( $instance['title'] ) ? $instance['title'] : __( 'Rooms', 'wp-bnb' );
|
||||
$building_id = ! empty( $instance['building_id'] ) ? (int) $instance['building_id'] : 0;
|
||||
$count = ! empty( $instance['count'] ) ? (int) $instance['count'] : -1;
|
||||
$show_availability = ! empty( $instance['show_availability'] );
|
||||
$show_price = ! empty( $instance['show_price'] );
|
||||
$layout = ! empty( $instance['layout'] ) ? $instance['layout'] : 'list';
|
||||
|
||||
// Auto-detect building from single building page.
|
||||
if ( ! $building_id && is_singular( Building::POST_TYPE ) ) {
|
||||
$building_id = get_the_ID();
|
||||
}
|
||||
|
||||
if ( ! $building_id ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get rooms for building.
|
||||
$search_args = array(
|
||||
'building_id' => $building_id,
|
||||
'limit' => $count,
|
||||
'orderby' => 'title',
|
||||
'order' => 'ASC',
|
||||
);
|
||||
|
||||
$rooms = Search::search( $search_args );
|
||||
|
||||
if ( empty( $rooms ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
echo $args['before_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
|
||||
if ( $title ) {
|
||||
echo $args['before_title'] . esc_html( apply_filters( 'widget_title', $title ) ) . $args['after_title']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
}
|
||||
|
||||
$list_class = 'compact' === $layout ? 'wp-bnb-building-rooms-compact' : 'wp-bnb-building-rooms-list';
|
||||
echo '<ul class="' . esc_attr( $list_class ) . '">';
|
||||
|
||||
foreach ( $rooms as $room ) {
|
||||
$status = get_post_meta( $room['id'], '_bnb_room_status', true ) ?: 'available';
|
||||
?>
|
||||
<li class="wp-bnb-building-room">
|
||||
<a href="<?php echo esc_url( $room['permalink'] ); ?>" class="wp-bnb-building-room-link">
|
||||
<span class="wp-bnb-building-room-title"><?php echo esc_html( $room['title'] ); ?></span>
|
||||
|
||||
<?php if ( ! empty( $room['room_number'] ) ) : ?>
|
||||
<span class="wp-bnb-building-room-number">#<?php echo esc_html( $room['room_number'] ); ?></span>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ( $show_availability ) : ?>
|
||||
<span class="wp-bnb-building-room-status wp-bnb-status-<?php echo esc_attr( $status ); ?>">
|
||||
<?php
|
||||
$statuses = Room::get_room_statuses();
|
||||
echo esc_html( $statuses[ $status ] ?? $status );
|
||||
?>
|
||||
</span>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ( $show_price && ! empty( $room['price_formatted'] ) ) : ?>
|
||||
<span class="wp-bnb-building-room-price">
|
||||
<?php echo esc_html( $room['price_formatted'] ); ?>
|
||||
</span>
|
||||
<?php endif; ?>
|
||||
</a>
|
||||
|
||||
<?php if ( 'list' === $layout ) : ?>
|
||||
<div class="wp-bnb-building-room-meta">
|
||||
<?php if ( ! empty( $room['capacity'] ) ) : ?>
|
||||
<span class="wp-bnb-meta-item">
|
||||
<span class="dashicons dashicons-groups"></span>
|
||||
<?php echo esc_html( $room['capacity'] ); ?>
|
||||
</span>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ( ! empty( $room['room_types'] ) ) : ?>
|
||||
<span class="wp-bnb-meta-item">
|
||||
<?php echo esc_html( $room['room_types'][0] ); ?>
|
||||
</span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</li>
|
||||
<?php
|
||||
}
|
||||
|
||||
echo '</ul>';
|
||||
|
||||
// Show view all link if there are more rooms.
|
||||
$building = get_post( $building_id );
|
||||
if ( $building && $count > 0 && count( $rooms ) >= $count ) {
|
||||
$all_rooms = Room::get_rooms_for_building( $building_id );
|
||||
if ( count( $all_rooms ) > $count ) {
|
||||
printf(
|
||||
'<a href="%s" class="wp-bnb-view-all-rooms">%s</a>',
|
||||
esc_url( get_permalink( $building_id ) ),
|
||||
esc_html__( 'View all rooms', 'wp-bnb' )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
echo $args['after_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
}
|
||||
|
||||
/**
|
||||
* Output the widget settings form.
|
||||
*
|
||||
* @param array $instance Current widget instance settings.
|
||||
* @return void
|
||||
*/
|
||||
public function form( $instance ): void {
|
||||
$title = ! empty( $instance['title'] ) ? $instance['title'] : __( 'Rooms', 'wp-bnb' );
|
||||
$building_id = ! empty( $instance['building_id'] ) ? (int) $instance['building_id'] : 0;
|
||||
$count = ! empty( $instance['count'] ) ? (int) $instance['count'] : -1;
|
||||
$show_availability = ! empty( $instance['show_availability'] );
|
||||
$show_price = ! empty( $instance['show_price'] );
|
||||
$layout = ! empty( $instance['layout'] ) ? $instance['layout'] : 'list';
|
||||
|
||||
// Get all buildings.
|
||||
$buildings = get_posts(
|
||||
array(
|
||||
'post_type' => Building::POST_TYPE,
|
||||
'post_status' => 'publish',
|
||||
'posts_per_page' => -1,
|
||||
'orderby' => 'title',
|
||||
'order' => 'ASC',
|
||||
)
|
||||
);
|
||||
?>
|
||||
<p>
|
||||
<label for="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>">
|
||||
<?php esc_html_e( 'Title:', 'wp-bnb' ); ?>
|
||||
</label>
|
||||
<input class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>"
|
||||
name="<?php echo esc_attr( $this->get_field_name( 'title' ) ); ?>"
|
||||
type="text" value="<?php echo esc_attr( $title ); ?>">
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<label for="<?php echo esc_attr( $this->get_field_id( 'building_id' ) ); ?>">
|
||||
<?php esc_html_e( 'Building:', 'wp-bnb' ); ?>
|
||||
</label>
|
||||
<select class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'building_id' ) ); ?>"
|
||||
name="<?php echo esc_attr( $this->get_field_name( 'building_id' ) ); ?>">
|
||||
<option value="0"><?php esc_html_e( '— Auto-detect from page —', 'wp-bnb' ); ?></option>
|
||||
<?php foreach ( $buildings as $building ) : ?>
|
||||
<option value="<?php echo esc_attr( $building->ID ); ?>" <?php selected( $building_id, $building->ID ); ?>>
|
||||
<?php echo esc_html( $building->post_title ); ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<small><?php esc_html_e( 'Leave as auto-detect to show rooms of the current building page.', 'wp-bnb' ); ?></small>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<label for="<?php echo esc_attr( $this->get_field_id( 'count' ) ); ?>">
|
||||
<?php esc_html_e( 'Number of rooms:', 'wp-bnb' ); ?>
|
||||
</label>
|
||||
<input class="tiny-text" id="<?php echo esc_attr( $this->get_field_id( 'count' ) ); ?>"
|
||||
name="<?php echo esc_attr( $this->get_field_name( 'count' ) ); ?>"
|
||||
type="number" min="-1" max="50" value="<?php echo esc_attr( $count ); ?>">
|
||||
<small><?php esc_html_e( '-1 for all rooms', 'wp-bnb' ); ?></small>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<label for="<?php echo esc_attr( $this->get_field_id( 'layout' ) ); ?>">
|
||||
<?php esc_html_e( 'Layout:', 'wp-bnb' ); ?>
|
||||
</label>
|
||||
<select class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'layout' ) ); ?>"
|
||||
name="<?php echo esc_attr( $this->get_field_name( 'layout' ) ); ?>">
|
||||
<option value="list" <?php selected( $layout, 'list' ); ?>>
|
||||
<?php esc_html_e( 'List (with details)', 'wp-bnb' ); ?>
|
||||
</option>
|
||||
<option value="compact" <?php selected( $layout, 'compact' ); ?>>
|
||||
<?php esc_html_e( 'Compact', 'wp-bnb' ); ?>
|
||||
</option>
|
||||
</select>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<input class="checkbox" type="checkbox" id="<?php echo esc_attr( $this->get_field_id( 'show_availability' ) ); ?>"
|
||||
name="<?php echo esc_attr( $this->get_field_name( 'show_availability' ) ); ?>"
|
||||
<?php checked( $show_availability ); ?>>
|
||||
<label for="<?php echo esc_attr( $this->get_field_id( 'show_availability' ) ); ?>">
|
||||
<?php esc_html_e( 'Show availability status', 'wp-bnb' ); ?>
|
||||
</label>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<input class="checkbox" type="checkbox" id="<?php echo esc_attr( $this->get_field_id( 'show_price' ) ); ?>"
|
||||
name="<?php echo esc_attr( $this->get_field_name( 'show_price' ) ); ?>"
|
||||
<?php checked( $show_price ); ?>>
|
||||
<label for="<?php echo esc_attr( $this->get_field_id( 'show_price' ) ); ?>">
|
||||
<?php esc_html_e( 'Show price', 'wp-bnb' ); ?>
|
||||
</label>
|
||||
</p>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Update widget settings.
|
||||
*
|
||||
* @param array $new_instance New settings.
|
||||
* @param array $old_instance Old settings.
|
||||
* @return array Updated settings.
|
||||
*/
|
||||
public function update( $new_instance, $old_instance ): array {
|
||||
$instance = array();
|
||||
$instance['title'] = ! empty( $new_instance['title'] ) ? sanitize_text_field( $new_instance['title'] ) : '';
|
||||
$instance['building_id'] = ! empty( $new_instance['building_id'] ) ? absint( $new_instance['building_id'] ) : 0;
|
||||
$instance['count'] = isset( $new_instance['count'] ) ? (int) $new_instance['count'] : -1;
|
||||
$instance['show_availability'] = ! empty( $new_instance['show_availability'] );
|
||||
$instance['show_price'] = ! empty( $new_instance['show_price'] );
|
||||
$instance['layout'] = ! empty( $new_instance['layout'] ) ? sanitize_text_field( $new_instance['layout'] ) : 'list';
|
||||
return $instance;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user