feat(13-protection-packages): Pakiety ochronne SOFT/PREMIUM z panelu WP
- Panel admina (wp-admin > Rezerwacje > Pakiety ochronne) do zarzadzania nazwami, cenami za dobe, aktywnoscia i opisami pakietow SOFT i PREMIUM (zapis w wp_options carei_protection_packages) - REST endpoint GET /carei/v1/protection-packages zwracajacy aktywne pakiety - Radio cards SOFT/PREMIUM w modalu rezerwacji nad pozycjami "Pakiety ochronne" z API (osobne zrodlo danych, separator wizualny) - Radio z deselect (klik zaznaczonego odznacza), natywny input z accent-color - Pakiet NIE wysylany w priceItems Softra (powodowalo HTTP 400) - zamiast tego doklejany do comments booking i zapisywany w _carei_protection_package meta - Summary frontend dokorysowuje wiersz pakietu w tabeli cen i dolicza do total gross (grandGross = softraGross + protectionTotal) - Plan 13-01 oznaczony jako superseded (klient zmienil zrodlo danych) - Phase 13 Complete, Milestone v0.5 Complete Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -597,6 +597,89 @@ button.carei-reservation-trigger:hover {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
/* ═══════════════════════════════════════════
|
||||
Protection Packages (SOFT / PREMIUM — zarządzane w panelu WP)
|
||||
═══════════════════════════════════════════ */
|
||||
.carei-form__row--protection-packages {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 12px;
|
||||
}
|
||||
.carei-form__protection-package {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
padding: 16px;
|
||||
border: 1px solid var(--carei-border);
|
||||
border-radius: var(--carei-radius);
|
||||
background: var(--carei-white);
|
||||
cursor: pointer;
|
||||
transition: border-color 0.2s;
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
.carei-form__protection-package:hover {
|
||||
border-color: rgba(47, 36, 130, 0.4);
|
||||
}
|
||||
.carei-form__protection-package.is-selected {
|
||||
border-color: var(--carei-blue);
|
||||
}
|
||||
.carei-form__protection-package__row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
min-width: 0;
|
||||
}
|
||||
.carei-form__protection-package__input {
|
||||
flex-shrink: 0;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
accent-color: var(--carei-blue);
|
||||
cursor: pointer;
|
||||
margin: 0;
|
||||
}
|
||||
.carei-form__protection-package__name {
|
||||
font-weight: 600;
|
||||
font-size: 15px;
|
||||
color: var(--carei-blue);
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
word-break: break-word;
|
||||
}
|
||||
.carei-form__protection-package__price {
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
color: #505050;
|
||||
margin-left: auto;
|
||||
white-space: nowrap;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.carei-form__protection-package__price strong {
|
||||
color: inherit;
|
||||
}
|
||||
.carei-form__protection-package__desc {
|
||||
font-size: 12px;
|
||||
color: #666;
|
||||
line-height: 1.4;
|
||||
}
|
||||
.carei-form__protection-package__desc:empty {
|
||||
display: none;
|
||||
}
|
||||
.carei-form__protection-divider {
|
||||
margin: 14px 0;
|
||||
border-top: 1px dashed rgba(47, 36, 130, 0.18);
|
||||
height: 0;
|
||||
}
|
||||
.carei-form__row--protection-packages:empty + .carei-form__protection-divider {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
.carei-form__row--protection-packages {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
.carei-form__checkbox-label--abroad {
|
||||
align-items: center;
|
||||
font-weight: 600;
|
||||
|
||||
@@ -83,6 +83,9 @@
|
||||
var summaryOverlay, summaryDetails, summaryTable, summaryTotal, summaryError;
|
||||
var summaryBack, summaryConfirm;
|
||||
var successView, successNumber, successClose;
|
||||
var protectionContainer;
|
||||
var protectionPackages = { soft: null, premium: null };
|
||||
var selectedProtectionKey = null;
|
||||
|
||||
function initRefs() {
|
||||
overlay = document.querySelector('[data-carei-modal]');
|
||||
@@ -102,6 +105,7 @@
|
||||
extrasWrapper = document.getElementById('carei-extras-wrapper');
|
||||
extrasContainer = document.getElementById('carei-extras-container');
|
||||
insuranceContainer = document.getElementById('carei-insurance-container');
|
||||
protectionContainer = document.getElementById('carei-protection-packages-container');
|
||||
abroadSection = document.getElementById('carei-abroad-section');
|
||||
abroadToggle = document.getElementById('carei-abroad-toggle');
|
||||
abroadSearch = document.getElementById('carei-abroad-search');
|
||||
@@ -419,6 +423,69 @@
|
||||
daysCount.innerHTML = 'Wybrano: <strong>' + diff + ' ' + (diff === 1 ? 'dzień' : 'dni') + '</strong>';
|
||||
}
|
||||
|
||||
// ─── Protection Packages (WP-managed: SOFT, PREMIUM) ──────────
|
||||
|
||||
function loadProtectionPackages() {
|
||||
return fetch(REST_URL + 'protection-packages', {
|
||||
credentials: 'same-origin'
|
||||
}).then(function (r) { return r.ok ? r.json() : null; })
|
||||
.then(function (data) {
|
||||
if (!data || typeof data !== 'object') return;
|
||||
protectionPackages.soft = data.soft || null;
|
||||
protectionPackages.premium = data.premium || null;
|
||||
renderProtectionPackages();
|
||||
}).catch(function (err) { console.error('Failed to load protection packages:', err); });
|
||||
}
|
||||
|
||||
function renderProtectionPackages() {
|
||||
if (!protectionContainer) return;
|
||||
protectionContainer.innerHTML = '';
|
||||
['soft', 'premium'].forEach(function (key) {
|
||||
var pkg = protectionPackages[key];
|
||||
if (!pkg) return;
|
||||
var price = parseFloat(pkg.pricePerDay || 0);
|
||||
var priceLabel = price > 0 ? price.toFixed(0) + ' zł/doba' : 'Gratis';
|
||||
var descHtml = pkg.description ? '<span class="carei-form__protection-package__desc">' + escHtml(pkg.description) + '</span>' : '';
|
||||
var card = document.createElement('label');
|
||||
card.className = 'carei-form__protection-package';
|
||||
card.setAttribute('data-key', key);
|
||||
card.setAttribute('data-price', price);
|
||||
card.innerHTML =
|
||||
'<span class="carei-form__protection-package__row">' +
|
||||
'<input type="radio" name="protectionPackage" value="' + escAttr(key) + '" class="carei-form__protection-package__input">' +
|
||||
'<span class="carei-form__protection-package__name">' + escHtml(pkg.name || '') + '</span>' +
|
||||
'<span class="carei-form__protection-package__price"><strong>' + escHtml(priceLabel) + '</strong></span>' +
|
||||
'</span>' +
|
||||
descHtml;
|
||||
card.addEventListener('click', function (e) {
|
||||
e.preventDefault();
|
||||
onProtectionCardClick(key);
|
||||
});
|
||||
protectionContainer.appendChild(card);
|
||||
});
|
||||
}
|
||||
|
||||
function onProtectionCardClick(key) {
|
||||
if (!protectionContainer) return;
|
||||
if (selectedProtectionKey === key) {
|
||||
selectedProtectionKey = null;
|
||||
} else {
|
||||
selectedProtectionKey = key;
|
||||
}
|
||||
var cards = protectionContainer.querySelectorAll('.carei-form__protection-package');
|
||||
cards.forEach(function (card) {
|
||||
var k = card.getAttribute('data-key');
|
||||
var input = card.querySelector('input');
|
||||
if (k === selectedProtectionKey) {
|
||||
card.classList.add('is-selected');
|
||||
if (input) input.checked = true;
|
||||
} else {
|
||||
card.classList.remove('is-selected');
|
||||
if (input) input.checked = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// ─── Load Extras from Pricelist ───────────────────────────────
|
||||
|
||||
function loadExtras() {
|
||||
@@ -875,9 +942,33 @@
|
||||
priceAfterDiscount: price
|
||||
});
|
||||
});
|
||||
// UWAGA: pakiet ochronny (SOFT/PREMIUM) zarządzany w panelu WP
|
||||
// NIE jest dołączany do priceItems — Softra nie zna tych ID (zwróciłaby HTTP 400).
|
||||
// Jest liczony osobno w getSelectedProtectionPayload() i dodawany do podsumowania po stronie frontu.
|
||||
return items;
|
||||
}
|
||||
|
||||
function getSelectedProtectionPayload() {
|
||||
if (!selectedProtectionKey || !protectionPackages[selectedProtectionKey]) return null;
|
||||
var pkg = protectionPackages[selectedProtectionKey];
|
||||
var pricePerDay = parseFloat(pkg.pricePerDay || 0);
|
||||
var days = getRentalDays();
|
||||
return {
|
||||
key: selectedProtectionKey,
|
||||
name: pkg.name,
|
||||
pricePerDay: pricePerDay,
|
||||
days: days,
|
||||
total: pricePerDay * days
|
||||
};
|
||||
}
|
||||
|
||||
function buildBookingComments(userMessage) {
|
||||
var pkg = getSelectedProtectionPayload();
|
||||
if (!pkg) return userMessage || '';
|
||||
var pkgLine = 'Pakiet ochronny: ' + pkg.name + ' — ' + pkg.pricePerDay.toFixed(2) + ' zł/doba × ' + pkg.days + ' = ' + pkg.total.toFixed(2) + ' zł (do doliczenia poza systemem)';
|
||||
return userMessage ? (pkgLine + '\n\n' + userMessage) : pkgLine;
|
||||
}
|
||||
|
||||
// ─── Step Transitions ──────────────────────────────────────────
|
||||
|
||||
function hideStep(el) {
|
||||
@@ -961,7 +1052,8 @@
|
||||
|
||||
// Selected extras
|
||||
var selectedExtras = getSelectedExtrasForApi();
|
||||
if (selectedExtras.length > 0) {
|
||||
var pkgForDetails = getSelectedProtectionPayload();
|
||||
if (selectedExtras.length > 0 || pkgForDetails) {
|
||||
html += '<div style="margin-top:8px"><strong>Wybrane opcje:</strong></div><ul style="margin:4px 0 0 16px;padding:0;list-style:disc;">';
|
||||
selectedExtras.forEach(function (ex) {
|
||||
var totalPrice = ex.priceAfterDiscount * (ex.amount || 1);
|
||||
@@ -970,6 +1062,12 @@
|
||||
: fmtPrice(totalPrice) + ' zł';
|
||||
html += '<li>' + escHtml(toSentenceCase(ex.name)) + ' — ' + priceInfo + '</li>';
|
||||
});
|
||||
if (pkgForDetails) {
|
||||
var pkgInfo = pkgForDetails.days > 1
|
||||
? fmtPrice(pkgForDetails.pricePerDay) + ' zł/doba × ' + pkgForDetails.days + ' = ' + fmtPrice(pkgForDetails.total) + ' zł'
|
||||
: fmtPrice(pkgForDetails.total) + ' zł';
|
||||
html += '<li>' + escHtml(pkgForDetails.name) + ' — ' + pkgInfo + '</li>';
|
||||
}
|
||||
html += '</ul>';
|
||||
}
|
||||
|
||||
@@ -980,6 +1078,8 @@
|
||||
summaryDetails.innerHTML = html;
|
||||
}
|
||||
|
||||
var protectionPayload = getSelectedProtectionPayload();
|
||||
|
||||
// Price table
|
||||
if (summaryTable && summary.pricelist) {
|
||||
var html = '<table><thead><tr><th>Nazwa</th><th>Ilość</th><th>Netto</th><th>Brutto</th></tr></thead><tbody>';
|
||||
@@ -991,16 +1091,30 @@
|
||||
'<td>' + fmtPrice(item.netValue) + '</td>' +
|
||||
'<td>' + fmtPrice(item.grossValue) + '</td></tr>';
|
||||
});
|
||||
if (protectionPayload) {
|
||||
html += '<tr class="carei-summary__protection-row">' +
|
||||
'<td>' + escHtml(protectionPayload.name) + ' <small>(do doliczenia)</small></td>' +
|
||||
'<td>' + protectionPayload.days + ' doba</td>' +
|
||||
'<td>—</td>' +
|
||||
'<td>' + fmtPrice(protectionPayload.total) + '</td></tr>';
|
||||
}
|
||||
html += '</tbody></table>';
|
||||
summaryTable.innerHTML = html;
|
||||
}
|
||||
|
||||
// Totals
|
||||
if (summaryTotal) {
|
||||
summaryTotal.innerHTML =
|
||||
var softraGross = parseFloat(summary.totalGrossValue || 0);
|
||||
var protectionTotal = protectionPayload ? protectionPayload.total : 0;
|
||||
var grandGross = softraGross + protectionTotal;
|
||||
var totalsHtml =
|
||||
'<div class="carei-summary__total-row"><span class="carei-summary__total-label">Netto:</span><span class="carei-summary__total-value">' + fmtPrice(summary.totalNetValue) + '</span></div>' +
|
||||
'<div class="carei-summary__total-row"><span class="carei-summary__total-label">VAT:</span><span class="carei-summary__total-value">' + fmtPrice(summary.totalVatValue) + '</span></div>' +
|
||||
'<div class="carei-summary__total-row carei-summary__total-row--gross"><span class="carei-summary__total-label">Do zapłaty:</span><span class="carei-summary__total-value">' + fmtPrice(summary.totalGrossValue) + ' zł</span></div>';
|
||||
'<div class="carei-summary__total-row"><span class="carei-summary__total-label">VAT:</span><span class="carei-summary__total-value">' + fmtPrice(summary.totalVatValue) + '</span></div>';
|
||||
if (protectionPayload) {
|
||||
totalsHtml += '<div class="carei-summary__total-row"><span class="carei-summary__total-label">Pakiet ochronny:</span><span class="carei-summary__total-value">' + fmtPrice(protectionPayload.total) + '</span></div>';
|
||||
}
|
||||
totalsHtml += '<div class="carei-summary__total-row carei-summary__total-row--gross"><span class="carei-summary__total-label">Do zapłaty:</span><span class="carei-summary__total-value">' + fmtPrice(grandGross) + ' zł</span></div>';
|
||||
summaryTotal.innerHTML = totalsHtml;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1047,7 +1161,8 @@
|
||||
phone: fd.phone,
|
||||
email: fd.email
|
||||
}],
|
||||
comments: fd.message || ''
|
||||
comments: buildBookingComments(fd.message || ''),
|
||||
protectionPackage: getSelectedProtectionPayload()
|
||||
};
|
||||
|
||||
// Add agreement items
|
||||
@@ -1344,6 +1459,7 @@
|
||||
initAbroad();
|
||||
initSubmit();
|
||||
initMap();
|
||||
loadProtectionPackages();
|
||||
}
|
||||
|
||||
/* ═══════════════════════════════════════════
|
||||
|
||||
@@ -8,6 +8,8 @@ class Carei_Admin_Panel {
|
||||
const POST_TYPE = 'carei_reservation';
|
||||
const META_PREFIX = '_carei_';
|
||||
|
||||
const PROTECTION_OPTION = 'carei_protection_packages';
|
||||
|
||||
private static $statuses = array(
|
||||
'nowe' => array( 'label' => 'Nowe', 'color' => '#2F2482' ),
|
||||
'przeczytane' => array( 'label' => 'Przeczytane', 'color' => '#f59e0b' ),
|
||||
@@ -24,6 +26,149 @@ class Carei_Admin_Panel {
|
||||
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' ) );
|
||||
}
|
||||
|
||||
// ─── Protection Packages (SOFT / PREMIUM) ────────────────────
|
||||
|
||||
public static function get_protection_packages_defaults() {
|
||||
return array(
|
||||
'soft' => array(
|
||||
'name' => 'Ubezpieczenie SOFT',
|
||||
'pricePerDay' => 0,
|
||||
'active' => true,
|
||||
'description' => '',
|
||||
),
|
||||
'premium' => array(
|
||||
'name' => 'Ubezpieczenie PREMIUM',
|
||||
'pricePerDay' => 0,
|
||||
'active' => true,
|
||||
'description' => '',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
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'],
|
||||
'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'],
|
||||
);
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
|
||||
public function register_protection_packages_page() {
|
||||
add_submenu_page(
|
||||
'edit.php?post_type=' . self::POST_TYPE,
|
||||
'Pakiety ochronne',
|
||||
'Pakiety ochronne',
|
||||
'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( 'Brak uprawnień.' );
|
||||
}
|
||||
$data = self::get_protection_packages();
|
||||
$saved = isset( $_GET['carei_saved'] ) && $_GET['carei_saved'] === '1';
|
||||
?>
|
||||
<div class="wrap">
|
||||
<h1>Pakiety ochronne</h1>
|
||||
<p>Konfiguracja pakietów wyświetlanych w sekcji <strong>Pakiety ochronne</strong> formularza rezerwacji. Cena podawana jest za dobę — total = cena × liczba dób rezerwacji.</p>
|
||||
<?php if ( $saved ) : ?>
|
||||
<div class="notice notice-success is-dismissible"><p>Zapisano.</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>Pakiet <?php echo esc_html( $label ); ?></h2>
|
||||
<table class="form-table">
|
||||
<tr>
|
||||
<th><label for="carei_<?php echo esc_attr( $key ); ?>_name">Nazwa wyświetlana</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 ); ?>_price">Cena za dobę (zł)</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>Status</th>
|
||||
<td><label><input type="checkbox" name="packages[<?php echo esc_attr( $key ); ?>][active]" value="1" <?php checked( $pkg['active'] ); ?>> Aktywny (widoczny w modalu)</label></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><label for="carei_<?php echo esc_attr( $key ); ?>_desc">Opis / zakres usług</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>
|
||||
</table>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
|
||||
<?php submit_button( 'Zapisz pakiety' ); ?>
|
||||
</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( 'Brak uprawnień.' );
|
||||
}
|
||||
if ( ! isset( $_POST['carei_protection_nonce'] ) || ! wp_verify_nonce( $_POST['carei_protection_nonce'], 'carei_protection_packages' ) ) {
|
||||
wp_die( 'Nieprawidłowy token.' );
|
||||
}
|
||||
|
||||
$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'];
|
||||
$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'] ) ) : '';
|
||||
$clean[ $key ] = array(
|
||||
'name' => $name !== '' ? $name : $def['name'],
|
||||
'pricePerDay' => $price,
|
||||
'active' => $active,
|
||||
'description' => $desc,
|
||||
);
|
||||
}
|
||||
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() {
|
||||
@@ -190,8 +335,19 @@ class Carei_Admin_Panel {
|
||||
'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( '%s — %s zł/doba × %d = %s zł', $name, number_format( $price, 2, ',', ' ' ), $days, number_format( $total, 2, ',', ' ' ) );
|
||||
}
|
||||
|
||||
$address = $meta['address'] ? json_decode( $meta['address'], true ) : null;
|
||||
$address_str = '';
|
||||
if ( $address ) {
|
||||
@@ -235,6 +391,7 @@ class Carei_Admin_Panel {
|
||||
<tr><th>Adres</th><td><?php echo esc_html( $address_str ?: '—' ); ?></td></tr>
|
||||
<tr class="carei-meta-divider"><td colspan="2"><hr></td></tr>
|
||||
<tr><th>Opcje dodatkowe</th><td><?php echo esc_html( $extras_str ?: 'Brak' ); ?></td></tr>
|
||||
<tr><th>Pakiet ochronny</th><td><?php echo esc_html( $protection_str ?: 'Brak' ); ?></td></tr>
|
||||
<tr><th>Wiadomość</th><td><?php echo esc_html( $meta['comments'] ?: '—' ); ?></td></tr>
|
||||
<tr class="carei-meta-divider"><td colspan="2"><hr></td></tr>
|
||||
<tr>
|
||||
@@ -401,6 +558,9 @@ class Carei_Admin_Panel {
|
||||
'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 ) {
|
||||
|
||||
@@ -152,6 +152,10 @@ class Carei_Reservation_Widget extends \Elementor\Widget_Base {
|
||||
|
||||
<div class="carei-form__divider"><span>Pakiety ochronne</span></div>
|
||||
<div class="carei-form__section">
|
||||
<div class="carei-form__row carei-form__row--protection-packages" id="carei-protection-packages-container">
|
||||
<!-- Dynamicznie z panelu WP (SOFT, PREMIUM) -->
|
||||
</div>
|
||||
<div class="carei-form__protection-divider" aria-hidden="true"></div>
|
||||
<div class="carei-form__row" id="carei-insurance-container">
|
||||
<!-- Dynamicznie z API pricelist -->
|
||||
</div>
|
||||
|
||||
@@ -130,6 +130,13 @@ class Carei_REST_Proxy {
|
||||
'callback' => array( $this, 'get_agreements' ),
|
||||
'permission_callback' => '__return_true',
|
||||
) );
|
||||
|
||||
// GET /protection-packages
|
||||
register_rest_route( self::NAMESPACE, '/protection-packages', array(
|
||||
'methods' => 'GET',
|
||||
'callback' => array( $this, 'get_protection_packages' ),
|
||||
'permission_callback' => '__return_true',
|
||||
) );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -298,4 +305,20 @@ class Carei_REST_Proxy {
|
||||
}
|
||||
return $this->respond( $api->get_agreements() );
|
||||
}
|
||||
|
||||
public function get_protection_packages( WP_REST_Request $request ) {
|
||||
$all = Carei_Admin_Panel::get_protection_packages();
|
||||
$out = array( 'soft' => null, 'premium' => null );
|
||||
foreach ( array( 'soft', 'premium' ) as $key ) {
|
||||
if ( isset( $all[ $key ] ) && ! empty( $all[ $key ]['active'] ) ) {
|
||||
$out[ $key ] = array(
|
||||
'key' => $key,
|
||||
'name' => $all[ $key ]['name'],
|
||||
'pricePerDay' => (float) $all[ $key ]['pricePerDay'],
|
||||
'description' => $all[ $key ]['description'],
|
||||
);
|
||||
}
|
||||
}
|
||||
return rest_ensure_response( $out );
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user