Implement Phase 8: Dashboard & Reports (v0.8.0)
Some checks failed
Create Release Package / build-release (push) Has been cancelled

- Add comprehensive admin dashboard with stat cards and widgets
- Add Chart.js for occupancy/revenue trend charts
- Add Reports page with Occupancy, Revenue, Guest tabs
- Add CSV and PDF export functionality (using mPDF)
- Add date range filters for reports

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-02-03 20:20:27 +01:00
parent 992d961066
commit b137fec4fb
11 changed files with 3739 additions and 87 deletions

View File

@@ -10,6 +10,8 @@ declare( strict_types=1 );
namespace Magdev\WpBnb;
use Magdev\WpBnb\Admin\Calendar as CalendarAdmin;
use Magdev\WpBnb\Admin\Dashboard as DashboardAdmin;
use Magdev\WpBnb\Admin\Reports as ReportsAdmin;
use Magdev\WpBnb\Admin\Seasons as SeasonsAdmin;
use Magdev\WpBnb\Blocks\BlockRegistrar;
use Magdev\WpBnb\Booking\Availability;
@@ -248,6 +250,7 @@ final class Plugin {
$is_plugin_page = strpos( $hook_suffix, 'wp-bnb' ) !== false;
$is_our_post_type = in_array( $post_type, array( Building::POST_TYPE, Room::POST_TYPE, Booking::POST_TYPE, Guest::POST_TYPE, Service::POST_TYPE ), true );
$is_edit_screen = in_array( $hook_suffix, array( 'post.php', 'post-new.php' ), true );
$is_dashboard = 'toplevel_page_wp-bnb' === $hook_suffix;
if ( ! $is_plugin_page && ! ( $is_our_post_type && $is_edit_screen ) ) {
return;
@@ -268,6 +271,18 @@ final class Plugin {
$script_deps[] = 'jquery-ui-sortable';
}
// Add Chart.js for dashboard.
if ( $is_dashboard ) {
wp_enqueue_script(
'chartjs',
'https://cdn.jsdelivr.net/npm/chart.js@4.4.1/dist/chart.umd.min.js',
array(),
'4.4.1',
true
);
$script_deps[] = 'chartjs';
}
wp_enqueue_script(
'wp-bnb-admin',
WP_BNB_URL . 'assets/js/admin.js',
@@ -276,43 +291,53 @@ final class Plugin {
true
);
wp_localize_script(
'wp-bnb-admin',
'wpBnbAdmin',
array(
'ajaxUrl' => admin_url( 'admin-ajax.php' ),
'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' ),
'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' ),
'searchingGuests' => __( 'Searching...', 'wp-bnb' ),
'noGuestsFound' => __( 'No guests found', 'wp-bnb' ),
'selectGuest' => __( 'Select', 'wp-bnb' ),
'guestBlocked' => __( 'Blocked', 'wp-bnb' ),
'perNightDescription' => __( 'This price will be charged per night of the stay.', 'wp-bnb' ),
'perBookingDescription' => __( 'This price will be charged once for the booking.', 'wp-bnb' ),
'justNow' => __( 'Just now', 'wp-bnb' ),
'updateAvailable' => __( 'Update available!', 'wp-bnb' ),
'upToDate' => __( '(You are up to date)', 'wp-bnb' ),
'checkingUpdates' => __( 'Checking for updates...', 'wp-bnb' ),
),
)
// Build localize data.
$localize_data = array(
'ajaxUrl' => admin_url( 'admin-ajax.php' ),
'nonce' => wp_create_nonce( 'wp_bnb_admin_nonce' ),
'postType' => $post_type,
'isDashboard' => $is_dashboard,
'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' ),
'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' ),
'searchingGuests' => __( 'Searching...', 'wp-bnb' ),
'noGuestsFound' => __( 'No guests found', 'wp-bnb' ),
'selectGuest' => __( 'Select', 'wp-bnb' ),
'guestBlocked' => __( 'Blocked', 'wp-bnb' ),
'perNightDescription' => __( 'This price will be charged per night of the stay.', 'wp-bnb' ),
'perBookingDescription' => __( 'This price will be charged once for the booking.', 'wp-bnb' ),
'justNow' => __( 'Just now', 'wp-bnb' ),
'updateAvailable' => __( 'Update available!', 'wp-bnb' ),
'upToDate' => __( '(You are up to date)', 'wp-bnb' ),
'checkingUpdates' => __( 'Checking for updates...', 'wp-bnb' ),
'occupancy' => __( 'Occupancy %', 'wp-bnb' ),
'revenue' => __( 'Revenue', 'wp-bnb' ),
),
);
// Add chart data for dashboard.
if ( $is_dashboard ) {
$localize_data['chartData'] = array(
'occupancy' => DashboardAdmin::get_occupancy_trend_data( 30 ),
'revenue' => DashboardAdmin::get_revenue_trend_data( 6 ),
);
}
wp_localize_script( 'wp-bnb-admin', 'wpBnbAdmin', $localize_data );
}
/**
@@ -448,6 +473,16 @@ final class Plugin {
array( $this, 'render_dashboard_page' )
);
// Reports submenu.
add_submenu_page(
'wp-bnb',
__( 'Reports', 'wp-bnb' ),
__( 'Reports', 'wp-bnb' ),
'manage_options',
'wp-bnb-reports',
array( $this, 'render_reports_page' )
);
// Settings submenu.
add_submenu_page(
'wp-bnb',
@@ -476,15 +511,16 @@ final class Plugin {
// Define the desired order of menu slugs.
$desired_order = array(
'wp-bnb', // Dashboard.
'wp-bnb', // Dashboard.
'edit.php?post_type=bnb_building', // Buildings.
'edit.php?post_type=bnb_room', // Rooms.
'edit.php?post_type=bnb_booking', // Bookings.
'edit.php?post_type=bnb_guest', // Guests.
'edit.php?post_type=bnb_service', // Services.
'wp-bnb-calendar', // Calendar.
'wp-bnb-seasons', // Seasons.
'wp-bnb-settings', // Settings (always last).
'wp-bnb-calendar', // Calendar.
'wp-bnb-reports', // Reports.
'wp-bnb-seasons', // Seasons.
'wp-bnb-settings', // Settings (always last).
);
$current_menu = $submenu['wp-bnb'];
@@ -528,39 +564,16 @@ final class Plugin {
* @return void
*/
public function render_dashboard_page(): void {
$license_valid = LicenseManager::is_license_valid();
$is_localhost = LicenseManager::is_localhost();
?>
<div class="wrap">
<h1><?php esc_html_e( 'WP BnB Dashboard', 'wp-bnb' ); ?></h1>
DashboardAdmin::render();
}
<?php if ( $is_localhost ) : ?>
<div class="notice notice-info">
<p>
<span class="dashicons dashicons-info" style="color: #72aee6;"></span>
<strong><?php esc_html_e( 'Development Mode', 'wp-bnb' ); ?></strong>
<?php esc_html_e( 'You are running on a local development environment. All features are enabled.', 'wp-bnb' ); ?>
</p>
</div>
<?php elseif ( ! $license_valid ) : ?>
<div class="notice notice-warning">
<p>
<?php
printf(
/* translators: %s: Link to settings page */
esc_html__( 'Your license is not active. Please %s to unlock all features.', 'wp-bnb' ),
'<a href="' . esc_url( admin_url( 'admin.php?page=wp-bnb-settings&tab=license' ) ) . '">' . esc_html__( 'activate your license', 'wp-bnb' ) . '</a>'
);
?>
</p>
</div>
<?php endif; ?>
<div class="wp-bnb-dashboard">
<p><?php esc_html_e( 'Welcome to WP BnB Management. Use the menu on the left to manage your buildings, rooms, bookings, and guests.', 'wp-bnb' ); ?></p>
</div>
</div>
<?php
/**
* Render reports page.
*
* @return void
*/
public function render_reports_page(): void {
ReportsAdmin::render();
}
/**