Files
rar-autopass/docs/design/5.5-uniformizare-ui.md
Claude Agent 1fbd894329 feat(web): uniformizare/standardizare UI/UX + lifecycle conturi (PRD 5.5)
Aduce toate suprafetele dashboard-ului la grila tabelului Trimiteri, muta
navigarea intr-un meniu de cont (hamburger) si da panoului admin actiuni
reale de ciclu de viata. 9 stories, 3 valuri. UI pur (reskin + reasezare)
cu O SINGURA exceptie backend: modelul de stare a contului.

- US-001 sectiunea "Ajutor" eliminata din Acasa (wayfinding redundant).
- US-002 Nomenclator la grila standard (_submissions.html ca referinta).
- US-003 macro autosend compact (Manual<->Auto). Semantica de PREZENTA
  `auto_send` (bifat->true, absent->false) NEALTERATA — compatibil cu ambele
  parsere (Form(bool) la /mapari, bool(form.get()) la import). Zero backend.
- US-004 accounts.status (pending/active/blocked/archived/deleted), migrare
  defensiva idempotenta derivata din `active`, gate worker claim_one pe
  status='active' (echivalenta active=1 <=> status='active' pastrata).
- US-005 tabel Mapari compact + panou Ajutor (<details>, proza o singura data),
  coloana "In coada".
- US-006 meniu hamburger dropdown (Cont/Integrare/Nomenclator/Admin/logout) +
  context is_authenticated/is_admin/csrf_token defensiv in base.html.
- US-007 tab-bar redus la Acasa+Mapari; rutele /_fragments/{cont,integrare,
  nomenclator} + deep-link ?tab= raman valide.
- US-008 rute admin block/archive/delete + bulk pe lista account_id,
  require_admin + CSRF + PRG, dev id=1 sarit in bulk.
- US-009 admin UI: selectie bife + master + bara bulk + kebab per-rand,
  grupare pe stare (bloc nou blocate/arhivate), nota "cont dev implicit" scoasa.

Stergere = SOFT: tombstone (status='deleted'), dar PII purjata IMEDIAT
(rar_creds_enc + chei API revocate + CUI eliberat pentru re-inregistrare),
GDPR/L.142.

VERIFY: 671 teste pass (+40). E2E browser (Playwright) a prins 2 bug-uri
invizibile la TestClient: bara bulk cu display:flex inline invingea [hidden]
(mutat in CSS .bulk-bar[hidden]); conturi arhivate cadeau sub "in asteptare"
(grupare pe status). /code-review high a prins 2 bug-uri reale: soft delete
pastra creds RAR + CUI la nesfarsit fara purjare accounts (GDPR neonorat);
apostrof in numele firmei rupea confirm() inline din kebab — ambele reparate,
plus cleanup boilerplate rute (_lifecycle_route).

Backend trimitere (worker masina stari/idempotenta/mapping) neatins, cu
exceptia gate-ului de cont. Design: docs/design/5.5-uniformizare-ui.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 11:56:05 +00:00

14 KiB

Design 5.5 — Uniformizare & standardizare UI/UX

Stare: aprobat (decizii utilizator 2026-06-23, vezi §10) Context: dashboard web HTMX (app/web/templates/), paleta dark/light deja livrata (5.3), erori 3-niveluri (5.4). Acest document = sursa de adevar vizuala pentru PRD 5.5. Unde PRD-ul descrie ce livram pe stories, aici descriem cum arata si de ce.

Nu reinventam estetica. Paleta, tipografia si tokenii din base.html (5.3) raman NESCHIMBATI la octet. Standardizarea = aducem toate tabelele si paginile la acelasi vocabular de componente care exista deja in tabelul Trimiteri (_submissions.html), tabelul considerat corect de referinta.


1. Problema (audit pe codul real)

Inventar al neuniformitatii curente:

Suprafata Simptom Referinta corecta
Tabel Mapari (_mapari.html) Labartat: coloana "Punere in coada" injecteaza prin macro autosend_toggle 3 randuri de text explicativ pe fiecare linie → randuri inalte, butoanele Salveaza/Sterge ies din viewport, trebuie scroll orizontal grila Trimiteri
Tabel Nomenclator (_nomenclator.html) Functional dar minim; nu imparte exact acelasi aspect/hover/aliniere cu Trimiteri grila Trimiteri
Acasa (_acasa.html) Sectiune "Ajutor: Mapari / Coduri RAR" redundanta (wayfinding repetat) — (se elimina)
Navigare Cont, Integrare, Nomenclator stau ca tab-uri amestecate cu lucrul zilnic; logout + link admin sunt agatate ad-hoc in coltul dreapta-sus al dashboard-ului, absente pe alte pagini meniu de cont dedicat
Panou admin (admin.html) Conturile in asteptare au doar "Activeaza" per-rand; lipsesc selectie multipla si actiunile blocare/arhivare/stergere. Nota "Cont dev implicit" e jargon intern nederivabil tabel cu selectie + bara bulk

Principiu de standardizare: un singur tabel, o singura componenta de antet de sectiune, un singur loc pentru ajutor (link/disclosure, nu text inline repetat pe randuri).


2. Design tokens (existenti — se reutilizeaza, nu se modifica)

Din base.html (:root dark + [data-theme="light"]). Citat aici doar ca referinta; nicio valoare noua de culoare. Orice suprafata noua foloseste color-mix(... var(--card)) pentru stari (lectia 5.3: zero literali hardcodati, altfel se sparge light mode).

--bg --card --ink --muted --line
--ok (verde) --warn (chihlimbar) --err (rosu) --accent (albastru)

Spacing: cardurile 16-20px padding; celule tabel 8px 10px; gap-uri 6/8/12/16px (scara existenta). Radius: 6px controale, 10px carduri, 99px pill-uri. Tipografie: tabel 14px tabular-nums, antet th 12px uppercase --muted. Nu introducem fonturi sau marimi noi.


3. Componenta canonica: Tabelul standard

Tabelul Trimiteri defineste contractul. Orice tabel din aplicatie il respecta:

.tablewrap > table
  thead th   -> 12px uppercase, color --muted, font-weight 500, white-space nowrap
  tbody td   -> 14px, padding 8px 10px, border-bottom 1px var(--line), nowrap implicit
  stare      -> <span class="pill {s-*}">{text uman}</span>   (glifa+text, nu doar culoare)
  coloana lunga (motiv) -> white-space:normal; max-width:280px   (singura exceptie de la nowrap)
  empty state -> .empty (centrat, --muted, cu CTA contextual)

Reguli care fac diferenta vizibila fata de "labartat":

  1. Coloanele de control sunt inguste si nowrap. Niciun text explicativ in celule. Explicatiile traiesc o singura data, in antetul cardului (link "Ajutor") sau intr-un <details>.
  2. Actiunile incap fara scroll orizontal. Coloana "Actiuni" la dreapta, white-space:nowrap, butoane scurte. Pe ecrane inguste scroll-ul ramane IN card (.tablewrap), nu in pagina.
  3. Densitate constanta. Inaltimea randului = o linie de text + padding. Sub-text (ex. "2 blocate", "acum: COD") merge in <div class="muted" style="font-size:12px"> sub valoarea principala, nu pe coloana separata.

3.1 Antet de sectiune standard (cu Ajutor)

+--------------------------------------------------------------+
| De rezolvat                                       [ Ajutor ] |   <- h2 15px la stanga, link la dreapta
+--------------------------------------------------------------+

Ajutor = link discret .cardlink care comuta un <details>/panou de text (vezi §5). Mutam acolo toata proza care azi se repeta pe randuri. Un singur loc, citit la nevoie.


4. Tabelul Mapari — inainte / dupa

Inainte (labartat)

Fiecare rand din "De rezolvat" si "Mapari salvate" poarta autosend_toggle, care randeaza:

  • "La fisierele viitoare cu aceasta operatie:" (12px)
  • checkbox + "Pune automat in coada"
  • "Nebifat = «Tine pentru verificare». Doar pentru aceasta operatie; nimic nu pleaca la RAR..." (11px)

x N randuri. Coloana e mai lata decat selectul de cod; Salveaza/Sterge sunt impinse afara.

Dupa (compact, ca Trimiteri)

De rezolvat                                            [ Ajutor ]
-----------------------------------------------------------------
 OPERATIE          SUGESTII        COD RAR        IN COADA   ACTIUNI
 RevTehBP          A012 (88%)      [ A012  v ]    (o) Auto   [Salveaza]
   2 blocate                                      ( ) Manual
-----------------------------------------------------------------
  • Coloana IN COADA = comutator scurt cu doua stari etichetate Auto / Manual (radio sau switch), fara nicio propozitie. Tooltip pe control: "Auto = pune automat in coada la fisierele viitoare cu aceasta operatie; Manual = tine pentru verificare."
  • Explicatia completa (de ce exista maparile, ce inseamna Auto vs Manual, ce e blocat) → in panoul Ajutor din antet, scris o singura data.
  • Invariant backend pastrat: controlul emite tot name="auto_send" value="true" cu semantica de prezenta (bifat→true, absent→false), exact ca azi. Zero atingere backend (lectia 5.3/3.6: reskin la nivel de macro, parserele /mapari si /_import/.../mapare-operatie raman valide).
  • "Mapari salvate" si "Formate de coloane" → aceeasi grila; sub-textul ("acum: COD — nume", "N coloane", maparea coloana→camp) ramane muted 12px sub valoare, nu pe coloane separate verbose.

Macro-ul autosend_toggle se rescrie compact (acelasi name/form/checked), deci se schimba intr-un singur loc si se propaga si in fluxul de import (mapcoloane) unde e refolosit.


5. Panoul Ajutor (mapari)

Un <details> nativ in antetul cardului "De rezolvat" (sau link care expandeaza acelasi <details>), inchis implicit, fara JS:

Ajutor (v)
  Maparile leaga o operatie din softul tau (cod intern ROAAUTO) de un cod RAR oficial.
  - Operatii necunoscute raman blocate in needs_mapping si NU pleaca la RAR pana le mapezi.
  - Sugestiile (%) vin din potrivire fuzzy pe denumire — verifica-le inainte sa salvezi.
  - In coada: Auto = la urmatoarele fisiere cu aceasta operatie, randurile intra automat in coada.
    Manual = raman pentru verificare; nimic nu pleaca la RAR pana confirmi tu.
  - La schimbarea unui cod, submission-urile blocate pe acea operatie se re-rezolva automat.

Avantaj: text scris o data, accesibil, fara cost de inaltime pe fiecare rand. <details> = accesibil din tastatura nativ, fara dependente.


6. Navigare: meniu hamburger (decizie: dropdown ancorat dreapta-sus)

6.1 Header

[Gateway RAR AUTOPASS] [test]                      [☀]  v1.0  [☰]
                                                              |
                                                   +------------------+
                                                   | Cont             |
                                                   | Integrare        |
                                                   | Nomenclator      |
                                                   | Panou admin      |   <- doar admin
                                                   |------------------|
                                                   | Iesi din cont    |   <- form POST /logout
                                                   +------------------+
  • Iconita (min 36x36, aria-label="Meniu cont", aria-expanded, aria-controls) langa toggle-ul de tema. Dropdown ancorat sub iconita, aliniat la dreapta. Fara overlay pe pagina.
  • Inchidere: click in afara, Esc, sau selectarea unui element. Focus trap minimal: Esc readuce focusul pe . Navigare cu sageti optionala (consistent cu pattern-ul tab existent), dar Tab natural e suficient.
  • Continut dependent de autentificare (vezi §6.3).

6.2 Tab-bar dupa mutare (decizie: doar Acasa · Mapari)

[ Acasa ]  [ Mapari ]

Cont, Integrare, Nomenclator parasesc tab-bar-ul → meniul . Raman doar cele doua suprafete de lucru zilnic. Badge-urile de contoare (Mapari) raman pe tab. Deep-link ?tab= si rutele /_fragments/{cont,integrare,nomenclator} raman valide (accesate acum din meniu, nu din tab-bar) — deci zero rute moarte, doar punctul de intrare se muta.

6.3 Stare de autentificare in header

base.html e partajat de login.html, signup.html, dashboard.html, admin.html. Meniul trebuie sa stie daca esti logat:

  • Autentificat: arata Cont, Integrare, Nomenclator, (Panou admin daca is_admin), separator, "Iesi din cont" (form POST /logout cu csrf_token).
  • Neautentificat (login/signup): meniul arata doar "Autentificare" / "Inregistrare" (sau iconita ascunsa pe aceste pagini — vezi PRD US). Niciun link de cont, niciun logout.

Necesita ca base.html sa primeasca is_authenticated, is_admin, csrf_token in context. Se adauga ca un helper de context partajat (un singur loc), nu duplicat in fiecare render. Acesta e singurul "backend touch" din zona de navigare si trebuie sa fie aditiv si defensiv (lipsa cheilor → meniu in stare neautentificata, nu eroare).


7. Panou admin: selectie + actiuni bulk

7.1 Tabel conturi in asteptare (si analog conturi active)

[v] Selecteaza tot                    2 selectate:
                            [Activeaza] [Blocheaza] [Arhiveaza] [Sterge]   <- bara bulk, apare la selectie
-----------------------------------------------------------------------
[v]  ID  COMPANIE     CUI      EMAIL          INREGISTRAT      ACTIUNI
[v]  7   Auto SRL     RO123    a@b.ro         12.06.2026       [ ... ]
[ ]  8   Moto SA      RO456    c@d.ro         13.06.2026       [ ... ]
-----------------------------------------------------------------------
  • Coloana de checkbox la stanga + un master "selecteaza tot" in antet.
  • Bara de actiuni bulk ascunsa pana exista o selectie; afiseaza numarul selectat si butoanele contextuale. Actioneaza pe toate randurile bifate (POST cu lista de account_id).
  • Actiuni per-rand in meniul [ ... ] (kebab): aceleasi verbe, pentru o singura tinta.
  • Verbele, ca stari de cont distincte (vezi §7.2): Activeaza, Blocheaza, Arhiveaza, Sterge.
    • Sterge = actiune distructiva → hx-confirm / dialog de confirmare obligatoriu.
    • Blocheaza/Arhiveaza reversibile → confirmare doar pe bulk (cantitate).
  • Stari vizuale ale verbelor: distructiv (Sterge) cu color:var(--err); restul neutre .cardlink.

7.2 Model de stare cont (impact backend — vezi PRD riscuri)

Azi: accounts.active (0/1); "pending" = inregistrat dar active=0. Cele 4 verbe cer stari distincte care nu incap intr-un bool. Propunere (PRD o ratifica): coloana accounts.status TEXT, migrare defensiva, derivata din active la prima rulare:

pending   -> inregistrat, neactivat inca           (active=0, status nesetat istoric)
active    -> operational                           (active=1)
blocked   -> suspendat reversibil                  (nu logheaza, worker nu trimite)
archived  -> ascuns din liste, date pastrate       (read-only)
deleted   -> stergere (GDPR/L.142)                 (hard delete SAU soft cu purge)
  • Worker claim_one gate-uieste pe status='active' (azi pe COALESCE(active,1)=1) — schimbare semantica de pastrat compatibila: active=1 ⇔ status='active'.
  • Contul dev id=1 e protejat de Blocheaza/Arhiveaza/Sterge (cont de sistem), exact ca azi la activate/deactivate. Daca e selectat in bulk, e sarit, nu eroare.
  • Nota "Cont dev implicit (id=1)" din pagina se elimina (jargon intern, nederivabil de operator). Protectia ramane in cod, nu o explicam in UI.

Aceasta e singura zona cu schema/backend real. Restul livrabilei e UI pur (reskin + reasezare).


8. Accesibilitate & paritate tema

  • AA pe light+dark pentru orice text nou (lectia 5.3: verzi/rosii hardcodate cad sub AA). Stari doar prin color-mix(... var(--card)), niciun literal.
  • Stare = glifa + text, nu doar culoare (pill-urile existente respecta deja).
  • Meniul : aria-expanded, aria-controls, inchidere pe Esc, focus readus pe trigger.
  • <details> Ajutor: accesibil nativ din tastatura.
  • Checkbox-uri admin: aria-label per rand ("Selecteaza contul {companie}"); master = "Selecteaza tot".
  • Toate controalele >=36px zona de atins (consistent cu toggle tema / .cardlink).

9. Motiune

Minima, consistenta cu existentul: dropdown fade/translate scurt (~120ms, ca .tab-link transition). <details> = comportament nativ. Fara animatii noi de amploare. Respecta prefers-reduced-motion daca adaugam tranzitii (omitere la cerere).

10. Decizii utilizator (2026-06-23)

  1. Meniu hamburger = dropdown ancorat dreapta-sus (nu drawer).
  2. Tab-bar = Acasa · Mapari; Nomenclator + Cont + Integrare + Panou admin → meniul .
  3. Mapari = grila compacta ca Trimiteri, toggle scurt Auto/Manual, link Ajutor in antet; textul repetat de pe randuri se elimina.
  4. Admin = selectie cu bife + bara de actiuni bulk (Activeaza/Blocheaza/Arhiveaza/Sterge) + actiuni per-rand; nota "cont dev implicit" eliminata.
  5. Sectiunea "Ajutor" de pe Acasa se elimina.
  6. Nomenclator capata exact aspectul tabelului Trimiteri.

11. Componente atinse (harta pentru PRD)

Componenta Fisier Tip schimbare
Header + meniu + context auth base.html (+ context render rute) reasezare + mic backend context
Tab-bar redus dashboard.html reasezare
Acasa fara Ajutor _acasa.html stergere
Mapari standard + toggle compact + Ajutor _mapari.html, _macros.html reskin UI (zero backend)
Nomenclator ca Trimiteri _nomenclator.html reskin UI
Admin selectie + bulk + verbe noi admin.html + rute /admin/* UI + backend (status)
Model stare cont schema.sql, users.py, worker gate backend + migrare