App: ledger - Page: index
PHP
index.php
|
HTML
index.pad
|
Result
|
<?php
// The month at a glance: what came in, what went out, what is left; six months of it as a // chart, this month's spending by category, the budgets, the accounts, the latest entries // - and a quick entry that ledger.js posts as JSON, answered by quick.php.
$totals = ledgerTotals ( $ledgerMonth ); $history = ledgerHistory ( $ledgerMonth ); $spending = ledgerSpending ( $ledgerMonth ); $budgets = ledgerBudgets ( $ledgerMonth ); $accounts = ledgerAccounts (); $latest = array_slice ( array_values ( array_filter ( ledgerRows ( $ledgerMonth ), fn ( $r ) => $r ['kind'] != 'transfer' ) ), 0, 8 ); $spendable = array_values ( array_filter ( ledgerCategories (), fn ( $c ) => $c ['kind'] == 'expense' ) ); $monthName = ledgerMonthName ( $ledgerMonth ); $today = date ( 'Y-m-d' );
$ledgerPage = $monthName;
?>
|
<div class="head"> <h1>{$monthName}</h1> <span class="dim">{$totals.entries} entries</span> </div>
<section class="kpis" aria-label="This month"> <div class="kpi in"><span>Income</span><b data-kpi="income">{$totals.income | money}</b></div> <div class="kpi out"><span>Spending</span><b data-kpi="spent">{$totals.spent | money}</b></div> <div class="kpi"><span>Left</span><b data-kpi="left">{$totals.left | money}</b></div> <div class="kpi"><span>Kept</span><b data-kpi="kept">{$totals.kept}%</b></div> </section>
<div class="columns">
<div class="main">
<section class="card"> <h2>Six months</h2> {chart 'bar', data='history', label='month', value='income, spending', title='Income and spending, six months'} </section>
<section class="card"> <h2>Where it went</h2> {if $totals.spent gt 0} {chart 'donut', data='spending', label='category', value='spent', title='Spending by category'} {else} <p class="dim">Nothing spent this month.</p> {/if} </section>
<section class="card"> <h2>Budgets <a class="more" href="{$padGo}budgets{?month}">Change</a></h2> <ul class="budgets"> {budgets} <li class="{$state}"> <div class="line"><span class="dot" style="background: {$color}"></span><b>{$name}</b><span>{$spent | money} of {$monthly | money}</span></div> {progress $share, max=100, label=$name, color=$tone} </li> @else@ <li class="dim">No budgets yet.</li> {/budgets} </ul> </section>
</div>
<aside class="side">
<section class="card quick"> <h2>Quick entry</h2> {form 'quick', action='?quick', class='quick-form'} <input type="hidden" name="month" value="{$ledgerMonth}"> <label for="q-amount">Amount</label> <input id="q-amount" name="amount" inputmode="decimal" placeholder="12.50" required pattern="[0-9]+([.,][0-9][0-9]?)?"> <label for="q-category">Category</label> <select id="q-category" name="category">{spendable}<option value="{$id}">{$name}</option>{/spendable}</select> <label for="q-note">Note</label> <input id="q-note" name="note" placeholder="Coffee" maxlength="120"> <button class="button primary">Spend it</button> <p class="said" role="status"></p> {/form} </section>
<section class="card"> <h2>Accounts</h2> <ul class="accounts"> {accounts}<li><span>{$name}</span><b class="{if $balance lt 0}neg{/if}">{$balance | money}</b></li>{/accounts} </ul> </section>
<section class="card"> <h2>Latest <a class="more" href="{$padGo}transactions{?month}">All</a></h2> <ul class="latest"> {latest}<li><span class="day">{$day | date('j M')}</span><span class="what">{$note}<small>{$category}</small></span><b class="{if $amount lt 0}neg{else}pos{/if}">{$amount | money}</b></li> @else@<li class="dim">No entries this month.</li>{/latest} </ul> </section>
</aside>
</div>
|
|
App: ledger - Page: transactions
PHP
transactions.php
|
HTML
transactions.pad
|
Result
|
<?php
// A month's transactions as one table - sorted and paged on the server by {datatable} - // narrowed to a category, an account or a word in the note. The same rows answer as CSV // (?transactions&padFormat=csv) and JSON: $padExpose names them.
$only = (int) padRequest ( 'category', 0 ); $from = (int) padRequest ( 'account', 0 ); $word = trim ( ledgerText ( 'q' ) );
$rows = array_map ( fn ( $r ) => array_diff_key ( $r, [ 'id' => 1, 'kind' => 1 ] ), ledgerRows ( $ledgerMonth, $only, $from, $word ) ); $shown = count ( $rows ); $sum = round ( array_sum ( array_column ( $rows, 'amount' ) ), 2 );
$categoryList = array_map ( fn ( $c ) => $c + [ 'chosen' => $c ['id'] == $only ], ledgerCategories () ); $accountList = array_map ( fn ( $a ) => $a + [ 'chosen' => $a ['id'] == $from ], ledgerAccounts () ); $monthName = ledgerMonthName ( $ledgerMonth ); $csvName = "ledger-$ledgerMonth.csv"; $csvQuery = http_build_query ( [ 'month' => $ledgerMonth, 'category' => $only, 'account' => $from, 'q' => $word, 'padFormat' => 'csv' ] );
$padExpose = [ 'rows' ]; $ledgerPage = "Transactions, $monthName";
?>
|
<div class="head"> <h1>Transactions <span class="dim">{$monthName}</span></h1> <a class="button" href="{$padGo}transactions&{$csvQuery}" download="{$csvName}">⬇ CSV</a> </div>
<form class="filters" method="get"> <input type="hidden" name="transactions" value=""> <input type="hidden" name="month" value="{$ledgerMonth}"> <label>Category <select name="category"><option value="0">All</option>{categoryList}<option value="{$id}"{if $chosen} selected{/if}>{$name}</option>{/categoryList}</select> </label> <label>Account <select name="account"><option value="0">All</option>{accountList}<option value="{$id}"{if $chosen} selected{/if}>{$name}</option>{/accountList}</select> </label> <label>Note <input type="search" name="q" value="{$word}" placeholder="a word"></label> <button class="button">Show</button> </form>
<section class="card table"> {if $shown gt 0} {datatable data='rows', columns='day, category, account, note, amount', format="amount:money, day:date('D j M')", totals='amount', sortable, rows=15, striped} {else} <p class="dim">No transactions here.</p> {/if} <p class="dim sum">{$shown} transactions, together {$sum | money}.</p> </section>
|
|
App: manual - Page: fragments/expressions_41
App: regression/errors - Page: eval/the_date_pipe_reads_a_date_that_does_not_exist_as_no_date
PHP
|
HTML
eval/the_date_pipe_reads_a_date_that_does_not_exist_as_no_date.pad
|
Result
|
|
{echo '2026-02-30' | date('Y-m-d')}
|
|
App: regression/errors - Page: syntax/date_names_a_change_it_cannot_read
PHP
|
HTML
syntax/date_names_a_change_it_cannot_read.pad
|
Result
|
|
{echo 0 | date('Y', 'nonsense words')}
|
|
App: regression/framework - Page: custom/an_application_function_can_answer_a_date_object
PHP
custom/an_application_function_can_answer_a_date_object.php
|
HTML
custom/an_application_function_can_answer_a_date_object.pad
|
Result
|
<?php
$order = 'x';
?>
|
[{$order | dueDate | date('Y-m-d')}][{$order | dueDate | ago('2020-01-03 03:04:05')}][{$order | dueDate}]
|
|
App: regression/framework - Page: expressions/a_built_in_function_is_found_in_its_own_case_only
PHP
|
HTML
expressions/a_built_in_function_is_found_in_its_own_case_only.pad
|
Result
|
|
[{echo DATE('Y', 0)}][{echo date('Y', 0)}][{echo 'a.b.c' | afterLast('.')}]
|
|
App: regression/framework - Page: expressions/a_built_in_written_as_a_call_reads_its_first_argument
PHP
|
HTML
expressions/a_built_in_written_as_a_call_reads_its_first_argument.pad
|
Result
|
|
{set $s = 'hello'}[{echo trim(' a ')}][{echo upper($s)}][{echo left($s, 2)}][{if upper($s) eq 'HELLO'}T{else}F{/if}][{echo 'x' . upper($s)}][{echo date('Y', 0)}][{echo $s | replace('l', upper('x'))}][{echo substr($s, 0, 3)}][{echo $s | left(2)}][{$s | left(3)}]
|
|
App: regression/framework - Page: expressions/a_date_object_is_its_text_to_operators_and_text_pipes
PHP
expressions/a_date_object_is_its_text_to_operators_and_text_pipes.php
|
HTML
expressions/a_date_object_is_its_text_to_operators_and_text_pipes.pad
|
Result
|
<?php
// A date object a page's PHP leaves is its text - Y-m-d H:i:s, as {$d} writes it - to an // operator, a pipe that takes text and a query value: compared as an object it stood above // every string, and | upper, . and {?d} ended the page on a TypeError.
$d = new DateTime ( '2020-01-02 03:04:05' );
?>
|
lt[{if $d lt '2030-01-01'}Y{else}N{/if}] gt[{if $d gt '2030-01-01'}Y{else}N{/if}] eq[{if $d eq '2020-01-02 03:04:05'}Y{else}N{/if}] [{$d | upper}] [{$d | left(10)}] [{echo $d . ' UTC'}] [{$d | date('Y')}] [{?d}]
|
|
App: regression/framework - Page: expressions/a_fallback_hands_a_date_object_on_as_the_moment_it_holds
PHP
expressions/a_fallback_hands_a_date_object_on_as_the_moment_it_holds.php
|
HTML
expressions/a_fallback_hands_a_date_object_on_as_the_moment_it_holds.pad
|
Result
|
<?php
$moment = new DateTimeImmutable ( '2020-01-01T03:00:00+03:00' );
?>
|
[{echo $moment | date('U')}][{echo ($moment ?? 'none') | date('U')}][{echo ($nothing ?? $moment) | date('U')}][{echo $moment | default('x') | date('U')}][{$moment | optional | date('U')}][{echo [$moment ?? 'none'] | php:count}]
|
|
App: regression/framework - Page: functions/a_date_modifier_starts_its_day_where_summer_time_begins_at_midnight
PHP
functions/a_date_modifier_starts_its_day_where_summer_time_begins_at_midnight.php
|
HTML
functions/a_date_modifier_starts_its_day_where_summer_time_begins_at_midnight.pad
|
Result
|
<?php
// Cairo's summer time began at midnight on 28 April 2023 - that day had no 00:00; // 1682672400 is noon on it.
$padTimezone = 'Africa/Cairo';
?>
|
[{echo 1682672400 | date('Y-m-d H:i', '1 jan')}][{echo 1682672400 | date('Y-m-d H:i', '1 jan +5 hours')}][{echo 1682672400 | date('Y-m-d H:i', 'Feb 5 -1 hour')}][{echo 1682672400 | date('Y-m-d H:i', '+1 day')}][{echo 1682672400 | date('Y-m-d H:i', 'midnight')}]
|
|
App: regression/framework - Page: functions/a_date_modifier_with_a_date_and_a_relative_time_keeps_the_time
PHP
functions/a_date_modifier_with_a_date_and_a_relative_time_keeps_the_time.php
|
HTML
functions/a_date_modifier_with_a_date_and_a_relative_time_keeps_the_time.pad
|
Result
|
<?php
// 1700000000 is 22:13 UTC on 14 November 2023.
$padTimezone = 'UTC';
?>
|
[{echo 1700000000 | date('Y-m-d H:i', '1 jan +5 hours')}][{echo 1700000000 | date('Y-m-d H:i', '2024-02-03 +90 minutes')}][{echo 1700000000 | date('Y-m-d H:i', 'Feb 5 -1 hour')}][{echo 1700000000 | date('Y-m-d H:i', '1 jan')}]
|
|
App: regression/framework - Page: functions/a_date_modifier_without_a_time_starts_its_day
PHP
functions/a_date_modifier_without_a_time_starts_its_day.php
|
HTML
functions/a_date_modifier_without_a_time_starts_its_day.pad
|
Result
|
<?php
// 1700000000 is 22:13 UTC on 14 November 2023.
$padTimezone = 'UTC';
?>
|
[{echo 1700000000 | date('Y-m-d H:i', '1 jan')}][{echo 1700000000 | date('Y-m-d H:i', '2024-02-03')}][{echo 1700000000 | date('Y-m-d H:i', 'Feb 5')}][{echo 1700000000 | date('Y-m-d H:i', '+1 week')}][{echo 1700000000 | date('Y-m-d H:i', '1 jan 2020 10:00')}]
|
|
App: regression/framework - Page: functions/date_formats_a_timestamp
PHP
|
HTML
functions/date_formats_a_timestamp.pad
|
Result
|
|
{echo 1702483200 | date('Y-m-d')}
|
|
App: regression/framework - Page: functions/date_gives_the_full_day_name
PHP
|
HTML
functions/date_gives_the_full_day_name.pad
|
Result
|
|
{echo 1702483200 | date('l')}
|
|
|