<?php
$B = htmlspecialchars(rtrim((string) ($baseUrl ?? ''), '/'));
if (!function_exists('pp_where')) {
    function pp_where(string $path, string $lang = 'php'): string {
        $l = $lang === 'js' ? 'JS' : 'PHP';
        return '<div class="help-where"><span class="help-where-tag"><i class="bi bi-geo-alt-fill"></i> Where</span>'
             . '<span class="help-where-path">' . $path . '</span>'
             . '<span class="help-where-lang ' . htmlspecialchars($lang) . '">' . $l . '</span></div>';
    }
}
?>
<h1><i class="bi bi-pencil-square"></i> Add &amp; Edit pages</h1>
<p class="lead">The data-entry forms. Set defaults, validate, calculate fields, and make fields react to each other —
each recipe below says <strong>exactly where the code goes</strong>.</p>

<h2>Events these pages fire</h2>
<table class="help-table">
    <thead><tr><th>Event</th><th>Where</th><th>Use for</th></tr></thead>
    <tbody>
        <tr><td>Before Add / Edit Load</td><td>Table → <b>Page Events</b> (PHP)</td><td>Defaults, prefill, hide fields before the form shows.</td></tr>
        <tr><td>Before Add / Edit Save</td><td>Table → <b>Page Events</b> (PHP)</td><td>Validate + change data before it's written.</td></tr>
        <tr><td>After Add / Edit Save</td><td>Table → <b>Page Events</b> (PHP)</td><td>Email, log, side-effects after it's stored.</td></tr>
        <tr><td>On Page Init</td><td>Table → <b>Client Events</b> (JS)</td><td>Your “on load” — focus, wire fields, initial UI.</td></tr>
        <tr><td>Before Form Submit</td><td>Table → <b>Client Events</b> (JS)</td><td>Last-second client validation; <code>return false</code> to stop.</td></tr>
        <tr><td>On Change / On Blur (a field)</td><td>Table → <b>Fields</b> → &lt;field&gt; → Client</td><td>React when one field changes.</td></tr>
        <tr><td>Calculate / Validate (a field)</td><td>Table → <b>Fields</b> → &lt;field&gt; → Server</td><td>Compute or check one field on the server.</td></tr>
    </tbody>
</table>

<h2>Recipes</h2>

<h3>1 · Default values for a new record</h3>
<?= pp_where('Events → <b>orders</b> → Page Events → <b>Before Add Load</b>', 'php') ?>
<pre><code>$data['status']     = 'draft';
$data['order_date'] = today();
$data['created_by'] = \PpPhp\Core\Security::CurrentUsername();</code></pre>

<h3>2 · Server-side validation</h3>
<?= pp_where('Events → <b>orders</b> → Page Events → <b>Before Edit Save</b>', 'php') ?>
<pre><code>if (($data['discount'] ?? 0) &gt; ($data['total'] ?? 0)) {
    $errors[] = 'Discount cannot exceed the total.';
    return false;   // block the save; the message shows on the form
}
// you can also change the data before it's written:
$data['updated_at'] = now();</code></pre>

<h3>3 · Calculate a field live as the user types</h3>
<?= pp_where('Events → <b>orders</b> → Fields → <b>quantity</b> → <b>On Change</b> (Client)', 'js') ?>
<pre><code>function recalc() {
    var qty   = +Runner.getControlValue('quantity') || 0;
    var price = +Runner.getControlValue('price')    || 0;
    Runner.setControlValue('line_total', (qty * price).toFixed(2));
}
recalc();
Runner.getControl('quantity').onChange(recalc);
Runner.getControl('price').onChange(recalc);</code></pre>

<h3>4 · Show a field only when another has a certain value</h3>
<?= pp_where('Events → <b>customers</b> → Fields → <b>type</b> → <b>On Change</b> (Client)', 'js') ?>
<pre><code>function sync() { Runner.getControl('vat_number').visible(Runner.getControlValue('type') === 'company'); }
sync();
Runner.getControl('type').onChange(sync);</code></pre>

<h3>5 · Autofill from the server when an email is entered</h3>
<?= pp_where('Events → <b>orders</b> → Fields → <b>email</b> → <b>On Blur</b> (Client)', 'js') ?>
<pre><code>var contact = await pp.run('findContact', { email: Runner.getControlValue('email') });
if (contact) Runner.setData({ customer_name: contact.name, phone: contact.phone });
// server side: Custom Functions → PHP → function action_findContact($params) { … return $row; }</code></pre>

<h3>6 · Confirm before the form submits</h3>
<?= pp_where('Events → <b>orders</b> → Client Events → <b>Before Form Submit</b>', 'js') ?>
<pre><code>if (!await pp.dialog.confirm('Submit this order?', 'You can’t edit it afterwards.')) return false;</code></pre>

<h3>7 · Require at least one detail line (Master/Detail)</h3>
<?= pp_where('Events → <b>orders</b> → Client Events → <b>Before Form Submit</b>', 'js') ?>
<pre><code>if (Runner.detail('order_items').count() === 0) {
    pp.dialog.toast('warning', 'Add at least one line item first.');
    return false;
}</code></pre>

<h3>8 · Total the child lines onto the master before saving</h3>
<?= pp_where('Events → <b>orders</b> → Client Events → <b>Before Form Submit</b>', 'js') ?>
<pre><code>var items = Runner.detail('order_items').getAllRecords();
Runner.setControlValue('total', items.reduce(function (s, it) { return s + (+it.qty) * (+it.price); }, 0));</code></pre>

<h3>9 · Email a receipt after saving</h3>
<?= pp_where('Events → <b>orders</b> → Page Events → <b>After Add Save</b>', 'php') ?>
<pre><code>pp_send_email($data['customer_email'], 'Order received', 'Your order #' . $id . ' is confirmed.');</code></pre>

<h3>10 · Lock the form to read-only for some users</h3>
<?= pp_where('Events → <b>orders</b> → Client Events → <b>On Page Init</b>', 'js') ?>
<pre><code>Runner.fields().forEach(function (f) { Runner.getControl(f).readonly(true); });
Runner.button('save').hide();</code></pre>

<div class="help-callout help-callout-info">
    <i class="bi bi-lightbulb"></i>
    <div>Client helpers (<code>Runner.getControl</code>, <code>setData</code>, <code>detail</code>, dialogs) →
        <a href="<?= $B ?>/help/PPjs">PP.js reference</a>. Server helpers (<code>dbExecute</code>,
        <code>pp_send_email</code>) → <a href="<?= $B ?>/help/DB">DB</a> &amp;
        <a href="<?= $B ?>/help/Helpers">Helpers</a>.</div>
</div>
