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>
13 KiB
PRD 5.22 — UI compact Trimiteri + bara contextuala "Aplica cod" + exemplu Reguli automate + fix buton "+" editor import
Stare: inchis
Mockup aprobat de utilizator (artifact
6efc43e0, v2, 2026-07-07). Decizii inchise: tabel desktop pe un rand cu header; status = bulina + tooltip; mediu = litera T/P; multi-cod = primul cod + badge+Ncu tooltip; sub-linie de problema = textul brut al erorii, mono, trunchiat, doar pe erori; bara "Aplica cod" contextuala la selectie; Reguli automate = exemplu concret in loc de paragraf descriptiv; fix no-op silentios la butonul "+" din editorul de import.
1. Obiectiv
Patru imbunatatiri UI/UX aprobate pe mockup: (a) lista Trimiteri devine tabel compact pe un singur rand pe desktop, cu header de coloane si semnalizare compacta status/mediu; (b) actiunea bulk "Aplica cod" devine bara contextuala vizibila doar la selectie; (c) sectiunea "Reguli automate (text)" din Mapari isi inlocuieste descrierea cu un exemplu concret; (d) butonul "+" din editorul de prestatii (import) nu mai esueaza silentios — feedback vizibil la succes si la refuz.
2. Non-Goals (anti scope-creep)
- NU se schimba logica backend a
bulk-fix(POST /trimiteri/bulk-fix) — doar prezentarea. - NU se schimba masina de stari
submissions, filtrele, paginarea sau modalul de detaliu. - NU se adauga functionalitate noua la regulile text (
/mapari/reguli-text) — doar microcopy. - NU se redeseneaza restul editorului de rand din import (doar zona chips "+").
- NU se ating API v1, worker-ul sau schema DB.
3. Stories atomice
US-001: Fix buton "+" chips prestatii — feedback la refuz si la succes
Ca operator care editeaza un rand de import vreau ca apasarea pe "+" sa aiba mereu un efect vizibil pentru ca azi codul invalid sau duplicat produce un raspuns identic, fara niciun mesaj ("nu se intampla nimic").
- Depinde de: —
- Fisiere:
app/web/routes.py(post_form_chips),app/web/templates/_chips_prestatii.html,tests/test_web_corectie_prestatii.py(~3 fisiere) - Test intai (RED):
tests/test_web_corectie_prestatii.py—test_add_cod_duplicat_afiseaza_mesaj,test_add_cod_invalid_afiseaza_mesaj,test_add_cod_reusit_marcheaza_chip_nou - Acceptance criteria:
- Ramurile
add,add_extra,add_flatdinpost_form_chips: cod care nu trece verificarea innomenclator_rar→ mesaj de eroare in fragmentul re-randat ("Cod necunoscut in nomenclator"), nu raspuns identic. - Cod deja prezent in lista (dedup) → mesaj "X este deja in lista — nu a fost adaugat inca o data", pe TOATE cele 3 ramuri.
- Adaugare reusita → chip-ul nou primeste clasa de evidentiere (
chip-nou, outline verde) + mesaj de confirmare "X adaugat" (aria-live pentru SR). - Mesajele traiesc in fragmentul
_chips_prestatii.html(swapouterHTMLpe#chips-section) si dispar la urmatoarea actiune reusita. python3 -m pytest -qverde.
- Ramurile
- Verificare E2E: browser pe import → Editeaza rand → alege cod deja adaugat → "+" → mesaj rosu vizibil; alege cod nou → "+" → chip verde evidentiat + mesaj.
US-002: Reguli automate — exemplu concret in loc de descriere
Ca utilizator al paginii Mapari vreau sa vad un exemplu de regula in loc de un paragraf explicativ pentru ca exemplul arata direct formatul si scuteste cititul.
- Depinde de: —
- Fisiere:
app/web/templates/_mapari.html,tests/test_web_mapari_text_rules.py(~2 fisiere) - Test intai (RED):
tests/test_web_mapari_text_rules.py—test_sectiune_reguli_afiseaza_exemplu_nu_descriere - Acceptance criteria:
- Textul descriptiv din capul sectiunii "Reguli automate (text)" (inclusiv
empty-state) e inlocuit cu un singur exemplu formatat:
Daca operatia contine "verificare" → Cod RAR = OE-2 Intretinere si revizie, cu pattern-ul si codul evidentiate vizual (chip warn / chip accent, ca in mockup). - Nicio schimbare functionala la tabel, adaugare, preview sau stergere reguli.
python3 -m pytest -qverde.
- Textul descriptiv din capul sectiunii "Reguli automate (text)" (inclusiv
empty-state) e inlocuit cu un singur exemplu formatat:
- Verificare E2E: browser pe Mapari → sectiunea Reguli automate afiseaza exemplul.
US-003: View-model rand trimitere — coduri multiple + eroare bruta
Ca dashboard vreau ca randul de trimitere sa expuna lista completa de coduri
RAR si textul brut al erorii pentru ca UI-ul compact afiseaza primul cod +N
(tooltip cu toate) si sub-linia de eroare cu mesajul RAR, nu eticheta explicativa.
- Depinde de: —
- Fisiere:
app/payload_view.py,app/web/routes.py(_submission_row_view),tests/test_payload_view.py,tests/test_web_submissions.py(~4 fisiere) - Test intai (RED):
tests/test_payload_view.py—test_coduri_rar_lista_ordonata_dedup,test_coduri_rar_gol_fara_prestatii;tests/test_web_submissions.py—test_rand_expune_eroare_bruta_doar_pe_error - Acceptance criteria:
prezentare_din_payloadintoarce camp noucoduri_rar: lista ordonata, dedup, a codurilor RAR (cod_prestatie) din TOATE prestatiile (lista goala cand nu exista); campurile existente raman neschimbate (compatibilitate)._submission_row_viewexpuneeroare_bruta: mesajul RAR brut cand exista (rar_error→ mesajul serverului, ex.ORA-12899...), altfelmotivscurt; sir gol pe stari fara problema.needs_mappingNU produceeroare_bruta(informatia "nemapat" traieste in coloana Cod RAR).python3 -m pytest -qverde.
- Verificare E2E: — (acoperit de US-004).
US-004: Trimiteri desktop — tabel cu header, un rand per trimitere
Ca operator pe desktop vreau trimiterile intr-un tabel compact cu header de coloane pentru ca este loc pe orizontala si scanez mai repede o lista pe un rand.
- Depinde de: US-003
- Fisiere:
app/web/templates/_submissions.html,app/web/templates/base.html(CSS),tests/test_web_submissions_layout.py(~3 fisiere) - Test intai (RED):
tests/test_web_submissions_layout.py—test_desktop_header_coloane,test_status_bulina_cu_tooltip,test_mediu_litera_t_p,test_multicod_badge_plus_n,test_sublinie_eroare_bruta_doar_pe_error - Acceptance criteria:
- Pe desktop (>= breakpoint existent), lista devine tabel/grid cu header: (checkbox) · Vehicul · Cod RAR · Operatie · Data · Status · Mediu · (actiuni). Un rand per trimitere, fara wrap; operatia primeste ellipsis.
- Status = DOAR bulina colorata (culorile claselor
s-*existente), nume stare complet intitle(tooltip); coloana are headerul "Status". - Mediu = litera in coloana proprie cu header "Mediu":
Palb pe fundal--err(productie),Tcontur discret (testare);titlecu numele complet. - Mai multe coduri: primul cod + badge
+Ncutitlecare listeaza toate codurile dincoduri_rar; un singur cod → fara badge; niciun cod →nemapat. - Sub-linia de problema apare DOAR cand
eroare_brutae ne-goala: text mono,--fs-xs, culoare--err, un singur rand cutext-overflow:ellipsis,titlecu textul complet. - Comportamente pastrate: click pe rand → modal detaliu; checkbox doar pe
gestionabil; buton "Trimite" doar petinut; paginare/filtre neatinse. python3 -m pytest -qverde.
- Verificare E2E: browser HTMX pe http://localhost:8010/ (desktop 1280px) — randuri pe o singura linie, header vizibil, tooltip-uri corecte.
US-005: Trimiteri mobil — bulina status + litera mediu
Ca operator pe mobil vreau aceleasi semnale compacte (bulina + T/P) pe lista de 2 linii pentru ca pill-urile cu text ocupa spatiu inutil pe ecran mic.
- Depinde de: US-004
- Fisiere:
app/web/templates/_submissions.html,app/web/templates/base.html(media query),tests/test_web_submissions_layout.py(~3 fisiere) - Test intai (RED):
tests/test_web_submissions_layout.py—test_mobil_pastreaza_doua_linii_cu_bulina_si_litera - Acceptance criteria:
- Sub breakpoint, randul revine la 2 linii (placuta / cod·operatie·data), iar in dreapta stau litera de mediu + bulina de status (+ butonul "Trimite" pe tinute).
- Fara header de tabel pe mobil; fara scroll orizontal la 390px.
python3 -m pytest -qverde.
- Verificare E2E: browser la 390px — lista lizibila, fara overflow orizontal.
US-006: Bara contextuala "Aplica cod" — vizibila doar la selectie
Ca operator vreau ca actiunile bulk sa apara doar cand am selectat randuri, cu text explicit pentru ca butonul permanent "Aplica cod" fara context e confuz.
- Depinde de: US-004
- Fisiere:
app/web/templates/_submissions.html,app/web/templates/base.html(CSS + JS numarare selectie),tests/test_web_bulk_fix.py(~3 fisiere) - Test intai (RED):
tests/test_web_bulk_fix.py—test_bara_bulk_ascunsa_implicit,test_bara_bulk_texte_explicite - Acceptance criteria:
- Inputul de cod + "Aplica cod" + "Sterge selectate" dispar din capul listei; apar intr-o bara contextuala (stil accent, ca in mockup) randata ascunsa si afisata prin JS cand >= 1 checkbox e bifat; dispare la deselectare.
- Bara contine: contor "N selectate", input cod RAR, buton "Aplica acest cod la N randuri", separator, buton "Sterge N randuri", actiune "Deselecteaza"; N se actualizeaza la fiecare bifare (JS, fara roundtrip).
- Sub bara: hint pe un rand — "Aplica codul RAR doar operatiilor fara cod din randurile selectate, apoi le repune in coada."
- Endpoint-urile, CSRF,
hx-confirmpe stergere sihx-disinheritraman functional identice;bulk_messagese afiseaza ca acum. - Starea barei supravietuieste re-randarii fragmentului (re-evaluare la
htmx:afterSwap— dupa swap selectia se pierde, bara se ascunde). python3 -m pytest -qverde.
- Verificare E2E: browser — capul listei curat; bifez 2 randuri blocate → bara apare cu "2 selectate"; aplic cod → lista se reincarca, bara dispare, sumar vizibil.
4. Riscuri
- Tabel vs. lista pe acelasi fragment:
_submissions.htmle folosit si de paginare/filtre/OOB — orice schimbare de structura trebuie sa pastreze id-urile (#submissions-wrap,#bulk-trimiteri, OOB-urile). Mitigare: pastram form-ul si id-urile existente, schimbam doar interiorul listei; testele de layout existente (test_web_submissions_layout.py) ruleaza inainte si dupa. rar_errorbrut poate contine detalii tehnice lungi: afisare pe un rand cu ellipsis +title; nu se logheaza/expune nimic nou (textul exista deja in modal).- JS-ul de numarare selectie ruleaza peste randuri re-randate de HTMX: legare prin delegare pe container, nu pe noduri (altfel handler-ii mor la swap).
- Doua semnale rotunde alaturate pe mobil (bulina status + litera mediu): litera are forma/continut diferit de bulina — validat in mockup; daca in practica se confunda, fallback aprobat: mediu doar pe randurile de productie.
5. Intrebari deschise
— (toate inchise prin mockup v2 aprobat)
6. Valuri de executie (graful de dependente)
Val 1: [US-001] [US-002] [US-003] ← fara dependente, fisiere disjuncte → paralel
Val 2: [US-004] ← deblocat de US-003
Val 3: [US-005] [US-006] ← deblocate de US-004; ating aceleasi fisiere → secvential intre ele
Raport VERIFY
Verdict: PASS — 2026-07-07, E2E in browser (Playwright, uvicorn pe DB temporar, 7 trimiteri seedate: sent/queued/held/needs_mapping/error, test+prod, multi-cod).
- Desktop 1280px: header Vehicul/Cod RAR/Operatie/Data/Status/Mediu; un rand per trimitere;
bulina colorata cu title;
Pfill rosu /Tcontur;OE-1 +2cu tooltip; sub-linieORA-12899...mono trunchiata doar pe rândul error;nemapatitalic fara sub-linie. - Bara bulk: ascunsa implicit; la 2 checkbox-uri → "2 selectate · Aplica acest cod la 2 randuri |
Sterge 2 randuri | Deselecteaza" + hint; aplicat OE-2 → ambele randuri →
queued, bara dispare. - Mapari: exemplul "Daca operatia contine «verificare» → Cod RAR = OE-2 Intretinere si revizie" inlocuieste descrierea.
- Chips "+": adaugare OE-1 → chip evidentiat (chip-nou) + "OE-1 adaugat."; duplicat → "OE-1 este deja in lista — nu a fost adaugat inca o data."; select gol → "Selecteaza un cod RAR din lista".
- Mobil 390px: fara header, 2 linii, T/P + bulina in dreapta, fara scroll orizontal.
- Suita completa: 1622 passed, 1 skipped.
Cauza-radacina REALA a bug-ului "+" (gasita LA VERIFY, nu in analiza statica): form-urile
parinte din modalele de editare au hx-disabled-elt="find button"; atributul se MOSTENESTE pe
butoanele chips, iar find button rezolvat relativ la butonul "+" (fara butoane descendente) →
null → TypeError intern htmx 1.9.12 INAINTE de request → nicio cerere, nicio eroare vizibila.
Fix: hx-disabled-elt="this" explicit pe toate butoanele hx-post din _chips_prestatii.html
(care si dezactiveaza butonul cat cererea e in zbor). No-op-urile silentioase server-side
(cod invalid pe add/add_flat, duplicat) erau defecte reale suplimentare, reparate separat.
Observatii non-blocante: (1) bulk_message ("N reusite") dispare imediat — HX-Trigger
trimiteriChanged reincarca lista peste raspunsul cu mesaj (comportament pre-existent);
(2) pe mobil, operatia e trunchiata agresiv pe randurile cu buton "Trimite" (spatiul e
consumat de actiune + mediu + status) — acceptat, informatia completa e in modal.