Files
rar-autopass/docs/prd/prd-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

16 KiB

PRD 5.5 — Uniformizare & standardizare UI/UX

Stare: aprobat (2026-06-23)

Proces: docs/ROADMAP.md §5. Contract RAR (sursa de adevar): docs/api-rar-contract.md. Design vizual (sursa de adevar pentru cum arata): docs/design/5.5-uniformizare-ui.md. Stare: draft → aprobat → in-executie → verify-pass → inchis.

1. Obiectiv

Aducem toate suprafetele dashboard-ului la acelasi vocabular de componente ca tabelul Trimiteri (referinta corecta), reasezam navigarea intr-un meniu de cont (hamburger) si dam panoului admin actiuni reale de ciclu de viata pe conturi. Tinta: aplicatia arata si se comporta uniform, fara tabele labartate, fara wayfinding redundant, fara scroll orizontal pentru actiuni. Detaliile vizuale si deciziile utilizatorului: docs/design/5.5-uniformizare-ui.md (§10).

2. Non-Goals (anti scope-creep)

  • Fara redesign de estetica: paleta/tipografia/tokenii din base.html (5.3) raman NESCHIMBATI la octet.
  • Fara atingere a fluxului de trimitere: worker (masina stari submissions, idempotenta, mapping-rezolvare) NEATINS, cu o singura exceptie controlata — gate-ul claim_one pe noua stare de cont (US-004), pastrand echivalenta active=1 ⇔ status='active'.
  • Fara schimbare a semanticii auto_send: comutatorul Auto/Manual ramane reskin la nivel de macro (name="auto_send", semantica de prezenta). Zero atingere a parserelor /mapari si /_import/....
  • Fara rute noi de date / fara HTTP nou pe chei API: lifecycle-ul conturilor e admin-only, sub require_admin + CSRF, exact ca rutele admin existente.
  • Fara responsive/mobile nou dincolo de ce ofera deja .tablewrap (scroll in card).
  • Tabelul Trimiteri ramane neatins — e referinta, nu tinta.

3. Stories atomice

US-001: Elimina sectiunea "Ajutor" din Acasa

Ca operator vreau o pagina Acasa fara wayfinding redundant pentru ca linkurile Mapari/Coduri RAR sunt deja in navigare.

  • Depinde de: —
  • Fisiere: app/web/templates/_acasa.html, tests/test_web_acasa.py (~2 fisiere)
  • Test intai (RED): tests/test_web_acasa.pytest_acasa_fara_sectiune_ajutor (randul "Ajutor:" + linkurile inline lipsesc din HTML-ul Acasa)
  • Acceptance criteria:
    • Blocul Ajutor: <a>Mapari</a> <a>Coduri RAR</a> (liniile ~47-55) eliminat din _acasa.html.
    • Restul Acasa (upload, "Primii pasi", sectiunea Trimiteri) neschimbat.
    • python3 -m pytest tests/test_web_acasa.py -q verde.
  • Verificare E2E: browser HTMX pe / — Acasa nu mai afiseaza randul Ajutor; upload + Trimiteri intacte.

US-002: Tabel Nomenclator cu aspectul tabelului Trimiteri

Ca operator vreau ca nomenclatorul sa arate identic cu Trimiteri pentru ca consistenta reduce sarcina cognitiva.

  • Depinde de: —
  • Fisiere: app/web/templates/_nomenclator.html, tests/test_web_nomenclator.py (~2 fisiere)
  • Test intai (RED): tests/test_web_nomenclator.pytest_nomenclator_grila_standard (.tablewrap + table
    • antet th standard + .pill pe cod; empty-state .empty)
  • Acceptance criteria:
    • Foloseste aceeasi structura .tablewrap > table cu antet th standard ca _submissions.html.
    • Codul prestatie ramane in .pill; coloanele aliniate, hover/aspect identice cu Trimiteri.
    • Empty-state pastrat (Nomenclator gol...), in .empty.
    • python3 -m pytest tests/test_web_nomenclator.py -q verde; AA light+dark (zero literali de culoare).
  • Verificare E2E: browser — Nomenclator si Trimiteri arata din aceeasi familie vizuala in dark si light.

US-003: Macro autosend_toggle compact (Auto / Manual)

Ca operator vreau un comutator scurt In coada, fara text repetat pe randuri pentru ca proza inline ingrasa randurile si impinge actiunile afara din ecran.

  • Depinde de: —
  • Fisiere: app/web/templates/_macros.html, tests/test_web_macros.py (~2 fisiere)
  • Test intai (RED): tests/test_web_macros.pytest_autosend_compact (macro-ul randeaza control Auto/Manual, pastreaza name="auto_send" value="true" + form= + starea checked, si NU mai contine propozitiile explicative "La fisierele viitoare..."/"Nebifat = ...")
  • Acceptance criteria:
    • autosend_toggle(form_id, checked) randeaza un comutator compact etichetat Auto / Manual (radio sau switch), nowrap, fara propozitii inline.
    • Pastreaza EXACT name="auto_send", value="true", semantica de prezenta (bifat→true / absent→false), form="{{form_id}}", checked reflecta checked.
    • Explicatia detaliata NU mai e in macro (se muta in panoul Ajutor, US-005). Tooltip scurt admis pe control.
    • python3 -m pytest tests/test_web_macros.py tests/test_import_e2e.py -q verde (parserele backend nealterate).
  • Verificare E2E: in fluxul import (mapcoloane) si in Mapari, comutatorul produce acelasi auto_send bool ca azi (queued vs needs_review neschimbat).

US-004: Model de stare a contului (accounts.status) + gate worker

Ca sistem vreau stari de cont distincte (pending/active/blocked/archived/deleted) pentru ca adminul are nevoie de blocare/arhivare/stergere, nu doar activ/inactiv.

  • Depinde de: —
  • Fisiere: app/schema.sql, app/db.py (migrare defensiva), app/users.py, app/worker/... (gate claim_one), tests/test_account_status.py, tests/test_worker_*.py (~5 fisiere)
  • Test intai (RED): tests/test_account_status.pytest_migrare_deriva_status_din_active, test_blocked_nu_e_claimuit, test_archived_nu_e_claimuit, test_dev_id1_protejat
  • Acceptance criteria:
    • Coloana accounts.status TEXT cu CHECK pe {pending,active,blocked,archived,deleted} (stergere = soft, status='deleted' + purjare de catre jobul de retentie T16); migrare defensiva si idempotenta (pattern _migrate ca la is_admin), derivata din active la prima rulare: active=1→active, altfel pending.
    • Helperi puri in users.py: set_account_status(id, status), delete_account(id), cu protectia contului dev id=1 (ridica/ignora, nu corupe).
    • Worker claim_one gate-uieste pe status='active', pastrand echivalenta cu COALESCE(active,1)=1 de azi (conturile blocked/archived NU sunt claimuite).
    • active ramane consistent (active=1 ⇔ status='active') cat timp coexista, fara regresie pe testele worker.
    • python3 -m pytest -q verde (suita completa).
  • Verificare E2E: marcheaza un cont blocked → submission-urile lui nu pleaca la RAR; active → pleaca.

US-005: Tabel Mapari standardizat + panou Ajutor

Ca operator vreau tabelele Mapari compacte ca Trimiteri, cu actiunile vizibile fara scroll si ajutor intr-un singur loc pentru ca acum sunt labartate si butoanele Salveaza/Sterge ies din ecran.

  • Depinde de: US-003
  • Fisiere: app/web/templates/_mapari.html, tests/test_web_mapari.py (~2 fisiere)
  • Test intai (RED): tests/test_web_mapari.pytest_mapari_grila_compacta (coloane inguste nowrap, actiuni la dreapta), test_mapari_ajutor_disclosure (un singur <details>/link Ajutor in antet, fara proza pe randuri)
  • Acceptance criteria:
    • Cele 3 sectiuni (De rezolvat / Mapari salvate / Formate coloane) folosesc grila standard ca Trimiteri; coloana "In coada" foloseste macro-ul compact din US-003.
    • Butoanele Salveaza/Sterge vizibile fara scroll orizontal pe latime de dashboard normala (coloana Actiuni la dreapta, nowrap); sub-text (N blocate, acum: COD) ca muted 12px sub valoare.
    • Antetul "De rezolvat" contine un link/<details> Ajutor cu explicatia maparilor + Auto/Manual, scrisa O SINGURA DATA; proza inline de pe randuri eliminata.
    • CSRF, hx-post, hx-target="#mapari-section", formularele si re-rezolvarea la edit cod — neschimbate.
    • python3 -m pytest tests/test_web_mapari.py -q verde; AA light+dark.
  • Verificare E2E: browser — mapezi o operatie (Salveaza vizibil fara scroll), comuti Auto/Manual, deschizi Ajutor; submission blocat se deblocheaza la salvarea codului (comportament neschimbat).

US-006: Meniu hamburger in header + context de autentificare

Ca utilizator vreau un meniu de cont in dreapta-sus cu Cont/Integrare/Nomenclator/Panou admin/logout pentru ca acestea nu sunt lucru zilnic si aglomereaza tab-bar-ul.

  • Depinde de: —
  • Fisiere: app/web/templates/base.html, app/web/routes.py (helper context partajat), tests/test_web_header_menu.py (~3 fisiere)
  • Test intai (RED): tests/test_web_header_menu.pytest_meniu_autentificat_are_linkuri_cont, test_meniu_admin_doar_pentru_admin, test_meniu_neautentificat_fara_logout (login/signup → fara linkuri de cont)
  • Acceptance criteria:
    • Iconita in header (langa toggle tema), aria-label, aria-expanded, aria-controls; dropdown ancorat dreapta-sus; inchidere la click-afara + Esc (focus readus pe ). Fara overlay.
    • Continut autentificat: Cont, Integrare, Nomenclator, Panou admin (doar is_admin), separator, Iesi din cont (form POST /logout cu csrf_token).
    • base.html primeste is_authenticated/is_admin/csrf_token printr-un helper de context partajat (un singur loc); defensiv: lipsa cheilor → meniu in stare neautentificata, nu eroare.
    • Pe login/signup meniul nu arata linkuri de cont/logout.
    • python3 -m pytest tests/test_web_header_menu.py -q verde.
  • Verificare E2E: browser — deschide/inchide (Esc + click-afara), linkurile navigheaza corect, logout iese; pe login meniul nu expune cont.

US-007: Tab-bar redus la Acasa · Mapari

Ca operator vreau un tab-bar doar cu suprafetele de lucru zilnic pentru ca Cont/Integrare/Nomenclator traiesc acum in meniul de cont.

  • Depinde de: US-006
  • Fisiere: app/web/templates/dashboard.html, tests/test_web_dashboard_tabs.py (~2 fisiere)
  • Test intai (RED): tests/test_web_dashboard_tabs.pytest_tabbar_doar_acasa_mapari, test_fragmente_mutate_inca_accesibile (/_fragments/{cont,integrare,nomenclator} raman 200 + deep-link ?tab=)
  • Acceptance criteria:
    • tabs in dashboard.html = doar acasa, mapari; badge-urile de contoare raman pe Mapari.
    • Logout + link admin ad-hoc din coltul dreapta-sus al dashboard-ului eliminate (mutate in meniul US-006).
    • Rutele /_fragments/cont|integrare|nomenclator + ?tab= raman valide (accesate din meniu); zero rute moarte, zero 404 pe deep-link existent.
    • Navigarea ARIA cu sageti pe tab-bar ramane corecta cu 2 tab-uri.
    • python3 -m pytest tests/test_web_dashboard_tabs.py -q verde.
  • Verificare E2E: browser — tab-bar arata doar Acasa/Mapari; deschizi Nomenclator/Cont/Integrare din , deep-link /?tab=integrare inca functioneaza.

US-008: Rute admin pentru ciclul de viata al conturilor (block/archive/delete + bulk)

Ca admin vreau endpointuri care blocheaza/arhiveaza/sterg conturi, individual si in bulk pentru ca panoul are nevoie sa actioneze pe selectie.

  • Depinde de: US-004
  • Fisiere: app/web/routes.py (rute /admin/*), tests/test_admin_lifecycle.py (~2 fisiere)
  • Test intai (RED): tests/test_admin_lifecycle.pytest_block_archive_delete_single, test_bulk_pe_lista_account_id, test_bulk_sare_contul_dev, test_non_admin_403, test_csrf_obligatoriu
  • Acceptance criteria:
    • Rute POST /admin/block, /admin/archive, /admin/delete (+ pastreaza activate) sub require_admin + CSRF, cu PRG (redirect inapoi la /admin), folosind helperii din US-004.
    • Accepta o LISTA de account_id (bulk) si o singura tinta (per-rand) prin acelasi handler.
    • Contul dev id=1 e sarit in bulk (nu eroare) si refuzat individual; delete cere confirmare la nivel UI (US-009) si purjeaza datele conform retentiei (GDPR/L.142).
    • Non-admin → 403; lipsa CSRF → respins.
    • python3 -m pytest tests/test_admin_lifecycle.py -q verde.
  • Verificare E2E: POST autentificat ca admin pe fiecare verb (single + bulk) muta starea corect; contul dev neatins.

US-009: Panou admin — selectie cu bife + bara bulk + actiuni per-rand

Ca admin vreau sa selectez conturi si sa aplic actiuni pe selectie pentru ca activarea/blocarea una cate una e lenta.

  • Depinde de: US-008
  • Fisiere: app/web/templates/admin.html, tests/test_web_admin.py (~2 fisiere)
  • Test intai (RED): tests/test_web_admin.pytest_admin_coloana_selectie_si_master, test_bara_bulk_cu_cele_4_verbe, test_actiuni_per_rand, test_fara_nota_cont_dev
  • Acceptance criteria:
    • Tabel conturi in asteptare (si analog active): coloana checkbox + master "Selecteaza tot" (aria-label per rand + master).
    • Bara de actiuni bulk (ascunsa pana la selectie) cu Activeaza / Blocheaza / Arhiveaza / Sterge; Sterge cu hx-confirm/dialog; trimite lista de account_id la rutele US-008.
    • Actiuni per-rand (kebab ...) cu aceleasi verbe; Sterge cu color:var(--err) + confirmare.
    • Nota "Cont dev implicit (id=1)" eliminata din pagina (protectia ramane in cod, US-004/US-008).
    • python3 -m pytest tests/test_web_admin.py -q verde; AA light+dark; tabel in grila standard.
  • Verificare E2E: browser ca admin — bifezi 2 conturi, bara bulk apare cu numarul selectat, Arhiveaza muta randurile; Sterge cere confirmare; contul dev nu poate fi selectat-distrus.

4. Riscuri

  • Schema accounts.status (US-004) = singura schimbare de date. Mitigare: migrare defensiva idempotenta (pattern _migrate deja folosit la accounts.active/users.is_admin), derivata din active, cu echivalenta active=1 ⇔ status='active' pana cand active poate fi retras intr-o livrabila viitoare. Testele worker existente sunt plasa.
  • base.html partajat (US-006): e folosit de login/signup/admin/dashboard. Risc de context lipsa → meniu rupt. Mitigare: helper de context partajat + defaulturi defensive (lipsa → neautentificat), test pe toate cele 4 pagini.
  • Coliziune pe fisiere intre stories (lectia 5.1 clobber): US-006 si US-007 ating ambele zona de navigare (base.html vs dashboard.html, plus scoaterea logout-ului ad-hoc din dashboard.html). Mitigare: US-007 depinde de US-006 si ruleaza secvential (acelasi teammate recomandat), nu in worktree-uri paralele.
  • delete cont (US-008): actiune distructiva ireversibila. Mitigare: confirmare UI obligatorie, contul dev protejat, purjare aliniata la retentia existenta (T16), nu stergere ad-hoc de date conexe fara plan.
  • Macro autosend (US-003): orice schimbare de name/semantica ar rupe tacit clasificarea queued/needs_review. Mitigare: test care asereaza name="auto_send" + prezenta, plus test_import_e2e ramane verde.

5. Intrebari deschise — REZOLVATE (aprobare utilizator 2026-06-23)

  • Stergere contsoft delete: status='deleted', scos imediat din toate listele, date purjate de jobul de retentie existent (T16, GDPR/L.142). NU hard DELETE imediat (auditabil + fereastra de revenire).
  • Blocheaza vs Arhiveazablocked = suspendare reversibila, contul ramane in liste, marcat vizibil, worker nu trimite; archived = scos din listele active, date pastrate read-only. Etichete confirmate.
  • Comutatorul In coadaradio etichetat Auto / Manual (explicit), nu switch on/off.

6. Valuri de executie (graful de dependente)

Val 1: [US-001] [US-002] [US-003] [US-004]   ← fara dependente, fisiere disjuncte → paralel
Val 2: [US-005]            ← dep US-003 (macro)
       [US-006]            ← fara dep (navigare/header)
       [US-008]            ← dep US-004 (rute admin pe model stare)
Val 3: [US-007]            ← dep US-006 (acelasi fisier de navigare → secvential, NU worktree paralel)
       [US-009]            ← dep US-008 (UI admin pe rutele de lifecycle)