-
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.
This commit is contained in:
+14
-9
@@ -1,8 +1,9 @@
|
||||
<section class="dead-hero card glow-blue">
|
||||
<section class="dead-hero card">
|
||||
<div>
|
||||
<span class="metric-icon purple"><?= icon('vault') ?></span>
|
||||
<p class="eyebrow">Dormant and disregarded</p>
|
||||
<h2>Dead account balance</h2>
|
||||
<p>Money here is excluded from usable monthly funds until you explicitly restore it.</p>
|
||||
<h2>Your out-of-use reserve</h2>
|
||||
<p>Money here is subtracted from spendable funds, remains fully traceable, and can later be restored to monthly income or earmarked for a target.</p>
|
||||
</div>
|
||||
<?php if ($hideBalance): ?>
|
||||
<button class="concealed-balance" type="button" data-concealed-balance data-value="<?= h(Support::money($balance, $symbol)) ?>">
|
||||
@@ -16,10 +17,14 @@
|
||||
<section class="content-grid dead-grid">
|
||||
<article class="card">
|
||||
<div class="card-heading"><div><p class="eyebrow">Manual movement</p><h2>Deposit or restore</h2></div></div>
|
||||
<form method="post" class="stack-form">
|
||||
<form method="post" class="stack-form" data-dead-transfer-form>
|
||||
<?= csrf_field() ?><input type="hidden" name="action" value="dead.move"><input type="hidden" name="month" value="<?= h($month) ?>">
|
||||
<label>Direction<select name="direction"><option value="deposit">Move into dormant account</option><option value="restore">Restore to this month’s usable budget</option></select></label>
|
||||
<label>Amount<div class="money-input"><span><?= h($symbol) ?></span><input type="number" name="amount" min="0.01" step="0.01" required></div></label>
|
||||
<div class="form-grid" data-restore-fields hidden>
|
||||
<label>Restore to<select name="destination_type" data-restore-type><option value="income">Monthly income</option><option value="item">Specific budget target</option></select></label>
|
||||
<label data-restore-item hidden>Budget target<select name="destination_id"><option value="">Choose a target</option><?php foreach ($items as $item): ?><option value="<?= (int) $item['id'] ?>"><?= h($item['name']) ?> · <?= h(Support::money($item['remaining_amount'], $symbol)) ?> left</option><?php endforeach; ?></select></label>
|
||||
</div>
|
||||
<label>Reason<textarea name="notes" rows="3" placeholder="Emergency reserve, return to groceries…"></textarea></label>
|
||||
<button class="button primary" type="submit">Record transfer</button>
|
||||
</form>
|
||||
@@ -27,9 +32,9 @@
|
||||
<article class="card">
|
||||
<div class="card-heading"><div><p class="eyebrow">Automatic rules</p><h2>How funds arrive here</h2></div><a class="text-link" href="<?= h(url('settings')) ?>">Configure →</a></div>
|
||||
<div class="rule-list">
|
||||
<div><span class="metric-icon blue">↙</span><p><strong>Income withholding</strong><small><?= h((string) $settings->get('dead.income_value', 0)) ?><?= $settings->get('dead.income_mode') === 'percent' ? '%' : ' fixed' ?> from each income source</small></p></div>
|
||||
<div><span class="metric-icon pink">↗</span><p><strong>Transaction pull</strong><small><?= h((string) $settings->get('dead.transaction_value', 0)) ?><?= $settings->get('dead.transaction_mode') === 'percent' ? '%' : ' fixed' ?> whenever an expense is recorded</small></p></div>
|
||||
<div><span class="metric-icon orange">◇</span><p><strong>Restorations</strong><small>Return to the selected month without changing historical expense records</small></p></div>
|
||||
<div><span class="metric-icon blue"><?= icon('wallet') ?></span><p><strong>Income withholding</strong><small><?= h((string) $settings->get('dead.income_value', 0)) ?><?= $settings->get('dead.income_mode') === 'percent' ? '%' : ' fixed' ?> from each income source</small></p></div>
|
||||
<div><span class="metric-icon pink"><?= icon('expense') ?></span><p><strong>Transaction pull</strong><small><?= h((string) $settings->get('dead.transaction_value', 0)) ?><?= $settings->get('dead.transaction_mode') === 'percent' ? '%' : ' fixed' ?> whenever an expense is recorded</small></p></div>
|
||||
<div><span class="metric-icon orange"><?= icon('data') ?></span><p><strong>Restorations</strong><small>Return to monthly income or identify a specific target without rewriting history</small></p></div>
|
||||
</div>
|
||||
</article>
|
||||
</section>
|
||||
@@ -37,7 +42,7 @@
|
||||
<article class="card">
|
||||
<div class="card-heading">
|
||||
<div><p class="eyebrow">Permanent paper trail</p><h2>Dormant ledger</h2></div>
|
||||
<label class="search-box"><span>⌕</span><input type="search" placeholder="Search movements…" data-table-search="dead-table"></label>
|
||||
<label class="search-box"><?= icon('search') ?><input type="search" placeholder="Search movements…" data-table-search="dead-table"></label>
|
||||
</div>
|
||||
<?php if ($entries === []): ?>
|
||||
<div class="empty-state"><strong>The account is empty</strong><p>Automatic or manual transfers will appear here.</p></div>
|
||||
@@ -51,7 +56,7 @@
|
||||
<td><?= h(date('M j, Y g:i A', strtotime($entry['created_at']))) ?></td>
|
||||
<td><a class="text-link" href="<?= h(url('dead-account', ['month' => $entry['month']])) ?>"><?= h($entry['month']) ?></a></td>
|
||||
<td><strong><?= h(ucwords(str_replace('_', ' ', $entry['kind']))) ?></strong><?php if ($entry['notes']): ?><small><?= h($entry['notes']) ?></small><?php endif; ?></td>
|
||||
<td><?= h(ucfirst((string) ($entry['source_type'] ?: 'manual'))) ?></td>
|
||||
<td><?php if ($entry['source_type'] === 'restore_item'): ?>Target: <?= h($entry['destination_name'] ?: 'Archived target') ?><?php elseif ($entry['source_type'] === 'restore_income'): ?>Monthly income<?php else: ?><?= h(ucwords(str_replace('_', ' ', (string) ($entry['source_type'] ?: 'manual')))) ?><?php endif; ?></td>
|
||||
<td class="<?= (float) $entry['amount'] >= 0 ? 'green' : 'orange' ?>"><strong><?= (float) $entry['amount'] >= 0 ? '+' : '' ?><?= h(Support::money($entry['amount'], $symbol)) ?></strong></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
|
||||
Reference in New Issue
Block a user