- base.html: listener htmx:beforeRequest scopat la #submissions-wrap care anuleaza (preventDefault) DOAR poll-ul periodic (fara requestConfig.triggeringEvent) cat timp modalul de detaliu e deschis SAU exista checkbox de bulk bifat. - F5/R6: trimiteriChanged si submit-ul de filtru au triggeringEvent -> trec mereu, deci pauza nu ramane lipita permanent daca randul bifat paraseste filtrul. - Resume automat (anularea nu opreste timer-ul htmx) + resume explicit pe checkbox change via delegare pe body -> trimiteriChanged from:body (pastreaza filtrul). - Vechea pauza pe „rand expandat" (5.8) era deja inlocuita de modalul global (US-003). - 3 teste noi in tests/test_web_modal.py; suita 843 passed, 1 deselected. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
262 lines
25 KiB
JSON
262 lines
25 KiB
JSON
{
|
|
"projectName": "autopass-5.9-ux-corectie-modal-mobil",
|
|
"branchName": "ralph/5.9-ux-corectie-modal-mobil",
|
|
"description": "Curatenie UX pe ecranul Trimiteri, fara schimbare a fluxului de trimitere catre RAR: detaliul+corectia trec intr-un MODAL global (in afara zonei de poll de 15s), editare in-place fara dublarea valorilor, butoane consolidate, fara chevron, eticheta umana scurta sub pill + cod brut in modal, cod RAR simplu. Plus design responsive/mobil (<768px) pentru toate paginile dashboard. Backend (worker, masina de stari, contract RAR, idempotenta, mapare) NEATINS logic; rutele isi pastreaza semnatura, se schimba doar hx-target si prezentarea. APLICA REVIZIILE OBLIGATORII R1-R12 din raportul AUTOPLAN (au prioritate unde difera de AC original). Sursa: docs/prd/prd-5.9-ux-corectie-modal-mobil.md.",
|
|
"techStack": {
|
|
"type": "python",
|
|
"commands": {
|
|
"start": "uvicorn app.main:app --reload --port 8010",
|
|
"build": "",
|
|
"lint": "",
|
|
"typecheck": "",
|
|
"test": "python3 -m pytest -q -m 'not live'"
|
|
},
|
|
"port": 8010
|
|
},
|
|
"userStories": [
|
|
{
|
|
"id": "US-001",
|
|
"title": "Eticheta umana scurta pe randul de afisare + cod brut disponibil pentru modal (R1)",
|
|
"description": "Ca dezvoltator vreau ca randul tabelului sa expuna o eticheta umana scurta a problemei (NU codul brut de catalog) pentru ca sub pill sa apara un text prietenos, consistent cu investitia 5.4 in erori umane.",
|
|
"priority": 10,
|
|
"acceptanceCriteria": [
|
|
"R1 OVERRIDE: NU se adauga helper nou `cod_eroare_din` care re-parseaza acelasi JSON (DRY). Se reutilizeaza `motiv_uman`/`eticheta_scurta` din `app/web/labels.py` deja existente.",
|
|
"`_submission_row_view` (`app/web/routes.py`) expune o eticheta umana scurta pe rand reutilizand `motiv` (deja intors nerandat) / `eticheta_scurta` — fara al 3-lea decoder al `rar_error`.",
|
|
"Eticheta este sir gol pe stari fara problema (`queued/sending/sent`) si ne-goala pe `error`/`needs_data`/`needs_mapping`.",
|
|
"Codul BRUT de catalog (ex. `RAR_EROARE_SERVER`, `COD_NEMAPAT`) ramane disponibil DOAR pentru modal, derivat din `parse_erori(...)[0]['cod']` (app/errors.py) — nu se pune pe rand.",
|
|
"Helperele sunt defensive la `rar_error` lipsa/JSON invalid (intorc sir gol, nu ridica).",
|
|
"`prez`, `motiv`, `stare_*` raman neschimbate (aditiv/non-regresie).",
|
|
"Teste in `tests/test_web_submissions.py`: `test_eticheta_umana_sub_pill` (R1 rename), eticheta prezenta pe error/needs_mapping, goala pe rand ok.",
|
|
"`python3 -m pytest tests/test_web_submissions.py -q` trece."
|
|
],
|
|
"tags": [
|
|
"backend"
|
|
],
|
|
"dependsOn": [],
|
|
"requiresBrowserCheck": false,
|
|
"requiresDesignReview": false,
|
|
"passes": true,
|
|
"failed": false,
|
|
"blocked": false,
|
|
"retries": 0,
|
|
"failureReason": "",
|
|
"notes": "Atins: app/web/routes.py (_eticheta_problema + _STARI_CU_PROBLEMA, camp eticheta_problema in _submission_row_view, motiv hoisted), app/web/labels.py (parse_erori expune `cod` brut aditiv pe ramurile imbogatite), tests/test_web_submissions.py (5 teste US-001). gates: tests PASS (819 suite, 22 fisier), /review (backend) PASS (no issues — DRY respectat, defensiv, aditiv non-regresie)."
|
|
},
|
|
{
|
|
"id": "US-003",
|
|
"title": "Component modal reutilizabil (overlay, focus-trap, a11y, inchidere pe succes)",
|
|
"description": "Ca operator vreau ca detaliul sa apara intr-o fereastra modala clar delimitata, in afara zonei de poll, pentru ca sa nu mai confund marginea cu tabelul si sa nu mi se mai inchida formularul la refresh.",
|
|
"priority": 15,
|
|
"acceptanceCriteria": [
|
|
"Container modal global `<div id=\"modal-detaliu\" role=\"dialog\" aria-modal=\"true\" hidden>` cu backdrop, plasat IN AFARA `#submissions-wrap` (poll-ul de 15s nu-l atinge). Corpul `#detaliu-modal-body` e tinta de swap pentru fragment + rutele corectie/mapare/lifecycle.",
|
|
"Ancora globala in `_coada.html` in afara `#submissions-wrap`; `#trimitere-detaliu` global inert vechi din `_coada.html` este ELIMINAT (rol preluat de `#modal-detaliu`).",
|
|
"Deschidere la `htmx:beforeRequest` de pe `tr.trimitere-row`: backdrop+dialog vizibile cu placeholder `Se incarca...` (`hx-indicator`), focus mutat in modal. Un singur modal o data.",
|
|
"Inchidere prin buton `x`, `Esc`, click pe backdrop: `hidden`, corp golit, focus readus pe randul declansator.",
|
|
"R7: focus-trap (Tab/Shift+Tab cicleaza in modal); `inert` SI `aria-hidden` pe ancestor STABIL `<main>` (NU pe `#submissions-wrap` care e swap target); scroll body blocat cat modalul e deschis; dialog cu `aria-labelledby` pe heading; buton `x` cu `aria-label`.",
|
|
"R3: tot codul inline-expand din 5.8 (chevron, `tr.detaliu-rand`, `marcheazaDetaliuDeschis`, `inchideDetaliu` pe rand, toggle single-open) ELIMINAT/inlocuit de logica modalului; `window.inchideDetaliu(id)` ramane expus dar inchide modalul.",
|
|
"R3 (EngF1): adauga in scope `tests/test_web_detaliu_inline.py` (rescrie/sterge) si `tests/test_acasa_trimiteri.py:71` (scoate assert `#trimitere-detaliu`). Niciun template/test nu mai refera `tr.detaliu-rand`/`#trimitere-detaliu`/`marcheazaDetaliuDeschis`/`aria-expanded` pe rand.",
|
|
"R5: pe succes corectie SI sterge, modalul se inchide + listener pe `HX-Trigger: trimiteriChanged` reincarca lista; pe load-error al fragmentului stare `Nu s-a putut incarca [Reincearca]/[Inchide]` (HTMX `responseError`), nu placeholder blocat.",
|
|
"Teste in `tests/test_web_modal.py`: `test_modal_container_in_afara_submissions_wrap`, `test_fragment_detaliu_tinteste_modalul`.",
|
|
"`python3 -m pytest tests/test_web_modal.py -q` trece."
|
|
],
|
|
"tags": [
|
|
"ui"
|
|
],
|
|
"dependsOn": [],
|
|
"requiresBrowserCheck": true,
|
|
"requiresDesignReview": true,
|
|
"passes": true,
|
|
"failed": false,
|
|
"blocked": false,
|
|
"retries": 0,
|
|
"failureReason": "",
|
|
"notes": "Cod-complet, salvat manual din working-tree dupa ce iteratiile 2-12 au ramas fara turns (30) inainte de commit. Atins: base.html (markup #modal-detaliu role=dialog aria-modal + #detaliu-modal-body swap target, +212 linii JS focus-trap/inert pe <main>/Esc/backdrop/trimiteriChanged listener), _coada.html (ancora globala in afara #submissions-wrap, sters #trimitere-detaliu inert vechi), _submissions.html (rand declanseaza modalul, sters tr.detaliu-rand sibling), _trimitere_detaliu.html (script rescris R4 fara marcheazaDetaliuDeschis/scrollIntoView), routes.py (minor), tests/test_web_detaliu_inline.py STERS, tests/test_acasa_trimiteri.py (scos assert #trimitere-detaliu), tests/test_web_modal.py NOU (3 teste). Gates: pytest PASS (test_web_modal 3/3; suita completa 819 passed). R3/R5/R7 cod-level verificate (grep: niciun refer rezidual la identificatorii stersi; aria-expanded ramas e doar pe meniul cont). DEFERAT la VERIFY (ROADMAP 5.6): requiresBrowserCheck (E2E gstack) + requiresDesignReview NErulate (loop fara browser/gstack)."
|
|
},
|
|
{
|
|
"id": "US-006",
|
|
"title": "Fundatie responsive — viewport, header, nav, modal full-screen mobil, breakpoint-uri",
|
|
"description": "Ca utilizator pe telefon vreau ca shell-ul aplicatiei sa fie utilizabil pentru ca azi header-ul, tab-bar-ul si modalul nou nu au tratament sub 768px.",
|
|
"priority": 20,
|
|
"acceptanceCriteria": [
|
|
"`<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">` prezent (confirmat/adaugat) in `base.html`.",
|
|
"Modal full-screen pe mobil: sub 768px modalul ocupa tot ecranul (fara backdrop lateral), buton `x` mare (>=44px), scroll intern; pe desktop ramane centrat cu latime marginita.",
|
|
"Header + nav: meniul de cont (un buton hamburger) si tab-bar-ul nu depasesc latimea pe 375px; tinte touch >=44px; fara scroll orizontal pe pagina.",
|
|
"Breakpoint-uri consistente definite o data (ex. `--bp-mobil: 768px`) si reutilizate; fara regresie pe desktop (>=1024px arata identic).",
|
|
"Teste in `tests/test_web_responsive.py`: `test_viewport_meta_prezent`, `test_modal_fullscreen_clasa_mobil`, `test_nav_colapsabil_sub_breakpoint`.",
|
|
"`python3 -m pytest tests/test_web_responsive.py -q` trece."
|
|
],
|
|
"tags": [
|
|
"ui"
|
|
],
|
|
"dependsOn": [
|
|
"US-003"
|
|
],
|
|
"requiresBrowserCheck": true,
|
|
"requiresDesignReview": true,
|
|
"passes": true,
|
|
"failed": false,
|
|
"blocked": false,
|
|
"retries": 0,
|
|
"failureReason": "",
|
|
"notes": "Atins: app/web/templates/base.html (conventie breakpoint unic 767px documentata; bloc `@media (max-width:767px)` US-006 extins cu: modal full-screen — overlay fara padding/align-stretch, dialog 100vw/100vh fara border-radius/umbra, modal-close 44x44px, scroll intern; header colapsat flex-wrap + main padding redus; tinte touch >=44px pe .icon-btn/.tab-link/.cont-menu items; comentariu desktop modal actualizat), tests/test_web_responsive.py NOU (3 teste: test_viewport_meta_prezent, test_modal_fullscreen_clasa_mobil, test_nav_colapsabil_sub_breakpoint). meta viewport deja prezent (confirmat, neatins). Nav colapsabil (hamburger cont + tab-bar overflow-x) deja livrat de PRD-uri anterioare; US-006 a adaugat doar tintele touch 44px sub breakpoint. Gates: pytest PASS (fisier 3/3; suita completa 829 passed, 1 deselected — fata de 826 inainte). DEFERAT la VERIFY: requiresBrowserCheck + requiresDesignReview (gstack browser la 375px pe / — fara scroll orizontal, hamburger deschide meniul, modal full-screen + inchidere din x) NErulate in loop fara browser."
|
|
},
|
|
{
|
|
"id": "US-002",
|
|
"title": "Tabel trimiteri — eticheta umana sub stare, fara chevron, cod RAR simplu, rand declanseaza modalul",
|
|
"description": "Ca operator vreau sa vad problema direct in tabel si un rand mai curat pentru ca sa stiu dintr-o privire ce rand are nevoie de mine.",
|
|
"priority": 30,
|
|
"acceptanceCriteria": [
|
|
"R1 OVERRIDE: sub pill-ul de Stare apare ETICHETA UMANA scurta (din US-001, NU codul brut), text mic muted (`s-error` pe `error`/`needs_*`), DOAR cand e ne-goala. Stare transmisa prin text, nu doar culoare.",
|
|
"R8: chevron ELIMINAT din coloana `#` (`_submissions.html:52-53`) si din CSS/JS asociat; regula touch `min-height/padding >=44px` pe rand INLOCUIESTE `@media pointer:coarse .chevron` (singura regula 44px); scoate logica toggle (re-click inchide) din `htmx:beforeRequest`.",
|
|
"Coloana Operatie linia 2: doar codul RAR (ex. `OE-2`), FARA prefixul `cod RAR:` — un `<span>` 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 rand-sibling. Randul-sibling `<tr class=\"detaliu-rand\">` din 5.8 este ELIMINAT.",
|
|
"R8: rand `role=\"button\"`, `tabindex=\"0\"`, `aria-haspopup=\"dialog\"`, FARA `aria-expanded`; focusabil; Enter/Space deschid modalul; hover/focus pastrate ca afordanta; tinta touch >=44px.",
|
|
"Teste in `tests/test_web_submissions.py`: `test_eticheta_umana_apare_sub_pill`, `test_fara_chevron_in_rand`, `test_cod_rar_fara_prefix_text`, `test_rand_deschide_modal`, plus test keyboard Enter/Space deschide modal + Esc readuce focus.",
|
|
"`python3 -m pytest tests/test_web_submissions.py -q` trece.",
|
|
"E2E (requiresBrowserCheck): gstack browser pe `/` — rand `error` arata eticheta umana sub pill; fara chevron; cod RAR fara `cod RAR:`; click pe rand deschide modalul (nu rand-sibling)."
|
|
],
|
|
"tags": [
|
|
"ui"
|
|
],
|
|
"dependsOn": [
|
|
"US-001",
|
|
"US-003"
|
|
],
|
|
"requiresBrowserCheck": true,
|
|
"requiresDesignReview": false,
|
|
"passes": true,
|
|
"failed": false,
|
|
"blocked": false,
|
|
"retries": 0,
|
|
"failureReason": "",
|
|
"notes": "Mare parte deja livrat de US-001 (camp eticheta_problema) si US-003 (rand declanseaza modalul). Atins: app/web/templates/_submissions.html (eticheta_problema sub pill cu clasa s-error doar cand ne-gol; col-operatie cod RAR ca chip cod-rar-cod fara prefixul 'cod RAR:'; nemapat muted), app/web/templates/base.html (CSS .eticheta-problema/.cod-rar-cod + R8 regula 44px touch-target pe tr.trimitere-row + hover/focus), tests/test_web_submissions.py (7 teste noi US-002 + actualizat test_operatie_contine_cod_rar si test_tabel_nu_are_coloana_motiv). Chevron inexistent in cod -> R8 doar adaugare regula 44px. Gates: pytest PASS (fisier 20; suita 826 passed, 1 deselected). DEFERAT la VERIFY: requiresBrowserCheck (gstack E2E pe /) + verificarea JS keyboard (Enter/Space deschide modal, Esc readuce focus) — netestabile in TestClient, acoperite prin assert pe markup/atribute (role=button, tabindex=0, aria-haspopup=dialog, fara aria-expanded) + prezenta handler-elor in base.html."
|
|
},
|
|
{
|
|
"id": "US-004",
|
|
"title": "Detaliu editabil in-place + butoane consolidate (in modal), ordine verticala definita",
|
|
"description": "Ca operator vreau sa corectez datele direct, o singura aparitie per camp, cu un buton clar pentru ca sa nu mai vad valorile de doua ori si sa nu mai ezit intre butoane.",
|
|
"priority": 35,
|
|
"acceptanceCriteria": [
|
|
"Zero dublare: blocul read-only de grila (`_trimitere_detaliu.html:19-32`) si formularul separat de corectie se contopesc intr-un singur formular cu campuri editabile pre-completate. Campurile editabile (`nr_inmatriculare`, `vin`, `data_prestatie`, `odometru_final`, `odometru_initial`) apar O SINGURA DATA.",
|
|
"Layout: `Numar inmatriculare` pe propriul rand (latime plina), `VIN (serie sasiu)` pe randul de DEDESUBT (latime plina). Restul campurilor pot ramane in grila.",
|
|
"R10 ordine verticala modal: (1) header `#id`+pill+motiv uman; (2) bloc eroare blocanta cand exista; (3) mapare inline cand `nemapate_inline`; (4) formular editabil (Nr. rand propriu, VIN dedesubt, apoi grila), cu operatie+cod read-only deasupra campurilor; (5) actiuni (primar, apoi Sterge separat); (6) `<details>` `Detalii tehnice` colapsat (Nr. prezentare RAR, Cod HTTP, Reincercari, timestamps, mesaj RAR brut + cod brut). Context read-only NU precede formularul.",
|
|
"Cod RAR simplu: nu mai exista campul etichetat `Cod RAR` separat (`:23`). R9: operatie+cod folosesc `prez.cod_rar` (fallback `nemapat`), NU `prez.cod`; afisate impreuna ca read-only (ex. `Operatie: Revizie · OE-2`), fara eticheta `Cod RAR`.",
|
|
"R2 OVERRIDE (buton primar conditionat de stare): `error` -> buton `Re-pune in coada` care posteaza pe `/trimitere/{id}/repune` (neschimbat); `needs_data`/`needs_mapping` -> buton `Salveaza si retrimite` care posteaza pe `/trimitere/{id}/corecteaza` (neschimbat). UN SINGUR buton primar per stare (clasa primara `--accent` umplut). Butonul `Re-pune in coada` gol vechi (`:55-59`) eliminat.",
|
|
"R11: UN SINGUR `Sterge` (outline distructiv, `var(--err)`/rosu) pe RAND SEPARAT (NU `margin-left:auto`), gap vizibil, full-width stivuit pe mobil; `hx-confirm` specific (`Stergi definitiv trimiterea #{id}? Nu se poate anula.`); posteaza pe `/trimitere/{id}/sterge` (neschimbat).",
|
|
"R9: sectiunea de mapare inline (5.7, `:71-116`) ramane functional identica, mutata in modal, tintind corpul modalului; cand `nemapate_inline`: linia `Operatie: X · nemapat` urmata de picker; dupa mapare re-render arata codul rezolvat.",
|
|
"R4: rescrie `<script>`-ul inline din `_trimitere_detaliu.html:161-176` pentru modal — FARA `marcheazaDetaliuDeschis`, FARA `scrollIntoView` pe randul de fundal; muta focusul in corpul modalului.",
|
|
"R5: disable-on-submit pe toate cele 3 forme (corectie/sterge/mapare); pe succes (queued sau sterge) modalul se inchide + `trimiteriChanged`.",
|
|
"Erorile de camp (`err_map`, `aria-invalid`, mesaj inline) si flash-ul de corectie raman. Comportamentul rutelor `/corecteaza` si `/repune` (validare, idempotency, re-rezolvare) NESCHIMBAT — test de regresie confirma acelasi rezultat ca azi.",
|
|
"Teste in `tests/test_web_corectie.py`: `test_camp_apare_o_singura_data`, `test_nr_si_vin_pe_randuri_separate`, `test_un_singur_buton_primar_per_stare` (R2), `test_error_foloseste_repune` (R2), `test_sterge_prezent_si_distinct`, `test_corectie_pastreaza_comportament` (regresie).",
|
|
"`python3 -m pytest tests/test_web_corectie.py -q` trece.",
|
|
"E2E (requiresBrowserCheck): gstack browser — `needs_data` arata fiecare camp o data (nr. pe un rand, VIN dedesubt), corectez data, `Salveaza si retrimite` -> rand `queued`; `error` arata `Re-pune in coada`; `Sterge` clar separat si rosu."
|
|
],
|
|
"tags": [
|
|
"ui"
|
|
],
|
|
"dependsOn": [
|
|
"US-003"
|
|
],
|
|
"requiresBrowserCheck": true,
|
|
"requiresDesignReview": true,
|
|
"passes": true,
|
|
"failed": false,
|
|
"blocked": false,
|
|
"retries": 0,
|
|
"failureReason": "",
|
|
"notes": "Implementat in _trimitere_detaliu.html (ordine R10): header+motiv, eroare blocanta, mapare inline, formular editabil cu campuri o singura data (nr rand propriu, VIN dedesubt) + operatie/cod read-only (prez.cod_rar, fallback nemapat), actiuni jos, <details> Detalii tehnice. R2/F7: buton primar conditionat de stare — error->Re-pune(/repune), needs_data/needs_mapping->Salveaza si retrimite(/corecteaza). R11: Sterge outline var(--err) pe rand separat, hx-confirm specific, full-width pe mobil (regula .detaliu-actiuni-jos in @media 767px). R5: hx-disabled-elt pe toate formele; inchidere pe succes prin HX-Trigger inchideModal. _detaliu_ctx si rutele NESCHIMBATE. 6 teste noi in test_web_corectie.py; suita 835 passed (-m 'not live'). Ramane VERIFY browser/design (requiresBrowserCheck/requiresDesignReview)."
|
|
},
|
|
{
|
|
"id": "US-007",
|
|
"title": "Responsive — paginile de continut (Mapari, Cont, Nomenclator, Integrare, Jurnal, Admin)",
|
|
"description": "Ca operator pe telefon vreau ca paginile de lucru sa fie lizibile pentru ca tabelele si formularele lor ies azi din ecran sub 768px.",
|
|
"priority": 40,
|
|
"acceptanceCriteria": [
|
|
"R12 politica per-tabel: tabele actionabile (Mapari) = CARD per rand sub 768px (adauga `data-eticheta` la `<td>`-uri, model 5.8 `.tabel-trimiteri`); dense read-only (Jurnal, Nomenclator) = `.tablewrap` cu scroll orizontal CONTAINED (nu deborda pagina).",
|
|
"R12: scopare `.tablewrap` sa NU atinga blocul `.tabel-trimiteri @media(max-width:767px)` din 5.8; test ca acele carduri 5.8 supravietuiesc.",
|
|
"Formularele (Cont, Mapari add-row, filtre, Integrare) stiveaza campurile pe o coloana sub 768px, inputuri full-width, butoane >=44px.",
|
|
"La 375px niciuna din pagini nu produce scroll orizontal de pagina (`scrollWidth <= clientWidth` pe `body`).",
|
|
"Fara regresie la >=1024px (layout actual pastrat).",
|
|
"Fisiere: `app/web/templates/_mapari.html`, `_cont.html`, `_nomenclator.html`, `_integrare.html`, `_jurnal.html`, `admin.html`, `base.html` (utilitar `.tablewrap`/card).",
|
|
"Teste in `tests/test_web_responsive.py`: `test_tabele_continut_au_clasa_responsive`, `test_formulare_full_width_mobil`.",
|
|
"`python3 -m pytest tests/test_web_responsive.py -q` trece.",
|
|
"E2E (requiresBrowserCheck): gstack browser la 375px pe `/?tab=mapari`, `?tab=jurnal`, Cont/Nomenclator/Integrare si `/admin` — fiecare fara scroll orizontal, tabele lizibile, formulare pe o coloana."
|
|
],
|
|
"tags": [
|
|
"ui"
|
|
],
|
|
"dependsOn": [
|
|
"US-006"
|
|
],
|
|
"requiresBrowserCheck": true,
|
|
"requiresDesignReview": false,
|
|
"passes": true,
|
|
"failed": false,
|
|
"blocked": false,
|
|
"retries": 0,
|
|
"failureReason": "",
|
|
"notes": "Implementat. R12 per-tabel: Mapari=CARD (clasa .tabel-card scopata separat de .tabel-trimiteri 5.8, data-eticheta pe td-uri in toate 4 tabelele); Jurnal/Nomenclator/Admin=.tablewrap scroll contained (deja existau; dense/admin-only, risc minim). Cont/Integrare=fara tabele, doar formulare stivate. CSS card+formulare in blocul @media(max-width:767px) din base.html (marker US-007). Formulare: inputuri full-width (!important doar pe mobil ca sa invinga latimile inline desktop), butoane >=44px, filtre jurnal pe o coloana. id=form-test-cheie adaugat la integrare pt scope. Override select mapari in card local in _mapari.html (evita batalia de ordine/specificitate cu stilul inline). Teste: test_tabele_continut_au_clasa_responsive, test_formulare_full_width_mobil, test_carduri_trimiteri_5_8_supravietuiesc (regresie). Suita: 838 passed, 1 deselected. E2E ramas pt browser (375px fara scroll orizontal de pagina pe fiecare pagina)."
|
|
},
|
|
{
|
|
"id": "US-008",
|
|
"title": "Responsive — Acasa (upload, status, filtre) + login/signup",
|
|
"description": "Ca utilizator pe telefon vreau ca prima pagina si autentificarea sa fie utilizabile pentru ca sunt punctele de intrare si azi nu au tratament mobil complet.",
|
|
"priority": 45,
|
|
"acceptanceCriteria": [
|
|
"Zona de upload, bara de status si bara de filtre (`_coada.html:25-59`) stiveaza pe o coloana sub 768px; inputuri/butoane full-width >=44px.",
|
|
"Tabelul de trimiteri pastreaza cardurile din 5.8 (verificat, nereparat daca deja ok).",
|
|
"`login.html` si `signup.html`: card centrat care nu depaseste latimea pe 375px, inputuri full-width, fara scroll orizontal.",
|
|
"Fara regresie la >=1024px.",
|
|
"Fisiere: `app/web/templates/_acasa.html`, `_upload.html`, `_status.html`, `_coada.html` (filtre), `login.html`, `signup.html`.",
|
|
"Teste in `tests/test_web_responsive.py`: `test_acasa_fara_scroll_orizontal_mobil`, `test_login_signup_full_width_mobil`.",
|
|
"`python3 -m pytest tests/test_web_responsive.py -q` trece.",
|
|
"E2E (requiresBrowserCheck): gstack browser la 375px pe `/`, `/login`, `/signup` — fara scroll orizontal; upload + filtre pe o coloana; carduri de trimiteri intacte."
|
|
],
|
|
"tags": [
|
|
"ui"
|
|
],
|
|
"dependsOn": [
|
|
"US-006"
|
|
],
|
|
"requiresBrowserCheck": true,
|
|
"requiresDesignReview": false,
|
|
"passes": true,
|
|
"failed": false,
|
|
"blocked": false,
|
|
"retries": 0,
|
|
"failureReason": "",
|
|
"notes": "Mobil (<767px): zona upload stivuita + buton alegere full-width; bara filtre o coloana cu inputuri/buton full-width >=44px (!important pe latimile inline); bara status alineata fara scroll; login/signup card .auth-card centrat max-width:100%. CSS scopat pe #import-section/#status-bar/#filtre-trimiteri/.auth-card in base.html (nu atinge .tabel-trimiteri 5.8). Teste: test_acasa_fara_scroll_orizontal_mobil, test_login_signup_full_width_mobil. Suita: 840 passed. E2E browser (375px /, /login, /signup) deferat VERIFY."
|
|
},
|
|
{
|
|
"id": "US-005",
|
|
"title": "Poll-ul nu mai inchide modalul si nu mai sterge bifele",
|
|
"description": "Ca operator vreau ca selectia si modalul sa supravietuiasca refresh-ului de 15s pentru ca azi formularul se inchide singur si bifele se sterg dupa cateva secunde.",
|
|
"priority": 50,
|
|
"acceptanceCriteria": [
|
|
"Modalul traieste in afara `#submissions-wrap` -> un swap de poll NU il mai atinge (rezolvat structural de US-003). Test: cu modalul deschis, un refresh al listei nu-l inchide.",
|
|
"R6 OVERRIDE: poll-ul de 15s (`#submissions-wrap`, `_coada.html:62-65`) se pune pe pauza SCOPAT DOAR pe trigger periodic `every 15s` cat timp: (a) modalul e deschis SAU (b) exista cel putin un checkbox de bulk bifat. `trimiteriChanged` si submit-ul de filtru TREC MEREU (nu se blocheaza). Resume pe checkbox `change`->gol via delegare pe body.",
|
|
"R6: evita blocajul permanent — daca randul bifat paraseste filtrul, pauza nu ramane lipita (pauza doar pe trigger periodic).",
|
|
"La pauza nu se pierde nici scroll, nici focus, nici selectia de checkbox-uri.",
|
|
"Logica veche de pauza pe `rand expandat` (5.8, `base.html:478-483`) inlocuita de aceasta.",
|
|
"Teste in `tests/test_web_modal.py`: `test_poll_pauzat_cat_modal_deschis`, `test_poll_pauzat_cat_exista_bifa`, `test_trimiteriChanged_inca_reincarca_cu_bifa` (R6).",
|
|
"`python3 -m pytest tests/test_web_modal.py -q` trece.",
|
|
"E2E (requiresBrowserCheck): gstack browser — bifez 2 trimiteri, astept >15s: bifele raman; deschid modalul, astept >15s: modalul ramane deschis cu datele intacte."
|
|
],
|
|
"tags": [
|
|
"ui"
|
|
],
|
|
"dependsOn": [
|
|
"US-002",
|
|
"US-003"
|
|
],
|
|
"requiresBrowserCheck": true,
|
|
"requiresDesignReview": false,
|
|
"passes": true,
|
|
"failed": false,
|
|
"blocked": false,
|
|
"retries": 0,
|
|
"failureReason": "",
|
|
"notes": "Poll-guard adaugat in base.html: htmx:beforeRequest scopat la #submissions-wrap, anuleaza (preventDefault) DOAR trigger-ul periodic (fara requestConfig.triggeringEvent) cat timp modalul e deschis SAU exista bifa de bulk. trimiteriChanged si submit-ul de filtru au triggeringEvent -> trec mereu (F5: fara blocaj permanent). Anularea nu opreste timer-ul htmx (se reprogrameaza) -> resume automat; resume explicit pe checkbox change via delegare pe body. Vechea pauza pe rand expandat (5.8) era deja inlocuita de modal (US-003). 3 teste noi in test_web_modal.py; suita 843 passed."
|
|
}
|
|
]
|
|
} |