$actions Buttons. * @param array $badges Small pills next to the title. */ public static function page_header( string $title, string $tagline = '', array $actions = [], array $badges = [] ): void { echo '
'; echo '

' . esc_html( $title ); if ( $badges ) { echo ''; foreach ( $badges as $badge ) { echo ''; if ( ! empty( $badge['icon'] ) ) { echo ''; } echo esc_html( $badge['label'] ) . ''; } echo ''; } if ( $actions ) { echo ''; foreach ( $actions as $action ) { printf( '%3$s', esc_attr( ! empty( $action['primary'] ) ? 'button button-primary' : 'button button-secondary' ), esc_url( $action['url'] ), esc_html( $action['label'] ) ); } echo ''; } echo '

'; if ( '' !== $tagline ) { echo '

' . esc_html( $tagline ) . '

'; } echo '
'; } /** * Row of stat cards (real numbers only — callers pass what they queried). * * @param array $stats Stat cards. */ public static function stat_cards( array $stats ): void { if ( ! $stats ) { return; } echo '
'; foreach ( $stats as $stat ) { $tone = in_array( $stat['tone'] ?? '', [ 'green', 'amber', 'red', 'blue' ], true ) ? '-' . $stat['tone'] : ''; echo '
'; echo '' . esc_html( $stat['label'] ) . ''; echo '' . esc_html( $stat['value'] ) . ''; if ( ! empty( $stat['hint'] ) ) { echo '' . esc_html( $stat['hint'] ) . ''; } echo '
'; } echo '
'; } public static function enqueue( string $hook ): void { if ( strpos( (string) $hook, 'bookingistic' ) === false ) { return; } wp_enqueue_style( 'bookingistic-admin', BOOKINGISTIC_URL . 'assets/admin/css/admin.css', [], BOOKINGISTIC_VERSION ); wp_enqueue_script( 'bookingistic-admin', BOOKINGISTIC_URL . 'assets/admin/js/admin.js', [], BOOKINGISTIC_VERSION, true ); wp_localize_script( 'bookingistic-admin', 'BookingisticAdmin', [ 'restUrl' => esc_url_raw( rest_url( BOOKINGISTIC_REST_NAMESPACE . '/' ) ), 'nonce' => wp_create_nonce( 'wp_rest' ), 'bookingsUrl' => admin_url( 'admin.php?page=bookingistic-bookings' ), 'customersUrl' => admin_url( 'admin.php?page=bookingistic-customers' ), 'i18n' => [ 'loading' => __( 'Loading…', 'bookingistic' ), 'noEvents' => __( 'No bookings in this range.', 'bookingistic' ), 'errorGeneric' => __( 'Could not load bookings.', 'bookingistic' ), 'dows' => [ __( 'Mon', 'bookingistic' ), __( 'Tue', 'bookingistic' ), __( 'Wed', 'bookingistic' ), __( 'Thu', 'bookingistic' ), __( 'Fri', 'bookingistic' ), __( 'Sat', 'bookingistic' ), __( 'Sun', 'bookingistic' ), ], ], ] ); } }