Files
2026-10-20 13:16:38 +09:00

215 lines
9.3 KiB
PHP

<?php
declare(strict_types=1);
require __DIR__ . '/includes/auth.php';
require __DIR__ . '/includes/engine.php';
// The calculation breakdown is internal: it is only rendered for a logged-in admin.
try {
$admin = viewing_admin();
} catch (Throwable $ex) {
$admin = null;
}
send_security_headers($admin !== null); // admin view is never cached
try {
$params = load_params();
$dbError = null;
} catch (Throwable $ex) {
$params = null;
$dbError = $ex->getMessage();
}
$tenors = $params['tenors'] ?? [1, 3, 6, 12, 24];
$cbTenors = $params['cashbackTenors'] ?? [];
?>
<!doctype html>
<html lang="id">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
<meta name="color-scheme" content="light dark">
<meta name="theme-color" content="#0b2e66">
<title>Kalkulator Cashback SERUBI · Bank Papua</title>
<?= theme_boot_script() ?>
<link rel="manifest" href="<?= e(base_url('manifest.webmanifest')) ?>">
<link rel="icon" href="<?= e(asset('assets/favicon.svg')) ?>" type="image/svg+xml">
<link rel="preload" href="<?= e(base_url('assets/fonts/archivo-var.woff2')) ?>" as="font" type="font/woff2" crossorigin>
<link rel="stylesheet" href="<?= e(asset('assets/css/base.css')) ?>">
<link rel="stylesheet" href="<?= e(asset('assets/css/app.css')) ?>">
<meta name="app-version" content="<?= e(app_version()) ?>">
</head>
<body class="page-calc">
<a class="skip-link" href="#hasil">Lewati ke hasil simulasi</a>
<header class="topbar">
<a class="brand" href="<?= e(base_url()) ?>" aria-label="Bank Papua SERUBI, beranda kalkulator">
<?= bank_logo('auto') ?>
<span class="brand-prog">SERUBI</span>
</a>
<div class="topbar-actions">
<button type="button" class="icon-btn" data-theme-toggle aria-label="Ganti tema terang/gelap">
<?= icon('moon', 'icon icon-moon') ?><?= icon('sun', 'icon icon-sun') ?>
</button>
<a class="text-btn" href="<?= e(base_url('admin/')) ?>"><?= icon('lock') ?><span>Admin</span></a>
</div>
</header>
<?php if ($dbError): ?>
<main class="desk desk-error">
<div class="panel-error" role="alert">
<?= icon('alert') ?>
<div>
<h1>Parameter tidak dapat dimuat</h1>
<p>Kalkulator membutuhkan database MySQL. Pastikan MySQL berjalan di port yang diatur pada <code>config.php</code>, lalu muat ulang halaman.</p>
</div>
</div>
</main>
<?php else: ?>
<main class="desk">
<section class="machine" aria-labelledby="machine-title">
<div class="machine-head">
<h1 id="machine-title">Kalkulator Cashback</h1>
<p>Tabungan/Giro + cashback dibandingkan deposito</p>
</div>
<div class="display" id="hasil" tabindex="-1">
<div class="display-top">
<span class="display-label">Cashback neto</span>
<span class="display-flag" id="dFlag"></span>
</div>
<output class="display-value" id="dNet" for="nominal tenor-group cust-group" aria-live="polite">Rp0</output>
<dl class="display-sub">
<div><dt>Bruto</dt><dd id="dGross">Rp0</dd></div>
<div><dt>Setara</dt><dd id="dEquiv">0,00% p.a.</dd></div>
<div><dt>Per bulan</dt><dd id="dMonthly">Rp0</dd></div>
</dl>
<p class="display-note" id="dNote" hidden></p>
</div>
<form class="keys" id="calcForm" novalidate>
<div class="field">
<label for="nominal">Nominal penempatan</label>
<div class="entry">
<span class="entry-prefix" aria-hidden="true">Rp</span>
<input id="nominal" name="nominal" type="text" inputmode="numeric" autocomplete="off" enterkeyhint="done"
value="55.000.000" aria-describedby="nominalHelp nominalErr" spellcheck="false">
</div>
<p class="help" id="nominalHelp">Cashback berlaku mulai <span id="minNominal">Rp50.000.000</span></p>
<p class="field-error" id="nominalErr" hidden></p>
<div class="quick" role="group" aria-label="Pilih nominal cepat">
<?php foreach ([50e6 => '50 jt', 100e6 => '100 jt', 250e6 => '250 jt', 500e6 => '500 jt', 1e9 => '1 M', 2e9 => '2 M'] as $v => $lbl): ?>
<button type="button" class="chip" data-amount="<?= (int)$v ?>"><?= e($lbl) ?></button>
<?php endforeach; ?>
</div>
</div>
<fieldset class="field" id="tenor-group">
<legend>Jangka waktu</legend>
<div class="segmented seg-tenor">
<?php foreach ($tenors as $t): $noCb = !in_array($t, $cbTenors, true); ?>
<label class="seg">
<input type="radio" name="tenor" value="<?= (int)$t ?>" <?= $t === 6 ? 'checked' : '' ?>>
<span class="seg-face">
<span class="seg-num"><?= (int)$t ?></span>
<span class="seg-unit">bulan</span>
<?php if ($noCb): ?><span class="seg-tag">tanpa cashback</span><?php endif; ?>
</span>
</label>
<?php endforeach; ?>
</div>
</fieldset>
<fieldset class="field" id="cust-group">
<legend>Jenis nasabah</legend>
<div class="segmented seg-cust">
<label class="seg"><input type="radio" name="cust" value="perorangan" checked><span class="seg-face">Perorangan</span></label>
<label class="seg"><input type="radio" name="cust" value="badan"><span class="seg-face">Badan usaha</span></label>
</div>
</fieldset>
<div class="machine-actions">
<button type="button" class="key key-plain" id="btnReset"><?= icon('reset') ?><span>Reset</span></button>
<button type="button" class="key key-plain" id="btnCopy"><?= icon('copy') ?><span>Salin ringkasan</span></button>
<button type="button" class="key key-gold" id="btnPrint"><?= icon('printer') ?><span>Cetak struk</span></button>
</div>
<p class="toast" id="toast" role="status" aria-live="polite"></p>
<p class="model-note" id="modelNote" role="status" hidden></p>
</form>
</section>
<section class="tape-wrap" aria-labelledby="tape-title">
<div class="tape-slot" aria-hidden="true"></div>
<article class="tape" id="tape">
<header class="tape-head">
<?= bank_logo('color', 'tape-logo') ?>
<h2 id="tape-title">Simulasi Cashback SERUBI</h2>
<p class="tape-meta"><time id="tDate"></time></p>
<dl class="lines lines-input">
<div><dt>Nominal</dt><dd id="tNominal"></dd></div>
<div><dt>Jangka waktu</dt><dd id="tTenor"></dd></div>
<div><dt>Jenis nasabah</dt><dd id="tCust"></dd></div>
</dl>
</header>
<section class="tape-sec">
<dl class="lines lines-total">
<div><dt>Cashback bruto</dt><dd id="tGross"></dd></div>
<div><dt>Pajak cashback <span id="tTaxRate"></span></dt><dd id="tTax"></dd></div>
<div class="is-strong"><dt>Cashback neto</dt><dd id="tNet"></dd></div>
<div><dt>Setara per tahun</dt><dd id="tEquiv"></dd></div>
</dl>
</section>
<section class="tape-sec">
<h3>Total diterima selama <span id="tTenor2"></span></h3>
<ol class="cmp" id="cmp"></ol>
<p class="tape-note">Total rate = rate produk + cashback neto disetahunkan.</p>
</section>
<?php if ($admin): ?>
<details class="tape-sec tape-details" id="detailCalc">
<summary><h3>Rincian perhitungan <span class="cmp-tag">Hanya admin</span></h3><?= icon('chevron', 'icon chev') ?></summary>
<div id="calcLines"></div>
</details>
<?php endif; ?>
<details class="tape-sec tape-details" id="detailPenalty">
<summary><h3>Bila dicairkan sebelum jatuh tempo</h3><?= icon('chevron', 'icon chev') ?></summary>
<dl class="lines" id="penaltyLines"></dl>
<p class="tape-note">Nasabah mengembalikan cashback neto beserta pajaknya, ditambah pinalti dari cashback neto.</p>
</details>
<footer class="tape-foot">
<p>Parameter berlaku per <span id="tParamDate"><?= e(fmt_datetime($params['updatedAt'])) ?></span>.</p>
<p class="tape-verify" id="tVerify" hidden></p>
<p>Hasil simulasi bersifat estimasi, bukan dokumen resmi atau penawaran yang mengikat, dan dapat berubah sesuai ketentuan Bank Papua.</p>
</footer>
</article>
</section>
</main>
<div class="mini-display" id="miniDisplay" aria-hidden="true">
<span class="mini-label">Cashback neto</span>
<span class="mini-value" id="mNet">Rp0</span>
<span class="mini-equiv" id="mEquiv"></span>
</div>
<?php
// Visitors calculate in the browser (instant, also offline) from the folded
// model: one margin per tenor instead of the bank's internal parameters.
// Printing and copying fetch the official numbers from calc.php.
// A logged-in admin also gets the full parameters for "Rincian perhitungan".
$client = ['model' => engine_client_model($params), 'calcUrl' => base_url('calc.php'), 'swUrl' => base_url('sw.js')];
if ($admin) {
$client['full'] = $params;
}
?>
<script nonce="<?= e(csp_nonce()) ?>">window.SERUBI_PUBLIC = <?= json_encode($client, JSON_HEX_TAG | JSON_HEX_AMP | JSON_UNESCAPED_UNICODE | JSON_PRESERVE_ZERO_FRACTION) ?>;</script>
<script src="<?= e(asset('assets/js/engine-public.js')) ?>"></script>
<?php if ($admin): ?><script src="<?= e(asset('assets/js/engine.js')) ?>"></script><?php endif; ?>
<script src="<?= e(asset('assets/js/format.js')) ?>"></script>
<script src="<?= e(asset('assets/js/app.js')) ?>"></script>
<?php endif; ?>
<script src="<?= e(asset('assets/js/theme.js')) ?>"></script>
</body>
</html>