refactor(ssr): compose the bulk-code form entirely in Selmer
Each bulk-code route now ends in a single sel/render call; all composition
(modal chrome, body, account grid, rows, footer, errors) happens in the
templates via {% extends %}/{% block %}/{% include %}/{% with %}, reading one
nested view-model (form-ctx). No HTML is stitched together in Clojure.
- Add components/modal-card.html: a base chrome with head/body/footer blocks;
bulk-code/card.html extends it. (Transaction Edit keeps its string-slot
edit-modal.html for now.)
- New top-level templates: open.html, form.html, card.html, body.html; rework
account-grid/account-row/footer/head to pull the shared component partials in
via {% include %}+{% with %} instead of hardcoding class strings or receiving
pre-rendered HTML strings.
- render-form / open-handler collapse to one sel/render of form.html / open.html.
bulk-code-body*, footer*, form-errors-html, account-grid*, the *errors* dynamic
var and ferr are gone; field errors are read straight from :form-errors.
- Extract sc/{select,button,a-button,a-icon-button}-ctx so templates can include
those partials with computed context (the render wrappers now call the -ctx fns).
Verified: rendered output is DOM-identical to the prior version across empty /
populated / error scenarios (whitespace-normalized token compare), plus browser
QA (open, vendor auto-populate, add/remove row, typeahead, per-row location swap,
percentage validation, submit); no JS errors.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -1,10 +1,8 @@
|
||||
{# One expense-account row, read entirely from a loop-bound `row` view-model
|
||||
(bulk-code/account-row-vm). The account typeahead reuses the shared
|
||||
components/typeahead.html partial (its context mapped in from row.account via a with
|
||||
block); the location select, percentage input, and remove button are inlined plain
|
||||
HTML. The location cell (#account-location-N) swaps just itself on account change; the
|
||||
remove button swaps the whole #bulk-code-form. Every dynamic attribute arrives
|
||||
pre-serialized as a string. #}
|
||||
{# One expense-account row, read from a loop-bound `row` view-model (account-row-vm). The
|
||||
account typeahead, location select, and remove button all reuse the shared component
|
||||
partials (typeahead.html / location-select.html / a-icon-button via its ctx); only the
|
||||
table layout is inline. The location cell (#account-location-N) swaps just itself on
|
||||
account change; the remove button swaps the whole #bulk-code-form. #}
|
||||
<tr class="{{ row.tr_classes }}"{{ row.tr_attrs|safe }}>
|
||||
<input type="hidden" name="{{ row.db_id_name }}"{% if row.db_id_value %} value="{{ row.db_id_value }}"{% endif %}>
|
||||
<td class="px-4 py-2">
|
||||
@@ -15,9 +13,7 @@
|
||||
</td>
|
||||
<td class="px-4 py-2" id="{{ row.location_cell_id }}">
|
||||
<div class="{{ row.location_field_classes }}"{{ row.location_field_attrs|safe }}>
|
||||
<select name="{{ row.location.name }}" class="{{ row.location.classes }}">
|
||||
{% for opt in row.location.options %}<option value="{{ opt.value }}"{% if opt.selected %} selected{% endif %}>{{ opt.label }}</option>{% endfor %}
|
||||
</select>
|
||||
{% with name=row.location.name classes=row.location.classes options=row.location.options %}{% include "templates/components/location-select.html" %}{% endwith %}
|
||||
<p class="mt-2 text-xs text-red-600 dark:text-red-500 h-4">{{ row.location_error }}</p>
|
||||
</div>
|
||||
</td>
|
||||
@@ -27,9 +23,5 @@
|
||||
<p class="mt-2 text-xs text-red-600 dark:text-red-500 h-4">{{ row.pct_error }}</p>
|
||||
</div>
|
||||
</td>
|
||||
<td class="px-4 py-2 align-top">
|
||||
<a class="account-remove-action p-3 inline-flex items-center justify-center bg-white dark:bg-gray-600 items-center text-sm font-medium border border-gray-300 dark:border-gray-700 text-center text-gray-500 hover:text-gray-800 rounded-lg dark:text-gray-400 dark:hover:text-gray-100"{{ row.remove_attrs|safe }}>
|
||||
<div class="h-4 w-4">{% include "templates/components/svg-x.html" %}</div>
|
||||
</a>
|
||||
</td>
|
||||
<td class="px-4 py-2 align-top"><a class="{{ row.remove.classes }}"{{ row.remove.attrs|safe }}><div class="h-4 w-4">{% include "templates/components/svg-x.html" %}</div></a></td>
|
||||
</tr>
|
||||
|
||||
Reference in New Issue
Block a user