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>
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":
- 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>. - 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. - 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/maparisi/_import/.../mapare-operatieraman valide). - "Mapari salvate" si "Formate de coloane" → aceeasi grila; sub-textul ("acum: COD — nume",
"N coloane", maparea coloana→camp) ramane
muted12px 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:Escreaduce focusul pe☰. Navigare cu sageti optionala (consistent cu pattern-ul tab existent), darTabnatural 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" (formPOST /logoutcucsrf_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/Arhiveazareversibile → confirmare doar pe bulk (cantitate).
- Stari vizuale ale verbelor: distructiv (
Sterge) cucolor: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_onegate-uieste pe status='active' (azi peCOALESCE(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 peEsc, focus readus pe trigger. <details>Ajutor: accesibil nativ din tastatura.- Checkbox-uri admin:
aria-labelper 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)
- Meniu hamburger = dropdown ancorat dreapta-sus (nu drawer).
- Tab-bar = Acasa · Mapari; Nomenclator + Cont + Integrare + Panou admin → meniul
☰. - Mapari = grila compacta ca Trimiteri, toggle scurt Auto/Manual, link Ajutor in antet; textul repetat de pe randuri se elimina.
- Admin = selectie cu bife + bara de actiuni bulk (Activeaza/Blocheaza/Arhiveaza/Sterge) + actiuni per-rand; nota "cont dev implicit" eliminata.
- Sectiunea "Ajutor" de pe Acasa se elimina.
- 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 |