first commit
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
<?= $this->extend('layout/main') ?>
|
||||
|
||||
<?= $this->section('content') ?>
|
||||
<h1 class="h4 mb-3"><?= esc($title) ?></h1>
|
||||
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-body">
|
||||
<?php $action = $op ? site_url('operations/' . $op['id']) : site_url('operations'); ?>
|
||||
<?= form_open($action, ['class' => 'row g-3']) ?>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label">Data</label>
|
||||
<input type="date" name="date" class="form-control" required
|
||||
value="<?= esc(old('date', $op['date'] ?? date('Y-m-d'))) ?>">
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label">Kwota (zł)</label>
|
||||
<input type="number" step="0.01" min="0.01" name="amount" class="form-control" required
|
||||
value="<?= esc(old('amount', $op['amount'] ?? '')) ?>">
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label">Typ</label>
|
||||
<?php $t = old('type', $op['type'] ?? 'expense'); ?>
|
||||
<select name="type" id="type" class="form-select" required>
|
||||
<option value="income" <?= $t === 'income' ? 'selected' : '' ?>>Przychód</option>
|
||||
<option value="expense" <?= $t === 'expense' ? 'selected' : '' ?>>Wydatek</option>
|
||||
</select>
|
||||
<div class="form-text">Wybór kategorii ustawia typ automatycznie.</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">Kategoria</label>
|
||||
<?php $selCat = old('category_id', $op['category_id'] ?? ''); ?>
|
||||
<select name="category_id" id="category_id" class="form-select">
|
||||
<option value="" data-type="">— bez kategorii —</option>
|
||||
<?php foreach ($categories as $c): ?>
|
||||
<option value="<?= $c['id'] ?>" data-type="<?= $c['type'] ?>"
|
||||
<?= (string) $selCat === (string) $c['id'] ? 'selected' : '' ?>>
|
||||
<?= esc($c['indent_label']) ?> (<?= $c['type'] === 'income' ? 'przychód' : 'wydatek' ?>)
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">Opis (opcjonalnie)</label>
|
||||
<input type="text" name="description" class="form-control" maxlength="255"
|
||||
value="<?= esc(old('description', $op['description'] ?? '')) ?>">
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<button type="submit" class="btn btn-primary">Zapisz</button>
|
||||
<a href="<?= site_url('operations') ?>" class="btn btn-link">Anuluj</a>
|
||||
</div>
|
||||
<?= form_close() ?>
|
||||
</div>
|
||||
</div>
|
||||
<?= $this->endSection() ?>
|
||||
|
||||
<?= $this->section('scripts') ?>
|
||||
<script>
|
||||
// Kategoria narzuca typ operacji (spojnosc ze zrodlem prawdy po stronie serwera).
|
||||
const cat = document.getElementById('category_id');
|
||||
const type = document.getElementById('type');
|
||||
function syncType() {
|
||||
const opt = cat.options[cat.selectedIndex];
|
||||
const t = opt.getAttribute('data-type');
|
||||
if (t) { type.value = t; type.setAttribute('disabled', 'disabled'); }
|
||||
else { type.removeAttribute('disabled'); }
|
||||
}
|
||||
cat.addEventListener('change', syncType);
|
||||
syncType();
|
||||
// disabled select nie wysyla wartosci -> odblokuj przy submit (serwer i tak wymusi typ z kategorii)
|
||||
type.form.addEventListener('submit', () => type.removeAttribute('disabled'));
|
||||
</script>
|
||||
<?= $this->endSection() ?>
|
||||
@@ -0,0 +1,107 @@
|
||||
<?= $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">
|
||||
<h1 class="h4 mb-0">Operacje</h1>
|
||||
<a href="<?= site_url('operations/new') ?>" class="btn btn-primary">+ Nowa operacja</a>
|
||||
</div>
|
||||
|
||||
<div class="card shadow-sm mb-3">
|
||||
<div class="card-body">
|
||||
<?= form_open('operations', ['method' => 'get', 'class' => 'row g-2 align-items-end']) ?>
|
||||
<div class="col-6 col-md-3">
|
||||
<label class="form-label small mb-1">Od</label>
|
||||
<input type="date" name="from" class="form-control" value="<?= esc($filter['from'] ?? '') ?>">
|
||||
</div>
|
||||
<div class="col-6 col-md-3">
|
||||
<label class="form-label small mb-1">Do</label>
|
||||
<input type="date" name="to" class="form-control" value="<?= esc($filter['to'] ?? '') ?>">
|
||||
</div>
|
||||
<div class="col-6 col-md-3">
|
||||
<label class="form-label small mb-1">Kategoria</label>
|
||||
<select name="category_id" class="form-select">
|
||||
<option value="">— wszystkie —</option>
|
||||
<?php foreach ($categories as $c): ?>
|
||||
<option value="<?= $c['id'] ?>" <?= (string) ($filter['category_id'] ?? '') === (string) $c['id'] ? 'selected' : '' ?>>
|
||||
<?= esc($c['indent_label']) ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-6 col-md-2">
|
||||
<label class="form-label small mb-1">Typ</label>
|
||||
<select name="type" class="form-select">
|
||||
<option value="">— oba —</option>
|
||||
<option value="income" <?= ($filter['type'] ?? '') === 'income' ? 'selected' : '' ?>>Przychód</option>
|
||||
<option value="expense" <?= ($filter['type'] ?? '') === 'expense' ? 'selected' : '' ?>>Wydatek</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-1">
|
||||
<button class="btn btn-outline-primary w-100">Filtruj</button>
|
||||
</div>
|
||||
<?= form_close() ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row g-3 mb-3">
|
||||
<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="card shadow-sm">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover mb-0 align-middle">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th>Data</th>
|
||||
<th>Kategoria</th>
|
||||
<th>Opis</th>
|
||||
<th class="text-end">Kwota</th>
|
||||
<th class="text-end">Akcje</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php if (empty($operations)): ?>
|
||||
<tr><td colspan="5" class="text-center text-muted py-4">Brak operacji dla wybranych filtrów.</td></tr>
|
||||
<?php else: foreach ($operations as $o): ?>
|
||||
<tr>
|
||||
<td><?= esc($o['date']) ?></td>
|
||||
<td>
|
||||
<?php
|
||||
if (! empty($o['category_name'])) {
|
||||
echo esc(! empty($o['parent_name'])
|
||||
? $o['parent_name'] . ' → ' . $o['category_name']
|
||||
: $o['category_name']);
|
||||
} else {
|
||||
echo '(bez kategorii)';
|
||||
}
|
||||
?>
|
||||
</td>
|
||||
<td class="text-muted"><?= esc($o['description'] ?? '') ?></td>
|
||||
<td class="text-end <?= $o['type'] === 'income' ? 'amount-income' : 'amount-expense' ?>">
|
||||
<?= $o['type'] === 'income' ? '+' : '−' ?><?= $fmt($o['amount']) ?>
|
||||
</td>
|
||||
<td class="text-end">
|
||||
<a href="<?= site_url('operations/' . $o['id'] . '/edit') ?>" class="btn btn-sm btn-outline-secondary">Edytuj</a>
|
||||
<a href="<?= site_url('operations/' . $o['id'] . '/delete') ?>" class="btn btn-sm btn-outline-danger"
|
||||
onclick="return confirm('Usunąć operację?')">Usuń</a>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; endif; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<?= $this->endSection() ?>
|
||||
Reference in New Issue
Block a user