Files
budget/views/transactions.php
T
Ty Clifford 51ee4ecb5a -
Finished the planner end to end.
Corrected rollover and yearly accounting, recurring targets, savings 
rules, and targeted dormant restorations.
Added editing/deletion for income, expenses, targets, and categories.
Rebuilt dashboard, analytics, calendar, settings, exports, 
authentication, and responsive mobile UI.
Added original artwork at 
[financial-flow.png](/Users/tyemeclifford/Documents/GH/budget/public/assets/images/financial-flow.png), 
generated with built-in Imagegen using an abstract financial-momentum 
landscape prompt.
Added 
[self-test.php](/Users/tyemeclifford/Documents/GH/budget/scripts/self-test.php).
Verification passed: automated accounting/export tests, full browser 
workflow, responsive 390px layout, light/dark themes, and no console 
errors. Tested with FrankenPHP v1.12.4. Live Mailgun delivery was not 
attempted without credentials.
2026-06-15 10:33:55 -04:00

67 lines
6.3 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<section class="page-intro">
<div><p class="eyebrow">Searchable expense ledger</p><h2>Every payment, one trail</h2><p>Link a payment to a target and its owing balance moves immediately.</p></div>
<button class="button primary" type="button" data-dialog-open="expense-dialog"><?= icon('plus') ?> Record expense</button>
</section>
<section class="summary-grid">
<article class="summary-card card"><span class="metric-icon blue"><?= icon('wallet') ?></span><div><small>Available</small><strong><?= h(Support::money($summary['gross_resources'], $symbol)) ?></strong></div></article>
<article class="summary-card card"><span class="metric-icon pink"><?= icon('expense') ?></span><div><small>Spent</small><strong><?= h(Support::money($summary['expenses'], $symbol)) ?></strong></div></article>
<article class="summary-card card"><span class="metric-icon purple"><?= icon('vault') ?></span><div><small>Set aside</small><strong><?= h(Support::money($summary['dead_deposits'], $symbol)) ?></strong></div></article>
<article class="summary-card card"><span class="metric-icon green"><?= icon('chart') ?></span><div><small>Remaining</small><strong class="<?= $summary['remaining'] < 0 ? 'red' : '' ?>"><?= h(Support::money($summary['remaining'], $symbol)) ?></strong></div></article>
</section>
<article class="card panel">
<div class="card-heading">
<div><p class="eyebrow"><?= h(date('F Y', strtotime($month . '-01'))) ?></p><h2>Transaction history</h2><p class="heading-note"><?= count($transactions) ?> recorded expense<?= count($transactions) === 1 ? '' : 's' ?></p></div>
<label class="search-box"><?= icon('search') ?><input type="search" placeholder="Search description, item, category…" data-table-search="expense-table"></label>
</div>
<?php if ($transactions === []): ?>
<div class="empty-state"><span class="empty-icon"><?= icon('expense') ?></span><strong>No expenses recorded</strong><p>Record a payment to start progressing this months targets.</p><button class="button small" type="button" data-dialog-open="expense-dialog">Record the first expense</button></div>
<?php else: ?>
<div class="table-wrap">
<table id="expense-table" class="data-table">
<thead><tr><th>Date</th><th>Description</th><th>Category / target</th><th>Amount</th><th>Dormant pull</th><th><span class="sr-only">Actions</span></th></tr></thead>
<tbody>
<?php foreach ($transactions as $transaction): ?>
<tr>
<td data-label="Date"><span class="table-date"><?= h(date('M j', strtotime($transaction['transacted_on']))) ?><small><?= h(date('Y', strtotime($transaction['transacted_on']))) ?></small></span></td>
<td data-label="Description"><strong><?= h($transaction['merchant']) ?></strong><?php if ($transaction['notes']): ?><small><?= h($transaction['notes']) ?></small><?php endif; ?></td>
<td data-label="Category / target"><span class="pill"><i style="--dot:<?= h($transaction['category_color'] ?: '#718096') ?>"></i><?= h($transaction['category_name'] ?: 'Uncategorized') ?></span><?php if ($transaction['item_name']): ?><small><?= h($transaction['item_name']) ?></small><?php endif; ?></td>
<td data-label="Amount"><strong class="amount-negative">-<?= h(Support::money($transaction['amount'], $symbol)) ?></strong></td>
<td data-label="Dormant pull"><?= h(Support::money($transaction['dead_pull_amount'], $symbol)) ?></td>
<td class="table-actions">
<button class="icon-button" type="button" data-dialog-open="expense-edit-<?= (int) $transaction['id'] ?>" aria-label="Edit <?= h($transaction['merchant']) ?>"><?= icon('edit') ?></button>
<form method="post" data-confirm="Delete this expense and reverse its dormant transfer?">
<?= csrf_field() ?><input type="hidden" name="action" value="transaction.delete"><input type="hidden" name="month" value="<?= h($month) ?>"><input type="hidden" name="id" value="<?= (int) $transaction['id'] ?>">
<button class="icon-button danger" type="submit" aria-label="Delete <?= h($transaction['merchant']) ?>"><?= icon('trash') ?></button>
</form>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php endif; ?>
</article>
<dialog id="expense-dialog">
<form method="post" class="dialog-card">
<?= csrf_field() ?><input type="hidden" name="action" value="transaction.add"><input type="hidden" name="month" value="<?= h($month) ?>">
<div class="dialog-heading"><div><p class="eyebrow">Progress a target</p><h2>Record expense</h2></div><button class="icon-button" type="button" data-dialog-close><?= icon('close') ?></button></div>
<?php require APP_ROOT . '/views/partials/transaction-fields.php'; ?>
<p class="form-note">Your configured per-transaction dormant rule is applied automatically.</p>
<div class="dialog-actions"><button class="button" type="button" data-dialog-close>Cancel</button><button class="button primary" type="submit">Record expense</button></div>
</form>
</dialog>
<?php foreach ($transactions as $transaction): ?>
<dialog id="expense-edit-<?= (int) $transaction['id'] ?>">
<form method="post" class="dialog-card">
<?= csrf_field() ?><input type="hidden" name="action" value="transaction.update"><input type="hidden" name="month" value="<?= h($month) ?>"><input type="hidden" name="id" value="<?= (int) $transaction['id'] ?>">
<div class="dialog-heading"><div><p class="eyebrow">Maintain transaction</p><h2>Edit <?= h($transaction['merchant']) ?></h2></div><button class="icon-button" type="button" data-dialog-close><?= icon('close') ?></button></div>
<?php $editingTransaction = $transaction; require APP_ROOT . '/views/partials/transaction-fields.php'; unset($editingTransaction); ?>
<div class="dialog-actions"><button class="button" type="button" data-dialog-close>Cancel</button><button class="button primary" type="submit">Save expense</button></div>
</form>
</dialog>
<?php endforeach; ?>