95 lines
4.1 KiB
PHP
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() ?>
|