753 lines
39 KiB
PHP
753 lines
39 KiB
PHP
<?php
|
||
if ( ! defined( 'ABSPATH' ) ) {
|
||
exit;
|
||
}
|
||
|
||
class Carei_Admin_Panel {
|
||
|
||
const POST_TYPE = 'carei_reservation';
|
||
const META_PREFIX = '_carei_';
|
||
|
||
const PROTECTION_OPTION = 'carei_protection_packages';
|
||
const EXTRAS_SEEN_OPTION = 'carei_extras_seen';
|
||
const EXTRAS_TRANSLATIONS_OPTION = 'carei_extras_translations';
|
||
|
||
private static $statuses = array(
|
||
'nowe' => array( 'color' => '#2F2482' ),
|
||
'przeczytane' => array( 'color' => '#f59e0b' ),
|
||
'zrealizowane' => array( 'color' => '#22c55e' ),
|
||
);
|
||
|
||
private static function get_status_label( $key ) {
|
||
switch ( $key ) {
|
||
case 'nowe':
|
||
return __( 'Nowe', 'carei-reservation' );
|
||
case 'przeczytane':
|
||
return __( 'Przeczytane', 'carei-reservation' );
|
||
case 'zrealizowane':
|
||
return __( 'Zrealizowane', 'carei-reservation' );
|
||
}
|
||
return $key;
|
||
}
|
||
|
||
public function __construct() {
|
||
add_action( 'init', array( $this, 'register_post_type' ) );
|
||
add_filter( 'manage_' . self::POST_TYPE . '_posts_columns', array( $this, 'admin_columns' ) );
|
||
add_action( 'manage_' . self::POST_TYPE . '_posts_custom_column', array( $this, 'render_column' ), 10, 2 );
|
||
add_action( 'restrict_manage_posts', array( $this, 'status_filter_dropdown' ) );
|
||
add_action( 'pre_get_posts', array( $this, 'filter_by_status' ) );
|
||
add_action( 'add_meta_boxes', array( $this, 'add_meta_boxes' ) );
|
||
add_action( 'save_post_' . self::POST_TYPE, array( $this, 'save_meta_box' ), 10, 2 );
|
||
add_action( 'edit_form_after_title', array( $this, 'auto_mark_read' ) );
|
||
add_action( 'admin_head', array( $this, 'admin_styles' ) );
|
||
add_action( 'admin_menu', array( $this, 'register_protection_packages_page' ) );
|
||
add_action( 'admin_post_carei_save_protection_packages', array( $this, 'handle_protection_packages_save' ) );
|
||
add_action( 'admin_menu', array( $this, 'register_extras_translations_page' ) );
|
||
add_action( 'admin_post_carei_save_extras_translations', array( $this, 'handle_extras_translations_save' ) );
|
||
}
|
||
|
||
// ─── Extras Translations (dynamic Softra pricelist item names) ────
|
||
|
||
public static function get_extras_seen() {
|
||
$seen = get_option( self::EXTRAS_SEEN_OPTION, array() );
|
||
if ( ! is_array( $seen ) ) return array();
|
||
$seen = array_values( array_unique( array_filter( array_map( 'strval', $seen ), 'strlen' ) ) );
|
||
sort( $seen, SORT_NATURAL | SORT_FLAG_CASE );
|
||
return $seen;
|
||
}
|
||
|
||
public static function get_extras_translations() {
|
||
$map = get_option( self::EXTRAS_TRANSLATIONS_OPTION, array() );
|
||
return is_array( $map ) ? $map : array();
|
||
}
|
||
|
||
public static function remember_extra_name( $pl_name ) {
|
||
$pl_name = trim( (string) $pl_name );
|
||
if ( $pl_name === '' ) return;
|
||
$seen = get_option( self::EXTRAS_SEEN_OPTION, array() );
|
||
if ( ! is_array( $seen ) ) $seen = array();
|
||
if ( ! in_array( $pl_name, $seen, true ) ) {
|
||
$seen[] = $pl_name;
|
||
update_option( self::EXTRAS_SEEN_OPTION, $seen, false );
|
||
}
|
||
}
|
||
|
||
public static function translate_extra_name( $pl_name, $locale = null ) {
|
||
if ( $locale === null ) {
|
||
$wp_locale = function_exists( 'determine_locale' ) ? determine_locale() : get_locale();
|
||
$locale = ( 0 === strpos( (string) $wp_locale, 'en' ) ) ? 'en' : 'pl';
|
||
}
|
||
if ( $locale !== 'en' ) return $pl_name;
|
||
$map = self::get_extras_translations();
|
||
if ( isset( $map[ $pl_name ] ) && $map[ $pl_name ] !== '' ) {
|
||
return $map[ $pl_name ];
|
||
}
|
||
return $pl_name;
|
||
}
|
||
|
||
public function register_extras_translations_page() {
|
||
add_submenu_page(
|
||
'edit.php?post_type=' . self::POST_TYPE,
|
||
__( 'Tłumaczenia extras', 'carei-reservation' ),
|
||
__( 'Tłumaczenia extras', 'carei-reservation' ),
|
||
'manage_options',
|
||
'carei-extras-translations',
|
||
array( $this, 'render_extras_translations_page' )
|
||
);
|
||
}
|
||
|
||
public function render_extras_translations_page() {
|
||
if ( ! current_user_can( 'manage_options' ) ) {
|
||
wp_die( esc_html__( 'Brak uprawnień.', 'carei-reservation' ) );
|
||
}
|
||
$seen = self::get_extras_seen();
|
||
$trans = self::get_extras_translations();
|
||
$saved = isset( $_GET['carei_saved'] ) && $_GET['carei_saved'] === '1';
|
||
?>
|
||
<div class="wrap">
|
||
<h1><?php esc_html_e( 'Tłumaczenia extras', 'carei-reservation' ); ?></h1>
|
||
<p><?php esc_html_e( 'Tłumaczenia nazw dodatkowych opcji (extras) zwracanych z API Softra. Puste pole = wersja polska jest używana także w wersji angielskiej (fallback).', 'carei-reservation' ); ?></p>
|
||
<?php if ( $saved ) : ?>
|
||
<div class="notice notice-success is-dismissible"><p><?php esc_html_e( 'Zapisano.', 'carei-reservation' ); ?></p></div>
|
||
<?php endif; ?>
|
||
<?php if ( empty( $seen ) ) : ?>
|
||
<div class="notice notice-info"><p><?php esc_html_e( 'Brak zebranych pozycji. Otwórz formularz rezerwacji i wybierz daty/oddział/klasę aby załadować pricelist — pozycje pojawią się tutaj automatycznie.', 'carei-reservation' ); ?></p></div>
|
||
<?php else : ?>
|
||
<form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" class="carei-extras-form">
|
||
<input type="hidden" name="action" value="carei_save_extras_translations">
|
||
<?php wp_nonce_field( 'carei_extras_translations', 'carei_extras_nonce' ); ?>
|
||
<table class="form-table striped">
|
||
<thead>
|
||
<tr>
|
||
<th style="width: 40%;"><?php esc_html_e( 'Nazwa PL (z API Softra)', 'carei-reservation' ); ?></th>
|
||
<th><?php esc_html_e( 'Tłumaczenie EN', 'carei-reservation' ); ?></th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<?php foreach ( $seen as $pl_name ) :
|
||
$en = isset( $trans[ $pl_name ] ) ? (string) $trans[ $pl_name ] : '';
|
||
?>
|
||
<tr>
|
||
<td><strong><?php echo esc_html( $pl_name ); ?></strong></td>
|
||
<td>
|
||
<input type="text" name="translations[<?php echo esc_attr( $pl_name ); ?>]" value="<?php echo esc_attr( $en ); ?>" class="regular-text" placeholder="<?php echo esc_attr__( 'EN translation...', 'carei-reservation' ); ?>">
|
||
</td>
|
||
</tr>
|
||
<?php endforeach; ?>
|
||
</tbody>
|
||
</table>
|
||
<?php submit_button( __( 'Zapisz tłumaczenia', 'carei-reservation' ) ); ?>
|
||
</form>
|
||
<?php endif; ?>
|
||
</div>
|
||
<?php
|
||
}
|
||
|
||
public function handle_extras_translations_save() {
|
||
if ( ! current_user_can( 'manage_options' ) ) {
|
||
wp_die( esc_html__( 'Brak uprawnień.', 'carei-reservation' ) );
|
||
}
|
||
if ( ! isset( $_POST['carei_extras_nonce'] ) || ! wp_verify_nonce( $_POST['carei_extras_nonce'], 'carei_extras_translations' ) ) {
|
||
wp_die( esc_html__( 'Nieprawidłowy token.', 'carei-reservation' ) );
|
||
}
|
||
|
||
$input = isset( $_POST['translations'] ) && is_array( $_POST['translations'] ) ? $_POST['translations'] : array();
|
||
$clean = array();
|
||
foreach ( $input as $pl_name => $en_value ) {
|
||
$pl = trim( (string) wp_unslash( $pl_name ) );
|
||
$en = sanitize_text_field( wp_unslash( (string) $en_value ) );
|
||
if ( $pl === '' ) continue;
|
||
$clean[ $pl ] = $en;
|
||
}
|
||
update_option( self::EXTRAS_TRANSLATIONS_OPTION, $clean, false );
|
||
|
||
$redirect = add_query_arg(
|
||
array(
|
||
'post_type' => self::POST_TYPE,
|
||
'page' => 'carei-extras-translations',
|
||
'carei_saved' => '1',
|
||
),
|
||
admin_url( 'edit.php' )
|
||
);
|
||
wp_safe_redirect( $redirect );
|
||
exit;
|
||
}
|
||
|
||
// ─── Protection Packages (SOFT / PREMIUM) ────────────────────
|
||
|
||
public static function get_protection_packages_defaults() {
|
||
return array(
|
||
'soft' => array(
|
||
'name' => __( 'Ubezpieczenie SOFT', 'carei-reservation' ),
|
||
'name_en' => 'SOFT Protection',
|
||
'pricePerDay' => 0,
|
||
'active' => true,
|
||
'description' => '',
|
||
'description_en' => '',
|
||
),
|
||
'premium' => array(
|
||
'name' => __( 'Ubezpieczenie PREMIUM', 'carei-reservation' ),
|
||
'name_en' => 'PREMIUM Protection',
|
||
'pricePerDay' => 0,
|
||
'active' => true,
|
||
'description' => '',
|
||
'description_en' => '',
|
||
),
|
||
);
|
||
}
|
||
|
||
public static function get_protection_packages() {
|
||
$defaults = self::get_protection_packages_defaults();
|
||
$stored = get_option( self::PROTECTION_OPTION, array() );
|
||
if ( ! is_array( $stored ) ) {
|
||
$stored = array();
|
||
}
|
||
$out = array();
|
||
foreach ( $defaults as $key => $def ) {
|
||
$item = isset( $stored[ $key ] ) && is_array( $stored[ $key ] ) ? $stored[ $key ] : array();
|
||
$out[ $key ] = array(
|
||
'name' => isset( $item['name'] ) && $item['name'] !== '' ? (string) $item['name'] : $def['name'],
|
||
'name_en' => isset( $item['name_en'] ) ? (string) $item['name_en'] : '',
|
||
'pricePerDay' => isset( $item['pricePerDay'] ) ? (float) $item['pricePerDay'] : (float) $def['pricePerDay'],
|
||
'active' => isset( $item['active'] ) ? (bool) $item['active'] : (bool) $def['active'],
|
||
'description' => isset( $item['description'] ) ? (string) $item['description'] : $def['description'],
|
||
'description_en' => isset( $item['description_en'] ) ? (string) $item['description_en'] : '',
|
||
);
|
||
}
|
||
return $out;
|
||
}
|
||
|
||
public function register_protection_packages_page() {
|
||
add_submenu_page(
|
||
'edit.php?post_type=' . self::POST_TYPE,
|
||
__( 'Pakiety ochronne', 'carei-reservation' ),
|
||
__( 'Pakiety ochronne', 'carei-reservation' ),
|
||
'manage_options',
|
||
'carei-protection-packages',
|
||
array( $this, 'render_protection_packages_page' )
|
||
);
|
||
}
|
||
|
||
public function render_protection_packages_page() {
|
||
if ( ! current_user_can( 'manage_options' ) ) {
|
||
wp_die( esc_html__( 'Brak uprawnień.', 'carei-reservation' ) );
|
||
}
|
||
$data = self::get_protection_packages();
|
||
$saved = isset( $_GET['carei_saved'] ) && $_GET['carei_saved'] === '1';
|
||
?>
|
||
<div class="wrap">
|
||
<h1><?php esc_html_e( 'Pakiety ochronne', 'carei-reservation' ); ?></h1>
|
||
<p><?php echo wp_kses( __( 'Konfiguracja pakietów wyświetlanych w sekcji <strong>Pakiety ochronne</strong> formularza rezerwacji. Cena podawana jest za dobę — total = cena × liczba dób rezerwacji.', 'carei-reservation' ), array( 'strong' => array() ) ); ?></p>
|
||
<?php if ( $saved ) : ?>
|
||
<div class="notice notice-success is-dismissible"><p><?php esc_html_e( 'Zapisano.', 'carei-reservation' ); ?></p></div>
|
||
<?php endif; ?>
|
||
<form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" class="carei-protection-form">
|
||
<input type="hidden" name="action" value="carei_save_protection_packages">
|
||
<?php wp_nonce_field( 'carei_protection_packages', 'carei_protection_nonce' ); ?>
|
||
|
||
<?php foreach ( array( 'soft' => 'SOFT', 'premium' => 'PREMIUM' ) as $key => $label ) :
|
||
$pkg = $data[ $key ];
|
||
?>
|
||
<div class="carei-protection-card">
|
||
<h2><?php echo esc_html( sprintf( __( 'Pakiet %s', 'carei-reservation' ), $label ) ); ?></h2>
|
||
<table class="form-table">
|
||
<tr>
|
||
<th><label for="carei_<?php echo esc_attr( $key ); ?>_name"><?php esc_html_e( 'Nazwa wyświetlana (PL)', 'carei-reservation' ); ?></label></th>
|
||
<td><input type="text" id="carei_<?php echo esc_attr( $key ); ?>_name" name="packages[<?php echo esc_attr( $key ); ?>][name]" value="<?php echo esc_attr( $pkg['name'] ); ?>" class="regular-text" required></td>
|
||
</tr>
|
||
<tr>
|
||
<th><label for="carei_<?php echo esc_attr( $key ); ?>_name_en"><?php esc_html_e( 'Nazwa wyświetlana (EN)', 'carei-reservation' ); ?></label></th>
|
||
<td>
|
||
<input type="text" id="carei_<?php echo esc_attr( $key ); ?>_name_en" name="packages[<?php echo esc_attr( $key ); ?>][name_en]" value="<?php echo esc_attr( $pkg['name_en'] ); ?>" class="regular-text" placeholder="<?php echo esc_attr__( 'Np. SOFT Protection', 'carei-reservation' ); ?>">
|
||
<p class="description"><?php esc_html_e( 'Puste = fallback do wersji polskiej.', 'carei-reservation' ); ?></p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<th><label for="carei_<?php echo esc_attr( $key ); ?>_price"><?php esc_html_e( 'Cena za dobę (zł)', 'carei-reservation' ); ?></label></th>
|
||
<td><input type="number" id="carei_<?php echo esc_attr( $key ); ?>_price" name="packages[<?php echo esc_attr( $key ); ?>][pricePerDay]" value="<?php echo esc_attr( $pkg['pricePerDay'] ); ?>" min="0" step="0.01" class="small-text" required></td>
|
||
</tr>
|
||
<tr>
|
||
<th><?php esc_html_e( 'Status', 'carei-reservation' ); ?></th>
|
||
<td><label><input type="checkbox" name="packages[<?php echo esc_attr( $key ); ?>][active]" value="1" <?php checked( $pkg['active'] ); ?>> <?php esc_html_e( 'Aktywny (widoczny w modalu)', 'carei-reservation' ); ?></label></td>
|
||
</tr>
|
||
<tr>
|
||
<th><label for="carei_<?php echo esc_attr( $key ); ?>_desc"><?php esc_html_e( 'Opis / zakres usług (PL)', 'carei-reservation' ); ?></label></th>
|
||
<td><textarea id="carei_<?php echo esc_attr( $key ); ?>_desc" name="packages[<?php echo esc_attr( $key ); ?>][description]" rows="3" cols="60" class="large-text"><?php echo esc_textarea( $pkg['description'] ); ?></textarea></td>
|
||
</tr>
|
||
<tr>
|
||
<th><label for="carei_<?php echo esc_attr( $key ); ?>_desc_en"><?php esc_html_e( 'Opis / zakres usług (EN)', 'carei-reservation' ); ?></label></th>
|
||
<td>
|
||
<textarea id="carei_<?php echo esc_attr( $key ); ?>_desc_en" name="packages[<?php echo esc_attr( $key ); ?>][description_en]" rows="3" cols="60" class="large-text" placeholder="<?php echo esc_attr__( 'Basic protection package...', 'carei-reservation' ); ?>"><?php echo esc_textarea( $pkg['description_en'] ); ?></textarea>
|
||
<p class="description"><?php esc_html_e( 'Puste = fallback do wersji polskiej.', 'carei-reservation' ); ?></p>
|
||
</td>
|
||
</tr>
|
||
</table>
|
||
</div>
|
||
<?php endforeach; ?>
|
||
|
||
<?php submit_button( __( 'Zapisz pakiety', 'carei-reservation' ) ); ?>
|
||
</form>
|
||
</div>
|
||
<style>
|
||
.carei-protection-card { background:#fff; border:1px solid #c3c4c7; border-left:4px solid #2F2482; padding:10px 20px; margin:20px 0; }
|
||
.carei-protection-card h2 { margin-top:10px; color:#2F2482; }
|
||
</style>
|
||
<?php
|
||
}
|
||
|
||
public function handle_protection_packages_save() {
|
||
if ( ! current_user_can( 'manage_options' ) ) {
|
||
wp_die( esc_html__( 'Brak uprawnień.', 'carei-reservation' ) );
|
||
}
|
||
if ( ! isset( $_POST['carei_protection_nonce'] ) || ! wp_verify_nonce( $_POST['carei_protection_nonce'], 'carei_protection_packages' ) ) {
|
||
wp_die( esc_html__( 'Nieprawidłowy token.', 'carei-reservation' ) );
|
||
}
|
||
|
||
$input = isset( $_POST['packages'] ) && is_array( $_POST['packages'] ) ? $_POST['packages'] : array();
|
||
$defaults = self::get_protection_packages_defaults();
|
||
$clean = array();
|
||
foreach ( $defaults as $key => $def ) {
|
||
$raw = isset( $input[ $key ] ) && is_array( $input[ $key ] ) ? $input[ $key ] : array();
|
||
$name = isset( $raw['name'] ) ? sanitize_text_field( wp_unslash( $raw['name'] ) ) : $def['name'];
|
||
$name_en = isset( $raw['name_en'] ) ? sanitize_text_field( wp_unslash( $raw['name_en'] ) ) : '';
|
||
$price = isset( $raw['pricePerDay'] ) ? (float) $raw['pricePerDay'] : 0;
|
||
if ( $price < 0 ) { $price = 0; }
|
||
$active = ! empty( $raw['active'] );
|
||
$desc = isset( $raw['description'] ) ? sanitize_textarea_field( wp_unslash( $raw['description'] ) ) : '';
|
||
$desc_en = isset( $raw['description_en'] ) ? sanitize_textarea_field( wp_unslash( $raw['description_en'] ) ) : '';
|
||
$clean[ $key ] = array(
|
||
'name' => $name !== '' ? $name : $def['name'],
|
||
'name_en' => $name_en,
|
||
'pricePerDay' => $price,
|
||
'active' => $active,
|
||
'description' => $desc,
|
||
'description_en' => $desc_en,
|
||
);
|
||
}
|
||
update_option( self::PROTECTION_OPTION, $clean );
|
||
|
||
$redirect = add_query_arg(
|
||
array(
|
||
'post_type' => self::POST_TYPE,
|
||
'page' => 'carei-protection-packages',
|
||
'carei_saved' => '1',
|
||
),
|
||
admin_url( 'edit.php' )
|
||
);
|
||
wp_safe_redirect( $redirect );
|
||
exit;
|
||
}
|
||
|
||
public function register_post_type() {
|
||
register_post_type( self::POST_TYPE, array(
|
||
'labels' => array(
|
||
'name' => __( 'Rezerwacje', 'carei-reservation' ),
|
||
'singular_name' => __( 'Rezerwacja', 'carei-reservation' ),
|
||
'menu_name' => __( 'Rezerwacje', 'carei-reservation' ),
|
||
'all_items' => __( 'Wszystkie rezerwacje', 'carei-reservation' ),
|
||
'view_item' => __( 'Zobacz rezerwację', 'carei-reservation' ),
|
||
'edit_item' => __( 'Szczegóły rezerwacji', 'carei-reservation' ),
|
||
'search_items' => __( 'Szukaj rezerwacji', 'carei-reservation' ),
|
||
'not_found' => __( 'Nie znaleziono rezerwacji', 'carei-reservation' ),
|
||
'not_found_in_trash' => __( 'Brak rezerwacji w koszu', 'carei-reservation' ),
|
||
),
|
||
'public' => false,
|
||
'show_ui' => true,
|
||
'show_in_menu' => true,
|
||
'menu_icon' => 'dashicons-car',
|
||
'menu_position' => 26,
|
||
'supports' => array( 'title' ),
|
||
'capability_type' => 'post',
|
||
'has_archive' => false,
|
||
'hierarchical' => false,
|
||
'show_in_rest' => false,
|
||
) );
|
||
}
|
||
|
||
// ─── Admin Columns ──────────────────────────────────────────
|
||
|
||
public function admin_columns( $columns ) {
|
||
return array(
|
||
'cb' => '<input type="checkbox" />',
|
||
'reservation_no' => __( 'Nr rezerwacji', 'carei-reservation' ),
|
||
'client' => __( 'Klient', 'carei-reservation' ),
|
||
'segment' => __( 'Segment', 'carei-reservation' ),
|
||
'dates' => __( 'Daty', 'carei-reservation' ),
|
||
'branch' => __( 'Oddział', 'carei-reservation' ),
|
||
'carei_status' => __( 'Status', 'carei-reservation' ),
|
||
'date' => __( 'Data', 'carei-reservation' ),
|
||
);
|
||
}
|
||
|
||
public function render_column( $column, $post_id ) {
|
||
switch ( $column ) {
|
||
case 'reservation_no':
|
||
$no = get_post_meta( $post_id, self::META_PREFIX . 'reservation_no', true ) ?: '—';
|
||
printf(
|
||
'<a class="row-title" href="%s"><strong>%s</strong></a>',
|
||
esc_url( get_edit_post_link( $post_id ) ),
|
||
esc_html( $no )
|
||
);
|
||
break;
|
||
case 'client':
|
||
$first = get_post_meta( $post_id, self::META_PREFIX . 'first_name', true );
|
||
$last = get_post_meta( $post_id, self::META_PREFIX . 'last_name', true );
|
||
echo esc_html( trim( $first . ' ' . $last ) ?: '—' );
|
||
break;
|
||
case 'segment':
|
||
echo esc_html( get_post_meta( $post_id, self::META_PREFIX . 'segment', true ) ?: '—' );
|
||
break;
|
||
case 'dates':
|
||
$from = get_post_meta( $post_id, self::META_PREFIX . 'date_from', true );
|
||
$to = get_post_meta( $post_id, self::META_PREFIX . 'date_to', true );
|
||
if ( $from && $to ) {
|
||
$from_fmt = date_i18n( 'd.m.Y H:i', strtotime( $from ) );
|
||
$to_fmt = date_i18n( 'd.m.Y H:i', strtotime( $to ) );
|
||
echo esc_html( $from_fmt . ' — ' . $to_fmt );
|
||
} else {
|
||
echo '—';
|
||
}
|
||
break;
|
||
case 'branch':
|
||
echo esc_html( get_post_meta( $post_id, self::META_PREFIX . 'pickup_branch', true ) ?: '—' );
|
||
break;
|
||
case 'carei_status':
|
||
$status = get_post_meta( $post_id, self::META_PREFIX . 'status', true ) ?: 'nowe';
|
||
$info = isset( self::$statuses[ $status ] ) ? self::$statuses[ $status ] : self::$statuses['nowe'];
|
||
printf(
|
||
'<span class="carei-status-badge" style="background:%s;">%s</span>',
|
||
esc_attr( $info['color'] ),
|
||
esc_html( self::get_status_label( $status ) )
|
||
);
|
||
break;
|
||
}
|
||
}
|
||
|
||
// ─── Status Filter ──────────────────────────────────────────
|
||
|
||
public function status_filter_dropdown( $post_type ) {
|
||
if ( $post_type !== self::POST_TYPE ) {
|
||
return;
|
||
}
|
||
$current = isset( $_GET['carei_status'] ) ? sanitize_text_field( $_GET['carei_status'] ) : '';
|
||
echo '<select name="carei_status">';
|
||
echo '<option value="">' . esc_html__( 'Wszystkie statusy', 'carei-reservation' ) . '</option>';
|
||
foreach ( self::$statuses as $key => $info ) {
|
||
printf(
|
||
'<option value="%s"%s>%s</option>',
|
||
esc_attr( $key ),
|
||
selected( $current, $key, false ),
|
||
esc_html( self::get_status_label( $key ) )
|
||
);
|
||
}
|
||
echo '</select>';
|
||
}
|
||
|
||
public function filter_by_status( $query ) {
|
||
if ( ! is_admin() || ! $query->is_main_query() ) {
|
||
return;
|
||
}
|
||
if ( ( $query->get( 'post_type' ) !== self::POST_TYPE ) ) {
|
||
return;
|
||
}
|
||
if ( ! empty( $_GET['carei_status'] ) ) {
|
||
$status = sanitize_text_field( $_GET['carei_status'] );
|
||
if ( isset( self::$statuses[ $status ] ) ) {
|
||
$query->set( 'meta_query', array(
|
||
array(
|
||
'key' => self::META_PREFIX . 'status',
|
||
'value' => $status,
|
||
),
|
||
) );
|
||
}
|
||
}
|
||
// Default sort by date desc
|
||
if ( ! $query->get( 'orderby' ) ) {
|
||
$query->set( 'orderby', 'date' );
|
||
$query->set( 'order', 'DESC' );
|
||
}
|
||
}
|
||
|
||
// ─── Meta Box ───────────────────────────────────────────────
|
||
|
||
public function add_meta_boxes() {
|
||
add_meta_box(
|
||
'carei_reservation_details',
|
||
__( 'Szczegóły rezerwacji', 'carei-reservation' ),
|
||
array( $this, 'render_meta_box' ),
|
||
self::POST_TYPE,
|
||
'normal',
|
||
'high'
|
||
);
|
||
}
|
||
|
||
public function render_meta_box( $post ) {
|
||
wp_nonce_field( 'carei_save_reservation', 'carei_reservation_nonce' );
|
||
|
||
$meta = array(
|
||
'reservation_no' => get_post_meta( $post->ID, self::META_PREFIX . 'reservation_no', true ),
|
||
'reservation_id' => get_post_meta( $post->ID, self::META_PREFIX . 'reservation_id', true ),
|
||
'customer_id' => get_post_meta( $post->ID, self::META_PREFIX . 'customer_id', true ),
|
||
'segment' => get_post_meta( $post->ID, self::META_PREFIX . 'segment', true ),
|
||
'date_from' => get_post_meta( $post->ID, self::META_PREFIX . 'date_from', true ),
|
||
'date_to' => get_post_meta( $post->ID, self::META_PREFIX . 'date_to', true ),
|
||
'pickup_branch' => get_post_meta( $post->ID, self::META_PREFIX . 'pickup_branch', true ),
|
||
'return_branch' => get_post_meta( $post->ID, self::META_PREFIX . 'return_branch', true ),
|
||
'first_name' => get_post_meta( $post->ID, self::META_PREFIX . 'first_name', true ),
|
||
'last_name' => get_post_meta( $post->ID, self::META_PREFIX . 'last_name', true ),
|
||
'email' => get_post_meta( $post->ID, self::META_PREFIX . 'email', true ),
|
||
'phone' => get_post_meta( $post->ID, self::META_PREFIX . 'phone', true ),
|
||
'pesel' => get_post_meta( $post->ID, self::META_PREFIX . 'pesel', true ),
|
||
'address' => get_post_meta( $post->ID, self::META_PREFIX . 'address', true ),
|
||
'extras' => get_post_meta( $post->ID, self::META_PREFIX . 'extras', true ),
|
||
'comments' => get_post_meta( $post->ID, self::META_PREFIX . 'comments', true ),
|
||
'status' => get_post_meta( $post->ID, self::META_PREFIX . 'status', true ) ?: 'nowe',
|
||
'protection' => get_post_meta( $post->ID, self::META_PREFIX . 'protection_package', true ),
|
||
);
|
||
|
||
$protection = $meta['protection'] ? json_decode( $meta['protection'], true ) : null;
|
||
$protection_str = '';
|
||
if ( is_array( $protection ) && ! empty( $protection['name'] ) ) {
|
||
$name = isset( $protection['name'] ) ? $protection['name'] : '';
|
||
$price = isset( $protection['pricePerDay'] ) ? (float) $protection['pricePerDay'] : 0;
|
||
$days = isset( $protection['days'] ) ? (int) $protection['days'] : 0;
|
||
$total = isset( $protection['total'] ) ? (float) $protection['total'] : ( $price * $days );
|
||
$protection_str = sprintf(
|
||
/* translators: 1: package name, 2: price per day, 3: number of days, 4: total */
|
||
__( '%1$s — %2$s zł/doba × %3$d = %4$s zł', 'carei-reservation' ),
|
||
$name,
|
||
number_format( $price, 2, ',', ' ' ),
|
||
$days,
|
||
number_format( $total, 2, ',', ' ' )
|
||
);
|
||
}
|
||
|
||
$address = $meta['address'] ? json_decode( $meta['address'], true ) : null;
|
||
$address_str = '';
|
||
if ( $address ) {
|
||
$parts = array_filter( array(
|
||
isset( $address['street'] ) ? $address['street'] : '',
|
||
isset( $address['zipCode'] ) ? $address['zipCode'] : '',
|
||
isset( $address['city'] ) ? $address['city'] : '',
|
||
) );
|
||
$address_str = implode( ', ', $parts );
|
||
}
|
||
|
||
$extras = $meta['extras'] ? json_decode( $meta['extras'], true ) : array();
|
||
$extras_str = '';
|
||
if ( is_array( $extras ) && ! empty( $extras ) ) {
|
||
$names = array_map( function ( $e ) {
|
||
return isset( $e['name'] ) ? $e['name'] : '';
|
||
}, $extras );
|
||
$extras_str = implode( ', ', array_filter( $names ) );
|
||
}
|
||
|
||
$from_fmt = $meta['date_from'] ? date_i18n( 'd.m.Y H:i', strtotime( $meta['date_from'] ) ) : '—';
|
||
$to_fmt = $meta['date_to'] ? date_i18n( 'd.m.Y H:i', strtotime( $meta['date_to'] ) ) : '—';
|
||
|
||
?>
|
||
<table class="carei-meta-table">
|
||
<tr><th><?php esc_html_e( 'Nr rezerwacji', 'carei-reservation' ); ?></th><td><?php echo esc_html( $meta['reservation_no'] ?: '—' ); ?></td></tr>
|
||
<tr><th><?php esc_html_e( 'ID rezerwacji (Softra)', 'carei-reservation' ); ?></th><td><?php echo esc_html( $meta['reservation_id'] ?: '—' ); ?></td></tr>
|
||
<tr><th><?php esc_html_e( 'ID klienta (Softra)', 'carei-reservation' ); ?></th><td><?php echo esc_html( $meta['customer_id'] ?: '—' ); ?></td></tr>
|
||
<tr class="carei-meta-divider"><td colspan="2"><hr></td></tr>
|
||
<tr><th><?php esc_html_e( 'Segment', 'carei-reservation' ); ?></th><td><?php echo esc_html( $meta['segment'] ?: '—' ); ?></td></tr>
|
||
<tr><th><?php esc_html_e( 'Data od', 'carei-reservation' ); ?></th><td><?php echo esc_html( $from_fmt ); ?></td></tr>
|
||
<tr><th><?php esc_html_e( 'Data do', 'carei-reservation' ); ?></th><td><?php echo esc_html( $to_fmt ); ?></td></tr>
|
||
<tr><th><?php esc_html_e( 'Oddział odbioru', 'carei-reservation' ); ?></th><td><?php echo esc_html( $meta['pickup_branch'] ?: '—' ); ?></td></tr>
|
||
<tr><th><?php esc_html_e( 'Oddział zwrotu', 'carei-reservation' ); ?></th><td><?php echo esc_html( $meta['return_branch'] ?: $meta['pickup_branch'] ?: '—' ); ?></td></tr>
|
||
<tr class="carei-meta-divider"><td colspan="2"><hr></td></tr>
|
||
<tr><th><?php esc_html_e( 'Imię', 'carei-reservation' ); ?></th><td><?php echo esc_html( $meta['first_name'] ?: '—' ); ?></td></tr>
|
||
<tr><th><?php esc_html_e( 'Nazwisko', 'carei-reservation' ); ?></th><td><?php echo esc_html( $meta['last_name'] ?: '—' ); ?></td></tr>
|
||
<tr><th><?php esc_html_e( 'Email', 'carei-reservation' ); ?></th><td><?php echo esc_html( $meta['email'] ?: '—' ); ?></td></tr>
|
||
<tr><th><?php esc_html_e( 'Telefon', 'carei-reservation' ); ?></th><td><?php echo esc_html( $meta['phone'] ?: '—' ); ?></td></tr>
|
||
<tr><th><?php esc_html_e( 'PESEL', 'carei-reservation' ); ?></th><td><?php echo esc_html( $meta['pesel'] ?: '—' ); ?></td></tr>
|
||
<tr><th><?php esc_html_e( 'Adres', 'carei-reservation' ); ?></th><td><?php echo esc_html( $address_str ?: '—' ); ?></td></tr>
|
||
<tr class="carei-meta-divider"><td colspan="2"><hr></td></tr>
|
||
<tr><th><?php esc_html_e( 'Opcje dodatkowe', 'carei-reservation' ); ?></th><td><?php echo esc_html( $extras_str ?: __( 'Brak', 'carei-reservation' ) ); ?></td></tr>
|
||
<tr><th><?php esc_html_e( 'Pakiet ochronny', 'carei-reservation' ); ?></th><td><?php echo esc_html( $protection_str ?: __( 'Brak', 'carei-reservation' ) ); ?></td></tr>
|
||
<tr><th><?php esc_html_e( 'Wiadomość', 'carei-reservation' ); ?></th><td><?php echo esc_html( $meta['comments'] ?: '—' ); ?></td></tr>
|
||
<tr class="carei-meta-divider"><td colspan="2"><hr></td></tr>
|
||
<tr>
|
||
<th><?php esc_html_e( 'Status', 'carei-reservation' ); ?></th>
|
||
<td>
|
||
<select name="carei_status">
|
||
<?php foreach ( self::$statuses as $key => $info ) : ?>
|
||
<option value="<?php echo esc_attr( $key ); ?>" <?php selected( $meta['status'], $key ); ?>>
|
||
<?php echo esc_html( self::get_status_label( $key ) ); ?>
|
||
</option>
|
||
<?php endforeach; ?>
|
||
</select>
|
||
</td>
|
||
</tr>
|
||
</table>
|
||
<?php
|
||
}
|
||
|
||
public function save_meta_box( $post_id, $post ) {
|
||
if ( ! isset( $_POST['carei_reservation_nonce'] ) ) {
|
||
return;
|
||
}
|
||
if ( ! wp_verify_nonce( $_POST['carei_reservation_nonce'], 'carei_save_reservation' ) ) {
|
||
return;
|
||
}
|
||
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
|
||
return;
|
||
}
|
||
if ( ! current_user_can( 'edit_post', $post_id ) ) {
|
||
return;
|
||
}
|
||
|
||
if ( isset( $_POST['carei_status'] ) ) {
|
||
$status = sanitize_text_field( $_POST['carei_status'] );
|
||
if ( isset( self::$statuses[ $status ] ) ) {
|
||
update_post_meta( $post_id, self::META_PREFIX . 'status', $status );
|
||
}
|
||
}
|
||
}
|
||
|
||
// ─── Auto Mark Read ─────────────────────────────────────────
|
||
|
||
public function auto_mark_read( $post ) {
|
||
if ( $post->post_type !== self::POST_TYPE ) {
|
||
return;
|
||
}
|
||
$status = get_post_meta( $post->ID, self::META_PREFIX . 'status', true );
|
||
if ( $status === 'nowe' ) {
|
||
update_post_meta( $post->ID, self::META_PREFIX . 'status', 'przeczytane' );
|
||
}
|
||
}
|
||
|
||
// ─── Admin Styles ───────────────────────────────────────────
|
||
|
||
public function admin_styles() {
|
||
$screen = get_current_screen();
|
||
if ( ! $screen || $screen->post_type !== self::POST_TYPE ) {
|
||
return;
|
||
}
|
||
?>
|
||
<style>
|
||
.carei-status-badge {
|
||
display: inline-block;
|
||
padding: 4px 10px;
|
||
border-radius: 12px;
|
||
color: #fff;
|
||
font-size: 12px;
|
||
font-weight: 600;
|
||
line-height: 1.4;
|
||
white-space: nowrap;
|
||
}
|
||
.carei-meta-table {
|
||
width: 100%;
|
||
border-collapse: collapse;
|
||
}
|
||
.carei-meta-table th {
|
||
text-align: left;
|
||
padding: 8px 12px;
|
||
width: 180px;
|
||
color: #1d2327;
|
||
font-weight: 600;
|
||
vertical-align: top;
|
||
}
|
||
.carei-meta-table td {
|
||
padding: 8px 12px;
|
||
color: #50575e;
|
||
}
|
||
.carei-meta-table tr:nth-child(odd):not(.carei-meta-divider) {
|
||
background: #f9f9f9;
|
||
}
|
||
.carei-meta-divider td {
|
||
padding: 4px 0;
|
||
}
|
||
.carei-meta-divider hr {
|
||
border: none;
|
||
border-top: 1px solid #e0e0e0;
|
||
margin: 0;
|
||
}
|
||
.carei-meta-table select {
|
||
min-width: 180px;
|
||
}
|
||
/* Hide title input — auto-generated */
|
||
#post-body-content #titlediv { display: none; }
|
||
</style>
|
||
<?php
|
||
}
|
||
|
||
// ─── Save Reservation (called from REST proxy) ──────────────
|
||
|
||
public static function save_reservation( $booking_data, $api_result ) {
|
||
$reservation_no = isset( $api_result['reservationNo'] ) ? $api_result['reservationNo'] : '';
|
||
$reservation_id = isset( $api_result['reservationId'] ) ? $api_result['reservationId'] : '';
|
||
|
||
$driver = array();
|
||
if ( isset( $booking_data['drivers'] ) && is_array( $booking_data['drivers'] ) && ! empty( $booking_data['drivers'] ) ) {
|
||
$driver = $booking_data['drivers'][0];
|
||
}
|
||
|
||
$first_name = isset( $driver['firstName'] ) ? $driver['firstName'] : '';
|
||
$last_name = isset( $driver['lastName'] ) ? $driver['lastName'] : '';
|
||
|
||
$title = sprintf(
|
||
/* translators: 1: reservation number or ID, 2: first name, 3: last name */
|
||
__( 'Rezerwacja #%1$s — %2$s %3$s', 'carei-reservation' ),
|
||
$reservation_no ?: $reservation_id,
|
||
$first_name,
|
||
$last_name
|
||
);
|
||
|
||
$post_id = wp_insert_post( array(
|
||
'post_type' => self::POST_TYPE,
|
||
'post_title' => trim( $title ),
|
||
'post_status' => 'publish',
|
||
), true );
|
||
|
||
if ( is_wp_error( $post_id ) ) {
|
||
error_log( 'Carei: Failed to save reservation — ' . $post_id->get_error_message() );
|
||
return false;
|
||
}
|
||
|
||
$pickup_branch = '';
|
||
if ( isset( $booking_data['pickUpLocation']['branchName'] ) ) {
|
||
$pickup_branch = $booking_data['pickUpLocation']['branchName'];
|
||
}
|
||
$return_branch = '';
|
||
if ( isset( $booking_data['returnLocation']['branchName'] ) ) {
|
||
$return_branch = $booking_data['returnLocation']['branchName'];
|
||
}
|
||
$segment = '';
|
||
if ( isset( $booking_data['carParameters']['categoryName'] ) ) {
|
||
$segment = $booking_data['carParameters']['categoryName'];
|
||
}
|
||
|
||
$meta = array(
|
||
'reservation_no' => $reservation_no,
|
||
'reservation_id' => $reservation_id,
|
||
'customer_id' => isset( $booking_data['customerId'] ) ? $booking_data['customerId'] : '',
|
||
'segment' => $segment,
|
||
'date_from' => isset( $booking_data['dateFrom'] ) ? $booking_data['dateFrom'] : '',
|
||
'date_to' => isset( $booking_data['dateTo'] ) ? $booking_data['dateTo'] : '',
|
||
'pickup_branch' => $pickup_branch,
|
||
'return_branch' => $return_branch,
|
||
'first_name' => $first_name,
|
||
'last_name' => $last_name,
|
||
'email' => isset( $driver['email'] ) ? $driver['email'] : '',
|
||
'phone' => isset( $driver['phone'] ) ? $driver['phone'] : '',
|
||
'pesel' => isset( $driver['pesel'] ) ? $driver['pesel'] : '',
|
||
'address' => isset( $driver['address'] ) ? wp_json_encode( $driver['address'] ) : '',
|
||
'extras' => isset( $booking_data['priceItems'] ) ? wp_json_encode( $booking_data['priceItems'] ) : '',
|
||
'comments' => isset( $booking_data['comments'] ) ? $booking_data['comments'] : '',
|
||
'status' => 'nowe',
|
||
'raw_response' => wp_json_encode( $api_result ),
|
||
'protection_package' => ( isset( $booking_data['protectionPackage'] ) && is_array( $booking_data['protectionPackage'] ) )
|
||
? wp_json_encode( $booking_data['protectionPackage'] )
|
||
: '',
|
||
);
|
||
|
||
foreach ( $meta as $key => $value ) {
|
||
update_post_meta( $post_id, self::META_PREFIX . $key, $value );
|
||
}
|
||
|
||
return $post_id;
|
||
}
|
||
}
|