Files
2026-07-06 20:16:00 +02:00

95 lines
4.1 KiB
PHP

<?= $this->extend('layout/main') ?>
<?= $this->section('content') ?>
<?php $fmt = static fn ($v) => number_format((float) $v, 2, ',', ' ') . ' zł'; ?>
<div class="d-flex justify-content-between align-items-center mb-3 flex-wrap gap-2">
<h1 class="h4 mb-0">Pulpit finansów</h1>
<?= form_open('finances', ['method' => 'get', 'class' => 'row g-2 align-items-end']) ?>
<div class="col-auto">
<label class="form-label small mb-1">Od</label>
<input type="date" name="from" class="form-control form-control-sm" value="<?= esc($from) ?>">
</div>
<div class="col-auto">
<label class="form-label small mb-1">Do</label>
<input type="date" name="to" class="form-control form-control-sm" value="<?= esc($to) ?>">
</div>
<div class="col-auto">
<button class="btn btn-sm btn-outline-primary">Pokaż</button>
</div>
<?= form_close() ?>
</div>
<div class="row g-3 mb-4">
<div class="col-md-4"><div class="card stat-card shadow-sm"><div class="card-body">
<div class="text-muted small">Przychody</div>
<div class="value amount-income"><?= $fmt($totals['income']) ?></div>
</div></div></div>
<div class="col-md-4"><div class="card stat-card shadow-sm"><div class="card-body">
<div class="text-muted small">Wydatki</div>
<div class="value amount-expense"><?= $fmt($totals['expense']) ?></div>
</div></div></div>
<div class="col-md-4"><div class="card stat-card shadow-sm"><div class="card-body">
<div class="text-muted small">Saldo</div>
<div class="value <?= $totals['balance'] >= 0 ? 'amount-income' : 'amount-expense' ?>"><?= $fmt($totals['balance']) ?></div>
</div></div></div>
</div>
<div class="row g-3">
<div class="col-12"><div class="card shadow-sm"><div class="card-body">
<h2 class="h6">Bilans miesięczny</h2>
<div id="chartMonthly"></div>
</div></div></div>
<div class="col-12"><div class="card shadow-sm"><div class="card-body">
<h2 class="h6">Wydatki wg kategorii</h2>
<div id="chartByCat"></div>
</div></div></div>
<div class="col-12"><div class="card shadow-sm"><div class="card-body">
<h2 class="h6">Saldo skumulowane</h2>
<div id="chartRunning"></div>
</div></div></div>
</div>
<?= $this->endSection() ?>
<?= $this->section('scripts') ?>
<script>
const monthly = <?= json_encode($monthly, JSON_UNESCAPED_UNICODE) ?>;
const byCat = <?= json_encode($byCat, JSON_UNESCAPED_UNICODE) ?>;
const running = <?= json_encode($running, JSON_UNESCAPED_UNICODE) ?>;
new ApexCharts(document.querySelector('#chartMonthly'), {
chart: { type: 'bar', height: 320 },
series: [
{ name: 'Przychody', data: monthly.map(r => Number(r.income)) },
{ name: 'Wydatki', data: monthly.map(r => Number(r.expense)) }
],
xaxis: { categories: monthly.map(r => r.ym) },
colors: ['#1a7f37', '#c62828'],
dataLabels: { enabled: false },
noData: { text: 'Brak danych w wybranym zakresie' }
}).render();
new ApexCharts(document.querySelector('#chartByCat'), {
chart: { type: 'bar', height: Math.max(320, byCat.length * 36) },
plotOptions: { bar: { horizontal: true, borderRadius: 3, distributed: true } },
series: [{ name: 'Wydatki', data: byCat.map(r => Number(r.total)) }],
xaxis: { categories: byCat.map(r => r.name) },
colors: ['#c62828', '#1565c0', '#2e7d32', '#f9a825', '#6a1b9a', '#00838f',
'#ef6c00', '#c2185b', '#5d4037', '#455a64', '#7cb342', '#0277bd'],
legend: { show: false },
dataLabels: { enabled: false },
noData: { text: 'Brak wydatków w zakresie' }
}).render();
new ApexCharts(document.querySelector('#chartRunning'), {
chart: { type: 'area', height: 300 },
series: [{ name: 'Saldo', data: running.map(r => Number(r.balance)) }],
xaxis: { categories: running.map(r => r.date), type: 'category' },
colors: ['#1565c0'],
stroke: { curve: 'smooth', width: 2 },
dataLabels: { enabled: false },
noData: { text: 'Brak danych w wybranym zakresie' }
}).render();
</script>
<?= $this->endSection() ?>