<?php
/*
Plugin Name: Kalkulator Kosztu Monitoringu (IT-R.PL)
Description: Prost y kalkulator kosztu monitoringu z krótkim kodem [monitoring_calculator]. Liczy sprzęt/usługę, netto/brutto.
Version: 1.0.0
Author: it-r.pl / superstrony.eu
*/
if (!defined('ABSPATH')) { exit; }
class ITR_Monitoring_Calculator {
private $slug = 'itr_monitoring_calculator';
// Cennik (netto)
private $prices = [
// Sprzęt
'gniazdo' => ['label' => 'Gniazdo', 'unit' => 'szt', 'price' => 79.00, 'group' => 'sprzet'],
'puszka' => ['label' => 'Puszka', 'unit' => 'szt', 'price' => 69.00, 'group' => 'sprzet'],
'kamera_4mp' => ['label' => 'Kamera 4MP', 'unit' => 'szt', 'price' => 300.00, 'group' => 'sprzet'],
'poe_adapter' => ['label' => 'Przejściówka PoE', 'unit' => 'szt', 'price' => 25.00, 'group' => 'sprzet'],
'switch_16' => ['label' => 'Switch 16 port', 'unit' => 'szt', 'price' => 468.00, 'group' => 'sprzet'],
'patchpanel_1u' => ['label' => 'Patchpanel 1U', 'unit' => 'szt', 'price' => 80.00, 'group' => 'sprzet'],
'patchcord' => ['label' => 'Patchcordy', 'unit' => 'szt', 'price' => 5.00, 'group' => 'sprzet'],
'nvr_16' => ['label' => 'Rejestrator 1U 16 kamer', 'unit' => 'szt', 'price' => 500.00, 'group' => 'sprzet'],
'hdd_1tb' => ['label' => 'Dysk 1TB', 'unit' => 'szt', 'price' => 264.00, 'group' => 'sprzet'],
'maskownica_1u' => ['label' => 'Maskownica 1U', 'unit' => 'szt', 'price' => 16.00, 'group' => 'sprzet'],
'listwa_1u' => ['label' => 'Listwa zasilająca 1U', 'unit' => 'szt', 'price' => 159.00, 'group' => 'sprzet'],
'szafa_sieciowa' => ['label' => 'Szafa sieciowa', 'unit' => 'szt', 'price' => 480.00, 'group' => 'sprzet'],
'przewod_mb' => ['label' => 'Przewód (mb)', 'unit' => 'mb', 'price' => 6.00, 'group' => 'sprzet'],
'koryta_mb' => ['label' => 'Koryta (mb)', 'unit' => 'mb', 'price' => 6.00, 'group' => 'sprzet'],
// Usługa
'montaz_szafy' => ['label' => 'Montaż szafy', 'unit' => 'szt', 'price' => 300.00, 'group' => 'usluga'],
'montaz_przewodu_mb' => ['label' => 'Montaż przewodu (mb)', 'unit' => 'mb', 'price' => 19.00, 'group' => 'usluga'],
'montaz_kamery' => ['label' => 'Montaż 1 szt. kamery', 'unit' => 'szt', 'price' => 200.00, 'group' => 'usluga'],
'konfiguracja' => ['label' => 'Konfiguracja (ryczałt)', 'unit' => 'szt', 'price' => 200.00, 'group' => 'usluga', 'is_flat' => true],
];
public function __construct() {
add_action('init', [$this, 'register_assets']);
add_shortcode('monitoring_calculator', [$this, 'render_shortcode']);
}
public function register_assets() {
// CSS
$css =
'.itr-mc{max-width:980px;margin:24px auto;padding:16px;border:1px solid #e5e7eb;border-radius:14px;background:#fff;box-shadow:0 6px 18px rgba(0,0,0,.06)}'.
'.itr-mc h3{margin:0 0 8px;font-size:22px}'.
'.itr-mc small{color:#6b7280}'.
'.itr-mc .bar{display:flex;gap:12px;align-items:center;justify-content:space-between;margin:10px 0 18px}'.
'.itr-mc .bar input[type=number]{width:120px;padding:8px 10px;border:1px solid #d1d5db;border-radius:10px}'.
'.itr-mc table{width:100%;border-collapse:separate;border-spacing:0 8px}'.
'.itr-mc th,.itr-mc td{text-align:left;padding:10px 12px;background:#f9fafb}'.
'.itr-mc tr td:first-child,.itr-mc tr th:first-child{border-radius:10px 0 0 10px}'.
'.itr-mc tr td:last-child,.itr-mc tr th:last-child{border-radius:0 10px 10px 0}'.
'.itr-mc .group{margin-top:22px;font-weight:700;color:#111827}'.
'.itr-mc .totals{margin-top:22px;display:grid;grid-template-columns:1fr 1fr;gap:12px}'.
'.itr-mc .totals .card{background:#f3f4f6;border-radius:12px;padding:12px 14px}'.
'.itr-mc .muted{color:#6b7280;font-weight:400}'.
'.itr-mc .right{text-align:right}'.
'.itr-mc .btn{display:inline-block;margin-top:12px;padding:10px 14px;border-radius:10px;background:#111827;color:#fff;text-decoration:none}'.
'.itr-mc .vat{display:flex;gap:10px;align-items:center;margin:12px 0 6px}'
;
wp_register_style($this->slug, false);
wp_add_inline_style($this->slug, $css);
// JS
wp_register_script($this->slug, '', [], false, true);
$prices = $this->prices;
$localized = [
'prices' => $prices,
'defaultVAT' => 23,
'currency' => 'zł',
'thousand' => ' ',
'decimal' => ',',
];
wp_add_inline_script($this->slug, 'window.ITR_MC = '.wp_json_encode($localized).';');
$js = <<<'JS'
(function(){
const fmt = (n)=>{
if(isNaN(n)) n = 0;
return n.toLocaleString('pl-PL', {minimumFractionDigits:2, maximumFractionDigits:2});
};
function recalc(root){
const vat = parseFloat(root.querySelector('[data-vat]')?.value || '23');
const rows = root.querySelectorAll('[data-row]');
let sumSprzet = 0, sumUsluga = 0;
rows.forEach(row=>{
const key = row.getAttribute('data-key');
const price = parseFloat(row.getAttribute('data-price'));
const isFlat = row.hasAttribute('data-flat');
let qty = parseFloat(row.querySelector('input')?.value || '0');
if(isFlat){ qty = qty > 0 ? 1 : 0; }
const line = price * qty;
row.querySelector('[data-line]')?.innerText = fmt(line);
if(row.getAttribute('data-group')==='sprzet') sumSprzet += line; else sumUsluga += line;
});
const netto = sumSprzet + sumUsluga;
const vatAmt = netto * (vat/100);
const brutto = netto + vatAmt;
root.querySelector('[data-sprzet]')!.innerText = fmt(sumSprzet);
root.querySelector('[data-usluga]')!.innerText = fmt(sumUsluga);
root.querySelector('[data-netto]')!.innerText = fmt(netto);
root.querySelector('[data-vat-amt]')!.innerText = fmt(vatAmt);
root.querySelector('[data-brutto]')!.innerText = fmt(brutto);
}
function mount(){
document.querySelectorAll('.itr-mc').forEach(root=>{
root.addEventListener('input', ()=>recalc(root), {passive:true});
recalc(root);
});
}
if(document.readyState==='complete' || document.readyState==='interactive') setTimeout(mount,0); else document.addEventListener('DOMContentLoaded', mount);
})();
JS;
wp_add_inline_script($this->slug, $js);
}
public function render_shortcode($atts){
wp_enqueue_style($this->slug);
wp_enqueue_script($this->slug);
$vat_default = 23; // możesz zmienić na inny domyślny
ob_start(); ?>
<div class="itr-mc" role="form" aria-label="Kalkulator kosztu monitoringu">
<h3>Kalkulator kosztu monitoringu</h3>
<div class="vat">
<label for="itr-mc-vat">Stawka VAT (%)</label>
<input id="itr-mc-vat" type="number" step="1" min="0" max="99" value="<?php echo esc_attr($vat_default); ?>" data-vat />
<small>Zmodyfikuj, jeśli stosujesz inną stawkę.</small>
</div>
<table>
<thead>
<tr>
<th>Pozycja</th>
<th>JM</th>
<th>Cena jedn. netto</th>
<th>Ilość</th>
<th class="right">Wartość netto</th>
</tr>
</thead>
<tbody>
<tr><td class="group" colspan="5">Sprzęt</td></tr>
<?php foreach($this->prices as $key=>$row): if($row['group']!== 'sprzet') continue; ?>
<tr data-row data-group="sprzet" data-key="<?php echo esc_attr($key); ?>" data-price="<?php echo esc_attr($row['price']); ?>">
<td><?php echo esc_html($row['label']); ?></td>
<td><?php echo esc_html($row['unit']); ?></td>
<td><?php echo number_format($row['price'],2,',',' '); ?> zł</td>
<td>
<input type="number" step="1" min="0" placeholder="0" aria-label="Ilość: <?php echo esc_attr($row['label']); ?>" />
</td>
<td class="right"><span data-line>0,00</span> zł</td>
</tr>
<?php endforeach; ?>
<tr><td class="group" colspan="5">Usługa</td></tr>
<?php foreach($this->prices as $key=>$row): if($row['group']!== 'usluga') continue; ?>
<tr data-row data-group="usluga" data-key="<?php echo esc_attr($key); ?>" data-price="<?php echo esc_attr($row['price']); ?>" <?php echo !empty($row['is_flat']) ? 'data-flat' : '';?>>
<td><?php echo esc_html($row['label']); ?></td>
<td><?php echo esc_html($row['unit']); ?></td>
<td><?php echo number_format($row['price'],2,',',' '); ?> zł</td>
<td>
<?php if(!empty($row['is_flat'])): ?>
<input type="number" step="1" min="0" max="1" placeholder="0" aria-label="Dodaj pozycję: <?php echo esc_attr($row['label']); ?>" />
<small class="muted">0 = nie liczy, 1 = dolicz</small>
<?php else: ?>
<input type="number" step="1" min="0" placeholder="0" aria-label="Ilość: <?php echo esc_attr($row['label']); ?>" />
<?php endif; ?>
</td>
<td class="right"><span data-line>0,00</span> zł</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<div class="totals">
<div class="card"><strong>Sprzęt (netto):</strong> <span class="right" style="float:right" data-sprzet>0,00</span> zł</div>
<div class="card"><strong>Usługa (netto):</strong> <span class="right" style="float:right" data-usluga>0,00</span> zł</div>
<div class="card"><strong>Suma netto:</strong> <span class="right" style="float:right" data-netto>0,00</span> zł</div>
<div class="card"><strong>VAT:</strong> <span class="right" style="float:right" data-vat-amt>0,00</span> zł</div>
<div class="card" style="grid-column:1 / -1"><strong>Suma brutto:</strong> <span class="right" style="float:right" data-brutto>0,00</span> zł</div>
</div>
<a href="#" class="btn" onclick="window.print();return false;">Wydrukuj / Zapisz do PDF</a>
<small class="muted" style="display:block;margin-top:8px">Wyliczenia mają charakter orientacyjny.</small>
</div>
<?php
return ob_get_clean();
}
}
new ITR_Monitoring_Calculator();