chore: curatare agresiva comentarii — scoatere referinte US/PRD din cod si template-uri
Eliminat zgomotul de trasabilitate (US-xxx, PRD x.x, Rn, OV-x, Tn, decizii/naratiune istorica) din 41 fisiere app/ + template-uri. Pastrate comentariile care documenteaza invarianti si logica ne-evidenta (idempotenta/hash, reconciliere anti-duplicat, RAR 500 esec definitiv, creds per cont, WAF User-Agent, 422 fara echo de parola, scope NULL->1), curatate doar de tokeni. Verificare: pentru cele 27 module .py curatate, structura de cod (tokeni non-comentariu/ non-string) e IDENTICA fata de HEAD -> doar comentarii/docstring-uri schimbate. Singura schimbare de cod e in tests/test_web_responsive.py (scos 3 assert pe markeri US-006/007/008, inlocuite de asertiunile structurale alaturate). 0 tokeni US/PRD reziduali in app/. Regresie: 896 passed, 1 deselected. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -44,12 +44,8 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{# US-001 (5.5): randul "Ajutor" (wayfinding Mapari/Coduri RAR) eliminat — navigarea
|
||||
traieste in tab-bar (Mapari) si in meniul de cont (Nomenclator etc.). #}
|
||||
|
||||
{# === Sectiunea Trimiteri ("Trimiterile tale"), permanenta sub upload (US-003).
|
||||
Suprimata la first-run (zero trimiteri): bara de upload acopera deja CTA-ul,
|
||||
iar empty-state-ul tabelului ar fi redundant (US-004 / D-5.1). === #}
|
||||
{# Sectiunea Trimiteri, permanenta sub upload. Suprimata la first-run (zero
|
||||
trimiteri): bara de upload acopera deja CTA-ul, iar empty-state-ul ar fi redundant. #}
|
||||
{% if are_trimiteri %}
|
||||
{% include '_coada.html' %}
|
||||
{% endif %}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
{#
|
||||
_coada.html — repurposat in 3.6 (US-003).
|
||||
Nu mai e un tab/panou separat: e sectiunea "Trimiterile tale" inclusa pe Acasa,
|
||||
sub zona de upload. Pastreaza filtrele (US-009) si tabelul (_submissions.html); detaliul
|
||||
se deschide acum in modalul global (#modal-detaliu). Poll aliniat la 15s (anti dublu-poll, M5).
|
||||
_coada.html — sectiunea "Trimiterile tale" inclusa pe Acasa, sub zona de upload.
|
||||
Filtre + tabel (_submissions.html); detaliul se deschide in modalul global (#modal-detaliu).
|
||||
#}
|
||||
<section id="trimiteri-section" aria-labelledby="trimiteri-heading"
|
||||
style="margin-top:22px; padding-top:18px; border-top:2px solid var(--line);">
|
||||
@@ -68,8 +66,4 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# PRD 5.9 US-003: detaliul s-a mutat intr-un MODAL global (#modal-detaliu in base.html),
|
||||
in afara #submissions-wrap -> poll-ul de 15s nu-l mai atinge. Randul declanseaza
|
||||
deschiderea (hx-target=#detaliu-modal-body). Vechiul panou inert #trimitere-detaliu
|
||||
a fost eliminat (rol preluat de modal). #}
|
||||
</section>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{#
|
||||
_eroare.html — macro card_erori(erori) (US-006, PRD 5.4).
|
||||
_eroare.html — macro card_erori(erori).
|
||||
|
||||
Primeste o lista de dict-uri cu cheile: problema, cauza, fix, field (sau None).
|
||||
Afiseaza 3 niveluri intr-un bloc scannabil:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{# _jurnal.html — tab Jurnal de aplicatie (US-006, PRD 5.6).
|
||||
{# _jurnal.html — tab Jurnal de aplicatie.
|
||||
Lista paginata de evenimente (app_events), redactate la scriere. Filtre tip/nivel/
|
||||
data + (admin) cont. Stil consistent cu tabelele PRD 5.5 (.tablewrap). #}
|
||||
data + (admin) cont. #}
|
||||
<section id="jurnal-section" aria-labelledby="jurnal-heading">
|
||||
<div class="card">
|
||||
<div style="display:flex; align-items:center; gap:8px; flex-wrap:wrap; margin:0 0 12px;">
|
||||
|
||||
@@ -1,18 +1,14 @@
|
||||
{# Macro-uri partajate intre template-urile de import si mapari. #}
|
||||
|
||||
{# US-003 (5.5): comutator COMPACT "In coada" — Manual <-> Auto pe un singur rand, fara
|
||||
proza inline (explicatia traieste o singura data in panoul Ajutor al cardului Mapari).
|
||||
Inlocuieste varianta verbose din 3.6 care injecta 3 randuri de text pe FIECARE linie de
|
||||
tabel (randuri inalte -> Salveaza/Sterge ieseau din viewport).
|
||||
|
||||
INVARIANT BACKEND (nealterat din 3.6): control = checkbox cu `name="auto_send" value="true"`
|
||||
si SEMANTICA DE PREZENTA (bifat -> trimite "true" -> True; nebifat -> camp absent -> False).
|
||||
{# Comutator COMPACT "In coada" — Manual <-> Auto pe un singur rand.
|
||||
INVARIANT BACKEND: control = checkbox cu `name="auto_send" value="true"` si
|
||||
SEMANTICA DE PREZENTA (bifat -> trimite "true" -> True; nebifat -> camp absent -> False).
|
||||
E singura forma compatibila cu AMBELE parsere: `Form(bool)` la /mapari SI `bool(form.get())`
|
||||
la /_import/.../mapare-operatie. Radio Auto/Manual cu value="false" ar trimite campul prezent
|
||||
pe "Manual" -> `bool("false")` = True la import (regresie tacuta). De aceea comutator vizual
|
||||
Manual<->Auto peste checkbox, NU doua radio-uri. Zero atingere backend.
|
||||
Manual<->Auto peste checkbox, NU doua radio-uri.
|
||||
- form_id: leaga input-ul de un <form> extern (necesar in celulele de tabel).
|
||||
- checked: starea STOCATA per mapare (H4) — bifat = Auto. #}
|
||||
- checked: starea STOCATA per mapare — bifat = Auto. #}
|
||||
{% macro autosend_toggle(form_id='', checked=True, label='') -%}
|
||||
<label class="autosend-toggle"
|
||||
title="Bifat = Auto: pune automat in coada la fisierele viitoare cu aceasta operatie. Nebifat = Manual: tine pentru verificare; nimic nu pleaca la RAR pana confirmi."
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
/* 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. */
|
||||
/* 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; }
|
||||
}
|
||||
@@ -18,11 +18,6 @@
|
||||
<!-- Sectiunea 1: De rezolvat (operatii needs_mapping) -->
|
||||
<!-- ============================================================ -->
|
||||
<div class="card">
|
||||
{# US-005 (5.5): antet standard + link Ajutor ca <details> nativ (fara JS). Toata proza
|
||||
care inainte se repeta inline (scopul maparilor, Auto/Manual) traieste acum AICI,
|
||||
o singura data, ascunsa implicit. #}
|
||||
{# US-010: sectiunea de ajutor (details.ajutor-mapari) eliminata.
|
||||
Empty-state „Nicio operatie nemapata" eliminat — sectiunea ramane goala (fara text). #}
|
||||
<h2 style="font-size:15px; margin:0 0 8px;">De rezolvat</h2>
|
||||
|
||||
{% if pending %}
|
||||
@@ -102,8 +97,6 @@
|
||||
Nicio mapare salvata inca. Pe masura ce mapezi operatii, ele apar aici si le poti edita oricand.
|
||||
</div>
|
||||
{% else %}
|
||||
{# US-005 (5.5): proza explicativa mutata in panoul Ajutor de la "De rezolvat" (o singura data). #}
|
||||
|
||||
<div data-dt="10">
|
||||
<div class="dt-tools">
|
||||
<input type="search" data-dt-search class="dt-search"
|
||||
@@ -150,7 +143,7 @@
|
||||
{{ ui.autosend_toggle(form_id="map-salv-" ~ loop.index, checked=m.auto_send) }}
|
||||
</td>
|
||||
<td style="text-align:right; white-space:nowrap;" data-eticheta="Actiuni">
|
||||
{# US-011: butoane icon mereu vizibile (fara kebab). SVG aria-hidden; aria-label pe buton.
|
||||
{# Butoane icon mereu vizibile (fara kebab). SVG aria-hidden; aria-label pe buton.
|
||||
data-dirty-form e citit de JS din base.html: la schimbarea select-ului din acelasi rand,
|
||||
JS adauga clasa "dirty" pe butonul de salvare (fundal --accent = modificari nesalvate). #}
|
||||
<button type="submit" form="map-salv-{{ loop.index }}"
|
||||
@@ -182,7 +175,6 @@
|
||||
|
||||
<!-- ============================================================ -->
|
||||
<!-- Sectiunea 3: Reguli automate pe text (operation_text_rules) -->
|
||||
<!-- US-010: mutata pe pozitia 3 (inainte de Formate de coloane) -->
|
||||
<!-- ============================================================ -->
|
||||
<div class="card">
|
||||
<h2 style="font-size:15px; margin:0 0 8px;">Reguli automate (text)</h2>
|
||||
@@ -266,7 +258,7 @@
|
||||
<button type="submit" form="rt-add">Adauga</button>
|
||||
</td>
|
||||
</tr>
|
||||
{# Preview pre-salvare (US-009): cate operatii nemapate potriveste pattern-ul. #}
|
||||
{# Preview pre-salvare: cate operatii nemapate potriveste pattern-ul. #}
|
||||
<tr>
|
||||
<td colspan="4" style="padding-top:0;">
|
||||
<div id="rt-preview" aria-live="polite"></div>
|
||||
@@ -279,7 +271,6 @@
|
||||
|
||||
<!-- ============================================================ -->
|
||||
<!-- Sectiunea 4: Formate de coloane salvate (column_mappings) -->
|
||||
<!-- US-010: mutata pe pozitia 4 (dupa Reguli automate) -->
|
||||
<!-- ============================================================ -->
|
||||
<div class="card">
|
||||
<h2 style="font-size:15px; margin:0 0 12px;">Formate de coloane salvate</h2>
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
{# US-002 (5.5): aceeasi grila standard ca tabelul Trimiteri (_submissions.html):
|
||||
.tablewrap > table, antet th standard (mostenit din base.html), cod in .pill,
|
||||
denumire ca text normal (singura coloana care se poate rupe pe randuri inguste),
|
||||
empty-state in .empty. Zero stiluri inline noi — totul vine din base.html. #}
|
||||
{# Aceeasi grila standard ca tabelul Trimiteri: cod in .pill, denumire ca text normal
|
||||
(singura coloana care se poate rupe pe randuri inguste), empty-state in .empty. #}
|
||||
{% if rows %}
|
||||
<div class="tablewrap">
|
||||
<table>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Rezumat stari (id stabil pentru OOB swap dupa editarea unui rand — US-002) -->
|
||||
<!-- Rezumat stari (id stabil pentru OOB swap dupa editarea unui rand) -->
|
||||
{% set status_labels = [
|
||||
('ok', 'gata de trimis'),
|
||||
('needs_review', 'verifica valori'),
|
||||
@@ -108,7 +108,7 @@
|
||||
{% endif %}
|
||||
|
||||
<!-- Tabel preview. Randurile au FORM PROPRIU pentru editare (NU sunt in #confirm-form,
|
||||
altfel Enter intr-un camp ar declansa trimiterea ireversibila — D-3.3). Bifele
|
||||
altfel Enter intr-un camp ar declansa trimiterea ireversibila). Bifele
|
||||
needs_review se asociaza la #confirm-form prin atributul form=. -->
|
||||
<div class="tablewrap">
|
||||
<table>
|
||||
@@ -142,7 +142,7 @@
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token or '' }}">
|
||||
<div class="sticky-bar">
|
||||
<div style="flex:1; min-width:280px;">
|
||||
<!-- Banner declarant (D12) — direct deasupra input-ului N -->
|
||||
<!-- Banner declarant — direct deasupra input-ului N -->
|
||||
<div class="banner warn" style="margin-bottom:10px; padding:8px 12px; border-radius:6px;"
|
||||
role="note" aria-live="polite">
|
||||
Confirmand, TU esti declarantul acestor
|
||||
@@ -199,7 +199,7 @@
|
||||
</form>
|
||||
|
||||
<!-- Contor "gata de trimis" citit din DOM (data-ok), ca OOB swap-ul de la editare
|
||||
sa actualizeze N fara a re-randa sectiunea (US-002). -->
|
||||
sa actualizeze N fara a re-randa sectiunea. -->
|
||||
<span id="preview-ok-count" data-ok="{{ summary.get('ok', 0) }}" hidden></span>
|
||||
|
||||
<div style="padding:8px 0 4px;">
|
||||
@@ -212,13 +212,13 @@
|
||||
|
||||
<script>
|
||||
(function() {
|
||||
/* D-1.2: un singur sticky bar pe ecran — cat preview-ul de import e activ,
|
||||
/* Un singur sticky bar pe ecran — cat preview-ul de import e activ,
|
||||
ascunde sectiunea Trimiteri de pe Acasa (se reveleaza la reset/commit din _upload.html). */
|
||||
var trim = document.getElementById('trimiteri-section');
|
||||
if (trim) trim.style.display = 'none';
|
||||
|
||||
/* nOk se citeste din DOM (#preview-ok-count[data-ok]) ca OOB swap-ul de la editare
|
||||
sa-l poata actualiza fara re-randarea sectiunii (D-3.1/D-3.4). */
|
||||
sa-l poata actualiza fara re-randarea sectiunii. */
|
||||
function getOk() {
|
||||
var el = document.getElementById('preview-ok-count');
|
||||
return el ? parseInt(el.dataset.ok || '0', 10) : 0;
|
||||
@@ -231,7 +231,7 @@
|
||||
var inp = document.getElementById('n-confirmat');
|
||||
var disp = document.getElementById('n-display');
|
||||
var btn = document.getElementById('confirm-btn');
|
||||
/* Nu re-activa confirm cat un rand e in editare (mutual-exclusion D-3.2). */
|
||||
/* Nu re-activa confirm cat un rand e in editare (mutual-exclusion). */
|
||||
var editing = document.querySelector('tr[data-editing="1"]') !== null;
|
||||
if (inp) inp.value = total;
|
||||
if (disp) disp.textContent = total;
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
{#
|
||||
_preview_rand.html — un singur rand de preview import (US-002, 3.6).
|
||||
_preview_rand.html — un singur rand de preview import.
|
||||
Doua moduri:
|
||||
- display (editing falsy): <tr> normal + buton "Editeaza" pe coloana de actiuni.
|
||||
- edit (editing truthy): <tr> cu un singur <td colspan> ce contine un FORM PROPRIU
|
||||
(NU #confirm-form) cu grila responsiva refolosita din _trimitere_detaliu.html.
|
||||
Swap pe RAND (hx-target pe #preview-row-N, outerHTML), NU pe #import-section (D-3.1).
|
||||
Swap pe RAND (hx-target pe #preview-row-N, outerHTML), NU pe #import-section.
|
||||
La save, optional OOB pe rezumat + contor "gata de trimis" (include_oob).
|
||||
#}
|
||||
{%- set res = row.resolved -%}
|
||||
@@ -80,7 +80,7 @@
|
||||
</tr>
|
||||
<script>
|
||||
(function() {
|
||||
/* Mutual-exclusion (D-3.2/3.6): cat un rand e in editare, dezactiveaza confirm + alte Editeaza. */
|
||||
/* Mutual-exclusion: cat un rand e in editare, dezactiveaza confirm + alte Editeaza. */
|
||||
var btn = document.getElementById('confirm-btn');
|
||||
if (btn) { btn.disabled = true; btn.title = 'Termina editarea randului inainte de a trimite.'; }
|
||||
document.querySelectorAll('.btn-editeaza').forEach(function(b) { b.disabled = true; });
|
||||
@@ -152,7 +152,7 @@
|
||||
</td>
|
||||
</tr>
|
||||
{% if include_oob %}
|
||||
{# OOB: actualizeaza rezumatul si contorul "gata de trimis" dupa save, fara a re-randa sectiunea (D-3.1). #}
|
||||
{# OOB: actualizeaza rezumatul si contorul "gata de trimis" dupa save, fara a re-randa sectiunea. #}
|
||||
{% set status_labels = [
|
||||
('ok','gata de trimis'), ('needs_review','verifica valori'), ('needs_mapping','fara cod RAR'),
|
||||
('needs_data','date lipsa'), ('already_sent','deja trimis'), ('duplicate_in_file','dublicat in fisier')] %}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{#
|
||||
OOB: actualizeaza inputul id="f-page" din #filtre-trimiteri (US-004 L2).
|
||||
Poll-ul de 15s (hx-include="#filtre-trimiteri") preia automat pagina curenta.
|
||||
OOB: actualizeaza inputul id="f-page" din #filtre-trimiteri.
|
||||
Reincarcarea (hx-include="#filtre-trimiteri") preia automat pagina curenta.
|
||||
Elementul OOB e extras din continutul normal de HTMX inainte de swap in #submissions-wrap.
|
||||
#}
|
||||
<input type="hidden" id="f-page" name="page" value="{{ page | default(1) }}" hx-swap-oob="true">
|
||||
@@ -13,7 +13,7 @@
|
||||
<span id="trimiteri-versiune" data-v="{{ versiune_trimiteri | default('') }}" hidden></span>
|
||||
|
||||
{% if rows %}
|
||||
{# US-011: form de stergere bulk. Selectia opereaza DOAR pe randuri blocate
|
||||
{# Form de stergere bulk. Selectia opereaza DOAR pe randuri blocate
|
||||
(gestionabil); sent/sending/queued nu au checkbox (read-only). #}
|
||||
<form id="bulk-trimiteri"
|
||||
hx-post="/trimiteri/sterge-bulk"
|
||||
@@ -43,9 +43,8 @@
|
||||
</tr></thead>
|
||||
<tbody>
|
||||
{% for r in rows %}
|
||||
{# PRD 5.9 US-003: randul declanseaza deschiderea MODALULUI global (#detaliu-modal-body),
|
||||
nu un rand-sibling. Clickabil/focusabil (role=button); Enter/Space deschid modalul
|
||||
(JS in base.html). Vechiul rand-sibling de detaliu a fost eliminat. #}
|
||||
{# Randul declanseaza deschiderea MODALULUI global (#detaliu-modal-body).
|
||||
Clickabil/focusabil (role=button); Enter/Space deschid modalul (JS in base.html). #}
|
||||
<tr id="trimitere-row-{{ r.id }}"
|
||||
class="trimitere-row"
|
||||
data-detaliu-id="{{ r.id }}"
|
||||
@@ -65,8 +64,8 @@
|
||||
<td class="col-id muted" data-eticheta="#">{{ r.id }}</td>
|
||||
<td class="col-stare" data-eticheta="Stare">
|
||||
<span class="pill {{ r.stare_css }}" title="{{ r.stare_text }}">{{ r.stare_scurt }}</span>
|
||||
{# PRD 5.9 US-002 (R1): eticheta umana scurta sub pill — text mic, `s-error`
|
||||
pe error/needs_* (singurele stari pe care `eticheta_problema` e ne-goala).
|
||||
{# Eticheta umana scurta sub pill — text mic, `s-error` pe error/needs_*
|
||||
(singurele stari pe care `eticheta_problema` e ne-goala).
|
||||
Stare transmisa prin TEXT, nu doar culoare. Codul brut ramane in modal. #}
|
||||
{% if r.eticheta_problema %}
|
||||
<div class="eticheta-problema s-error">{{ r.eticheta_problema }}</div>
|
||||
@@ -75,14 +74,14 @@
|
||||
<td class="col-vehicul" data-eticheta="Vehicul">
|
||||
{{ r.prez.vehicul_nr }}
|
||||
{% if r.prez.vin_scurt and r.prez.vin_scurt != '—' %}
|
||||
{# US-005: VIN pe rand separat sub nr (element block, nu span inline) #}
|
||||
{# VIN pe rand separat sub nr (element block, nu span inline) #}
|
||||
<div class="muted" style="font-size:12px;">{{ r.prez.vin_scurt }}</div>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="col-operatie" data-eticheta="Operatie">
|
||||
<div>{{ r.prez.operatie }}</div>
|
||||
{# PRD 5.9 US-002: doar codul RAR (ex. OE-2), FARA prefixul "cod RAR:" — chip
|
||||
muted discret; cand nemapat afiseaza "nemapat" muted (comportament 5.8). #}
|
||||
{# Doar codul RAR (ex. OE-2), FARA prefixul "cod RAR:" — chip muted discret;
|
||||
cand nemapat afiseaza "nemapat" muted. #}
|
||||
{% if r.prez.cod_rar and r.prez.cod_rar != '—' %}
|
||||
<div class="cod-rar-sub"><span class="cod-rar-cod">{{ r.prez.cod_rar }}</span></div>
|
||||
{% else %}
|
||||
@@ -100,7 +99,7 @@
|
||||
</form>
|
||||
|
||||
{#
|
||||
Paginare numerotata (US-004 PRD 5.10).
|
||||
Paginare numerotata.
|
||||
Afisata doar cand exista mai mult de o pagina.
|
||||
Fiecare link pastreaza filtrele curente (status, vehicul, data_de, data_pana).
|
||||
Pagina curenta: aria-current="page" (semantic).
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
{% from "_eroare.html" import card_erori %}
|
||||
{% import '_macros.html' as ui %}
|
||||
{# PRD 5.9 US-004: detaliu editabil in-place, butoane consolidate, ordine verticala R10.
|
||||
Fragmentul se swap-uieste in corpul modalului global (#detaliu-modal-body). Heading-ul
|
||||
poarta id-ul folosit de aria-labelledby al dialogului.
|
||||
R9: operatie + cod RAR rezolvat apar IMPREUNA, read-only, folosind `prez.cod_rar`
|
||||
{# Detaliu editabil in-place. Fragmentul se swap-uieste in corpul modalului global
|
||||
(#detaliu-modal-body). Heading-ul poarta id-ul folosit de aria-labelledby al dialogului.
|
||||
Operatie + cod RAR rezolvat apar IMPREUNA, read-only, folosind `prez.cod_rar`
|
||||
(fallback „nemapat"), fara eticheta separata „Cod RAR". #}
|
||||
{% set cod_afis = prez.cod_rar if (prez.cod_rar and prez.cod_rar != '—') else 'nemapat' %}
|
||||
<div class="card" id="detaliu-card-{{ id }}" style="border:none; padding:0; margin:0;">
|
||||
|
||||
{# === R10 (1): header — #id + pill + motiv uman === #}
|
||||
{# === Header — #id + pill + motiv uman === #}
|
||||
<div style="display:flex; align-items:center; gap:8px; flex-wrap:wrap; margin:0 0 8px;">
|
||||
<h2 id="detaliu-modal-titlu" style="font-size:15px; margin:0;">Detaliu trimitere #{{ id }}</h2>
|
||||
<span class="pill {{ stare_css }}">{{ stare_text }}</span>
|
||||
@@ -19,7 +18,7 @@
|
||||
<p class="muted" style="margin:0 0 12px; font-size:13px;">{{ stare_subtext }}</p>
|
||||
{% endif %}
|
||||
|
||||
{# === R10 (2): bloc eroare blocanta — DOAR in read-only (US-008).
|
||||
{# === Bloc eroare blocanta — DOAR in read-only.
|
||||
In editare, cardul 3-niveluri e inlocuit cu: erori per-camp in macro `camp`
|
||||
(text simplu .s-error) + rezumat top-of-form pentru erori fara camp (mai jos). === #}
|
||||
{% if not editabil and erori_3n %}
|
||||
@@ -28,7 +27,7 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{# === R10 (3) + R9: mapare inline (PRD 5.7) — alege cod RAR pentru operatiile nemapate.
|
||||
{# === Mapare inline — alege cod RAR pentru operatiile nemapate.
|
||||
Cand nemapate_inline, linia „Operatie: X · nemapat" apare in formularul de mai jos
|
||||
(cod_afis = nemapat), iar aici e picker-ul; dupa mapare, re-render arata codul rezolvat. === #}
|
||||
{% if nemapate_inline %}
|
||||
@@ -78,7 +77,7 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{# === R10 (4): formular editabil (needs_data/needs_mapping) SAU context read-only.
|
||||
{# === Formular editabil (needs_data/needs_mapping) SAU context read-only.
|
||||
Zero dublare: campurile vehiculului apar O SINGURA DATA — editabile cand randul e
|
||||
corectabil, altfel read-only. Operatie + cod RAR read-only deasupra campurilor. === #}
|
||||
{% if editabil %}
|
||||
@@ -90,7 +89,7 @@
|
||||
{% if corectie_error %}role="alert"{% endif %}>{{ corectie_msg }}</div>
|
||||
{% endif %}
|
||||
|
||||
{# US-008 (M6): erori fara camp (field None) nu dispar silentios in editare —
|
||||
{# Erori fara camp (field None) nu dispar silentios in editare —
|
||||
cardul 3n e ascuns, deci adaugam un rezumat simplu top-of-form.
|
||||
Erori cu camp raman afisate per-camp de macro-ul `camp` de mai jos. #}
|
||||
{% for e in erori_3n if not e.field %}
|
||||
@@ -114,7 +113,7 @@
|
||||
hx-disabled-elt="find button">
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
|
||||
|
||||
{# US-006: select cod RAR pe stari editabile (needs_data/needs_mapping), cu nomenclator.
|
||||
{# Select cod RAR pe stari editabile (needs_data/needs_mapping), cu nomenclator.
|
||||
Read-only pe sent/sending/queued/error (nomenclator_rar gol → ramura else). #}
|
||||
{% if nomenclator_rar %}
|
||||
<div style="margin:0 0 12px;">
|
||||
@@ -133,15 +132,15 @@
|
||||
</select>
|
||||
</div>
|
||||
{% else %}
|
||||
{# Operatie + cod RAR read-only deasupra campurilor (R9, fara eticheta „Cod RAR"). #}
|
||||
{# Operatie + cod RAR read-only deasupra campurilor (fara eticheta „Cod RAR"). #}
|
||||
<div style="margin:0 0 12px;">
|
||||
<div class="muted" style="font-size:12px;">Operatie</div>
|
||||
<div>{{ prez.operatie }} · {{ cod_afis }}</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{# US-007: operatie service (cod intern + denumire venita prin API/import), distinct de
|
||||
operatia RAR mapata. Conventie US-002: op_service_cod="" cand lipseste → randul absent. #}
|
||||
{# Operatie service (cod intern + denumire venita prin API/import), distinct de
|
||||
operatia RAR mapata. op_service_cod="" cand lipseste → randul absent. #}
|
||||
{% if prez.op_service_cod %}
|
||||
<div style="margin:0 0 12px;">
|
||||
<div class="muted" style="font-size:12px;">Operatie service</div>
|
||||
@@ -160,7 +159,7 @@
|
||||
{{ camp('odometru_initial', 'Odometru initial (daca e cerut)', form_odo_initial) }}
|
||||
</div>
|
||||
|
||||
{# === R10 (5): actiune primara conditionata de stare (R2). needs_data/needs_mapping
|
||||
{# === Actiune primara conditionata de stare. needs_data/needs_mapping
|
||||
-> „Salveaza si retrimite" pe /corecteaza. UN SINGUR buton primar per stare. === #}
|
||||
<div style="margin-top:14px;">
|
||||
<button type="submit">Salveaza si retrimite</button>
|
||||
@@ -177,8 +176,8 @@
|
||||
<div style="word-break:break-all;">{{ prez.vin }}</div>
|
||||
</div>
|
||||
<div><div class="muted" style="font-size:12px;">Operatie</div><div>{{ prez.operatie }} · {{ cod_afis }}</div></div>
|
||||
{# US-007: operatie service (cod intern + denumire), distinct de operatia RAR.
|
||||
Conventie US-002: op_service_cod="" cand lipseste → randul absent (fara "—"). #}
|
||||
{# Operatie service (cod intern + denumire), distinct de operatia RAR.
|
||||
op_service_cod="" cand lipseste → randul absent (fara "—"). #}
|
||||
{% if prez.op_service_cod %}
|
||||
<div><div class="muted" style="font-size:12px;">Operatie service</div>
|
||||
<div>{{ prez.op_service_cod }}{% if prez.op_service_denumire %} — {{ prez.op_service_denumire }}{% endif %}</div></div>
|
||||
@@ -188,17 +187,17 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{# === R10 (5): actiuni de jos — primar Re-pune (doar error) + Sterge pe RAND SEPARAT (R2/R11) === #}
|
||||
{# === Actiuni de jos — primar Re-pune (doar error) + Sterge pe RAND SEPARAT === #}
|
||||
{% if status == 'error' or gestionabil %}
|
||||
<div class="detaliu-actiuni-jos" style="margin-top:14px; padding-top:12px; border-top:1px solid var(--line);">
|
||||
{# R2: error -> buton primar „Re-pune in coada" pe /repune (error nu e editabil pentru #}
|
||||
{# campuri vehicul, dar US-006b permite schimbarea cod_prestatie prin acelasi formular). #}
|
||||
{# Error -> buton primar „Re-pune in coada" pe /repune (error nu e editabil pentru #}
|
||||
{# campuri vehicul, dar se poate schimba cod_prestatie prin acelasi formular). #}
|
||||
{% if status == 'error' %}
|
||||
<form hx-post="/trimitere/{{ id }}/repune"
|
||||
hx-target="#detaliu-modal-body" hx-swap="innerHTML"
|
||||
hx-disabled-elt="find button" style="margin:0 0 10px;">
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
|
||||
{# US-006b: select cod_prestatie optional in formularul /repune (doar pentru error). #}
|
||||
{# Select cod_prestatie optional in formularul /repune (doar pentru error). #}
|
||||
{% if nomenclator_rar %}
|
||||
<label for="cod-rar-error-{{ id }}" style="display:block; font-size:12px; color:var(--muted); margin-bottom:4px;">
|
||||
Operatie RAR (optional — schimba codul si re-pune)
|
||||
@@ -219,7 +218,7 @@
|
||||
</form>
|
||||
{% endif %}
|
||||
|
||||
{# R11: UN SINGUR Sterge, outline distructiv (var(--err)), pe rand separat, full-width pe mobil. #}
|
||||
{# UN SINGUR Sterge, outline distructiv (var(--err)), pe rand separat, full-width pe mobil. #}
|
||||
{% if gestionabil %}
|
||||
<form hx-post="/trimitere/{{ id }}/sterge"
|
||||
hx-target="#detaliu-modal-body" hx-swap="innerHTML"
|
||||
@@ -235,7 +234,7 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{# === R10 (6): Detalii tehnice — colapsat implicit === #}
|
||||
{# === Detalii tehnice — colapsat implicit === #}
|
||||
<details style="margin-top:14px;">
|
||||
<summary class="muted" style="font-size:12px; cursor:pointer;">Detalii tehnice</summary>
|
||||
<div style="display:grid; grid-template-columns:repeat(auto-fit, minmax(200px, 1fr)); gap:10px 24px; margin-top:10px;">
|
||||
@@ -257,7 +256,6 @@
|
||||
{% endif %}
|
||||
</details>
|
||||
</div>
|
||||
{# PRD 5.9 US-004 (R4): scriptul inline vechi (marcheazaDetaliuDeschis / scrollIntoView pe
|
||||
randul-sibling) a fost eliminat de US-003. Focus-ul post-swap (incl. re-render corectie/
|
||||
mapare) e gestionat de htmx:afterSettle pe #detaliu-modal-body din base.html. R5: inchiderea
|
||||
modalului pe succes (queued/sterge) vine din HX-Trigger `inchideModal` emis de rute. #}
|
||||
{# Focus-ul post-swap (incl. re-render corectie/mapare) e gestionat de htmx:afterSettle pe
|
||||
#detaliu-modal-body din base.html. Inchiderea modalului pe succes (queued/sterge) vine
|
||||
din HX-Trigger `inchideModal` emis de rute. #}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<div id="import-section">
|
||||
{% set pas = 1 %}{% include '_stepper.html' %}
|
||||
{# US-004 (3.6): bara de upload accentuata (border de accent) ca sa ramana punctul
|
||||
de intrare evident chiar cu tabelul Trimiteri lung dedesubt (D-1.1/D-5.2). #}
|
||||
{# Bara de upload accentuata (border de accent) ca sa ramana punctul
|
||||
de intrare evident chiar cu tabelul Trimiteri lung dedesubt. #}
|
||||
{% from '_eroare.html' import card_erori %}
|
||||
<div class="card" style="border-color:var(--accent);">
|
||||
|
||||
@@ -105,7 +105,7 @@
|
||||
var dz = document.getElementById('drop-zone');
|
||||
var frm = document.getElementById('upload-form');
|
||||
|
||||
/* US-003 (3.6): un singur sticky bar pe ecran — cand re-apare zona de upload
|
||||
/* Un singur sticky bar pe ecran — cand re-apare zona de upload
|
||||
(reset sau dupa commit), sectiunea Trimiteri redevine vizibila. */
|
||||
var trim = document.getElementById('trimiteri-section');
|
||||
if (trim) trim.style.display = '';
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
{% block title %}Conturi clienti — Gateway RAR AUTOPASS{% endblock %}
|
||||
{% block content %}
|
||||
|
||||
{# US-009 (5.5): metadate verbe de ciclu de viata (eticheta, ruta, clasa). #}
|
||||
{# Metadate verbe de ciclu de viata (eticheta, ruta, clasa). #}
|
||||
{% set VERBS = {
|
||||
'activate': ('Activeaza', '/admin/activate', ''),
|
||||
'block': ('Blocheaza', '/admin/block', ''),
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<title>{% block title %}Gateway RAR AUTOPASS{% endblock %}</title>
|
||||
<script src="/static/htmx.min.js"></script>
|
||||
<script>
|
||||
// US-002 (3.6): raspunsurile de editare-rand contin un <tr> (swap pe rand) PLUS
|
||||
// Raspunsurile de editare-rand contin un <tr> (swap pe rand) PLUS
|
||||
// elemente OOB non-rand (#preview-rezumat, #preview-ok-count). Fara fragmente-template,
|
||||
// htmx parseaza raspunsul care incepe cu <tr> in context de tabel (<table><tbody>) si
|
||||
// "foster-parent"-eaza div/span-urile OOB afara din fragment -> swapError + contoare pierdute.
|
||||
@@ -14,8 +14,8 @@
|
||||
htmx.config.useTemplateFragments = true;
|
||||
</script>
|
||||
<script>
|
||||
// Anti-FOUC (US-001 PRD 5.3, extins US-014 PRD 5.10): citeste preferinta tema din
|
||||
// localStorage inainte de primul paint; seteaza data-theme pe <html> sincron, fara blink.
|
||||
// Anti-FOUC: citeste preferinta tema din localStorage inainte de primul
|
||||
// paint; seteaza data-theme pe <html> sincron, fara blink.
|
||||
// Cunoaste toate cele 4 teme: light/dark/petrol/auto. Valoare legacy/necunoscuta -> auto.
|
||||
// 'auto' se rezolva la 'light' sau 'dark' dupa prefers-color-scheme (fara blink).
|
||||
(function() {
|
||||
@@ -33,12 +33,9 @@
|
||||
})();
|
||||
</script>
|
||||
<style>
|
||||
/* US-013 (PRD 5.10): IBM Plex Sans + Mono self-hosted (latin-ext pentru diacritice romanesti).
|
||||
font-display:swap permite text vizibil inainte de incarcare (FOUT system-ui->IBM Plex).
|
||||
FOUT pe tabular-nums: IBM Plex Sans are metrici apropiate de system-ui; reflow-ul vizibil
|
||||
pe VIN/coduri e acceptat explicit — fontul se incarca din /static/ (acelasi origin).
|
||||
IBM Plex Sans/Mono self-host, subset latin + latin-ext de pe fontsource
|
||||
(@fontsource/ibm-plex-sans + @fontsource/ibm-plex-mono, v5.0.8), woff2 valide. */
|
||||
/* IBM Plex Sans + Mono self-hosted (latin-ext pentru diacritice romanesti).
|
||||
font-display:swap permite text vizibil inainte de incarcare (FOUT system-ui->IBM Plex);
|
||||
reflow-ul vizibil pe VIN/coduri e acceptat explicit. */
|
||||
@font-face {
|
||||
font-family: "IBM Plex Sans";
|
||||
font-style: normal;
|
||||
@@ -103,38 +100,32 @@
|
||||
src: url("/static/fonts/IBMPlexMono-Regular-latin.woff2") format("woff2");
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+20AC, U+2122, U+FEFF, U+FFFD;
|
||||
}
|
||||
/* Paleta dark (default) — accent azur ROMFAST conform DESIGN.md */
|
||||
/* Paleta dark (default) — accent azur ROMFAST */
|
||||
:root { --bg:#0f1218; --card:#181c24; --ink:#e6e9ef; --muted:#8b93a7; --line:#262b36;
|
||||
--ok:#2FBF8F; --warn:#E0A93B; --err:#E05D5D; --accent:#2E74D6; }
|
||||
/* Paleta light — accent azur inchis pentru contrast AA pe alb (#1F66C9: 5.51:1 pe alb) */
|
||||
[data-theme="light"] { --bg:#f5f7fa; --card:#ffffff; --ink:#1a1d24; --muted:#5c6473; --line:#e2e5ea;
|
||||
--ok:#15803d; --warn:#b45309; --err:#dc2626; --accent:#1F66C9; }
|
||||
/* Paleta Petrol (US-014) — tema intunecata alternativa, accent teal #0E7C7B.
|
||||
/* Paleta Petrol — tema intunecata alternativa, accent teal #0E7C7B.
|
||||
Wordmark-ul FAST #2E74D6 coexista armonios: ambele sunt reci/saturate, contrast AA pe --card #161e20. */
|
||||
[data-theme="petrol"] { --bg:#0e1416; --card:#161e20; --ink:#e6e9ef; --muted:#8b93a7; --line:#232c2e;
|
||||
--ok:#2FBF8F; --warn:#E0A93B; --err:#E05D5D; --accent:#0E7C7B; }
|
||||
* { box-sizing:border-box; }
|
||||
/* PRD 5.9 US-006 — CONVENTIE BREAKPOINT: un singur prag mobil la 768px.
|
||||
/* CONVENTIE BREAKPOINT: un singur prag mobil la 768px.
|
||||
CSS custom properties NU functioneaza in `@media`, deci pragul nu poate fi o
|
||||
variabila; folosim consecvent `@media (max-width:767px)` peste tot (mobil) si
|
||||
`@media (max-width:1024px)` doar pentru densitatea tabelului. >=1024px = layout
|
||||
desktop neschimbat (fara regresie). Orice regula mobila noua reutilizeaza 767px. */
|
||||
body { margin:0; font:15px/1.5 "IBM Plex Sans",system-ui,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
|
||||
background:var(--bg); color:var(--ink); -webkit-font-smoothing:antialiased; }
|
||||
/* US-012c (PRD 5.10): grila 3 coloane — stanga (logo ROMFAST) | centru (titlu+env) | dreapta (controale). */
|
||||
/* Grila 3 coloane — stanga (logo ROMFAST) | centru (titlu+env) | dreapta (controale). */
|
||||
header { padding:16px 24px; border-bottom:1px solid var(--line);
|
||||
display:grid; grid-template-columns:1fr auto 1fr; align-items:center; gap:8px; min-height:92px; }
|
||||
.header-left { display:flex; align-items:center; }
|
||||
.header-center { display:flex; flex-direction:column; align-items:center; text-align:center; }
|
||||
.header-right { display:flex; align-items:center; justify-content:flex-end; gap:8px; }
|
||||
/* US-012c: logo PNG ROMFAST in header-left (brand top-left ca pe romfast.ro).
|
||||
32px inaltime — usor mai mare decat in header-center (28px) pentru vizibilitate ca brand anchor.
|
||||
margin:0 — aliniat stanga, NU centrat (era `margin:3px auto 0` cand era sub titlu).
|
||||
Logo transparent: ok pe dark/light/petrol fara filtre de culoare. */
|
||||
/* Logo ROMFAST la dimensiunea de pe romfast.ro (~60px inaltime), aliniat stanga. */
|
||||
/* Logo ROMFAST aliniat stanga; transparent, ok pe dark/light/petrol fara filtre de culoare. */
|
||||
.brand-logo { height:60px; width:auto; display:block; margin:0; }
|
||||
/* Env badge mic sub titlu in header-center (US-012c): nu mai echilibreaza optic dreapta
|
||||
(logo-ul face asta), ci identifica mediul langa titlu. Pastrat mic, color:var(--muted). */
|
||||
.header-center .env { font-size:11px; margin-top:2px; }
|
||||
header h1 { font-size:20px; margin:0; font-weight:700; letter-spacing:-.01em; }
|
||||
header .env { font-size:12px; color:var(--muted); border:1px solid var(--line); padding:2px 8px; border-radius:99px; }
|
||||
@@ -210,7 +201,7 @@
|
||||
button { background:var(--accent); border-color:var(--accent); color:#fff; cursor:pointer; }
|
||||
button:hover { filter:brightness(1.08); }
|
||||
.chk { font-size:13px; color:var(--muted); display:flex; align-items:center; gap:6px; }
|
||||
/* Tab-bar (US-003) */
|
||||
/* Tab-bar */
|
||||
.tab-bar { display:flex; gap:2px; overflow-x:auto; -webkit-overflow-scrolling:touch;
|
||||
border-bottom:1px solid var(--line); margin-bottom:16px; padding-bottom:0;
|
||||
scrollbar-width:none; }
|
||||
@@ -224,7 +215,7 @@
|
||||
border-color:var(--line); border-bottom-color:var(--card); }
|
||||
.tab-panel { min-height:120px; }
|
||||
.status-bar { margin-bottom:12px; }
|
||||
/* Eroare 3 niveluri (US-006, PRD 5.4) */
|
||||
/* Eroare 3 niveluri */
|
||||
.eroare-3n { margin-top:10px; }
|
||||
.eroare-3n-item { padding:8px 10px; border-left:3px solid var(--err);
|
||||
background:color-mix(in srgb, var(--err) 8%, var(--card));
|
||||
@@ -237,13 +228,13 @@
|
||||
.eroare-3n-label { font-weight:500; }
|
||||
/* Inline fix per camp in preview */
|
||||
.camp-fix { color:var(--accent); font-size:11px; margin-top:2px; display:block; }
|
||||
/* Meniu hamburger cont (US-006 PRD 5.5) — dropdown ancorat dreapta-sus */
|
||||
/* Meniu hamburger cont — dropdown ancorat dreapta-sus */
|
||||
.cont-menu-wrap { position:relative; }
|
||||
.icon-btn { background:transparent; border:1px solid var(--line); color:var(--ink); cursor:pointer;
|
||||
border-radius:6px; min-height:36px; min-width:36px; font-size:16px; padding:4px 8px;
|
||||
line-height:1; display:inline-flex; align-items:center; justify-content:center; }
|
||||
.icon-btn:hover { background:var(--line); }
|
||||
/* US-011: variante icon-btn — dirty (modificari nesalvate) + danger (destructiv) */
|
||||
/* Variante icon-btn — dirty (modificari nesalvate) + danger (destructiv) */
|
||||
.icon-btn.dirty { background:var(--accent); color:#fff; border-color:var(--accent); }
|
||||
.icon-btn.dirty:hover { filter:brightness(0.9); }
|
||||
.icon-btn.danger { color:var(--err); border-color:var(--err); }
|
||||
@@ -260,7 +251,7 @@
|
||||
.cont-menu form { margin:0; }
|
||||
/* Kebab partajat (actiuni per-rand in tabele). Meniul e position:fixed si pozitionat de JS:
|
||||
altfel `.tablewrap { overflow-x:auto }` induce overflow-y:auto si TAIE dropdown-ul pe ultimul
|
||||
rand (bug 5.5 — meniul nu se vedea). fixed scoate meniul din contextul de clipping al tabelului. */
|
||||
rand. fixed scoate meniul din contextul de clipping al tabelului. */
|
||||
.kebab { position:relative; display:inline-block; }
|
||||
.kebab > summary { list-style:none; cursor:pointer; display:inline-flex; align-items:center;
|
||||
justify-content:center; min-height:32px; min-width:32px; padding:4px 10px;
|
||||
@@ -288,7 +279,7 @@
|
||||
.dt-pager button { background:transparent; color:var(--ink); border:1px solid var(--line);
|
||||
padding:5px 12px; min-height:32px; }
|
||||
.dt-pager button:disabled { opacity:.45; cursor:default; }
|
||||
/* === Tabel trimiteri (PRD 5.8 US-007): fara scroll orizontal. SCOPAT prin
|
||||
/* === Tabel trimiteri: fara scroll orizontal. SCOPAT prin
|
||||
.tabel-trimiteri ca sa NU strice celelalte tabele (.tablewrap e partajat de
|
||||
Mapari/Formate). Permitem wrap controlat pe coloanele text + latimi rezonabile. === */
|
||||
.tabel-trimiteri table { table-layout:fixed; }
|
||||
@@ -302,16 +293,15 @@
|
||||
.tabel-trimiteri .col-operatie > div { line-height:1.35; }
|
||||
/* secundarul muted („cod RAR" / „nemapat") — >=12px, contrast pe var(--muted) >=4.5:1 */
|
||||
.tabel-trimiteri .cod-rar-sub { font-size:12px; margin-top:2px; }
|
||||
/* PRD 5.9 US-002: codul RAR pe linia 2 — chip discret, fara prefixul „cod RAR:". */
|
||||
/* Codul RAR pe linia 2 — chip discret, fara prefixul „cod RAR:". */
|
||||
.tabel-trimiteri .cod-rar-cod { display:inline-block; font-family:"IBM Plex Mono",ui-monospace,monospace;
|
||||
font-size:12px; padding:1px 7px; border:1px solid var(--line);
|
||||
border-radius:99px; color:var(--muted); }
|
||||
/* PRD 5.9 US-002 (R1): eticheta umana scurta sub pill — text mic; clasa `s-error`
|
||||
o coloreaza (apare doar pe error/needs_*). Stare prin text, nu doar culoare. */
|
||||
/* Eticheta umana scurta sub pill — text mic; clasa `s-error` o coloreaza
|
||||
(apare doar pe error/needs_*). Stare prin text, nu doar culoare. */
|
||||
.tabel-trimiteri .eticheta-problema { font-size:12px; line-height:1.3; margin-top:3px; }
|
||||
/* PRD 5.9 US-002 (R8): randul e clickabil (deschide modalul) -> tinta de atins >=44px
|
||||
(touch) + afordanta hover/focus. Inlocuieste vechea regula `@media pointer:coarse
|
||||
.chevron` (chevron eliminat); este SINGURA regula 44px pe rand. */
|
||||
/* Randul e clickabil (deschide modalul) -> tinta de atins >=44px (touch) +
|
||||
afordanta hover/focus. */
|
||||
.tabel-trimiteri tr.trimitere-row { min-height:44px; }
|
||||
.tabel-trimiteri tr.trimitere-row > td { padding-top:11px; padding-bottom:11px; }
|
||||
.tabel-trimiteri tr.trimitere-row:hover { background:color-mix(in srgb, var(--accent) 6%, transparent); }
|
||||
@@ -321,10 +311,10 @@
|
||||
@media (max-width:1024px) {
|
||||
.tabel-trimiteri .col-actualizat { display:none; }
|
||||
}
|
||||
/* === Modal detaliu (PRD 5.9 US-003): fereastra modala globala, in afara zonei de
|
||||
poll (#submissions-wrap). Backdrop + dialog centrat pe desktop; focus-trap +
|
||||
/* === Modal detaliu: fereastra modala globala, in afara zonei de poll
|
||||
(#submissions-wrap). Backdrop + dialog centrat pe desktop; focus-trap +
|
||||
scroll-lock + inert pe <main> sunt in JS. Varianta full-screen mobil: vezi blocul
|
||||
`@media (max-width:767px)` US-006 de mai jos. === */
|
||||
`@media (max-width:767px)` de mai jos. === */
|
||||
.modal-overlay { position:fixed; inset:0; z-index:1100; display:flex;
|
||||
align-items:flex-start; justify-content:center; padding:40px 16px; overflow-y:auto; }
|
||||
.modal-overlay[hidden] { display:none; }
|
||||
@@ -341,9 +331,9 @@
|
||||
body.modal-open { overflow:hidden; }
|
||||
.modal-eroare { padding:16px 4px; }
|
||||
.modal-eroare .actiuni { margin-top:12px; display:flex; gap:10px; flex-wrap:wrap; }
|
||||
/* === PRD 5.9 US-006: fundatie responsive mobil (<768px) ===
|
||||
/* === Fundatie responsive mobil (<768px) ===
|
||||
Breakpoint unic 767px (vezi conventia de sus). Cuprinde: card per rand pe tabelul
|
||||
de trimiteri (5.8, pastrat), modal full-screen, header/nav colapsat cu tinte touch
|
||||
de trimiteri, modal full-screen, header/nav colapsat cu tinte touch
|
||||
>=44px. Desktop (>=1024px) ramane neschimbat — regulile de baza nu se modifica. */
|
||||
@media (max-width:767px) {
|
||||
/* Tabel trimiteri: card per rand (eticheta:valoare stivuit) -> fara scroll orizontal */
|
||||
@@ -366,7 +356,7 @@
|
||||
padding:16px; padding-top:56px; overflow-y:auto; }
|
||||
.modal-close { width:44px; height:44px; top:8px; right:8px; font-size:24px; }
|
||||
|
||||
/* US-004 (R11): actiunile de jos din detaliu (Re-pune / Sterge) full-width stivuit pe mobil. */
|
||||
/* Actiunile de jos din detaliu (Re-pune / Sterge) full-width stivuit pe mobil. */
|
||||
.detaliu-actiuni-jos button { width:100%; }
|
||||
|
||||
/* Header + nav colapsate: pe mobil trece de la grid la flex wrap.
|
||||
@@ -383,9 +373,9 @@
|
||||
.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 ===
|
||||
/* === 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
|
||||
scopata SEPARAT de `.tabel-trimiteri` 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; }
|
||||
@@ -417,11 +407,11 @@
|
||||
#card-cont button, #form-test-cheie button,
|
||||
#jurnal-section #filtre-jurnal button { min-height:44px; width:100%; }
|
||||
|
||||
/* === PRD 5.9 US-008: Acasa (upload, status, filtre) + login/signup pe mobil ===
|
||||
/* === Acasa (upload, status, filtre) + login/signup pe mobil ===
|
||||
Zona de upload, bara de status si bara de filtre (`_coada.html`) stiveaza pe O
|
||||
coloana sub 767px; inputuri/butoane full-width cu tinta touch >=44px. Scopat pe
|
||||
id-urile sectiunilor de pe Acasa ca sa NU atinga tabelul de trimiteri (5.8),
|
||||
modalul sau paginile de continut (US-007). */
|
||||
id-urile sectiunilor de pe Acasa ca sa NU atinga tabelul de trimiteri,
|
||||
modalul sau paginile de continut. */
|
||||
/* Bara de upload: zona slim (returning user) trece pe coloana; butonul full-width. */
|
||||
#import-section .drop-zone { flex-direction:column; align-items:stretch; text-align:left; }
|
||||
#import-section #upload-btn { width:100%; min-height:44px; }
|
||||
@@ -441,16 +431,14 @@
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
{# US-012c (PRD 5.10): grila 3 coloane — stanga (logo ROMFAST) | centru (titlu+env) | dreapta (controale).
|
||||
Decizie env badge: mutat in header-center sub <h1> (mic, color:muted) — nu suprapune logo-ul
|
||||
si pastreaza centrarea optica a titlului in coloana auto. #}
|
||||
{# Grila 3 coloane — stanga (logo ROMFAST) | centru (titlu+env) | dreapta (controale). #}
|
||||
<header>
|
||||
{# Celula stanga: logo ROMFAST (US-012c: brand top-left ca pe romfast.ro) #}
|
||||
{# Celula stanga: logo ROMFAST #}
|
||||
<div class="header-left">
|
||||
{# US-012b/c: logo PNG real, 288x175 RGBA transparent — ok pe toate temele fara filtre. #}
|
||||
{# Logo PNG real, RGBA transparent — ok pe toate temele fara filtre. #}
|
||||
<img src="/static/romfast_logo.png" alt="ROMFAST" class="brand-logo">
|
||||
</div>
|
||||
{# Celula centru: titlu + badge env mic (US-012c: env mutat din header-left aici) #}
|
||||
{# Celula centru: titlu + badge env mic #}
|
||||
<div class="header-center">
|
||||
<h1>Gateway RAR AUTOPASS</h1>
|
||||
<span class="env">{{ rar_env }}</span>
|
||||
@@ -462,14 +450,14 @@
|
||||
title="Comuta tema">☀</button>
|
||||
<span class="muted" style="font-size:13px;">v{{ version }}</span>
|
||||
{% if is_authenticated|default(false) %}
|
||||
{# Meniu cont (US-006 PRD 5.5): Cont/Integrare/Nomenclator + (admin) + logout.
|
||||
{# Meniu cont: Cont/Integrare/Nomenclator + (admin) + logout.
|
||||
Pe paginile neautentificate (login/signup) nu se randeaza deloc. #}
|
||||
<div class="cont-menu-wrap">
|
||||
<button id="cont-menu-toggle" class="icon-btn"
|
||||
aria-haspopup="true" aria-expanded="false" aria-controls="cont-menu"
|
||||
aria-label="Meniu cont" title="Meniu cont">☰</button>
|
||||
<div id="cont-menu" class="cont-menu" role="menu" aria-labelledby="cont-menu-toggle" hidden>
|
||||
{# US-009 (PRD 5.10): Mapari mutat din tab-bar in meniu, cu badge needs_mapping. #}
|
||||
{# Mapari, cu badge needs_mapping. #}
|
||||
{% set _mapari_badge = (badges.mapari if (badges is defined and badges and badges.mapari) else 0) %}
|
||||
<a role="menuitem" href="/?tab=mapari">Mapari{% if _mapari_badge %}<span class="tab-badge" aria-hidden="true" style="display:inline-flex; align-items:center; justify-content:center; min-width:18px; height:18px; margin-left:6px; padding:0 5px; border-radius:99px; background:var(--err); color:#fff; font-size:11px; font-weight:700;">{{ _mapari_badge }}</span>{% endif %}</a>
|
||||
<hr>
|
||||
@@ -488,14 +476,14 @@
|
||||
{% endif %}
|
||||
</div>
|
||||
</header>
|
||||
{# aria-live pentru anuntarea schimbarilor de tema (US-014, accesibilitate) #}
|
||||
{# aria-live pentru anuntarea schimbarilor de tema (accesibilitate) #}
|
||||
<span id="tema-live" role="status" aria-live="polite"
|
||||
style="position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;"></span>
|
||||
<main>{% block content %}{% endblock %}</main>
|
||||
{# Modal detaliu trimitere (PRD 5.9 US-003): container global, SIBLING al <main>
|
||||
(nu descendent), ca `inert`+`aria-hidden` pe <main> sa nu-l prinda si pe el (R7).
|
||||
Corpul #detaliu-modal-body e tinta de swap pentru fragment + rutele corectie/
|
||||
mapare/lifecycle. Traieste in afara #submissions-wrap -> poll-ul de 15s nu-l atinge. #}
|
||||
{# Modal detaliu trimitere: container global, SIBLING al <main> (nu descendent),
|
||||
ca `inert`+`aria-hidden` pe <main> sa nu-l prinda si pe el. Corpul
|
||||
#detaliu-modal-body e tinta de swap pentru fragment + rutele corectie/mapare/
|
||||
lifecycle. Traieste in afara #submissions-wrap -> poll-ul nu-l atinge. #}
|
||||
<div id="modal-detaliu" class="modal-overlay" role="dialog" aria-modal="true"
|
||||
aria-labelledby="detaliu-modal-titlu" hidden>
|
||||
<div class="modal-backdrop" data-modal-close></div>
|
||||
@@ -505,7 +493,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
// Comutator tema ciclic (US-014 PRD 5.10): click cicleaza Light->Dark->Petrol->Auto.
|
||||
// Comutator tema ciclic: click cicleaza Light->Dark->Petrol->Auto.
|
||||
// Separare init (sincronizare iconita/label) de persistenta (doar la click explicit).
|
||||
// 'auto' se rezolva la paint prin anti-FOUC; aici setam data-theme rezolvat.
|
||||
(function() {
|
||||
@@ -528,7 +516,7 @@
|
||||
var s = VALID[stored] ? stored : 'auto';
|
||||
btn.innerHTML = ICONS[s];
|
||||
btn.setAttribute('aria-label', 'Tema: ' + LABELS[s] + ', apasa pentru ' + NEXT[s]);
|
||||
btn.title = LABELS[s]; // US-014b: doar numele temei (ex. "Petrol"), nu ciclul intreg
|
||||
btn.title = LABELS[s]; // doar numele temei (ex. "Petrol"), nu ciclul intreg
|
||||
}
|
||||
function _setTheme(t) {
|
||||
document.documentElement.setAttribute('data-theme', _resolved(t));
|
||||
@@ -547,7 +535,7 @@
|
||||
})();
|
||||
</script>
|
||||
<script>
|
||||
// Meniu cont (US-006 PRD 5.5): dropdown ancorat dreapta-sus. Deschide/inchide la click,
|
||||
// Meniu cont: dropdown ancorat dreapta-sus. Deschide/inchide la click,
|
||||
// inchide la Esc (focus readus pe buton) si la click in afara. Fara dependente.
|
||||
(function() {
|
||||
var toggle = document.getElementById('cont-menu-toggle');
|
||||
@@ -624,7 +612,7 @@
|
||||
})();
|
||||
</script>
|
||||
<script>
|
||||
// US-011: dirty state pentru butoanele de salvare din tabelele de mapari.
|
||||
// Dirty state pentru butoanele de salvare din tabelele de mapari.
|
||||
// Cand utilizatorul schimba un select dintr-un form de mapare, butonul de salvare
|
||||
// legat prin data-dirty-form devine evidentiat (clasa "dirty" → fundal --accent).
|
||||
// Starea "dirty" e efemera per-render: un swap outerHTML o reseteaza automat.
|
||||
@@ -700,11 +688,11 @@
|
||||
})();
|
||||
</script>
|
||||
<script>
|
||||
// Modal detaliu trimitere (PRD 5.9 US-003): inlocuieste detaliul inline (5.8). Detaliul
|
||||
// se incarca prin HTMX in #detaliu-modal-body (in afara #submissions-wrap, deci poll-ul
|
||||
// de 15s nu-l atinge). Aici: deschidere la click pe rand, inchidere (x/Esc/backdrop),
|
||||
// focus-trap, scroll-lock, inert+aria-hidden pe <main> (R7), stare de eroare la load
|
||||
// esuat (R5), inchidere pe succes corectie/sterge (HX-Trigger inchideModal, R5).
|
||||
// Modal detaliu trimitere: detaliul se incarca prin HTMX in #detaliu-modal-body
|
||||
// (in afara #submissions-wrap, deci poll-ul nu-l atinge). Aici: deschidere la click
|
||||
// pe rand, inchidere (x/Esc/backdrop), focus-trap, scroll-lock, inert+aria-hidden pe
|
||||
// <main>, stare de eroare la load esuat, inchidere pe succes corectie/sterge
|
||||
// (HX-Trigger inchideModal).
|
||||
(function() {
|
||||
var overlay = document.getElementById('modal-detaliu');
|
||||
if (!overlay) return;
|
||||
@@ -721,7 +709,7 @@
|
||||
' select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])'),
|
||||
function(el) { return el.offsetParent !== null || el === document.activeElement; });
|
||||
}
|
||||
// R7: focus-trap — Tab/Shift+Tab cicleaza in interiorul dialogului.
|
||||
// focus-trap — Tab/Shift+Tab cicleaza in interiorul dialogului.
|
||||
function trapFocus(e) {
|
||||
if (e.key !== 'Tab') return;
|
||||
var f = focusable();
|
||||
@@ -755,7 +743,6 @@
|
||||
if (t && t.focus) t.focus(); // focus readus pe rand
|
||||
}
|
||||
// API public: butonul „Inchide" din fragment + inchiderea pe succes corectie/sterge.
|
||||
// (Semnatura veche inchideDetaliu(id) pastrata, dar exista un singur modal o data.)
|
||||
window.inchideDetaliu = function() { close(); };
|
||||
|
||||
// Inchidere: x si backdrop (elemente cu data-modal-close), Esc.
|
||||
@@ -778,7 +765,7 @@
|
||||
var f = focusable();
|
||||
if (f.length) f[0].focus();
|
||||
});
|
||||
// R5: load-error al fragmentului (GET esuat) -> stare Reincearca/Inchide, nu placeholder blocat.
|
||||
// Load-error al fragmentului (GET esuat) -> stare Reincearca/Inchide, nu placeholder blocat.
|
||||
body.addEventListener('htmx:responseError', function(evt) {
|
||||
if (!isOpen()) return;
|
||||
var elt = evt.detail && evt.detail.elt;
|
||||
@@ -796,7 +783,7 @@
|
||||
{ target: body, swap: 'innerHTML' });
|
||||
});
|
||||
|
||||
// R5: inchidere pe succes corectie/sterge — ruta emite HX-Trigger `inchideModal`.
|
||||
// Inchidere pe succes corectie/sterge — ruta emite HX-Trigger `inchideModal`.
|
||||
// Lista se reincarca separat prin `trimiteriChanged` (#submissions-wrap). Maparea
|
||||
// inline NU emite inchideModal -> modalul ramane deschis sa arate codul rezolvat.
|
||||
document.body.addEventListener('inchideModal', function() { close(); });
|
||||
|
||||
@@ -1,11 +1,6 @@
|
||||
{% extends "base.html" %}
|
||||
{% block content %}
|
||||
|
||||
{# US-009 (PRD 5.10): tab-bar-ul Acasa/Mapari a fost eliminat. Mapari s-a mutat in meniul
|
||||
hamburger (#cont-menu in base.html). Acasa e continutul principal direct — nicio schela ARIA
|
||||
role="tablist"/"tab"/"tabpanel" orfana. Rutele /_fragments/* si deep-link-urile ?tab=
|
||||
raman valide (navigare prin meniu → full page reload). #}
|
||||
|
||||
<!-- Bara de status: mereu vizibila -->
|
||||
<div id="status-bar" class="status-bar card"
|
||||
hx-get="/_fragments/status"
|
||||
|
||||
Reference in New Issue
Block a user