feat(5.9): US-007 - responsive pagini de continut (card Mapari, scroll contained Jurnal/Nomenclator/Admin, formulare stivate)

- base.html @media(max-width:767px): clasa .tabel-card (card per rand) scopata
  SEPARAT de .tabel-trimiteri 5.8; reguli formular full-width + butoane >=44px
  scopate pe #card-cont / #form-test-cheie / #filtre-jurnal (marker US-007)
- _mapari.html: tabel-card + data-eticheta pe toate 4 tabelele; override select
  in card local (evita batalia de specificitate cu stilul inline)
- _integrare.html: id=form-test-cheie (ancora de scope pe formularul de test)
- R12 per-tabel: Mapari=card; Jurnal/Nomenclator/Admin=.tablewrap scroll contained;
  Cont/Integrare=fara tabele (doar formulare)
- tests: +3 (tabele clasa responsive, formulare full-width, regresie carduri 5.8)
- suita: 838 passed, 1 deselected
- prd.json US-007 passes=true + notes; progress.txt

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Claude Agent
2026-06-25 09:17:47 +00:00
parent 141949dc95
commit d3433015ad
6 changed files with 220 additions and 25 deletions

View File

@@ -229,7 +229,8 @@
{# Formular test conexiune #}
<div class="card" style="margin-bottom:16px;">
<h3 style="margin:0 0 12px; font-size:15px;">Testeaza conexiunea</h3>
<form hx-post="/integrare/test-cheie"
<form id="form-test-cheie"
hx-post="/integrare/test-cheie"
hx-target="#integrare-test-rezultat"
hx-swap="innerHTML"
style="display:flex; gap:8px; flex-wrap:wrap; align-items:flex-end;">

View File

@@ -4,6 +4,10 @@
/* Selectul de cod RAR e principalul vinovat de latimea tabelelor de mapari. Il limitam ca
tabelul sa incapa in card fara scroll orizontal -> coloana Actiuni (kebab) ramane vizibila. */
#mapari-section td select { width:100%; max-width:240px; min-width:150px; }
/* US-007 (R12): in card per rand (sub 767px) selectul/inputurile umplu cardul. */
@media (max-width:767px) {
#mapari-section td select, #mapari-section td input[type=text] { max-width:none; min-width:0; }
}
</style>
{% if message %}
@@ -42,7 +46,7 @@
<input type="search" data-dt-search class="dt-search"
placeholder="Cauta operatie sau cod..." aria-label="Cauta in operatiile de rezolvat">
</div>
<div class="tablewrap">
<div class="tablewrap tabel-card">
<table>
<thead><tr>
<th>Operatie</th>
@@ -58,7 +62,7 @@
{# data-dt-row = haystack de cautare (randul contine un <select> cu tot nomenclatorul). #}
<tr data-dt-row="{{ e.cod_op_service }} {{ e.denumire or '' }}
{%- for s in e.suggestions[:3] %} {{ s.cod_prestatie }}{% endfor %}">
<td>
<td data-eticheta="Operatie">
<form id="map-rez-{{ loop.index }}" hx-post="/mapari" hx-target="#mapari-section" hx-swap="outerHTML">
<input type="hidden" name="csrf_token" value="{{ csrf_token or '' }}">
<input type="hidden" name="cod_op_service" value="{{ e.cod_op_service }}">
@@ -67,14 +71,14 @@
<span class="pill" title="submission-uri blocate">{{ e.blocked }} blocate</span></div>
<div class="muted">{{ e.denumire or '(fara denumire)' }}</div>
</td>
<td class="muted" style="font-size:12px;">
<td class="muted" style="font-size:12px;" data-eticheta="Sugestii">
{% if e.suggestions %}
{% for s in e.suggestions[:3] %}
<span class="sugg">{{ s.cod_prestatie }} ({{ s.score|round|int }}%)</span>{% if not loop.last %}, {% endif %}
{% endfor %}
{% else %}—{% endif %}
</td>
<td>
<td data-eticheta="Cod RAR">
<select name="cod_prestatie" form="map-rez-{{ loop.index }}" required
aria-label="Cod RAR pentru {{ e.cod_op_service }}">
<option value="">— alege cod RAR —</option>
@@ -85,7 +89,7 @@
{% endfor %}
</select>
</td>
<td>
<td data-eticheta="In coada">
{{ ui.autosend_toggle(form_id="map-rez-" ~ loop.index, checked=True) }}
</td>
<td>
@@ -120,7 +124,7 @@
<input type="search" data-dt-search class="dt-search"
placeholder="Cauta operatie sau cod RAR..." aria-label="Cauta in maparile salvate">
</div>
<div class="tablewrap">
<div class="tablewrap tabel-card">
<table>
<thead><tr>
<th>Operatie</th>
@@ -132,7 +136,7 @@
{% for m in saved_mappings %}
{# data-dt-row = haystack de cautare (randul contine un <select> cu tot nomenclatorul). #}
<tr data-dt-row="{{ m.cod_op_service }} {{ m.cod_prestatie }} {{ m.nume_prestatie or '' }}">
<td>
<td data-eticheta="Operatie">
<form id="map-salv-{{ loop.index }}" hx-post="/mapari/salvate" hx-target="#mapari-section" hx-swap="outerHTML">
<input type="hidden" name="csrf_token" value="{{ csrf_token or '' }}">
<input type="hidden" name="cod_op_service" value="{{ m.cod_op_service }}">
@@ -147,7 +151,7 @@
acum: {{ m.cod_prestatie }}{% if m.nume_prestatie %} — {{ m.nume_prestatie }}{% endif %}
</div>
</td>
<td>
<td data-eticheta="Cod RAR">
<select name="cod_prestatie" form="map-salv-{{ loop.index }}" required
aria-label="Cod RAR pentru {{ m.cod_op_service }}">
{% for n in nomenclator %}
@@ -157,10 +161,10 @@
{% endfor %}
</select>
</td>
<td>
<td data-eticheta="In coada">
{{ ui.autosend_toggle(form_id="map-salv-" ~ loop.index, checked=m.auto_send) }}
</td>
<td style="text-align:right; white-space:nowrap;">
<td style="text-align:right; white-space:nowrap;" data-eticheta="Actiuni">
{# Salveaza/Sterge in meniu contextual (kebab) — randul ramane ingust. Butoanele se
leaga prin form= de cele doua form-uri hx-post definite in prima celula a randului. #}
<details class="kebab">
@@ -203,7 +207,7 @@
<input type="search" data-dt-search class="dt-search"
placeholder="Cauta coloana sau camp..." aria-label="Cauta in formatele de coloane">
</div>
<div class="tablewrap">
<div class="tablewrap tabel-card">
<table>
<thead><tr>
<th>Coloane</th>
@@ -214,15 +218,15 @@
<tbody>
{% for f in column_formats %}
<tr>
<td style="white-space:nowrap;">
<td style="white-space:nowrap;" data-eticheta="Coloane">
<strong>{{ f.columns | length }} coloane</strong>
</td>
<td class="muted" style="font-size:12px; white-space:normal; max-width:340px;">
<td class="muted" style="font-size:12px; white-space:normal; max-width:340px;" data-eticheta="Mapari (coloana &rarr; camp)">
{% for col, camp in f.mappings.items() %}
<span class="sugg">{{ col }}</span> &rarr; {{ camp }}{% if not loop.last %}; {% endif %}
{% endfor %}
</td>
<td>
<td data-eticheta="Format data">
<form id="fmt-edit-{{ loop.index }}" hx-post="/formate-coloane/editeaza"
hx-target="#mapari-section" hx-swap="outerHTML"
style="display:flex; gap:6px; align-items:center;">
@@ -274,7 +278,7 @@
</div>
{% endif %}
<div class="tablewrap">
<div class="tablewrap tabel-card">
<table>
<thead><tr>
<th>Daca operatia contine</th>
@@ -285,7 +289,7 @@
<tbody>
{% for r in text_rules %}
<tr>
<td>
<td data-eticheta="Daca operatia contine">
<form id="rt-del-{{ loop.index }}" hx-post="/mapari/reguli-text/sterge"
hx-target="#mapari-section" hx-swap="outerHTML"
hx-confirm="Stergi regula «{{ r.pattern }}»?">
@@ -294,10 +298,10 @@
</form>
<div>contine <strong>«{{ r.pattern }}»</strong></div>
</td>
<td class="muted" style="font-size:12px;">
<td class="muted" style="font-size:12px;" data-eticheta="Cod RAR">
{{ r.cod_prestatie }}
</td>
<td class="muted" style="font-size:12px;">
<td class="muted" style="font-size:12px;" data-eticheta="In coada">
{% if r.auto_send %}Auto (in coada){% else %}Manual (verificare){% endif %}
</td>
<td style="text-align:right; white-space:nowrap;">
@@ -310,7 +314,7 @@
{% endfor %}
{# Rand de adaugare (mereu prezent ca placeholder, inclusiv in empty state). #}
<tr>
<td>
<td data-eticheta="Daca operatia contine">
<form id="rt-add" hx-post="/mapari/reguli-text" hx-target="#mapari-section" hx-swap="outerHTML">
<input type="hidden" name="csrf_token" value="{{ csrf_token or '' }}">
<input type="text" name="pattern" required
@@ -324,7 +328,7 @@
hx-include="#rt-add">
</form>
</td>
<td>
<td data-eticheta="Cod RAR">
<select name="cod_prestatie" form="rt-add" required aria-label="Cod RAR pentru regula text">
<option value="">— alege cod RAR —</option>
{% for n in nomenclator %}
@@ -332,7 +336,7 @@
{% endfor %}
</select>
</td>
<td>
<td data-eticheta="In coada">
{{ ui.autosend_toggle(form_id="rt-add", checked=False) }}
</td>
<td style="text-align:right; white-space:nowrap;">

View File

@@ -256,6 +256,40 @@
.icon-btn { min-height:44px; min-width:44px; }
.tab-link { min-height:44px; padding:10px 14px; }
.cont-menu a, .cont-menu button { min-height:44px; }
/* === PRD 5.9 US-007 (R12): paginile de continut pe mobil ===
Tabele ACTIONABILE (Mapari) -> card per rand. Clasa proprie `.tabel-card`,
scopata SEPARAT de `.tabel-trimiteri` (5.8) ca sa NU strice cardurile de
trimiteri. Tabele DENSE read-only (Jurnal, Nomenclator) + Admin raman in
`.tablewrap` (scroll orizontal CONTAINED, definit global mai sus). */
.tabel-card table { table-layout:auto; }
.tabel-card thead { display:none; }
.tabel-card table, .tabel-card tbody, .tabel-card tr, .tabel-card td { display:block; width:auto; }
.tabel-card tr { border:1px solid var(--line); border-radius:8px; padding:10px 12px; margin-bottom:10px; }
.tabel-card td { border-bottom:none; padding:5px 0; }
.tabel-card td::before { content:attr(data-eticheta); display:block; color:var(--muted);
font-size:12px; margin-bottom:3px; }
/* Celulele fara eticheta (doar actiuni) nu primesc antet gol. */
.tabel-card td:not([data-eticheta])::before,
.tabel-card td[data-eticheta=""]::before { display:none; }
/* Controale full-width in card; butoanele primesc tinta touch >=44px. */
.tabel-card td select, .tabel-card td input[type=text],
.tabel-card td input[type=search] { width:100%; max-width:none; }
.tabel-card td button { width:100%; min-height:44px; }
/* Formulare de continut: o coloana, inputuri/selecturi full-width, butoane >=44px.
Scopat strict pe controalele de formular din sectiunile de continut (nu atinge
tabelul de trimiteri, modalul, taburile ARIA sau butoanele de copiere absolute). */
#card-cont input[type=email], #card-cont input[type=password],
#form-test-cheie input[type=password],
#jurnal-section select, #jurnal-section input[type=date],
#jurnal-section input[type=number] {
/* !important fiindca aceste inputuri au latimi inline (ex. width:280px / max-width:100px)
pe desktop; le suprascriem DOAR sub 767px, deci desktop ramane neschimbat. */
width:100% !important; max-width:none !important; box-sizing:border-box; }
#jurnal-section #filtre-jurnal > div { width:100%; }
#card-cont button, #form-test-cheie button,
#jurnal-section #filtre-jurnal button { min-height:44px; width:100%; }
}
</style>
</head>