Trimiteri desktop = tabel grid cu header, un rand per trimitere: status = bulina cu tooltip, mediu = litera T/P, multi-cod = primul cod + badge +N, sub-linie de eroare cu textul brut RAR doar pe error/needs_data. Mobil: 2 linii prin grid-areas, fara header. Actiunile bulk apar doar la selectie (bara contextuala cu contor + texte explicite). Mapari: exemplu concret in loc de descriere la Reguli automate. Fix buton "+" chips (nu facea nimic, fara eroare): hx-disabled-elt="find button" mostenit de la form-ul parinte crapa htmx inainte de request -> hx-disabled-elt="this" explicit pe butoanele chips; separat, no-op-urile silentioase din post_form_chips au acum mesaje (cod invalid/duplicat) si confirmare cu chip evidentiat la succes. Suita: 1622 passed. Verify E2E in browser (desktop 1280 + mobil 390). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
250 lines
12 KiB
HTML
250 lines
12 KiB
HTML
{#
|
||
_chips_prestatii.html — sectiunea de prestatii chips (E4, server-driven via /form-chips).
|
||
|
||
Re-randata de endpoint-ul /form-chips la fiecare add/remove de chip.
|
||
Inclusa si din _form_editare.html pentru randarea initiala.
|
||
|
||
Starea chip-urilor traieste in input-uri hidden din form (NU in DB mid-edit).
|
||
Fiecare operatie are un picker propriu cand e nemapata (E4 binding op<->cod).
|
||
Reveal odometru initial semnalat prin data-has-r-odo="true" si chip-warn pe R-ODO/I-ODO.
|
||
|
||
Context vars (toate cu defaults):
|
||
prestatii_chips — list of {cod_prestatie, cod_op_service, denumire}
|
||
nomenclator_rar — list of {cod_prestatie, nume_prestatie} pentru picker
|
||
has_r_odo — True daca orice chip e R-ODO sau I-ODO (server-computed)
|
||
form_chips_url — URL pentru HTMX; default '/form-chips'
|
||
chips_section_id — ID div (default 'chips-section')
|
||
csrf_token — CSRF (trecut prin hx-include din form parinte)
|
||
#}
|
||
{% set _chips_url = form_chips_url or '/form-chips' %}
|
||
{% set _sec_id = chips_section_id or 'chips-section' %}
|
||
{% set _chips = prestatii_chips or [] %}
|
||
{% set _has_ops = _chips | selectattr('cod_op_service') | list | length > 0 %}
|
||
{# chips_submission_id e setat din _detaliu_ctx cand chips sunt randate in modalul de detaliu.
|
||
Lipseste cand _chips_prestatii.html e rerandat via /form-chips (stateless, fara submission). #}
|
||
{% set _sub_id = chips_submission_id if chips_submission_id is defined else none %}
|
||
|
||
<div id="{{ _sec_id }}" data-has-r-odo="{{ 'true' if has_r_odo else 'false' }}"
|
||
aria-live="polite" aria-label="Prestatii cod RAR">
|
||
|
||
{# ===== Input-uri hidden pentru starea curenta a chip-urilor =====
|
||
TOATE itemele emit 3 hidden inputs (cod poate fi "" pentru unmapped).
|
||
Paralele index-by-index: cod_prestatie[i], chip_op_service[i], chip_denumire[i].
|
||
Filtrate la submit de post_corectie_trimitere (coduri goale = neschimbate). #}
|
||
{% for chip in _chips %}
|
||
<input type="hidden" name="cod_prestatie" value="{{ chip.cod_prestatie or '' }}">
|
||
<input type="hidden" name="chip_op_service" value="{{ chip.cod_op_service or '' }}">
|
||
<input type="hidden" name="chip_denumire" value="{{ chip.denumire or '' }}">
|
||
{% endfor %}
|
||
|
||
<div class="camp-slim" style="margin-bottom:8px;">
|
||
<label>Prestatii — cod RAR pe fiecare operatie</label>
|
||
|
||
{% if _has_ops %}
|
||
{# ===== Mod operatii: UN picker PE operatie (E4 binding) ===== #}
|
||
{% for chip in _chips %}
|
||
{% if chip.cod_op_service %}
|
||
{% set _is_warn = chip.cod_prestatie in ('R-ODO', 'I-ODO') %}
|
||
{% set _nemapat = not chip.cod_prestatie %}
|
||
{% set _e_nou = (chips_added_cod is defined) and chips_added_cod and chip.cod_prestatie == chips_added_cod %}
|
||
<div class="op-row {% if _nemapat %}op-row-warn{% endif %}" style="margin-bottom:6px;">
|
||
<span class="op-row-name">
|
||
{{ chip.cod_op_service }}
|
||
{% if chip.denumire and chip.denumire != chip.cod_op_service %}
|
||
<span class="muted" style="font-weight:400;font-size:11px;"> — {{ chip.denumire }}</span>
|
||
{% endif %}
|
||
{% if _nemapat %}
|
||
<span style="color:var(--warn);font-size:10px;font-weight:400;"> · lipsa cod</span>
|
||
{% endif %}
|
||
</span>
|
||
<span style="display:flex;align-items:center;gap:8px;">
|
||
{% if chip.cod_prestatie %}
|
||
{# ===== Operatie mapata: chip cu × ===== #}
|
||
<span class="chip {% if _is_warn %}chip-warn{% endif %} {% if _e_nou %}chip-nou{% endif %}"
|
||
aria-label="Prestatie {{ chip.cod_prestatie }} adaugata pentru {{ chip.cod_op_service }}">
|
||
{{ chip.cod_prestatie }}
|
||
<button type="button" class="chip-del"
|
||
hx-post="{{ _chips_url }}"
|
||
hx-disabled-elt="this"
|
||
hx-include="closest form"
|
||
hx-target="#{{ _sec_id }}"
|
||
hx-swap="outerHTML"
|
||
hx-vals='{"chips_action":"remove","chips_remove_index":{{ loop.index0 }}}'
|
||
aria-label="Sterge codul {{ chip.cod_prestatie }} pentru {{ chip.cod_op_service }}">
|
||
×
|
||
</button>
|
||
</span>
|
||
{# "salveaza ca regula op->cod" — apare doar cand submission_id e cunoscut
|
||
(in modalul de detaliu, nu la re-randarea stateless via /form-chips).
|
||
Reuse EXACT save_mapping + reresolve_account via endpoint dedicat.
|
||
hx-include="closest form" propaga csrf_token din form-ul parinte. #}
|
||
<span id="save-rule-slot-{{ loop.index0 }}" class="save-rule-slot">
|
||
{% if _sub_id and chip.cod_op_service and chip.cod_prestatie %}
|
||
<button type="button"
|
||
style="font-size:10px;color:var(--muted);background:none;border:none;cursor:pointer;text-decoration:underline;padding:0;margin-left:4px;line-height:1;"
|
||
hx-post="/trimitere/{{ _sub_id }}/salveaza-regula-chip"
|
||
hx-disabled-elt="this"
|
||
hx-include="closest form"
|
||
hx-target="#detaliu-modal-body"
|
||
hx-swap="innerHTML"
|
||
hx-vals='{"salveaza_op":{{ chip.cod_op_service | tojson }},"salveaza_cod":{{ chip.cod_prestatie | tojson }}}'
|
||
aria-label="Salveaza regula {{ chip.cod_op_service }} -> {{ chip.cod_prestatie }}">
|
||
salveaza ca regula
|
||
</button>
|
||
{% endif %}
|
||
</span>
|
||
{% else %}
|
||
{# ===== Operatie nemapata: picker galben cu "alege cod RAR" ===== #}
|
||
<select name="chips_add_cod_{{ loop.index0 }}"
|
||
id="picker-op-{{ loop.index0 }}"
|
||
aria-label="Alege cod RAR pentru {{ chip.cod_op_service }}"
|
||
style="min-width:160px;font-size:11px;height:26px;">
|
||
<option value="">— alege cod RAR —</option>
|
||
{% for n in (nomenclator_rar or []) %}
|
||
<option value="{{ n.cod_prestatie }}">{{ n.cod_prestatie }} — {{ n.nume_prestatie }}</option>
|
||
{% endfor %}
|
||
</select>
|
||
<button type="button"
|
||
class="add-code"
|
||
hx-post="{{ _chips_url }}"
|
||
hx-disabled-elt="this"
|
||
hx-include="closest form"
|
||
hx-target="#{{ _sec_id }}"
|
||
hx-swap="outerHTML"
|
||
hx-vals='{"chips_action":"add","chips_add_op_index":{{ loop.index0 }}}'
|
||
aria-label="Adauga cod RAR pentru {{ chip.cod_op_service }}">
|
||
+ Adauga
|
||
</button>
|
||
{% endif %}
|
||
</span>
|
||
</div>
|
||
{% endif %}
|
||
{% endfor %}
|
||
|
||
{# ===== Chips extra + picker '+ Adauga alta operatie / cod RAR' in mod operatii ===== #}
|
||
{# Chips extra: cod_op_service gol, cod_prestatie setat — afisate flat cu × (reuse remove_flat).
|
||
Containerul .chips se randeaza DOAR cand exista chips extra — altfel ramanea
|
||
un chenar gol nefinisat sub randurile de operatie. #}
|
||
{% set _extra_chips = _chips | rejectattr('cod_op_service') | selectattr('cod_prestatie') | list %}
|
||
{% if _extra_chips %}
|
||
<div class="chips" role="group" aria-label="Coduri RAR suplimentare" style="margin-top:4px;">
|
||
{% for chip in _extra_chips %}
|
||
{% set _is_warn_extra = chip.cod_prestatie in ('R-ODO', 'I-ODO') %}
|
||
{% set _e_nou_extra = (chips_added_cod is defined) and chips_added_cod and chip.cod_prestatie == chips_added_cod %}
|
||
<span class="chip {% if _is_warn_extra %}chip-warn{% endif %} {% if _e_nou_extra %}chip-nou{% endif %}"
|
||
aria-label="Cod RAR suplimentar {{ chip.cod_prestatie }}">
|
||
{{ chip.cod_prestatie }}
|
||
<button type="button" class="chip-del"
|
||
hx-post="{{ _chips_url }}"
|
||
hx-disabled-elt="this"
|
||
hx-include="closest form"
|
||
hx-target="#{{ _sec_id }}"
|
||
hx-swap="outerHTML"
|
||
hx-vals='{"chips_action":"remove_flat","chips_remove_cod":"{{ chip.cod_prestatie }}"}'
|
||
aria-label="Sterge codul suplimentar {{ chip.cod_prestatie }}">×</button>
|
||
</span>
|
||
{% endfor %}
|
||
</div>
|
||
{% endif %}
|
||
{% if nomenclator_rar %}
|
||
<span style="display:inline-flex;align-items:center;gap:4px;margin-top:4px;">
|
||
<select name="chips_add_cod_flat"
|
||
aria-label="Adauga cod RAR suplimentar"
|
||
style="min-width:160px;font-size:11px;height:26px;border:1px dashed color-mix(in srgb,var(--accent) 55%,var(--line));border-radius:5px;background:transparent;color:var(--accent);">
|
||
<option value="">+ Adauga alta operatie / cod RAR</option>
|
||
{% for n in nomenclator_rar %}
|
||
<option value="{{ n.cod_prestatie }}">{{ n.cod_prestatie }} — {{ n.nume_prestatie }}</option>
|
||
{% endfor %}
|
||
</select>
|
||
<button type="button"
|
||
class="add-code"
|
||
hx-post="{{ _chips_url }}"
|
||
hx-disabled-elt="this"
|
||
hx-include="closest form"
|
||
hx-target="#{{ _sec_id }}"
|
||
hx-swap="outerHTML"
|
||
hx-vals='{"chips_action":"add_extra"}'
|
||
aria-label="Adauga cod RAR suplimentar la trimitere">
|
||
+
|
||
</button>
|
||
</span>
|
||
{% else %}
|
||
{# T-D1/T-E5 (5.16): empty state in mod operatii cand nomenclatorul lipseste #}
|
||
<div class="chips-nom-gol" style="font-size:11px;color:var(--warn);padding:4px 0;margin-top:4px;">
|
||
Nomenclator indisponibil — adaugarea de coduri suplimentare nu e posibila.
|
||
</div>
|
||
{% endif %}
|
||
{% else %}
|
||
{# ===== Mod plat: lista de coduri libere (corectie pura, fara op_service) ===== #}
|
||
<div class="chips" role="group" aria-label="Coduri RAR selectate">
|
||
{% for chip in _chips %}
|
||
{% if chip.cod_prestatie %}
|
||
{% set _is_warn_flat = chip.cod_prestatie in ('R-ODO', 'I-ODO') %}
|
||
{% set _e_nou_flat = (chips_added_cod is defined) and chips_added_cod and chip.cod_prestatie == chips_added_cod %}
|
||
<span class="chip {% if _is_warn_flat %}chip-warn{% endif %} {% if _e_nou_flat %}chip-nou{% endif %}"
|
||
aria-label="Prestatie {{ chip.cod_prestatie }}">
|
||
{{ chip.cod_prestatie }}
|
||
<button type="button" class="chip-del"
|
||
hx-post="{{ _chips_url }}"
|
||
hx-disabled-elt="this"
|
||
hx-include="closest form"
|
||
hx-target="#{{ _sec_id }}"
|
||
hx-swap="outerHTML"
|
||
hx-vals='{"chips_action":"remove_flat","chips_remove_cod":"{{ chip.cod_prestatie }}"}'
|
||
aria-label="Sterge codul {{ chip.cod_prestatie }}">×</button>
|
||
</span>
|
||
{% endif %}
|
||
{% endfor %}
|
||
{# Picker adaugare cod nou in mod plat #}
|
||
{% if nomenclator_rar %}
|
||
<span style="display:inline-flex;align-items:center;gap:4px;">
|
||
<select name="chips_add_cod_flat"
|
||
aria-label="Adauga cod RAR nou"
|
||
style="font-size:11px;height:22px;border:1px dashed color-mix(in srgb,var(--accent) 55%,var(--line));border-radius:5px;background:transparent;color:var(--accent);">
|
||
<option value="">+ cod</option>
|
||
{% for n in nomenclator_rar %}
|
||
<option value="{{ n.cod_prestatie }}">{{ n.cod_prestatie }} — {{ n.nume_prestatie }}</option>
|
||
{% endfor %}
|
||
</select>
|
||
<button type="button"
|
||
class="add-code"
|
||
hx-post="{{ _chips_url }}"
|
||
hx-disabled-elt="this"
|
||
hx-include="closest form"
|
||
hx-target="#{{ _sec_id }}"
|
||
hx-swap="outerHTML"
|
||
hx-vals='{"chips_action":"add_flat"}'
|
||
aria-label="Adauga cod RAR selectat in lista">
|
||
+
|
||
</button>
|
||
</span>
|
||
{% else %}
|
||
{# T-D1/T-E5 (5.16): empty state in mod plat cand nomenclatorul lipseste #}
|
||
<div class="chips-nom-gol" style="font-size:11px;color:var(--warn);padding:4px 0;">
|
||
Nomenclator indisponibil — nu se pot adauga coduri RAR momentan.
|
||
</div>
|
||
{% endif %}
|
||
</div>
|
||
{% endif %}
|
||
|
||
{# Rezultatul ultimei adaugari, in ambele moduri: refuz (rol=alert) sau confirmare.
|
||
Clasa chips-extra-error pastrata pe eroare (selector stabil pentru teste/QA). #}
|
||
{% if chips_error is defined and chips_error %}
|
||
<div class="chips-extra-error" style="font-size:11px;color:var(--err);padding:2px 0;" role="alert">
|
||
{{ chips_error }}
|
||
</div>
|
||
{% elif chips_ok is defined and chips_ok %}
|
||
<div class="chips-adaugat-ok" style="font-size:11px;color:var(--ok);padding:2px 0;" role="status">
|
||
{{ chips_ok }}
|
||
</div>
|
||
{% endif %}
|
||
|
||
{# Hint discret fara chips (debut) #}
|
||
{% if not _chips %}
|
||
<div style="font-size:10px;color:var(--muted);padding:4px 0;">
|
||
Niciun cod RAR inca — alege din picker (sus) sau adauga prin mapare.
|
||
</div>
|
||
{% endif %}
|
||
</div>
|
||
</div>
|