diff --git a/.gitignore b/.gitignore index 50cbee6..730886b 100644 --- a/.gitignore +++ b/.gitignore @@ -81,3 +81,11 @@ venv/ # --- Playwright MCP: artefacte sesiune browser (snapshot-uri, stare locala) --- .playwright-mcp/ + +# --- Ralph: runtime loop autonom (stare locala, nu artefact de proiect) --- +scripts/ralph/logs/ +scripts/ralph/screenshots/ +scripts/ralph/archive/ +scripts/ralph/.last-branch +scripts/ralph/.ralph.pid +scripts/ralph/usage.jsonl diff --git a/docs/prd/prd-5.9-ux-corectie-modal-mobil.md b/docs/prd/prd-5.9-ux-corectie-modal-mobil.md new file mode 100644 index 0000000..21d4053 --- /dev/null +++ b/docs/prd/prd-5.9-ux-corectie-modal-mobil.md @@ -0,0 +1,482 @@ + +# PRD 5.9 — Corectie inline in modal + consolidare actiuni + design mobil + +**Stare**: draft + +> Proces: `docs/ROADMAP.md` §5. Contract RAR (sursa de adevar): `docs/api-rar-contract.md`. +> Starea trece: `draft → aprobat → in-executie → verify-pass → inchis`. + +## 1. Obiectiv + +Curatenie UX pe ecranul de Trimiteri, fara nicio schimbare a fluxului de trimitere catre RAR. +Raportat de utilizator dupa 5.8: containerul de detaliu s-a aglomerat si nu mai e clar la ce sa +te uiti. Sase corectii, toate UI/prezentare: + +1. **Detaliul + corectia trec intr-un formular MODAL** (overlay centrat, in afara zonei + `#submissions-wrap` reincarcata la 15s). Rezolva direct bug-ul „formularul se inchide singur dupa + cateva secunde / se sterg bifele" (azi randul-sibling de detaliu traieste IN regiunea de poll, iar + bifele de bulk se pierd la fiecare refresh) si „nu se distinge marginea containerului de restul + tabelului" (overlay clar delimitat). **Inlocuieste** abordarea inline-row din 5.8 US-008. +2. **Editare in-place fara dublarea valorilor**: azi fiecare camp apare de DOUA ori in detaliu — o + data read-only (`_trimitere_detaliu.html:19-32`) si inca o data ca input in „Corecteaza si + re-trimite" (`:130-156`). Modalul afiseaza fiecare camp O SINGURA DATA, direct editabil. +3. **Consolidarea butoanelor**: azi „Re-pune in coada", „Sterge" si „Salveaza si re-pune in coada" + sunt imprastiate in 2 locuri cu culori similare (`:53-69` + `:153-155`), plus „Sterge selectate" + bulk pe tabel. Ramane **un** singur buton principal „Salveaza si retrimite" (salvarea repune mereu + in coada; retry pur = salvezi fara modificari) + **un** „Sterge" rosu, vizibil distantat. Bulk + „Sterge selectate" ramane DOAR pe tabel. +4. **Fara chevron pe randuri** (`_submissions.html:53`) — inutil odata ce detaliul e modal. +5. **Codul de eroare in tabel**, sub eticheta de stare (ex. `RAR_EROARE_SERVER`, `COD_NEMAPAT`), doar + pe randurile cu problema — fara coloana noua (prietenos mobil). +6. **Cod RAR simplu** in tabel (fara prefixul „cod RAR:", `_submissions.html:66`) si in modal (fara + campul etichetat „Cod RAR" separat — codul apare langa operatie). + +Plus, transversal: **design responsive/mobil pentru TOATE paginile dashboard** (azi exista carduri +doar pe tabelul de trimiteri sub 768px, din 5.8; restul paginilor — Mapari, Cont, Nomenclator, +Integrare, Jurnal, Admin, login/signup — si modalul nou nu au tratament mobil). + +## 2. Non-Goals (anti scope-creep) + +- Fara modificari la worker, masina de stari, contractul RAR, idempotenta sau logica de mapare. + Rutele backend (`/corecteaza`, `/repune`, `/sterge`, `/mapeaza`, `/sterge-bulk`) raman ca semnatura + si comportament — se schimba DOAR `hx-target`-ul (modalul) si prezentarea. +- Fara redesign vizual al continutului paginilor (culori, tipografie, structura de informatie) — + doar **adaptare responsive** (stivuire, latimi, tinte touch) pe layout-ul existent. +- Fara animatii elaborate de deschidere modal — un fade/scale simplu e destul (APP UI). +- Nu schimbam ce campuri sunt editabile (raman `nr_inmatriculare`, `vin`, `data_prestatie`, + `odometru_final`, `odometru_initial`) si nici validarea lor (`corecteaza` neatins logic). +- Fara stergerea sectiunii de mapare inline (5.7) — se muta ca atare in modal. +- Fara framework CSS nou (Bootstrap/Tailwind) — extindem variabilele si `base.html` existente. + +## 3. Stories atomice + +> Backend/date + UI pentru acelasi comportament = stories separate. `Fisiere` + `Depinde de` +> complete decid paralelizarea. + +--- + +### US-001: `cod_eroare` scurt disponibil pe randul de afisare +**Ca** dezvoltator **vreau** codul de eroare (cheia din catalog) expus pe randul tabelului +**pentru ca** sa-l pot afisa sub eticheta de stare fara sa re-parsez `rar_error` in template. + +- **Depinde de**: — +- **Fisiere**: `app/web/routes.py` (`_submission_row_view`), `app/web/labels.py` (helper extragere cod), + `tests/test_web_submissions.py` +- **Test intai (RED)**: `tests/test_web_submissions.py` — + `test_cod_eroare_prezent_pe_rand_error`, `test_cod_eroare_prezent_pe_needs_mapping`, + `test_cod_eroare_gol_pe_rand_ok` +- **Acceptance criteria**: + - [ ] `_submission_row_view` intoarce in plus `cod_eroare: str` = codul scurt din catalog + (`app/errors.py` `cod`, ex. `RAR_EROARE_SERVER`, `COD_NEMAPAT`) extras din `rar_error` + (superset 5.4) sau derivat din `status` cand nu exista `rar_error` (ex. `needs_mapping → + COD_NEMAPAT`). Sir gol pe stari fara problema (`queued/sending/sent`). + - [ ] Extragerea e un helper pur in `labels.py` (ex. `cod_eroare_din(status, rar_error) -> str`), + defensiv la `rar_error` lipsa/JSON invalid (intoarce `""`, nu ridica). + - [ ] `prez`, `motiv`, `stare_*` raman neschimbate (aditiv). + - [ ] `python3 -m pytest tests/test_web_submissions.py -q` trece. +- **Verificare E2E**: — + +### US-002: Tabel trimiteri — cod eroare sub stare, fara chevron, cod RAR simplu +**Ca** operator **vreau** sa vad codul problemei direct in tabel si un rand mai curat **pentru ca** +sa stiu dintr-o privire ce rand are nevoie de mine. + +- **Depinde de**: US-001, US-003 (randul declanseaza modalul) +- **Fisiere**: `app/web/templates/_submissions.html`, `app/web/templates/base.html` (CSS), + `tests/test_web_submissions.py` +- **Test intai (RED)**: `tests/test_web_submissions.py` — + `test_cod_eroare_apare_sub_pill`, `test_fara_chevron_in_rand`, + `test_cod_rar_fara_prefix_text`, `test_rand_deschide_modal` +- **Acceptance criteria**: + - [ ] Sub pill-ul de Stare apare `r.cod_eroare` (text mic, muted, `s-error` pe `error`/`needs_*`), + DOAR cand e ne-gol. Nu se transmite stare doar prin culoare (codul e text). + - [ ] **Chevron eliminat** din coloana `#` (`_submissions.html:52-53`) si din CSS/JS asociat. + - [ ] Coloana Operatie linia 2: doar codul (ex. `OE-2`), **fara** prefixul „cod RAR:" — un + `` muted/pill; cand nemapat afiseaza „nemapat" muted (comportament 5.8 pastrat). + - [ ] Randul (`tr.trimitere-row`) declanseaza deschiderea modalului (US-003): `hx-get + /_fragments/trimitere/{id}` cu `hx-target` pe corpul modalului, NU pe un rand-sibling. + Randul-sibling `` din 5.8 este **eliminat**. + - [ ] Pe touch tinta randului ramane >=44px; randul ramane `role="button"`, `tabindex="0"`, + focusabil; Enter/Space deschid modalul. + - [ ] `python3 -m pytest tests/test_web_submissions.py -q` trece. +- **Verificare E2E**: gstack browser pe `/` — un rand `error` arata codul sub pill; nu exista + chevron; codul RAR apare fara „cod RAR:"; click pe rand deschide modalul (nu rand-sibling). + +### US-003: Component modal reutilizabil (overlay, focus-trap, a11y) +**Ca** operator **vreau** ca detaliul sa apara intr-o fereastra modala clar delimitata **pentru ca** +sa nu mai confund marginea cu tabelul si sa nu mi se mai inchida formularul la refresh. + +- **Depinde de**: — +- **Fisiere**: `app/web/templates/base.html` (markup `#modal-detaliu` + CSS + JS), + `app/web/templates/_coada.html` (ancora globala in afara `#submissions-wrap`), + `tests/test_web_modal.py` +- **Test intai (RED)**: `tests/test_web_modal.py` — + `test_modal_container_in_afara_submissions_wrap`, + `test_fragment_detaliu_tinteste_modalul` +- **Acceptance criteria**: + - [ ] Container modal global `