From 35e97faae5e29e57748c790fbb2c16808dae80da Mon Sep 17 00:00:00 2001 From: Claude Agent Date: Thu, 25 Jun 2026 09:23:37 +0000 Subject: [PATCH] feat(5.9): US-008 - responsive Acasa (upload/status/filtre) + login/signup - base.html: bloc @media (max-width:767px) US-008, scopat pe id-urile de pe Acasa - upload (#import-section): drop-zone pe coloana, buton alegere full-width >=44px - filtre (#filtre-trimiteri): o coloana, inputuri/buton full-width >=44px (!important pe latimile inline) - status (#status-bar): randuri aliniate, fara scroll orizontal - login.html/signup.html: clasa .auth-card centrata, max-width:100% pe mobil - tabelul de trimiteri 5.8 neatins (doar verificat intact) - teste noi: test_acasa_fara_scroll_orizontal_mobil, test_login_signup_full_width_mobil - suita: 840 passed, 1 deselected Co-Authored-By: Claude Opus 4.8 (1M context) --- app/web/templates/base.html | 21 ++++++++++ app/web/templates/login.html | 2 +- app/web/templates/signup.html | 2 +- scripts/ralph/prd.json | 6 +-- scripts/ralph/progress.txt | 37 +++++++++++++++++ tests/test_web_responsive.py | 78 +++++++++++++++++++++++++++++++++++ 6 files changed, 141 insertions(+), 5 deletions(-) diff --git a/app/web/templates/base.html b/app/web/templates/base.html index 8a255a2..45b69bf 100644 --- a/app/web/templates/base.html +++ b/app/web/templates/base.html @@ -290,6 +290,27 @@ #jurnal-section #filtre-jurnal > div { width:100%; } #card-cont button, #form-test-cheie button, #jurnal-section #filtre-jurnal button { min-height:44px; width:100%; } + + /* === PRD 5.9 US-008: Acasa (upload, status, filtre) + login/signup pe mobil === + Zona de upload, bara de status si bara de filtre (`_coada.html`) stiveaza pe O + coloana sub 767px; inputuri/butoane full-width cu tinta touch >=44px. Scopat pe + id-urile sectiunilor de pe Acasa ca sa NU atinga tabelul de trimiteri (5.8), + modalul sau paginile de continut (US-007). */ + /* Bara de upload: zona slim (returning user) trece pe coloana; butonul full-width. */ + #import-section .drop-zone { flex-direction:column; align-items:stretch; text-align:left; } + #import-section #upload-btn { width:100%; min-height:44px; } + /* Bara de status: contoarele/randurile raman aliniate la stanga, fara scroll orizontal. */ + #status-bar > div { gap:10px; } + /* Bara de filtre trimiteri: o coloana, fiecare control full-width, buton >=44px. + !important suprascrie latimile inline (ex. max-width:180px pe vehicul) DOAR pe mobil. */ + #filtre-trimiteri { flex-direction:column; align-items:stretch; } + #filtre-trimiteri > div { width:100%; } + #filtre-trimiteri select, #filtre-trimiteri input[type=text], + #filtre-trimiteri input[type=date] { width:100% !important; max-width:none !important; } + #filtre-trimiteri button { width:100%; min-height:44px; } + + /* Card de autentificare (login/signup): centrat si nu depaseste viewport-ul pe mobil. */ + .auth-card { max-width:100%; margin:24px auto; } } diff --git a/app/web/templates/login.html b/app/web/templates/login.html index d308314..b17ab16 100644 --- a/app/web/templates/login.html +++ b/app/web/templates/login.html @@ -1,7 +1,7 @@ {% extends "base.html" %} {% block title %}Autentificare — Gateway RAR AUTOPASS{% endblock %} {% block content %} -
+

Autentificare

{% if error %} diff --git a/app/web/templates/signup.html b/app/web/templates/signup.html index cc061fe..75ead6a 100644 --- a/app/web/templates/signup.html +++ b/app/web/templates/signup.html @@ -1,7 +1,7 @@ {% extends "base.html" %} {% block title %}Inregistrare — Gateway RAR AUTOPASS{% endblock %} {% block content %} -
+
{% if api_key %}
Contul a fost creat. Salveaza cheia API acum — nu o vei mai putea vedea.
diff --git a/scripts/ralph/prd.json b/scripts/ralph/prd.json index 98e98a4..cc06198 100644 --- a/scripts/ralph/prd.json +++ b/scripts/ralph/prd.json @@ -220,12 +220,12 @@ ], "requiresBrowserCheck": true, "requiresDesignReview": false, - "passes": false, + "passes": true, "failed": false, "blocked": false, "retries": 0, "failureReason": "", - "notes": "" + "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", @@ -259,4 +259,4 @@ "notes": "" } ] -} \ No newline at end of file +} diff --git a/scripts/ralph/progress.txt b/scripts/ralph/progress.txt index 809632b..7cbbb57 100644 --- a/scripts/ralph/progress.txt +++ b/scripts/ralph/progress.txt @@ -194,3 +194,40 @@ Note: PRD APROBAT 2026-06-24 cu revizii obligatorii R1-R12 (raport AUTOPLAN). R1 - VERIFY: gstack browser la 375px pe /?tab=mapari, ?tab=jurnal, Cont/Nomenclator/Integrare, /admin — fiecare fara scroll orizontal de pagina, tabele lizibile, formulare pe o coloana. --- + +======================================================================== +## US-008 — Responsive Acasa (upload, status, filtre) + login/signup +======================================================================== +Status: PASS (loop). E2E browser deferat la VERIFY. + +### Ce s-a facut: +- base.html: bloc nou sub `@media (max-width:767px)` (marcat US-008), scopat strict pe + id-urile sectiunilor de pe Acasa, ca sa NU atinga `.tabel-trimiteri` (5.8), modalul (US-003/004) + sau paginile de continut (US-007): + - `#import-section .drop-zone` -> coloana (flex-direction:column, align stretch); + `#import-section #upload-btn` -> full-width, min-height:44px. + - `#filtre-trimiteri` -> coloana; `> div` full-width; select/input[text]/input[date] + `width:100% !important; max-width:none !important` (suprascrie max-width:180px inline pe vehicul); + buton full-width >=44px. + - `#status-bar > div` gap redus (randuri deja flex-wrap) -> fara scroll orizontal. + - `.auth-card` -> max-width:100%; margin:24px auto (centrat, nu depaseste viewport pe mobil). +- login.html / signup.html: cardul primeste clasa `auth-card` (inputurile aveau deja width:100% inline). +- Tabelul de trimiteri (carduri 5.8) NEATINS — doar verificat intact (test US-007 existent). + +### Teste (test_web_responsive.py, +2): +- test_acasa_fara_scroll_orizontal_mobil — ancore #import-section/#status-bar/#filtre-trimiteri + + reguli mobil de stivuire/full-width (seed 1 submission ca sectiunea Trimiteri sa se randeze). +- test_login_signup_full_width_mobil — /login + /signup: .auth-card centrat, width:100%, max-width:100% mobil. + +### Gates: +- Tests: PASS — suita completa 840 passed, 1 deselected (era 838; +2 US-008). +- Browser (E2E requiresBrowserCheck): DEFERAT la VERIFY (375px pe /, /login, /signup — + fara scroll orizontal; upload + filtre pe o coloana; carduri trimiteri intacte). + +### Learnings: +- `_coada.html` (filtrele + #submissions-wrap) se include in `_acasa.html` DOAR cand `are_trimiteri` + e True (zero trimiteri = bara upload acopera CTA-ul). Testul de markup pentru `#filtre-trimiteri` + trebuie sa semene un submission; regulile CSL traiesc oricum in base.html (mereu prezente). +- login/signup mosteneau deja `width:100%` inline + `margin:40px auto`; lipsea doar plafonarea + latimii pe mobil — rezolvata centralizat prin clasa `.auth-card` (fara duplicare de stil inline). +--- diff --git a/tests/test_web_responsive.py b/tests/test_web_responsive.py index 411709f..546aab1 100644 --- a/tests/test_web_responsive.py +++ b/tests/test_web_responsive.py @@ -10,6 +10,7 @@ orizontal) sunt deferate la VERIFY (gstack browser). from __future__ import annotations +import json import os import re import tempfile @@ -32,6 +33,29 @@ def _create_account_user(email: str, name: str = "Service", password: str = "par conn.close() +def _insert_submission(acct: int, status: str = "needs_data") -> int: + from app.db import get_connection + + conn = get_connection() + try: + p = { + "vin": "WVWZZZ1JZXW000888", + "nr_inmatriculare": "B888ZZZ", + "data_prestatie": "2026-06-18", + "odometru_final": "55000", + "prestatii": [{"cod_prestatie": "R-FRANE", "denumire": "Reparatie frane"}], + } + cur = conn.execute( + "INSERT INTO submissions (idempotency_key, account_id, status, payload_json) " + "VALUES (?, ?, ?, ?)", + (f"k-{status}-{os.urandom(4).hex()}", acct, status, json.dumps(p)), + ) + conn.commit() + return int(cur.lastrowid) + finally: + conn.close() + + def _login(client, email: str, password: str = "parolasecreta10") -> None: resp = client.get("/login") m = re.search(r'name="csrf_token"\s+value="([^"]+)"', resp.text) or \ @@ -214,3 +238,57 @@ def test_carduri_trimiteri_5_8_supravietuiesc(client): assert ".tabel-trimiteri td::before" in mobil # Cele doua mecanisme coexista, scopate distinct. assert ".tabel-card thead" in mobil + + +# ============================================================ +# PRD 5.9 US-008: responsive Acasa (upload, status, filtre) + login/signup +# ============================================================ + + +def test_acasa_fara_scroll_orizontal_mobil(client): + """US-008: pe Acasa sub 767px zona de upload, bara de status si bara de filtre + stiveaza pe O coloana, cu inputuri/butoane full-width >=44px. Verificam ancorele + de scope (id-uri) + regulile CSS mobil din base.html (toate sub `@media (max-width:767px)`), + fara sa atingem cardurile de trimiteri 5.8 (verificate separat).""" + acct = _create_account_user("a8@test.com") + _insert_submission(acct) # sectiunea Trimiteri (filtre + wrap) apare doar cu randuri + _login(client, "a8@test.com") + html = client.get("/?tab=acasa").text + + # Ancore de scope prezente in markup. + assert 'id="import-section"' in html + assert 'id="status-bar"' in html + assert 'id="filtre-trimiteri"' in html + assert "US-008" in html + + mobil = html[html.find("@media (max-width:767px)"):] + + # Bara de upload: zona de drop trece pe coloana, butonul de alegere full-width. + assert "#import-section .drop-zone" in mobil + assert "#import-section #upload-btn" in mobil + + # Bara de filtre: o coloana, controale full-width, buton >=44px. + assert "#filtre-trimiteri" in mobil + filtre = mobil[mobil.find("#filtre-trimiteri"):] + assert "width:100% !important" in filtre # suprascrie latimile inline (max-width:180px etc.) + assert "min-height:44px" in mobil + + # Bara de status stiveaza pe coloana (scope dedicat). + assert "#status-bar" in mobil + + +def test_login_signup_full_width_mobil(client): + """US-008: login.html si signup.html randeaza un card centrat (`.auth-card`, margin auto) + care nu depaseste latimea pe mobil (max-width:100% sub 767px), cu inputuri full-width. + Rutele `/login` si `/signup` sunt publice (fara autentificare).""" + for ruta in ("/login", "/signup"): + html = client.get(ruta).text + # Card de autentificare marcat si centrat. + assert "auth-card" in html, ruta + assert "margin:40px auto" in html or "margin:24px auto" in html, ruta + # Inputurile sunt full-width. + assert "width:100%" in html, ruta + # Regula mobil: cardul nu depaseste viewport-ul. + mobil = html[html.find("@media (max-width:767px)"):] + assert ".auth-card" in mobil, ruta + assert "max-width:100%" in mobil, ruta