diff --git a/scripts/ralph/archive/prd-20260112-094257.json b/scripts/ralph/archive/prd-20260112-094257.json
new file mode 100644
index 0000000..68ebd18
--- /dev/null
+++ b/scripts/ralph/archive/prd-20260112-094257.json
@@ -0,0 +1,609 @@
+{
+ "projectName": "mobile-ux-improvements",
+ "branchName": "ralph/bulk-receipt-upload",
+ "description": "Corectarea comportamentului de refresh pentru bulk upload, implementarea selecției multiple pe mobil cu interfață Android nativă, afișarea numelui fișierului pentru toate bonurile, și rezolvarea bug-urilor de UX raportate.",
+ "cssRules": {
+ "documentation": [
+ "docs/ONBOARDING_CSS.md",
+ "docs/DESIGN_TOKENS.md",
+ "docs/CSS_PATTERNS.md"
+ ],
+ "goldenRules": [
+ "Folosește DOAR design tokens - NICIODATĂ valori hardcodate",
+ "Verifică CSS_PATTERNS.md înainte de a scrie CSS nou",
+ "Testează în AMBELE teme (light + dark mode)",
+ "NICIODATĂ :deep() în componente (PrimeVue → vendor/)",
+ "NICIODATĂ duplicate CSS (write once, use everywhere)"
+ ],
+ "mobileLayoutTokens": {
+ "topBarHeight": "56px",
+ "bottomNavHeight": "56px",
+ "fabSize": "56px",
+ "fabBottomOffset": "72px",
+ "touchTargetMin": "48px"
+ },
+ "selectionModeColors": {
+ "selected": {
+ "background": "var(--blue-50)",
+ "border": "var(--blue-500)"
+ },
+ "selectedDark": {
+ "background": "var(--blue-900)",
+ "border": "var(--blue-400)"
+ }
+ }
+ },
+ "userStories": [
+ {
+ "id": "US-001",
+ "title": "Backend - Stocare Batch și Processing Status",
+ "description": "Ca developer, vreau să extind schema Receipt pentru a stoca informații de batch, pentru că am nevoie de persistență pentru tracking.",
+ "priority": 1,
+ "acceptanceCriteria": [
+ "Câmpuri noi în tabelul receipts: batch_id, processing_status, processing_error, file_hash, processing_started_at, processing_completed_at",
+ "Index pe batch_id, file_hash, processing_status",
+ "Migration reversibilă cu Alembic"
+ ],
+ "passes": true,
+ "notes": "Completed previously"
+ },
+ {
+ "id": "US-002",
+ "title": "Backend - Endpoint List cu Batch Info",
+ "description": "Ca developer, vreau să extind endpoint-ul GET /receipts pentru a include info de batch.",
+ "priority": 2,
+ "acceptanceCriteria": [
+ "Response include câmpurile de batch și processing pentru fiecare receipt",
+ "Filtrare pe processing_status și batch_id funcționează",
+ "Response include processing_stats"
+ ],
+ "passes": true,
+ "notes": "Completed previously"
+ },
+ {
+ "id": "US-003",
+ "title": "Backend - Reject Automat pentru Duplicate (File Hash)",
+ "description": "Ca sistem, vreau să detectez și să reject fișierele duplicate la upload.",
+ "priority": 3,
+ "acceptanceCriteria": [
+ "SHA-256 hash pentru duplicate detection",
+ "Response include existing_receipt_id pentru duplicates"
+ ],
+ "passes": true,
+ "notes": "Completed previously"
+ },
+ {
+ "id": "US-004",
+ "title": "Frontend - Drag Anywhere pentru Upload",
+ "description": "Ca utilizator, vreau să pot trage fișiere oriunde pe pagina de bonuri.",
+ "priority": 4,
+ "acceptanceCriteria": [
+ "DragDropOverlay.vue componentă",
+ "Global listeners cleanup în onUnmounted"
+ ],
+ "passes": true,
+ "notes": "Completed previously"
+ },
+ {
+ "id": "US-005",
+ "title": "Frontend - Row Grouping per Batch în DataTable",
+ "description": "Ca utilizator, vreau să văd bonurile din același batch grupate vizual.",
+ "priority": 5,
+ "acceptanceCriteria": [
+ "BatchGroupHeader.vue componentă",
+ "Grupuri sortate după processing_started_at descending"
+ ],
+ "passes": true,
+ "notes": "Completed previously"
+ },
+ {
+ "id": "US-006",
+ "title": "Frontend - Coloană Status Procesare în Tabel",
+ "description": "Ca utilizator, vreau să văd statusul fiecărui bon din batch într-o coloană dedicată.",
+ "priority": 6,
+ "acceptanceCriteria": [
+ "ProcessingStatusCell.vue componentă",
+ "Status updates în real-time via polling"
+ ],
+ "passes": true,
+ "notes": "Completed previously"
+ },
+ {
+ "id": "US-007",
+ "title": "Frontend - Mesaj Eroare Vizibil în Listă",
+ "description": "Ca utilizator, vreau să văd mesajul de eroare direct în listă.",
+ "priority": 7,
+ "acceptanceCriteria": [
+ "Truncated error message cu tooltip pentru full text"
+ ],
+ "passes": true,
+ "notes": "Completed previously"
+ },
+ {
+ "id": "US-008",
+ "title": "Frontend - Quick Filter Chips pentru Statusuri Procesare",
+ "description": "Ca utilizator, vreau filtre rapide pentru bonurile cu erori sau în procesare.",
+ "priority": 8,
+ "acceptanceCriteria": [
+ "Chips 'În procesare (N)' și 'Cu erori (N)' în status bar"
+ ],
+ "passes": true,
+ "notes": "Completed previously"
+ },
+ {
+ "id": "US-009",
+ "title": "Frontend - Lock Row în Procesare (Read-Only)",
+ "description": "Ca utilizator, vreau ca bonurile în procesare să fie read-only.",
+ "priority": 9,
+ "acceptanceCriteria": [
+ "Butoane și checkbox disabled pentru pending/processing",
+ "Tooltip pe butoane dezactivate"
+ ],
+ "passes": true,
+ "notes": "Completed previously"
+ },
+ {
+ "id": "US-010",
+ "title": "Frontend - Retry Individual și Retry All Failed",
+ "description": "Ca utilizator, vreau să pot re-procesa bonurile cu erori.",
+ "priority": 10,
+ "acceptanceCriteria": [
+ "Buton Reîncercă per rând failed",
+ "Buton Reîncercă toate erorile în BatchGroupHeader"
+ ],
+ "passes": true,
+ "notes": "Completed previously"
+ },
+ {
+ "id": "US-011",
+ "title": "Frontend - Auto-Resume Polling la Refresh/Revenire",
+ "description": "Ca utilizator, vreau ca procesarea să continue când revin.",
+ "priority": 11,
+ "acceptanceCriteria": [
+ "localStorage pentru active batch IDs",
+ "Auto-resume polling la onMounted"
+ ],
+ "passes": true,
+ "notes": "Completed previously"
+ },
+ {
+ "id": "US-012",
+ "title": "Backend - Auto-Cleanup Erori După 7 Zile",
+ "description": "Ca sistem, vreau să șterg automat bonurile cu erori după 7 zile.",
+ "priority": 12,
+ "acceptanceCriteria": [
+ "Background job pentru cleanup",
+ "Șterge receipts și attachments"
+ ],
+ "passes": true,
+ "notes": "Completed previously"
+ },
+ {
+ "id": "US-013",
+ "title": "Cleanup - Eliminare Pagină Separată Bulk Upload",
+ "description": "Ca developer, vreau să elimin pagina separată de bulk upload.",
+ "priority": 13,
+ "acceptanceCriteria": [
+ "Route redirect pentru backwards compatibility",
+ "Șterge componente nefolosite"
+ ],
+ "passes": true,
+ "notes": "Completed previously"
+ },
+ {
+ "id": "US-014",
+ "title": "Backend - Endpoint Cancel Job Individual",
+ "description": "Ca sistem, vreau un endpoint API pentru anularea unui job specific de procesare.",
+ "priority": 14,
+ "acceptanceCriteria": [
+ "POST /api/data-entry/bulk/cancel/{job_id} endpoint creat",
+ "Job-uri cu status completed/failed returnează 400 Bad Request",
+ "Job-uri pending/processing sunt marcate cancelled",
+ "Response include: {success, job_id, cancelled_at, message}"
+ ],
+ "passes": true,
+ "notes": "Completed previously"
+ },
+ {
+ "id": "US-015",
+ "title": "Backend - Endpoint Cancel Batch Complet",
+ "description": "Ca sistem, vreau un endpoint API pentru anularea tuturor job-urilor dintr-un batch.",
+ "priority": 15,
+ "acceptanceCriteria": [
+ "POST /api/data-entry/bulk/cancel-batch/{batch_id} endpoint creat",
+ "Response include: {success, batch_id, cancelled_count, skipped_count, message}"
+ ],
+ "passes": true,
+ "notes": "Completed previously"
+ },
+ {
+ "id": "US-016",
+ "title": "Frontend - Store Actions pentru Cancel",
+ "description": "Ca dezvoltator, vreau acțiuni în batchProgressStore pentru cancel.",
+ "priority": 16,
+ "acceptanceCriteria": [
+ "batchProgressStore.cancelJob(jobId) implementat",
+ "batchProgressStore.cancelBatch(batchId) implementat"
+ ],
+ "passes": true,
+ "notes": "Completed previously"
+ },
+ {
+ "id": "US-017",
+ "title": "Frontend - Afișare Jobs Pending în Tabel",
+ "description": "Ca utilizator, vreau să văd fișierele încărcate imediat în tabel.",
+ "priority": 17,
+ "acceptanceCriteria": [
+ "După upload success, rândurile pentru jobs apar instant în tabel",
+ "Tabelul poate randa atât Receipt-uri cât și BatchJob-uri"
+ ],
+ "passes": true,
+ "notes": "Completed previously"
+ },
+ {
+ "id": "US-018",
+ "title": "Frontend - Tranziție Job → Receipt când OCR Termină",
+ "description": "Ca sistem, vreau ca rândul de job să se transforme în receipt când OCR termină.",
+ "priority": 18,
+ "acceptanceCriteria": [
+ "Când polling detectează job completed cu receipt_id, rândul se actualizează",
+ "Tranziția e smooth - rândul NU dispare și reapare"
+ ],
+ "passes": true,
+ "notes": "Completed previously"
+ },
+ {
+ "id": "US-019",
+ "title": "Frontend - Animație Status Change",
+ "description": "Ca utilizator, vreau o indicație vizuală când un fișier își schimbă statusul.",
+ "priority": 19,
+ "acceptanceCriteria": [
+ "Badge-ul de status se schimbă cu CSS transition opacity 300ms",
+ "Highlight verde/roșu subtil pentru completed/failed"
+ ],
+ "passes": true,
+ "notes": "Completed previously"
+ },
+ {
+ "id": "US-020",
+ "title": "Frontend - Buton Cancel Individual pe Row",
+ "description": "Ca utilizator, vreau un buton Cancel pe fiecare fișier pending/processing.",
+ "priority": 20,
+ "acceptanceCriteria": [
+ "Fișierele pending/processing au icon Cancel (×)",
+ "După cancel success, rândul dispare cu fade-out 300ms"
+ ],
+ "passes": true,
+ "notes": "Completed previously"
+ },
+ {
+ "id": "US-021",
+ "title": "Frontend - Buton Cancel All în BatchGroupHeader",
+ "description": "Ca utilizator, vreau un buton pentru a anula toate fișierele dintr-un batch.",
+ "priority": 21,
+ "acceptanceCriteria": [
+ "BatchGroupHeader are buton 'Anulează tot' pentru batch-uri cu pending/processing jobs",
+ "Job-urile completed/failed rămân vizibile"
+ ],
+ "passes": true,
+ "notes": "Completed previously"
+ },
+ {
+ "id": "US-022",
+ "title": "Frontend - Checkbox Disabled pentru Jobs în Procesare",
+ "description": "Ca utilizator, vreau ca checkbox-urile să fie disabled pentru fișiere în procesare.",
+ "priority": 22,
+ "acceptanceCriteria": [
+ "Checkbox-ul este disabled pentru rânduri de tip job",
+ "Select All NU include job-urile în procesare"
+ ],
+ "passes": true,
+ "notes": "Completed previously"
+ },
+ {
+ "id": "US-023",
+ "title": "Frontend - Restore Jobs la Refresh/Revenire",
+ "description": "Ca utilizator, vreau să văd job-urile pending când revin pe pagină.",
+ "priority": 23,
+ "acceptanceCriteria": [
+ "La onMounted, verifică localStorage pentru active batch IDs",
+ "Job-urile pending/processing apar în tabel"
+ ],
+ "passes": true,
+ "notes": "Completed previously"
+ },
+ {
+ "id": "US-024",
+ "title": "Backend - Endpoint Bulk Delete",
+ "description": "Ca frontend, vreau să pot trimite o listă de ID-uri pentru ștergere.",
+ "priority": 24,
+ "acceptanceCriteria": [
+ "DELETE /api/data-entry/receipts/bulk acceptă body: { ids: [...] }",
+ "Returnează partial success response"
+ ],
+ "passes": true,
+ "notes": "Completed previously"
+ },
+ {
+ "id": "US-025",
+ "title": "Frontend - Buton Șterge în Bulk Actions Bar",
+ "description": "Ca utilizator, vreau să văd un buton 'Șterge' când am selecții.",
+ "priority": 25,
+ "acceptanceCriteria": [
+ "Butonul 'Șterge' apare în bulk actions bar când selectedReceipts.length > 0",
+ "Butonul are icon pi-trash și severity danger"
+ ],
+ "passes": true,
+ "notes": "Completed previously"
+ },
+ {
+ "id": "US-026",
+ "title": "Frontend - Dialog Confirmare Ștergere Bulk",
+ "description": "Ca utilizator, vreau o confirmare înainte de ștergere.",
+ "priority": 26,
+ "acceptanceCriteria": [
+ "La click pe 'Șterge', apare dialog cu mesaj confirmare",
+ "Dialog-ul folosește PrimeVue ConfirmDialog"
+ ],
+ "passes": true,
+ "notes": "Completed previously"
+ },
+ {
+ "id": "US-027",
+ "title": "Frontend - Bulk Delete cu Partial Success Toast",
+ "description": "Ca utilizator, vreau să văd rezultatul ștergerii.",
+ "priority": 27,
+ "acceptanceCriteria": [
+ "Toast arată rezultatul: 'X bonuri șterse'",
+ "Bonurile șterse dispar instant din listă",
+ "Selecția se golește după ștergere"
+ ],
+ "passes": true,
+ "notes": "Completed previously"
+ },
+ {
+ "id": "US-028",
+ "title": "Frontend - Navigare la Pagina Anterioară când Lista Devine Goală",
+ "description": "Ca utilizator, vreau să fiu redirecționat când șterg toate bonurile de pe pagină.",
+ "priority": 28,
+ "acceptanceCriteria": [
+ "După bulk delete, dacă lista devine goală și currentPage > 1, navigare la pagina anterioară",
+ "Dacă eram pe pagina 1, afișează empty state"
+ ],
+ "passes": true,
+ "notes": "Completed previously"
+ },
+ {
+ "id": "US-029",
+ "title": "Frontend - Metodă updateReceiptInPlace în Store",
+ "description": "Ca frontend, vreau să actualizez un singur rând fără să re-renderez toată lista.",
+ "priority": 29,
+ "acceptanceCriteria": [
+ "Metoda updateReceiptInPlace(receiptId, updates) în receiptsStore",
+ "Object.assign pentru updates, nu înlocuire array"
+ ],
+ "passes": true,
+ "notes": "Completed previously"
+ },
+ {
+ "id": "US-030",
+ "title": "Backend - SSE Endpoint pentru Status Updates",
+ "description": "Ca frontend, vreau să primesc notificări real-time despre schimbări de status.",
+ "priority": 30,
+ "acceptanceCriteria": [
+ "GET /api/data-entry/receipts/sse/status returnează SSE stream",
+ "Format eveniment: {receipt_id, status, processing_status}"
+ ],
+ "passes": true,
+ "notes": "Completed previously"
+ },
+ {
+ "id": "US-031",
+ "title": "Frontend - SSE Client Service",
+ "description": "Ca frontend, vreau să mă conectez la SSE și să actualizez rândurile individual.",
+ "priority": 31,
+ "acceptanceCriteria": [
+ "sseService.js cu connect(), disconnect(), onStatusChange()",
+ "Folosește native EventSource API"
+ ],
+ "passes": true,
+ "notes": "Completed previously"
+ },
+ {
+ "id": "US-032",
+ "title": "Frontend - Înlocuire Polling cu SSE",
+ "description": "Ca frontend, vreau să folosesc SSE în loc de polling.",
+ "priority": 32,
+ "acceptanceCriteria": [
+ "SSE în loc de setInterval pentru auto-refresh",
+ "La primire eveniment SSE, apelează updateReceiptInPlace()"
+ ],
+ "passes": true,
+ "notes": "Completed previously"
+ },
+ {
+ "id": "US-033",
+ "title": "Frontend - Graceful Degradation la SSE Failure",
+ "description": "Ca utilizator, vreau ca aplicația să funcționeze și fără SSE.",
+ "priority": 33,
+ "acceptanceCriteria": [
+ "Dacă SSE fail, activează fallback la polling clasic",
+ "Retry SSE periodic (la 30s)"
+ ],
+ "passes": true,
+ "notes": "Completed previously"
+ },
+ {
+ "id": "US-034",
+ "title": "Fix - Refresh Individual vs Refresh Total",
+ "description": "Ca utilizator, vreau ca bonurile să se actualizeze individual fără să se reîncarce toată lista, pentru că vreau să văd progresul în timp real fără să pierd poziția.",
+ "priority": 34,
+ "acceptanceCriteria": [
+ "SSE handler NU apelează store.fetchReceipts() când un receipt nu este în pagina curentă",
+ "Verifică dacă receipt-ul aparține unui batch activ și îl adaugă local dacă nu există",
+ "Ordinea bonurilor din batch rămâne stabilă (nu se reordonează)",
+ "npm run typecheck passes",
+ "Verify in browser: uploadează 5 bonuri, nu se reîncarcă pagina între procesări"
+ ],
+ "technicalNotes": "Modificare în handleSSEStatusChange din ReceiptsListView.vue:2397. Când receipt nu e găsit: verifică dacă batch_id e în batchProgressStore, apoi fetch individual receipt și inserează local în poziția corectă.",
+ "passes": true,
+ "notes": "Completed in iteration 1"
+ },
+ {
+ "id": "US-035",
+ "title": "Fix - Bonuri cu Eroare Rămân în Listă",
+ "description": "Ca utilizator, vreau ca bonurile cu eroare de procesare să rămână vizibile în listă, pentru că vreau să le pot edita manual sau să le șterg.",
+ "priority": 35,
+ "acceptanceCriteria": [
+ "Bonurile cu processing_status='failed' NU sunt eliminate din view după refresh",
+ "Eroarea de extragere dată/sumă afișează bonul cu status 'Eroare' și buton 'Editează'",
+ "Link rapid 'Editează manual' duce la formularul de editare cu datele disponibile pre-populate",
+ "Bonurile failed au highlight vizual (roșu subtil) pentru identificare ușoară",
+ "npm run typecheck passes",
+ "Verify in browser: bon cu eroare OCR rămâne în listă și poate fi editat"
+ ],
+ "technicalNotes": "Bonurile cu eroare ar trebui să aibă status='draft' și processing_status='failed'. Nu se șterg la refresh, doar se actualizează in-place.",
+ "passes": true,
+ "notes": "Completed in iteration 2"
+ },
+ {
+ "id": "US-036",
+ "title": "Afișare Nume Fișier pentru Toate Bonurile",
+ "description": "Ca utilizator, vreau să văd numele fișierului original pentru bonurile procesate, pentru că vreau să identific care bon corespunde cărui fișier uploadat.",
+ "priority": 36,
+ "acceptanceCriteria": [
+ "Coloana 'Fișier' afișează original_filename și pentru receipt-uri completate, nu doar pentru job-uri",
+ "Pe mobil, numele fișierului apare sub partener (font mic, gri)",
+ "Tooltip pe desktop arată numele complet dacă e trunchiat",
+ "Dacă receipt nu are original_filename, afișează '-'",
+ "npm run typecheck passes",
+ "Verify in browser: bon procesat afișează numele fișierului original"
+ ],
+ "technicalNotes": "Backend trebuie să populeze original_filename pe receipt din job-ul OCR. Verifică că auto-save service copiază filename din job la receipt.",
+ "passes": true,
+ "notes": "Completed in iteration 3"
+ },
+ {
+ "id": "US-037",
+ "title": "Fix - Upload Nu Mai Face Refresh Automat",
+ "description": "Ca utilizator, vreau ca selectarea fișierelor să nu reîncarce pagina, pentru că pierd fișierele selectate înainte să apăs 'Procesează'.",
+ "priority": 37,
+ "acceptanceCriteria": [
+ "Selectarea fișierelor via input NU declanșează refresh/reload pagină",
+ "Fișierele selectate rămân în listă până la submit explicit",
+ "Comportament identic pe desktop și mobil (Chrome, Safari)",
+ "Nu există race condition între clonarea fișierelor și resetarea input-ului",
+ "npm run typecheck passes",
+ "Verify on mobile: selectează 5 fișiere, toate rămân în listă"
+ ],
+ "technicalNotes": "Bug probabil în onBulkFileInputChange sau în interacțiunea cu store. Verifică că nu există watchers care declanșează refresh la schimbări de state. Test specific pe Chrome Android - vezi gotcha din CLAUDE.md despre File API.",
+ "passes": true,
+ "notes": "Completed in iteration 4"
+ },
+ {
+ "id": "US-038",
+ "title": "Mobile - Selecție Multiplă prin Long-Press",
+ "description": "Ca utilizator mobil, vreau să selectez bonuri prin apăsare lungă, pentru că vreau să pot șterge sau acționa asupra mai multor bonuri simultan.",
+ "priority": 38,
+ "acceptanceCriteria": [
+ "Long-press (500ms) pe un card activează modul de selecție",
+ "Card-ul selectat primește checkmark și background diferit (var(--blue-50))",
+ "După activare, tap simplu pe alte carduri le adaugă/elimină din selecție",
+ "Tap în afara cardurilor dezactivează modul selecție",
+ "Header contextual arată numărul de elemente selectate",
+ "npm run typecheck passes",
+ "Verify on mobile: long-press selectează, tap adaugă la selecție"
+ ],
+ "technicalNotes": "Implementare cu setTimeout(500ms) pe touchstart, clear pe touchend/touchmove. CSS: .receipt-card.selected { background: var(--blue-50); border-color: var(--blue-500); }",
+ "passes": true,
+ "notes": "Completed in iteration 5"
+ },
+ {
+ "id": "US-039",
+ "title": "Mobile - Select All și Buton Ștergere",
+ "description": "Ca utilizator mobil, vreau să am butoane 'Selectează tot' și 'Șterge' în modul selecție, pentru că vreau să pot șterge rapid mai multe bonuri.",
+ "priority": 39,
+ "acceptanceCriteria": [
+ "În modul selecție, apare top bar contextual cu: număr selectate, buton 'Selectează tot', buton X pentru ieșire",
+ "Apare bottom bar cu buton 'Șterge' (roșu, icon coș)",
+ "'Selectează tot' selectează toate bonurile din pagina curentă",
+ "Buton 'Șterge' afișează confirmare înainte de ștergere",
+ "După ștergere, modul selecție se dezactivează",
+ "npm run typecheck passes",
+ "Verify on mobile: select all + delete funcționează"
+ ],
+ "technicalNotes": "Top bar: position: sticky; top: 0. Bottom bar: position: fixed; bottom: 0. Animație slide-in pentru bars.",
+ "passes": true,
+ "notes": "Completed in iteration 6"
+ },
+ {
+ "id": "US-040",
+ "title": "Mobile - Layout Android Nativ pentru Lista Bonuri",
+ "description": "Ca utilizator mobil, vreau o interfață similară cu aplicațiile Android native, pentru că vreau experiență familiară și intuitivă.",
+ "priority": 40,
+ "acceptanceCriteria": [
+ "Top Bar fixă cu: hamburger/back (stânga), titlu centrat, search+filter+more (dreapta)",
+ "Filter Chips sub top bar (orizontal scrollabil): Toate, Ciorne, În așteptare, Validate, Respinse",
+ "Bottom Navigation fixă cu 4 tab-uri: Bonuri (activ), Upload, Rapoarte, Setări",
+ "FAB (56x56px) în colț dreapta jos, 16px de la margine, 72px de la bottom",
+ "FAB se ascunde când scroll în jos, apare când scroll în sus",
+ "Lista ocupă spațiul dintre top bar și bottom nav",
+ "npm run typecheck passes",
+ "Verify on mobile: layout similar cu Gmail/WhatsApp"
+ ],
+ "technicalNotes": "CSS: .mobile-top-bar { position: fixed; top: 0; height: 56px; z-index: 1000 }. .mobile-bottom-nav { position: fixed; bottom: 0; height: 56px }. .mobile-fab { position: fixed; bottom: 72px; right: 16px; width: 56px; border-radius: 16px }",
+ "passes": true,
+ "notes": "Completed in iteration 7"
+ },
+ {
+ "id": "US-041",
+ "title": "Mobile - Layout Android pentru Editare/Creare Bon",
+ "description": "Ca utilizator mobil, vreau interfață de editare bon similară cu compose email în Gmail, pentru că vreau butoane de acțiune accesibile și layout familiar.",
+ "priority": 41,
+ "acceptanceCriteria": [
+ "Top Bar cu: X/back (stânga), titlu centrat, attach+save icons (dreapta)",
+ "Content Area scrollabilă cu form fields 100% width",
+ "Bottom Action Bar fixă cu: 'Salvează Ciornă' (secondary), 'Trimite pentru Validare' (primary)",
+ "Keyboard-aware: bottom bar se mută deasupra tastaturii",
+ "npm run typecheck passes",
+ "Verify on mobile: layout similar cu Gmail compose"
+ ],
+ "technicalNotes": "CSS: .mobile-receipt-form { padding-bottom: 80px }. .mobile-form-bottom-bar { position: fixed; bottom: 0; display: flex; gap: var(--space-sm) }. Butoane cu flex: 1 pentru width egal.",
+ "passes": true,
+ "notes": "Completed in iteration 8"
+ },
+ {
+ "id": "US-042",
+ "title": "Mobile - Layout Android pentru Vizualizare Bon",
+ "description": "Ca utilizator mobil, vreau interfață de vizualizare bon similară cu view email în Gmail, pentru că vreau acțiuni rapide și navigare ușoară.",
+ "priority": 42,
+ "acceptanceCriteria": [
+ "Top Bar cu: back arrow (stânga), edit+delete+more icons (dreapta)",
+ "Content Area cu detalii bon (read-only)",
+ "Bottom Action Bar cu butoane contextuale: DRAFT→Editează/Trimite, PENDING→Validează/Respinge, APPROVED→Anulează",
+ "npm run typecheck passes",
+ "Verify on mobile: acțiuni accesibile din bottom bar"
+ ],
+ "technicalNotes": "Refolosește stilurile din US-041. Butoanele din bottom bar se schimbă dinamic bazat pe receipt.status.",
+ "passes": true,
+ "notes": "Completed in iteration 9"
+ },
+ {
+ "id": "US-043",
+ "title": "Păstrare Ordine Bonuri la Refresh",
+ "description": "Ca utilizator, vreau ca bonurile să rămână în ordinea în care au fost uploadate, pentru că vreau să urmăresc progresul fiecărui bon uploadat.",
+ "priority": 43,
+ "acceptanceCriteria": [
+ "Bonurile din același batch păstrează ordinea de upload (nu se reordonează)",
+ "Un bon finalizat rămâne în aceeași poziție vizuală, nu sare la sfârșit",
+ "SSE updates modifică status-ul in-place, fără a muta rândul",
+ "Refresh manual poate reordona, dar SSE updates nu",
+ "npm run typecheck passes",
+ "Verify in browser: bon procesat nu își schimbă poziția în listă"
+ ],
+ "technicalNotes": "Lista trebuie sortată by created_at DESC sau by batch order, nu by last_modified. updateReceiptInPlace din store NU trebuie să reordoneze array-ul.",
+ "passes": true,
+ "notes": "Completed in iteration 10"
+ }
+ ]
+}
diff --git a/scripts/ralph/prd.json b/scripts/ralph/prd.json
index 68ebd18..11e8b87 100644
--- a/scripts/ralph/prd.json
+++ b/scripts/ralph/prd.json
@@ -1,19 +1,23 @@
{
- "projectName": "mobile-ux-improvements",
- "branchName": "ralph/bulk-receipt-upload",
- "description": "Corectarea comportamentului de refresh pentru bulk upload, implementarea selecției multiple pe mobil cu interfață Android nativă, afișarea numelui fișierului pentru toate bonurile, și rezolvarea bug-urilor de UX raportate.",
+ "projectName": "unified-mobile-material-design",
+ "branchName": "ralph/unified-mobile-md",
+ "description": "Extinderea interfeței Material Design la toate paginile aplicației în modul mobil pentru consistență UI/UX",
"cssRules": {
"documentation": [
"docs/ONBOARDING_CSS.md",
"docs/DESIGN_TOKENS.md",
- "docs/CSS_PATTERNS.md"
+ "docs/CSS_PATTERNS.md",
+ "docs/MOBILE_PATTERNS.md"
],
"goldenRules": [
"Folosește DOAR design tokens - NICIODATĂ valori hardcodate",
"Verifică CSS_PATTERNS.md înainte de a scrie CSS nou",
"Testează în AMBELE teme (light + dark mode)",
"NICIODATĂ :deep() în componente (PrimeVue → vendor/)",
- "NICIODATĂ duplicate CSS (write once, use everywhere)"
+ "NICIODATĂ duplicate CSS (write once, use everywhere)",
+ "Mobile: toate paginile folosesc MobileTopBar + MobileBottomNav",
+ "Mobile: filtrele se pun în BottomSheet, NU inline",
+ "Mobile: selecția afișează acțiuni în footer, NU în header"
],
"mobileLayoutTokens": {
"topBarHeight": "56px",
@@ -21,589 +25,316 @@
"fabSize": "56px",
"fabBottomOffset": "72px",
"touchTargetMin": "48px"
- },
- "selectionModeColors": {
- "selected": {
- "background": "var(--blue-50)",
- "border": "var(--blue-500)"
- },
- "selectedDark": {
- "background": "var(--blue-900)",
- "border": "var(--blue-400)"
- }
}
},
"userStories": [
{
- "id": "US-001",
- "title": "Backend - Stocare Batch și Processing Status",
- "description": "Ca developer, vreau să extind schema Receipt pentru a stoca informații de batch, pentru că am nevoie de persistență pentru tracking.",
+ "id": "US-101a",
+ "title": "Creare MobileTopBar.vue component",
+ "description": "Ca developer vreau componentă MobileTopBar.vue extrasă din ReceiptsListView pentru reutilizare",
"priority": 1,
"acceptanceCriteria": [
- "Câmpuri noi în tabelul receipts: batch_id, processing_status, processing_error, file_hash, processing_started_at, processing_completed_at",
- "Index pe batch_id, file_hash, processing_status",
- "Migration reversibilă cu Alembic"
+ "Componentă src/shared/components/mobile/MobileTopBar.vue creată",
+ "Props: title (string), showBack (boolean), showMenu (boolean), actions (array)",
+ "Emit events: menu-click, back-click, action-click",
+ "Stiluri CSS extrase din ReceiptsListView (.mobile-top-bar)",
+ "Dark mode support cu [data-theme='dark']",
+ "npm run build passes"
],
"passes": true,
- "notes": "Completed previously"
- },
- {
- "id": "US-002",
- "title": "Backend - Endpoint List cu Batch Info",
- "description": "Ca developer, vreau să extind endpoint-ul GET /receipts pentru a include info de batch.",
- "priority": 2,
- "acceptanceCriteria": [
- "Response include câmpurile de batch și processing pentru fiecare receipt",
- "Filtrare pe processing_status și batch_id funcționează",
- "Response include processing_stats"
- ],
- "passes": true,
- "notes": "Completed previously"
- },
- {
- "id": "US-003",
- "title": "Backend - Reject Automat pentru Duplicate (File Hash)",
- "description": "Ca sistem, vreau să detectez și să reject fișierele duplicate la upload.",
- "priority": 3,
- "acceptanceCriteria": [
- "SHA-256 hash pentru duplicate detection",
- "Response include existing_receipt_id pentru duplicates"
- ],
- "passes": true,
- "notes": "Completed previously"
- },
- {
- "id": "US-004",
- "title": "Frontend - Drag Anywhere pentru Upload",
- "description": "Ca utilizator, vreau să pot trage fișiere oriunde pe pagina de bonuri.",
- "priority": 4,
- "acceptanceCriteria": [
- "DragDropOverlay.vue componentă",
- "Global listeners cleanup în onUnmounted"
- ],
- "passes": true,
- "notes": "Completed previously"
- },
- {
- "id": "US-005",
- "title": "Frontend - Row Grouping per Batch în DataTable",
- "description": "Ca utilizator, vreau să văd bonurile din același batch grupate vizual.",
- "priority": 5,
- "acceptanceCriteria": [
- "BatchGroupHeader.vue componentă",
- "Grupuri sortate după processing_started_at descending"
- ],
- "passes": true,
- "notes": "Completed previously"
- },
- {
- "id": "US-006",
- "title": "Frontend - Coloană Status Procesare în Tabel",
- "description": "Ca utilizator, vreau să văd statusul fiecărui bon din batch într-o coloană dedicată.",
- "priority": 6,
- "acceptanceCriteria": [
- "ProcessingStatusCell.vue componentă",
- "Status updates în real-time via polling"
- ],
- "passes": true,
- "notes": "Completed previously"
- },
- {
- "id": "US-007",
- "title": "Frontend - Mesaj Eroare Vizibil în Listă",
- "description": "Ca utilizator, vreau să văd mesajul de eroare direct în listă.",
- "priority": 7,
- "acceptanceCriteria": [
- "Truncated error message cu tooltip pentru full text"
- ],
- "passes": true,
- "notes": "Completed previously"
- },
- {
- "id": "US-008",
- "title": "Frontend - Quick Filter Chips pentru Statusuri Procesare",
- "description": "Ca utilizator, vreau filtre rapide pentru bonurile cu erori sau în procesare.",
- "priority": 8,
- "acceptanceCriteria": [
- "Chips 'În procesare (N)' și 'Cu erori (N)' în status bar"
- ],
- "passes": true,
- "notes": "Completed previously"
- },
- {
- "id": "US-009",
- "title": "Frontend - Lock Row în Procesare (Read-Only)",
- "description": "Ca utilizator, vreau ca bonurile în procesare să fie read-only.",
- "priority": 9,
- "acceptanceCriteria": [
- "Butoane și checkbox disabled pentru pending/processing",
- "Tooltip pe butoane dezactivate"
- ],
- "passes": true,
- "notes": "Completed previously"
- },
- {
- "id": "US-010",
- "title": "Frontend - Retry Individual și Retry All Failed",
- "description": "Ca utilizator, vreau să pot re-procesa bonurile cu erori.",
- "priority": 10,
- "acceptanceCriteria": [
- "Buton Reîncercă per rând failed",
- "Buton Reîncercă toate erorile în BatchGroupHeader"
- ],
- "passes": true,
- "notes": "Completed previously"
- },
- {
- "id": "US-011",
- "title": "Frontend - Auto-Resume Polling la Refresh/Revenire",
- "description": "Ca utilizator, vreau ca procesarea să continue când revin.",
- "priority": 11,
- "acceptanceCriteria": [
- "localStorage pentru active batch IDs",
- "Auto-resume polling la onMounted"
- ],
- "passes": true,
- "notes": "Completed previously"
- },
- {
- "id": "US-012",
- "title": "Backend - Auto-Cleanup Erori După 7 Zile",
- "description": "Ca sistem, vreau să șterg automat bonurile cu erori după 7 zile.",
- "priority": 12,
- "acceptanceCriteria": [
- "Background job pentru cleanup",
- "Șterge receipts și attachments"
- ],
- "passes": true,
- "notes": "Completed previously"
- },
- {
- "id": "US-013",
- "title": "Cleanup - Eliminare Pagină Separată Bulk Upload",
- "description": "Ca developer, vreau să elimin pagina separată de bulk upload.",
- "priority": 13,
- "acceptanceCriteria": [
- "Route redirect pentru backwards compatibility",
- "Șterge componente nefolosite"
- ],
- "passes": true,
- "notes": "Completed previously"
- },
- {
- "id": "US-014",
- "title": "Backend - Endpoint Cancel Job Individual",
- "description": "Ca sistem, vreau un endpoint API pentru anularea unui job specific de procesare.",
- "priority": 14,
- "acceptanceCriteria": [
- "POST /api/data-entry/bulk/cancel/{job_id} endpoint creat",
- "Job-uri cu status completed/failed returnează 400 Bad Request",
- "Job-uri pending/processing sunt marcate cancelled",
- "Response include: {success, job_id, cancelled_at, message}"
- ],
- "passes": true,
- "notes": "Completed previously"
- },
- {
- "id": "US-015",
- "title": "Backend - Endpoint Cancel Batch Complet",
- "description": "Ca sistem, vreau un endpoint API pentru anularea tuturor job-urilor dintr-un batch.",
- "priority": 15,
- "acceptanceCriteria": [
- "POST /api/data-entry/bulk/cancel-batch/{batch_id} endpoint creat",
- "Response include: {success, batch_id, cancelled_count, skipped_count, message}"
- ],
- "passes": true,
- "notes": "Completed previously"
- },
- {
- "id": "US-016",
- "title": "Frontend - Store Actions pentru Cancel",
- "description": "Ca dezvoltator, vreau acțiuni în batchProgressStore pentru cancel.",
- "priority": 16,
- "acceptanceCriteria": [
- "batchProgressStore.cancelJob(jobId) implementat",
- "batchProgressStore.cancelBatch(batchId) implementat"
- ],
- "passes": true,
- "notes": "Completed previously"
- },
- {
- "id": "US-017",
- "title": "Frontend - Afișare Jobs Pending în Tabel",
- "description": "Ca utilizator, vreau să văd fișierele încărcate imediat în tabel.",
- "priority": 17,
- "acceptanceCriteria": [
- "După upload success, rândurile pentru jobs apar instant în tabel",
- "Tabelul poate randa atât Receipt-uri cât și BatchJob-uri"
- ],
- "passes": true,
- "notes": "Completed previously"
- },
- {
- "id": "US-018",
- "title": "Frontend - Tranziție Job → Receipt când OCR Termină",
- "description": "Ca sistem, vreau ca rândul de job să se transforme în receipt când OCR termină.",
- "priority": 18,
- "acceptanceCriteria": [
- "Când polling detectează job completed cu receipt_id, rândul se actualizează",
- "Tranziția e smooth - rândul NU dispare și reapare"
- ],
- "passes": true,
- "notes": "Completed previously"
- },
- {
- "id": "US-019",
- "title": "Frontend - Animație Status Change",
- "description": "Ca utilizator, vreau o indicație vizuală când un fișier își schimbă statusul.",
- "priority": 19,
- "acceptanceCriteria": [
- "Badge-ul de status se schimbă cu CSS transition opacity 300ms",
- "Highlight verde/roșu subtil pentru completed/failed"
- ],
- "passes": true,
- "notes": "Completed previously"
- },
- {
- "id": "US-020",
- "title": "Frontend - Buton Cancel Individual pe Row",
- "description": "Ca utilizator, vreau un buton Cancel pe fiecare fișier pending/processing.",
- "priority": 20,
- "acceptanceCriteria": [
- "Fișierele pending/processing au icon Cancel (×)",
- "După cancel success, rândul dispare cu fade-out 300ms"
- ],
- "passes": true,
- "notes": "Completed previously"
- },
- {
- "id": "US-021",
- "title": "Frontend - Buton Cancel All în BatchGroupHeader",
- "description": "Ca utilizator, vreau un buton pentru a anula toate fișierele dintr-un batch.",
- "priority": 21,
- "acceptanceCriteria": [
- "BatchGroupHeader are buton 'Anulează tot' pentru batch-uri cu pending/processing jobs",
- "Job-urile completed/failed rămân vizibile"
- ],
- "passes": true,
- "notes": "Completed previously"
- },
- {
- "id": "US-022",
- "title": "Frontend - Checkbox Disabled pentru Jobs în Procesare",
- "description": "Ca utilizator, vreau ca checkbox-urile să fie disabled pentru fișiere în procesare.",
- "priority": 22,
- "acceptanceCriteria": [
- "Checkbox-ul este disabled pentru rânduri de tip job",
- "Select All NU include job-urile în procesare"
- ],
- "passes": true,
- "notes": "Completed previously"
- },
- {
- "id": "US-023",
- "title": "Frontend - Restore Jobs la Refresh/Revenire",
- "description": "Ca utilizator, vreau să văd job-urile pending când revin pe pagină.",
- "priority": 23,
- "acceptanceCriteria": [
- "La onMounted, verifică localStorage pentru active batch IDs",
- "Job-urile pending/processing apar în tabel"
- ],
- "passes": true,
- "notes": "Completed previously"
- },
- {
- "id": "US-024",
- "title": "Backend - Endpoint Bulk Delete",
- "description": "Ca frontend, vreau să pot trimite o listă de ID-uri pentru ștergere.",
- "priority": 24,
- "acceptanceCriteria": [
- "DELETE /api/data-entry/receipts/bulk acceptă body: { ids: [...] }",
- "Returnează partial success response"
- ],
- "passes": true,
- "notes": "Completed previously"
- },
- {
- "id": "US-025",
- "title": "Frontend - Buton Șterge în Bulk Actions Bar",
- "description": "Ca utilizator, vreau să văd un buton 'Șterge' când am selecții.",
- "priority": 25,
- "acceptanceCriteria": [
- "Butonul 'Șterge' apare în bulk actions bar când selectedReceipts.length > 0",
- "Butonul are icon pi-trash și severity danger"
- ],
- "passes": true,
- "notes": "Completed previously"
- },
- {
- "id": "US-026",
- "title": "Frontend - Dialog Confirmare Ștergere Bulk",
- "description": "Ca utilizator, vreau o confirmare înainte de ștergere.",
- "priority": 26,
- "acceptanceCriteria": [
- "La click pe 'Șterge', apare dialog cu mesaj confirmare",
- "Dialog-ul folosește PrimeVue ConfirmDialog"
- ],
- "passes": true,
- "notes": "Completed previously"
- },
- {
- "id": "US-027",
- "title": "Frontend - Bulk Delete cu Partial Success Toast",
- "description": "Ca utilizator, vreau să văd rezultatul ștergerii.",
- "priority": 27,
- "acceptanceCriteria": [
- "Toast arată rezultatul: 'X bonuri șterse'",
- "Bonurile șterse dispar instant din listă",
- "Selecția se golește după ștergere"
- ],
- "passes": true,
- "notes": "Completed previously"
- },
- {
- "id": "US-028",
- "title": "Frontend - Navigare la Pagina Anterioară când Lista Devine Goală",
- "description": "Ca utilizator, vreau să fiu redirecționat când șterg toate bonurile de pe pagină.",
- "priority": 28,
- "acceptanceCriteria": [
- "După bulk delete, dacă lista devine goală și currentPage > 1, navigare la pagina anterioară",
- "Dacă eram pe pagina 1, afișează empty state"
- ],
- "passes": true,
- "notes": "Completed previously"
- },
- {
- "id": "US-029",
- "title": "Frontend - Metodă updateReceiptInPlace în Store",
- "description": "Ca frontend, vreau să actualizez un singur rând fără să re-renderez toată lista.",
- "priority": 29,
- "acceptanceCriteria": [
- "Metoda updateReceiptInPlace(receiptId, updates) în receiptsStore",
- "Object.assign pentru updates, nu înlocuire array"
- ],
- "passes": true,
- "notes": "Completed previously"
- },
- {
- "id": "US-030",
- "title": "Backend - SSE Endpoint pentru Status Updates",
- "description": "Ca frontend, vreau să primesc notificări real-time despre schimbări de status.",
- "priority": 30,
- "acceptanceCriteria": [
- "GET /api/data-entry/receipts/sse/status returnează SSE stream",
- "Format eveniment: {receipt_id, status, processing_status}"
- ],
- "passes": true,
- "notes": "Completed previously"
- },
- {
- "id": "US-031",
- "title": "Frontend - SSE Client Service",
- "description": "Ca frontend, vreau să mă conectez la SSE și să actualizez rândurile individual.",
- "priority": 31,
- "acceptanceCriteria": [
- "sseService.js cu connect(), disconnect(), onStatusChange()",
- "Folosește native EventSource API"
- ],
- "passes": true,
- "notes": "Completed previously"
- },
- {
- "id": "US-032",
- "title": "Frontend - Înlocuire Polling cu SSE",
- "description": "Ca frontend, vreau să folosesc SSE în loc de polling.",
- "priority": 32,
- "acceptanceCriteria": [
- "SSE în loc de setInterval pentru auto-refresh",
- "La primire eveniment SSE, apelează updateReceiptInPlace()"
- ],
- "passes": true,
- "notes": "Completed previously"
- },
- {
- "id": "US-033",
- "title": "Frontend - Graceful Degradation la SSE Failure",
- "description": "Ca utilizator, vreau ca aplicația să funcționeze și fără SSE.",
- "priority": 33,
- "acceptanceCriteria": [
- "Dacă SSE fail, activează fallback la polling clasic",
- "Retry SSE periodic (la 30s)"
- ],
- "passes": true,
- "notes": "Completed previously"
- },
- {
- "id": "US-034",
- "title": "Fix - Refresh Individual vs Refresh Total",
- "description": "Ca utilizator, vreau ca bonurile să se actualizeze individual fără să se reîncarce toată lista, pentru că vreau să văd progresul în timp real fără să pierd poziția.",
- "priority": 34,
- "acceptanceCriteria": [
- "SSE handler NU apelează store.fetchReceipts() când un receipt nu este în pagina curentă",
- "Verifică dacă receipt-ul aparține unui batch activ și îl adaugă local dacă nu există",
- "Ordinea bonurilor din batch rămâne stabilă (nu se reordonează)",
- "npm run typecheck passes",
- "Verify in browser: uploadează 5 bonuri, nu se reîncarcă pagina între procesări"
- ],
- "technicalNotes": "Modificare în handleSSEStatusChange din ReceiptsListView.vue:2397. Când receipt nu e găsit: verifică dacă batch_id e în batchProgressStore, apoi fetch individual receipt și inserează local în poziția corectă.",
- "passes": true,
"notes": "Completed in iteration 1"
},
{
- "id": "US-035",
- "title": "Fix - Bonuri cu Eroare Rămân în Listă",
- "description": "Ca utilizator, vreau ca bonurile cu eroare de procesare să rămână vizibile în listă, pentru că vreau să le pot edita manual sau să le șterg.",
- "priority": 35,
+ "id": "US-101b",
+ "title": "Creare MobileBottomNav.vue component",
+ "description": "Ca developer vreau componentă MobileBottomNav.vue pentru navigarea de jos pe mobil",
+ "priority": 2,
"acceptanceCriteria": [
- "Bonurile cu processing_status='failed' NU sunt eliminate din view după refresh",
- "Eroarea de extragere dată/sumă afișează bonul cu status 'Eroare' și buton 'Editează'",
- "Link rapid 'Editează manual' duce la formularul de editare cu datele disponibile pre-populate",
- "Bonurile failed au highlight vizual (roșu subtil) pentru identificare ușoară",
- "npm run typecheck passes",
- "Verify in browser: bon cu eroare OCR rămâne în listă și poate fi editat"
+ "Componentă src/shared/components/mobile/MobileBottomNav.vue creată",
+ "Props: items (array of {to, icon, label, active})",
+ "4 linkuri: Bonuri, Upload, Rapoarte, Setări",
+ "Stiluri CSS extrase din ReceiptsListView (.mobile-bottom-nav)",
+ "router-link pentru navigare",
+ "npm run build passes"
],
- "technicalNotes": "Bonurile cu eroare ar trebui să aibă status='draft' și processing_status='failed'. Nu se șterg la refresh, doar se actualizează in-place.",
- "passes": true,
- "notes": "Completed in iteration 2"
+ "passes": false,
+ "notes": ""
},
{
- "id": "US-036",
- "title": "Afișare Nume Fișier pentru Toate Bonurile",
- "description": "Ca utilizator, vreau să văd numele fișierului original pentru bonurile procesate, pentru că vreau să identific care bon corespunde cărui fișier uploadat.",
- "priority": 36,
+ "id": "US-101c",
+ "title": "Creare MobileSelectionFooter.vue component",
+ "description": "Ca developer vreau componentă pentru acțiuni batch când sunt selectate elemente",
+ "priority": 3,
"acceptanceCriteria": [
- "Coloana 'Fișier' afișează original_filename și pentru receipt-uri completate, nu doar pentru job-uri",
- "Pe mobil, numele fișierului apare sub partener (font mic, gri)",
- "Tooltip pe desktop arată numele complet dacă e trunchiat",
- "Dacă receipt nu are original_filename, afișează '-'",
- "npm run typecheck passes",
- "Verify in browser: bon procesat afișează numele fișierului original"
+ "Componentă src/shared/components/mobile/MobileSelectionFooter.vue creată",
+ "Props: visible (boolean), actions (array of {label, icon, severity, handler})",
+ "Animație slide-up cu Transition",
+ "Stiluri din .mobile-selection-bottom-bar",
+ "npm run build passes"
],
- "technicalNotes": "Backend trebuie să populeze original_filename pe receipt din job-ul OCR. Verifică că auto-save service copiază filename din job la receipt.",
- "passes": true,
- "notes": "Completed in iteration 3"
+ "passes": false,
+ "notes": ""
},
{
- "id": "US-037",
- "title": "Fix - Upload Nu Mai Face Refresh Automat",
- "description": "Ca utilizator, vreau ca selectarea fișierelor să nu reîncarce pagina, pentru că pierd fișierele selectate înainte să apăs 'Procesează'.",
- "priority": 37,
+ "id": "US-102",
+ "title": "Definire MD3 color tokens în CSS",
+ "description": "Ca developer vreau variabile CSS pentru Material Design 3 color system",
+ "priority": 4,
"acceptanceCriteria": [
- "Selectarea fișierelor via input NU declanșează refresh/reload pagină",
- "Fișierele selectate rămân în listă până la submit explicit",
- "Comportament identic pe desktop și mobil (Chrome, Safari)",
- "Nu există race condition între clonarea fișierelor și resetarea input-ului",
- "npm run typecheck passes",
- "Verify on mobile: selectează 5 fișiere, toate rămân în listă"
+ "Fișier src/assets/css/core/md3-tokens.css creat",
+ "Tokens: --md-sys-color-primary, --md-sys-color-on-primary, --md-sys-color-surface, --md-sys-color-on-surface, --md-sys-color-outline",
+ "Dark mode variants cu [data-theme='dark']",
+ "Auto dark mode cu @media (prefers-color-scheme: dark)",
+ "Import adăugat în main.css",
+ "npm run build passes"
],
- "technicalNotes": "Bug probabil în onBulkFileInputChange sau în interacțiunea cu store. Verifică că nu există watchers care declanșează refresh la schimbări de state. Test specific pe Chrome Android - vezi gotcha din CLAUDE.md despre File API.",
- "passes": true,
- "notes": "Completed in iteration 4"
+ "passes": false,
+ "notes": ""
},
{
- "id": "US-038",
- "title": "Mobile - Selecție Multiplă prin Long-Press",
- "description": "Ca utilizator mobil, vreau să selectez bonuri prin apăsare lungă, pentru că vreau să pot șterge sau acționa asupra mai multor bonuri simultan.",
- "priority": 38,
+ "id": "US-103",
+ "title": "Refactor ReceiptsListView să folosească componente comune",
+ "description": "Ca developer vreau ReceiptsListView să folosească noile componente pentru validare API",
+ "priority": 5,
"acceptanceCriteria": [
- "Long-press (500ms) pe un card activează modul de selecție",
- "Card-ul selectat primește checkmark și background diferit (var(--blue-50))",
- "După activare, tap simplu pe alte carduri le adaugă/elimină din selecție",
- "Tap în afara cardurilor dezactivează modul selecție",
- "Header contextual arată numărul de elemente selectate",
- "npm run typecheck passes",
- "Verify on mobile: long-press selectează, tap adaugă la selecție"
+ "Import MobileTopBar, MobileBottomNav, MobileSelectionFooter în ReceiptsListView",
+ "Înlocuire template HTML cu componente",
+ "Ștergere CSS duplicat din ReceiptsListView (>200 linii)",
+ "Funcționalitate identică cu implementarea actuală",
+ "Verify in browser că lista bonuri funcționează identic pe mobil",
+ "npm run build passes"
],
- "technicalNotes": "Implementare cu setTimeout(500ms) pe touchstart, clear pe touchend/touchmove. CSS: .receipt-card.selected { background: var(--blue-50); border-color: var(--blue-500); }",
- "passes": true,
- "notes": "Completed in iteration 5"
+ "passes": false,
+ "notes": ""
},
{
- "id": "US-039",
- "title": "Mobile - Select All și Buton Ștergere",
- "description": "Ca utilizator mobil, vreau să am butoane 'Selectează tot' și 'Șterge' în modul selecție, pentru că vreau să pot șterge rapid mai multe bonuri.",
- "priority": 39,
+ "id": "US-104",
+ "title": "Eliminare buton delete duplicat din header tabel",
+ "description": "Ca utilizator vreau butonul delete doar în footer, nu și în header când e selecție activă",
+ "priority": 6,
"acceptanceCriteria": [
- "În modul selecție, apare top bar contextual cu: număr selectate, buton 'Selectează tot', buton X pentru ieșire",
- "Apare bottom bar cu buton 'Șterge' (roșu, icon coș)",
- "'Selectează tot' selectează toate bonurile din pagina curentă",
- "Buton 'Șterge' afișează confirmare înainte de ștergere",
- "După ștergere, modul selecție se dezactivează",
- "npm run typecheck passes",
- "Verify on mobile: select all + delete funcționează"
+ "În ReceiptsListView, bulk-actions-bar afișat DOAR când !isMobile",
+ "Pe mobil, delete apare DOAR în mobile-selection-bottom-bar (footer)",
+ "Pe desktop, delete rămâne în bulk-actions-bar (header tabel)",
+ "Verify in browser: pe mobil delete e doar în footer",
+ "Verify in browser: pe desktop delete e în header",
+ "npm run build passes"
],
- "technicalNotes": "Top bar: position: sticky; top: 0. Bottom bar: position: fixed; bottom: 0. Animație slide-in pentru bars.",
- "passes": true,
- "notes": "Completed in iteration 6"
+ "passes": false,
+ "notes": ""
},
{
- "id": "US-040",
- "title": "Mobile - Layout Android Nativ pentru Lista Bonuri",
- "description": "Ca utilizator mobil, vreau o interfață similară cu aplicațiile Android native, pentru că vreau experiență familiară și intuitivă.",
- "priority": 40,
+ "id": "US-105",
+ "title": "Adăugare buton Înapoi în editare bon",
+ "description": "Ca utilizator vreau să pot reveni la lista de bonuri din pagina de editare cu buton ←",
+ "priority": 7,
"acceptanceCriteria": [
- "Top Bar fixă cu: hamburger/back (stânga), titlu centrat, search+filter+more (dreapta)",
- "Filter Chips sub top bar (orizontal scrollabil): Toate, Ciorne, În așteptare, Validate, Respinse",
- "Bottom Navigation fixă cu 4 tab-uri: Bonuri (activ), Upload, Rapoarte, Setări",
- "FAB (56x56px) în colț dreapta jos, 16px de la margine, 72px de la bottom",
- "FAB se ascunde când scroll în jos, apare când scroll în sus",
- "Lista ocupă spațiul dintre top bar și bottom nav",
- "npm run typecheck passes",
- "Verify on mobile: layout similar cu Gmail/WhatsApp"
+ "MobileTopBar adăugat în ReceiptCreateUnifiedView.vue",
+ "showBack=true pentru a afișa săgeata ←",
+ "Click pe ← navighează la /data-entry",
+ "Title dinamic: 'Bon nou' pentru create, 'Editare Bon' pentru edit",
+ "Verify in browser că butonul funcționează",
+ "npm run build passes"
],
- "technicalNotes": "CSS: .mobile-top-bar { position: fixed; top: 0; height: 56px; z-index: 1000 }. .mobile-bottom-nav { position: fixed; bottom: 0; height: 56px }. .mobile-fab { position: fixed; bottom: 72px; right: 16px; width: 56px; border-radius: 16px }",
- "passes": true,
- "notes": "Completed in iteration 7"
+ "passes": false,
+ "notes": ""
},
{
- "id": "US-041",
- "title": "Mobile - Layout Android pentru Editare/Creare Bon",
- "description": "Ca utilizator mobil, vreau interfață de editare bon similară cu compose email în Gmail, pentru că vreau butoane de acțiune accesibile și layout familiar.",
- "priority": 41,
+ "id": "US-112",
+ "title": "Creare BottomSheet.vue component pentru filtre",
+ "description": "Ca utilizator vreau să pot accesa filtrele într-un bottom sheet pe mobil",
+ "priority": 8,
"acceptanceCriteria": [
- "Top Bar cu: X/back (stânga), titlu centrat, attach+save icons (dreapta)",
- "Content Area scrollabilă cu form fields 100% width",
- "Bottom Action Bar fixă cu: 'Salvează Ciornă' (secondary), 'Trimite pentru Validare' (primary)",
- "Keyboard-aware: bottom bar se mută deasupra tastaturii",
- "npm run typecheck passes",
- "Verify on mobile: layout similar cu Gmail compose"
+ "Componentă src/shared/components/mobile/BottomSheet.vue creată",
+ "v-model:visible pentru control",
+ "Animație slide-up smooth",
+ "Drag handle în partea de sus",
+ "Close pe tap outside overlay",
+ "Slot default pentru conținut",
+ "npm run build passes"
],
- "technicalNotes": "CSS: .mobile-receipt-form { padding-bottom: 80px }. .mobile-form-bottom-bar { position: fixed; bottom: 0; display: flex; gap: var(--space-sm) }. Butoane cu flex: 1 pentru width egal.",
- "passes": true,
- "notes": "Completed in iteration 8"
+ "passes": false,
+ "notes": ""
},
{
- "id": "US-042",
- "title": "Mobile - Layout Android pentru Vizualizare Bon",
- "description": "Ca utilizator mobil, vreau interfață de vizualizare bon similară cu view email în Gmail, pentru că vreau acțiuni rapide și navigare ușoară.",
- "priority": 42,
+ "id": "US-106",
+ "title": "Dashboard Mobile cu Swipeable KPI Cards",
+ "description": "Ca utilizator vreau KPI-uri ca carousel swipeable pe mobil cu dots indicator",
+ "priority": 9,
"acceptanceCriteria": [
- "Top Bar cu: back arrow (stânga), edit+delete+more icons (dreapta)",
- "Content Area cu detalii bon (read-only)",
- "Bottom Action Bar cu butoane contextuale: DRAFT→Editează/Trimite, PENDING→Validează/Respinge, APPROVED→Anulează",
- "npm run typecheck passes",
- "Verify on mobile: acțiuni accesibile din bottom bar"
+ "Componentă src/shared/components/mobile/SwipeableCards.vue creată",
+ "Touch swipe left/right funcțional (touchstart, touchmove, touchend)",
+ "Dots indicator pentru poziție curentă",
+ "DashboardView.vue folosește componenta când isMobile",
+ "Fallback la layout grid normal pe desktop",
+ "npm run build passes"
],
- "technicalNotes": "Refolosește stilurile din US-041. Butoanele din bottom bar se schimbă dinamic bazat pe receipt.status.",
- "passes": true,
- "notes": "Completed in iteration 9"
+ "passes": false,
+ "notes": ""
},
{
- "id": "US-043",
- "title": "Păstrare Ordine Bonuri la Refresh",
- "description": "Ca utilizator, vreau ca bonurile să rămână în ordinea în care au fost uploadate, pentru că vreau să urmăresc progresul fiecărui bon uploadat.",
- "priority": 43,
+ "id": "US-107",
+ "title": "InvoicesView Mobile Material Design",
+ "description": "Ca utilizator vreau pagina de facturi să aibă același header Material ca lista bonuri",
+ "priority": 10,
"acceptanceCriteria": [
- "Bonurile din același batch păstrează ordinea de upload (nu se reordonează)",
- "Un bon finalizat rămâne în aceeași poziție vizuală, nu sare la sfârșit",
- "SSE updates modifică status-ul in-place, fără a muta rândul",
- "Refresh manual poate reordona, dar SSE updates nu",
- "npm run typecheck passes",
- "Verify in browser: bon procesat nu își schimbă poziția în listă"
+ "MobileTopBar adăugat cu title 'Facturi'",
+ "Actions în header: refresh (pi-refresh), export (pi-download)",
+ "MobileBottomNav adăugat",
+ "Filtre existente mutate în BottomSheet pe mobil",
+ "Verify in browser că arată consistent cu bonuri",
+ "npm run build passes"
],
- "technicalNotes": "Lista trebuie sortată by created_at DESC sau by batch order, nu by last_modified. updateReceiptInPlace din store NU trebuie să reordoneze array-ul.",
- "passes": true,
- "notes": "Completed in iteration 10"
+ "passes": false,
+ "notes": ""
+ },
+ {
+ "id": "US-108",
+ "title": "TrialBalanceView Mobile Material Design",
+ "description": "Ca utilizator vreau pagina de balanță să aibă același header Material",
+ "priority": 11,
+ "acceptanceCriteria": [
+ "MobileTopBar adăugat cu title 'Balanță de Verificare'",
+ "Actions în header: export (pi-download)",
+ "MobileBottomNav adăugat",
+ "Filtre existente mutate în BottomSheet pe mobil",
+ "npm run build passes"
+ ],
+ "passes": false,
+ "notes": ""
+ },
+ {
+ "id": "US-109",
+ "title": "BankCashRegisterView Mobile Material Design",
+ "description": "Ca utilizator vreau pagina de trezorerie să aibă același header Material",
+ "priority": 12,
+ "acceptanceCriteria": [
+ "MobileTopBar adăugat cu title 'Trezorerie'",
+ "Actions în header: refresh, export",
+ "MobileBottomNav adăugat",
+ "Filtre în BottomSheet pe mobil",
+ "npm run build passes"
+ ],
+ "passes": false,
+ "notes": ""
+ },
+ {
+ "id": "US-110",
+ "title": "ServerLogsView Mobile Material Design",
+ "description": "Ca admin vreau pagina de loguri să aibă interfață Material",
+ "priority": 13,
+ "acceptanceCriteria": [
+ "MobileTopBar adăugat cu title 'Loguri Server'",
+ "Actions în header: refresh, export",
+ "MobileBottomNav adăugat",
+ "npm run build passes"
+ ],
+ "passes": false,
+ "notes": ""
+ },
+ {
+ "id": "US-111",
+ "title": "CacheStatsView Mobile Material Design",
+ "description": "Ca admin vreau pagina de statistici cache să aibă interfață Material",
+ "priority": 14,
+ "acceptanceCriteria": [
+ "MobileTopBar adăugat cu title 'Statistici Cache'",
+ "Actions în header: refresh",
+ "MobileBottomNav adăugat",
+ "npm run build passes"
+ ],
+ "passes": false,
+ "notes": ""
+ },
+ {
+ "id": "US-113",
+ "title": "Batch Actions per Module contextuale",
+ "description": "Ca utilizator vreau acțiuni batch diferite în funcție de modulul curent",
+ "priority": 15,
+ "acceptanceCriteria": [
+ "MobileSelectionFooter acceptă prop actions ca array",
+ "Bonuri: Delete + Export",
+ "Facturi (dacă se adaugă selecție): Export + Print",
+ "Fiecare acțiune are icon, label, severity, handler",
+ "npm run build passes"
+ ],
+ "passes": false,
+ "notes": ""
+ },
+ {
+ "id": "US-118",
+ "title": "Creare MOBILE_PATTERNS.md documentație",
+ "description": "Ca developer vreau documentație dedicată pentru pattern-urile mobile",
+ "priority": 16,
+ "acceptanceCriteria": [
+ "Fișier docs/MOBILE_PATTERNS.md creat",
+ "Table of Contents cu linkuri rapide",
+ "Secțiuni: MobileTopBar, MobileBottomNav, MobileSelectionFooter, BottomSheet, SwipeableCards",
+ "Exemple de cod copy-paste pentru fiecare componentă",
+ "Secțiune Quick Start pentru devs noi",
+ "Diagrame ASCII pentru layout mobile"
+ ],
+ "passes": false,
+ "notes": ""
+ },
+ {
+ "id": "US-115",
+ "title": "Actualizare CSS_PATTERNS.md cu Mobile Material Design",
+ "description": "Ca developer viitor vreau referință la MOBILE_PATTERNS.md în CSS_PATTERNS.md",
+ "priority": 17,
+ "acceptanceCriteria": [
+ "Secțiune nouă 'Mobile Material Design' în CSS_PATTERNS.md",
+ "Link către docs/MOBILE_PATTERNS.md pentru detalii",
+ "Rezumat scurt al componentelor disponibile",
+ "Breakpoint-uri mobile documentate"
+ ],
+ "passes": false,
+ "notes": ""
+ },
+ {
+ "id": "US-116",
+ "title": "Actualizare DESIGN_TOKENS.md cu MD3 Tokens",
+ "description": "Ca developer vreau documentație pentru noile MD3 color tokens",
+ "priority": 18,
+ "acceptanceCriteria": [
+ "Secțiune nouă 'Material Design 3 Tokens' în DESIGN_TOKENS.md",
+ "Tabel cu toate variabilele --md-sys-color-*",
+ "Mapping la tokens existenți",
+ "Exemple pentru dark mode"
+ ],
+ "passes": false,
+ "notes": ""
+ },
+ {
+ "id": "US-117",
+ "title": "Actualizare CLAUDE.md cu reguli Mobile Development",
+ "description": "Ca Claude Code vreau reguli clare pentru dezvoltare mobilă",
+ "priority": 19,
+ "acceptanceCriteria": [
+ "Secțiune nouă '### Mobile Development Rules' în CLAUDE.md",
+ "Regulă: Toate paginile mobile folosesc MobileTopBar",
+ "Regulă: Filtrele pe mobil în BottomSheet",
+ "Regulă: Selecția afișează acțiuni în footer",
+ "Regulă: Touch targets minim 44x44px",
+ "Checklist rapid pentru code review mobile"
+ ],
+ "passes": false,
+ "notes": ""
+ },
+ {
+ "id": "US-119",
+ "title": "Actualizare claude-learn-frontend.md cu pattern-uri noi",
+ "description": "Ca Claude Code vreau pattern-urile salvate în memoria pentru sesiuni viitoare",
+ "priority": 20,
+ "acceptanceCriteria": [
+ "Pattern: Mobile Material Design Component Architecture",
+ "Pattern: Bottom Sheet Filter Pattern",
+ "Pattern: Mobile Selection Mode Flow",
+ "Gotcha: Nu duplica delete button în header și footer",
+ "Format corect cu @date și tags #mobile #material-design"
+ ],
+ "passes": false,
+ "notes": ""
}
]
}
diff --git a/scripts/ralph/progress.txt b/scripts/ralph/progress.txt
index 7d81886..0918bad 100644
--- a/scripts/ralph/progress.txt
+++ b/scripts/ralph/progress.txt
@@ -1,516 +1,15 @@
# Ralph Progress Log
-Started: Sat Jan 11 02:30:00 PM UTC 2026
-Project: bulk-upload-list-integration (continuation of bulk-receipt-upload)
-Branch: ralph/bulk-receipt-upload (existing)
-PRD: tasks/prd-bulk-upload-list-integration.md
-Note: Continuing on same branch - bulk upload base already implemented
+Started: $(date)
+Project: unified-mobile-material-design
+Branch: ralph/unified-mobile-md
+Total Stories: 20
---
-[2026-01-11 14:05:11] Starting Ralph for project: bulk-upload-list-integration
-[2026-01-11 14:05:11] Max iterations: 50
-[2026-01-11 14:05:11] === Iteration 1/50 ===
-[2026-01-11 14:05:11] Working on story: US-011
-[2026-01-11 14:05:11] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_1_US-011.log)
-[2026-01-11 15:02:40] SUCCESS: Story US-011 passed!
-[2026-01-11 15:02:40] Changes committed
-[2026-01-11 15:02:40] Progress: 1/13 stories completed
-[2026-01-11 15:02:42] === Iteration 2/50 ===
-[2026-01-11 15:02:42] Working on story: US-012
-[2026-01-11 15:02:42] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_2_US-012.log)
-[2026-01-11 15:08:26] SUCCESS: Story US-012 passed!
-[2026-01-11 15:08:26] Changes committed
-[2026-01-11 15:08:26] Progress: 2/13 stories completed
-[2026-01-11 15:08:28] === Iteration 3/50 ===
-[2026-01-11 15:08:28] Working on story: US-007
-[2026-01-11 15:08:28] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_3_US-007.log)
-[2026-01-11 15:16:09] SUCCESS: Story US-007 passed!
-[2026-01-11 15:16:09] Changes committed
-[2026-01-11 15:16:09] Progress: 3/13 stories completed
-[2026-01-11 15:16:11] === Iteration 4/50 ===
-[2026-01-11 15:16:11] Working on story: US-001
-[2026-01-11 15:16:11] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_4_US-001.log)
-[2026-01-11 15:20:19] SUCCESS: Story US-001 passed!
-[2026-01-11 15:20:19] Changes committed
-[2026-01-11 15:20:19] Progress: 4/13 stories completed
-[2026-01-11 15:20:21] === Iteration 5/50 ===
-[2026-01-11 15:20:21] Working on story: US-002
-[2026-01-11 15:20:21] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_5_US-002.log)
-[2026-01-11 15:25:52] Story US-002 not yet complete, continuing...
-[2026-01-11 15:25:52] Progress: 4/13 stories completed
-[2026-01-11 15:25:54] === Iteration 6/50 ===
-[2026-01-11 15:25:54] Working on story: US-002
-[2026-01-11 15:25:54] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_6_US-002.log)
-[2026-01-11 15:28:49] SUCCESS: Story US-002 passed!
-[2026-01-11 15:28:49] Changes committed
-[2026-01-11 15:28:49] Progress: 5/13 stories completed
-[2026-01-11 15:28:51] === Iteration 7/50 ===
-[2026-01-11 15:28:51] Working on story: US-003
-[2026-01-11 15:28:51] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_7_US-003.log)
-[2026-01-11 15:31:48] SUCCESS: Story US-003 passed!
-[2026-01-11 15:31:48] Changes committed
-[2026-01-11 15:31:48] Progress: 6/13 stories completed
-[2026-01-11 15:31:50] === Iteration 8/50 ===
-[2026-01-11 15:31:50] Working on story: US-004
-[2026-01-11 15:31:50] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_8_US-004.log)
-[2026-01-11 15:36:36] SUCCESS: Story US-004 passed!
-[2026-01-11 15:36:37] Changes committed
-[2026-01-11 15:36:37] Progress: 7/13 stories completed
-[2026-01-11 15:36:39] === Iteration 9/50 ===
-[2026-01-11 15:36:39] Working on story: US-005
-[2026-01-11 15:36:39] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_9_US-005.log)
-[2026-01-11 15:41:56] SUCCESS: Story US-005 passed!
-[2026-01-11 15:41:56] Changes committed
-[2026-01-11 15:41:56] Progress: 8/13 stories completed
-[2026-01-11 15:41:58] === Iteration 10/50 ===
-[2026-01-11 15:41:58] Working on story: US-010
-[2026-01-11 15:41:58] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_10_US-010.log)
-[2026-01-11 15:48:38] SUCCESS: Story US-010 passed!
-[2026-01-11 15:48:38] Changes committed
-[2026-01-11 15:48:38] Progress: 9/13 stories completed
-[2026-01-11 15:48:40] === Iteration 11/50 ===
-[2026-01-11 15:48:40] Working on story: US-006
-[2026-01-11 15:48:40] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_11_US-006.log)
-[2026-01-11 15:48:44] Story US-006 not yet complete, continuing...
-[2026-01-11 15:48:44] Progress: 9/13 stories completed
-[2026-01-11 15:48:46] === Iteration 12/50 ===
-[2026-01-11 15:48:46] Working on story: US-006
-[2026-01-11 15:48:46] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_12_US-006.log)
-[2026-01-11 15:57:30] SUCCESS: Story US-006 passed!
-[2026-01-11 15:57:30] Changes committed
-[2026-01-11 15:57:30] Progress: 10/13 stories completed
-[2026-01-11 15:57:32] === Iteration 13/50 ===
-[2026-01-11 15:57:32] Working on story: US-009
-[2026-01-11 15:57:32] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_13_US-009.log)
-[2026-01-11 15:58:11] Story US-009 not yet complete, continuing...
-[2026-01-11 15:58:11] Progress: 10/13 stories completed
-[2026-01-11 15:58:13] === Iteration 14/50 ===
-[2026-01-11 15:58:13] Working on story: US-009
-[2026-01-11 15:58:13] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_14_US-009.log)
-[2026-01-11 15:58:16] Story US-009 not yet complete, continuing...
-[2026-01-11 15:58:16] Progress: 10/13 stories completed
-[2026-01-11 15:58:18] === Iteration 15/50 ===
-[2026-01-11 15:58:18] Working on story: US-009
-[2026-01-11 15:58:18] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_15_US-009.log)
-[2026-01-11 15:58:22] Story US-009 not yet complete, continuing...
-[2026-01-11 15:58:22] Progress: 10/13 stories completed
-[2026-01-11 15:58:24] === Iteration 16/50 ===
-[2026-01-11 15:58:24] Working on story: US-009
-[2026-01-11 15:58:24] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_16_US-009.log)
-[2026-01-11 15:58:27] Story US-009 not yet complete, continuing...
-[2026-01-11 15:58:27] Progress: 10/13 stories completed
-[2026-01-11 15:58:29] === Iteration 17/50 ===
-[2026-01-11 15:58:29] Working on story: US-009
-[2026-01-11 15:58:29] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_17_US-009.log)
-[2026-01-11 15:58:33] Story US-009 not yet complete, continuing...
-[2026-01-11 15:58:33] Progress: 10/13 stories completed
-[2026-01-11 15:58:35] === Iteration 18/50 ===
-[2026-01-11 15:58:35] Working on story: US-009
-[2026-01-11 15:58:35] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_18_US-009.log)
-[2026-01-11 15:58:39] Story US-009 not yet complete, continuing...
-[2026-01-11 15:58:39] Progress: 10/13 stories completed
-[2026-01-11 15:58:41] === Iteration 19/50 ===
-[2026-01-11 15:58:41] Working on story: US-009
-[2026-01-11 15:58:41] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_19_US-009.log)
-[2026-01-11 15:58:44] Story US-009 not yet complete, continuing...
-[2026-01-11 15:58:44] Progress: 10/13 stories completed
-[2026-01-11 15:58:46] === Iteration 20/50 ===
-[2026-01-11 15:58:46] Working on story: US-009
-[2026-01-11 15:58:46] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_20_US-009.log)
-[2026-01-11 15:58:50] Story US-009 not yet complete, continuing...
-[2026-01-11 15:58:50] Progress: 10/13 stories completed
-[2026-01-11 15:58:52] === Iteration 21/50 ===
-[2026-01-11 15:58:52] Working on story: US-009
-[2026-01-11 15:58:52] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_21_US-009.log)
-[2026-01-11 15:58:56] Story US-009 not yet complete, continuing...
-[2026-01-11 15:58:56] Progress: 10/13 stories completed
-[2026-01-11 15:58:58] === Iteration 22/50 ===
-[2026-01-11 15:58:58] Working on story: US-009
-[2026-01-11 15:58:58] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_22_US-009.log)
-[2026-01-11 15:59:01] Story US-009 not yet complete, continuing...
-[2026-01-11 15:59:01] Progress: 10/13 stories completed
-[2026-01-11 15:59:03] === Iteration 23/50 ===
-[2026-01-11 15:59:03] Working on story: US-009
-[2026-01-11 15:59:03] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_23_US-009.log)
-[2026-01-11 15:59:07] Story US-009 not yet complete, continuing...
-[2026-01-11 15:59:07] Progress: 10/13 stories completed
-[2026-01-11 15:59:09] === Iteration 24/50 ===
-[2026-01-11 15:59:09] Working on story: US-009
-[2026-01-11 15:59:09] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_24_US-009.log)
-[2026-01-11 15:59:12] Story US-009 not yet complete, continuing...
-[2026-01-11 15:59:12] Progress: 10/13 stories completed
-[2026-01-11 15:59:14] === Iteration 25/50 ===
-[2026-01-11 15:59:14] Working on story: US-009
-[2026-01-11 15:59:14] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_25_US-009.log)
-[2026-01-11 15:59:18] Story US-009 not yet complete, continuing...
-[2026-01-11 15:59:18] Progress: 10/13 stories completed
-[2026-01-11 15:59:20] === Iteration 26/50 ===
-[2026-01-11 15:59:20] Working on story: US-009
-[2026-01-11 15:59:20] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_26_US-009.log)
-[2026-01-11 15:59:23] Story US-009 not yet complete, continuing...
-[2026-01-11 15:59:23] Progress: 10/13 stories completed
-[2026-01-11 15:59:25] === Iteration 27/50 ===
-[2026-01-11 15:59:25] Working on story: US-009
-[2026-01-11 15:59:25] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_27_US-009.log)
-[2026-01-11 15:59:29] Story US-009 not yet complete, continuing...
-[2026-01-11 15:59:29] Progress: 10/13 stories completed
-[2026-01-11 15:59:31] === Iteration 28/50 ===
-[2026-01-11 15:59:31] Working on story: US-009
-[2026-01-11 15:59:31] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_28_US-009.log)
-[2026-01-11 15:59:35] Story US-009 not yet complete, continuing...
-[2026-01-11 15:59:35] Progress: 10/13 stories completed
-[2026-01-11 15:59:37] === Iteration 29/50 ===
-[2026-01-11 15:59:37] Working on story: US-009
-[2026-01-11 15:59:37] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_29_US-009.log)
-[2026-01-11 15:59:40] Story US-009 not yet complete, continuing...
-[2026-01-11 15:59:40] Progress: 10/13 stories completed
-[2026-01-11 15:59:42] === Iteration 30/50 ===
-[2026-01-11 15:59:42] Working on story: US-009
-[2026-01-11 15:59:42] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_30_US-009.log)
-[2026-01-11 15:59:46] Story US-009 not yet complete, continuing...
-[2026-01-11 15:59:46] Progress: 10/13 stories completed
-[2026-01-11 15:59:48] === Iteration 31/50 ===
-[2026-01-11 15:59:48] Working on story: US-009
-[2026-01-11 15:59:48] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_31_US-009.log)
-[2026-01-11 15:59:52] Story US-009 not yet complete, continuing...
-[2026-01-11 15:59:52] Progress: 10/13 stories completed
-[2026-01-11 15:59:54] === Iteration 32/50 ===
-[2026-01-11 15:59:54] Working on story: US-009
-[2026-01-11 15:59:54] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_32_US-009.log)
-[2026-01-11 15:59:57] Story US-009 not yet complete, continuing...
-[2026-01-11 15:59:57] Progress: 10/13 stories completed
-[2026-01-11 15:59:59] === Iteration 33/50 ===
-[2026-01-11 15:59:59] Working on story: US-009
-[2026-01-11 15:59:59] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_33_US-009.log)
-[2026-01-11 16:04:24] SUCCESS: Story US-009 passed!
-[2026-01-11 16:04:24] Changes committed
-[2026-01-11 16:04:24] Progress: 11/13 stories completed
-[2026-01-11 16:04:26] === Iteration 34/50 ===
-[2026-01-11 16:04:26] Working on story: US-008
-[2026-01-11 16:04:26] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_34_US-008.log)
-[2026-01-11 16:08:14] SUCCESS: Story US-008 passed!
-[2026-01-11 16:08:14] Changes committed
-[2026-01-11 16:08:14] Progress: 12/13 stories completed
-[2026-01-11 16:08:16] === Iteration 35/50 ===
-[2026-01-11 16:08:16] Working on story: US-013
-[2026-01-11 16:08:16] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_35_US-013.log)
-[2026-01-11 16:12:10] Story US-013 not yet complete, continuing...
-[2026-01-11 16:12:10] Progress: 12/13 stories completed
-[2026-01-11 16:12:12] === Iteration 36/50 ===
-[2026-01-11 16:12:12] Working on story: US-013
-[2026-01-11 16:12:12] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_36_US-013.log)
-[2026-01-11 16:14:52] SUCCESS: Story US-013 passed!
-[2026-01-11 16:14:52] Changes committed
-[2026-01-11 16:14:52] Progress: 13/13 stories completed
-[2026-01-11 16:14:54] === Iteration 37/50 ===
-[2026-01-11 16:14:54] SUCCESS: All stories completed! 🎉
-[2026-01-11 16:14:54] === Ralph Session Complete ===
-[2026-01-11 16:14:54] Final progress: 13/13 stories completed
-[2026-01-11 16:14:54] Branch: ralph/bulk-receipt-upload
-[2026-01-11 16:14:54] Logs: /workspace/roa2web/scripts/ralph/logs
-
----
-## Phase 2: Real-Time Progress în Listă
-Started: 2026-01-11 19:40
-Project: bulk-upload-realtime-progress
-Branch: ralph/bulk-receipt-upload (CONTINUĂ - NU crea branch nou!)
-PRD: tasks/prd-bulk-upload-realtime-progress.md
-
-Această fază extinde bulk upload-ul din Phase 1 (US-001→US-013 COMPLETE) cu:
-- Afișare fișiere imediat în tabel după upload
-- Progres real-time pe măsură ce sunt procesate
-- Cancel individual și batch
-- Animații pentru status changes
-
-### Noile User Stories (US-014 → US-023):
-
-| ID | Title | Priority | Status |
-|----|-------|----------|--------|
-| US-014 | Backend - Cancel Job Individual | 14 | pending |
-| US-015 | Backend - Cancel Batch Complet | 15 | pending |
-| US-016 | Frontend - Store Actions Cancel | 16 | pending |
-| US-017 | Frontend - Afișare Jobs în Tabel | 17 | pending |
-| US-018 | Frontend - Tranziție Job→Receipt | 18 | pending |
-| US-019 | Frontend - Animație Status Change | 19 | pending |
-| US-020 | Frontend - Cancel Individual Row | 20 | pending |
-| US-021 | Frontend - Cancel All în Header | 21 | pending |
-| US-022 | Frontend - Checkbox Disabled Jobs | 22 | pending |
-| US-023 | Frontend - Restore Jobs Refresh | 23 | pending |
-
----
-(Ralph va adăuga aici progresul per iterație)
-[2026-01-11 19:42:53] Starting Ralph for project: bulk-upload-realtime-progress
-[2026-01-11 19:42:53] Max iterations: 50
-[2026-01-11 19:42:53] === Iteration 1/50 ===
-[2026-01-11 19:42:53] Working on story: US-014
-[2026-01-11 19:42:53] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_1_US-014.log)
-[2026-01-11 19:47:06] SUCCESS: Story US-014 passed!
-[2026-01-11 19:47:07] Changes committed
-[2026-01-11 19:47:07] Progress: 14/23 stories completed
-[2026-01-11 19:47:09] === Iteration 2/50 ===
-[2026-01-11 19:47:09] Working on story: US-015
-[2026-01-11 19:47:09] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_2_US-015.log)
-[2026-01-11 19:53:13] Story US-015 not yet complete, continuing...
-[2026-01-11 19:53:13] Progress: 14/23 stories completed
-[2026-01-11 19:53:15] === Iteration 3/50 ===
-[2026-01-11 19:53:15] Working on story: US-015
-[2026-01-11 19:53:15] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_3_US-015.log)
-[2026-01-11 19:57:53] Starting Ralph for project: bulk-upload-realtime-progress
-[2026-01-11 19:57:53] Max iterations: 50
-[2026-01-11 19:57:53] === Iteration 1/50 ===
-[2026-01-11 19:57:53] Working on story: US-015
-[2026-01-11 19:57:53] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_1_US-015.log)
-[2026-01-11 20:00:23] SUCCESS: Story US-015 passed!
-[2026-01-11 20:00:23] Changes committed
-[2026-01-11 20:00:23] Progress: 15/23 stories completed
-[2026-01-11 20:00:25] === Iteration 2/50 ===
-[2026-01-11 20:00:25] Working on story: US-016
-[2026-01-11 20:00:25] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_2_US-016.log)
-[2026-01-11 20:06:04] SUCCESS: Story US-016 passed!
-[2026-01-11 20:06:04] Changes committed
-[2026-01-11 20:06:04] Progress: 16/23 stories completed
-[2026-01-11 20:06:06] === Iteration 3/50 ===
-[2026-01-11 20:06:06] Working on story: US-017
-[2026-01-11 20:06:06] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_3_US-017.log)
-[2026-01-11 20:12:04] Story US-017 not yet complete, continuing...
-[2026-01-11 20:12:04] Progress: 16/23 stories completed
-[2026-01-11 20:12:06] === Iteration 4/50 ===
-[2026-01-11 20:12:06] Working on story: US-017
-[2026-01-11 20:12:06] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_4_US-017.log)
-[2026-01-11 20:16:17] SUCCESS: Story US-017 passed!
-[2026-01-11 20:16:17] Changes committed
-[2026-01-11 20:16:17] Progress: 17/23 stories completed
-[2026-01-11 20:16:19] === Iteration 5/50 ===
-[2026-01-11 20:16:19] Working on story: US-018
-[2026-01-11 20:16:19] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_5_US-018.log)
-[2026-01-11 20:22:23] SUCCESS: Story US-018 passed!
-[2026-01-11 20:22:23] Changes committed
-[2026-01-11 20:22:23] Progress: 18/23 stories completed
-[2026-01-11 20:22:25] === Iteration 6/50 ===
-[2026-01-11 20:22:25] Working on story: US-019
-[2026-01-11 20:22:25] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_6_US-019.log)
-[2026-01-11 20:27:28] SUCCESS: Story US-019 passed!
-[2026-01-11 20:27:28] Changes committed
-[2026-01-11 20:27:28] Progress: 19/23 stories completed
-[2026-01-11 20:27:30] === Iteration 7/50 ===
-[2026-01-11 20:27:30] Working on story: US-020
-[2026-01-11 20:27:30] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_7_US-020.log)
-[2026-01-11 20:32:44] SUCCESS: Story US-020 passed!
-[2026-01-11 20:32:44] Changes committed
-[2026-01-11 20:32:44] Progress: 20/23 stories completed
-[2026-01-11 20:32:46] === Iteration 8/50 ===
-[2026-01-11 20:32:46] Working on story: US-021
-[2026-01-11 20:32:46] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_8_US-021.log)
-[2026-01-11 20:35:59] SUCCESS: Story US-021 passed!
-[2026-01-11 20:35:59] Changes committed
-[2026-01-11 20:35:59] Progress: 21/23 stories completed
-[2026-01-11 20:36:01] === Iteration 9/50 ===
-[2026-01-11 20:36:01] Working on story: US-022
-[2026-01-11 20:36:01] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_9_US-022.log)
-[2026-01-11 20:38:17] SUCCESS: Story US-022 passed!
-[2026-01-11 20:38:17] Changes committed
-[2026-01-11 20:38:17] Progress: 22/23 stories completed
-[2026-01-11 20:38:19] === Iteration 10/50 ===
-[2026-01-11 20:38:19] Working on story: US-023
-[2026-01-11 20:38:19] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_10_US-023.log)
-[2026-01-11 20:44:18] Story US-023 not yet complete, continuing...
-[2026-01-11 20:44:18] Progress: 22/23 stories completed
-[2026-01-11 20:44:20] === Iteration 11/50 ===
-[2026-01-11 20:44:20] Working on story: US-023
-[2026-01-11 20:44:20] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_11_US-023.log)
-[2026-01-11 20:46:15] SUCCESS: Story US-023 passed!
-[2026-01-11 20:46:15] Changes committed
-[2026-01-11 20:46:15] Progress: 23/23 stories completed
-[2026-01-11 20:46:17] === Iteration 12/50 ===
-[2026-01-11 20:46:17] SUCCESS: All stories completed! 🎉
-[2026-01-11 20:46:17] === Ralph Session Complete ===
-[2026-01-11 20:46:17] Final progress: 23/23 stories completed
-[2026-01-11 20:46:17] Branch: ralph/bulk-receipt-upload
-[2026-01-11 20:46:17] Logs: /workspace/roa2web/scripts/ralph/logs
-
----
-## Phase 3: Bulk Actions & SSE Real-time Updates
-Started: 2026-01-11 21:50
-Project: bulk-actions-sse-refresh
-Branch: ralph/bulk-receipt-upload (CONTINUĂ - NU crea branch nou!)
-PRD: tasks/prd-bulk-actions-sse-refresh.md
-
-Această fază adaugă:
-- Bulk Delete pentru bonuri selectate
-- SSE (Server-Sent Events) pentru actualizări real-time
-- Eliminare polling în favoarea SSE
-- Graceful degradation cu fallback la polling
-
-### Noile User Stories (US-024 → US-033):
-
-| ID | Title | Priority | Status |
-|----|-------|----------|--------|
-| US-024 | Backend - Endpoint Bulk Delete | 24 | pending |
-| US-025 | Frontend - Buton Șterge Bulk Actions | 25 | pending |
-| US-026 | Frontend - Dialog Confirmare Ștergere | 26 | pending |
-| US-027 | Frontend - Bulk Delete Partial Success | 27 | pending |
-| US-028 | Frontend - Navigare Pagină Anterioară | 28 | pending |
-| US-029 | Frontend - updateReceiptInPlace Store | 29 | pending |
-| US-030 | Backend - SSE Endpoint Status Updates | 30 | pending |
-| US-031 | Frontend - SSE Client Service | 31 | pending |
-| US-032 | Frontend - Înlocuire Polling cu SSE | 32 | pending |
-| US-033 | Frontend - Graceful Degradation SSE | 33 | pending |
-
----
-(Ralph va adăuga aici progresul per iterație)
-[2026-01-11 22:12:45] Starting Ralph for project: bulk-actions-sse-refresh
-[2026-01-11 22:12:45] Max iterations: 50
-[2026-01-11 22:12:45] === Iteration 1/50 ===
-[2026-01-11 22:12:45] Working on story: US-024
-[2026-01-11 22:12:45] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_1_US-024.log)
-[2026-01-11 22:48:00] MANUAL: US-024 marked as passed (code complete, Claude timed out after 30+ minutes)
-[2026-01-11 22:48:04] Starting Ralph for project: bulk-actions-sse-refresh
-[2026-01-11 22:48:04] Max iterations: 50
-[2026-01-11 22:48:04] === Iteration 1/50 ===
-[2026-01-11 22:48:04] Working on story: US-025
-[2026-01-11 22:48:04] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_1_US-025.log)
-[2026-01-11 22:51:34] SUCCESS: Story US-025 passed!
-[2026-01-11 22:51:34] Changes committed
-[2026-01-11 22:51:34] Progress: 25/33 stories completed
-[2026-01-11 22:51:36] === Iteration 2/50 ===
-[2026-01-11 22:51:36] Working on story: US-026
-[2026-01-11 22:51:36] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_2_US-026.log)
-[2026-01-11 22:55:07] SUCCESS: Story US-026 passed!
-[2026-01-11 22:55:07] Changes committed
-[2026-01-11 22:55:07] Progress: 26/33 stories completed
-[2026-01-11 22:55:09] === Iteration 3/50 ===
-[2026-01-11 22:55:09] Working on story: US-027
-[2026-01-11 22:55:09] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_3_US-027.log)
-[2026-01-11 22:59:03] SUCCESS: Story US-027 passed!
-[2026-01-11 22:59:03] Changes committed
-[2026-01-11 22:59:03] Progress: 27/33 stories completed
-[2026-01-11 22:59:05] === Iteration 4/50 ===
-[2026-01-11 22:59:05] Working on story: US-028
-[2026-01-11 22:59:05] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_4_US-028.log)
-[2026-01-11 23:03:22] SUCCESS: Story US-028 passed!
-[2026-01-11 23:03:22] Changes committed
-[2026-01-11 23:03:22] Progress: 28/33 stories completed
-[2026-01-11 23:03:24] === Iteration 5/50 ===
-[2026-01-11 23:03:24] Working on story: US-029
-[2026-01-11 23:03:24] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_5_US-029.log)
-[2026-01-11 23:04:38] SUCCESS: Story US-029 passed!
-[2026-01-11 23:04:38] Changes committed
-[2026-01-11 23:04:38] Progress: 29/33 stories completed
-[2026-01-11 23:04:40] === Iteration 6/50 ===
-[2026-01-11 23:04:40] Working on story: US-030
-[2026-01-11 23:04:40] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_6_US-030.log)
-[2026-01-11 23:35:52] MANUAL: US-030 marked as passed (SSE endpoint complete, Claude timed out after 30+ minutes)
-[2026-01-11 23:35:57] Starting Ralph for project: bulk-actions-sse-refresh
-[2026-01-11 23:35:57] Max iterations: 50
-[2026-01-11 23:35:57] === Iteration 1/50 ===
-[2026-01-11 23:35:57] Working on story: US-031
-[2026-01-11 23:35:57] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_1_US-031.log)
-[2026-01-11 23:37:36] SUCCESS: Story US-031 passed!
-[2026-01-11 23:37:36] Changes committed
-[2026-01-11 23:37:36] Progress: 31/33 stories completed
-[2026-01-11 23:37:38] === Iteration 2/50 ===
-[2026-01-11 23:37:38] Working on story: US-032
-[2026-01-11 23:37:38] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_2_US-032.log)
-[2026-01-11 23:41:53] SUCCESS: Story US-032 passed!
-[2026-01-11 23:41:53] Changes committed
-[2026-01-11 23:41:53] Progress: 32/33 stories completed
-[2026-01-11 23:41:55] === Iteration 3/50 ===
-[2026-01-11 23:41:55] Working on story: US-033
-[2026-01-11 23:41:55] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_3_US-033.log)
-[2026-01-11 23:44:52] SUCCESS: Story US-033 passed!
-[2026-01-11 23:44:53] Changes committed
-[2026-01-11 23:44:53] Progress: 33/33 stories completed
-[2026-01-11 23:44:55] === Iteration 4/50 ===
-[2026-01-11 23:44:55] SUCCESS: All stories completed! 🎉
-[2026-01-11 23:44:55] === Ralph Session Complete ===
-[2026-01-11 23:44:55] Final progress: 33/33 stories completed
-[2026-01-11 23:44:55] Branch: ralph/bulk-receipt-upload
-[2026-01-11 23:44:55] Logs: /workspace/roa2web/scripts/ralph/logs
-
----
-## Phase 2: Mobile UX Improvements
-Started: 2026-01-12
-
-### New User Stories Added:
-- US-034: Fix - Refresh Individual vs Refresh Total
-- US-035: Fix - Bonuri cu Eroare Rămân în Listă
-- US-036: Afișare Nume Fișier pentru Toate Bonurile
-- US-037: Fix - Upload Nu Mai Face Refresh Automat
-- US-038: Mobile - Selecție Multiplă prin Long-Press
-- US-039: Mobile - Select All și Buton Ștergere
-- US-040: Mobile - Layout Android Nativ pentru Lista Bonuri
-- US-041: Mobile - Layout Android pentru Editare/Creare Bon
-- US-042: Mobile - Layout Android pentru Vizualizare Bon
-- US-043: Păstrare Ordine Bonuri la Refresh
-
-### Prioritization:
-Faza 1 (Bug Fixes): US-034, US-035, US-037, US-043
-Faza 2 (Mobile Enhancements): US-036, US-038, US-039
-Faza 3 (Mobile Native Layout): US-040, US-041, US-042
-[2026-01-12 07:34:34] Starting Ralph for project: mobile-ux-improvements
-[2026-01-12 07:34:34] Max iterations: 50
-[2026-01-12 07:34:34] === Iteration 1/50 ===
-[2026-01-12 07:34:34] Working on story: US-034
-[2026-01-12 07:34:34] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_1_US-034.log)
-[2026-01-12 07:38:22] SUCCESS: Story US-034 passed!
-[2026-01-12 07:38:22] Changes committed
-[2026-01-12 07:38:22] Progress: 34/43 stories completed
-[2026-01-12 07:38:24] === Iteration 2/50 ===
-[2026-01-12 07:38:24] Working on story: US-035
-[2026-01-12 07:38:24] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_2_US-035.log)
-[2026-01-12 07:41:39] SUCCESS: Story US-035 passed!
-[2026-01-12 07:41:39] Changes committed
-[2026-01-12 07:41:39] Progress: 35/43 stories completed
-[2026-01-12 07:41:41] === Iteration 3/50 ===
-[2026-01-12 07:41:41] Working on story: US-036
-[2026-01-12 07:41:41] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_3_US-036.log)
-[2026-01-12 07:46:55] SUCCESS: Story US-036 passed!
-[2026-01-12 07:46:56] Changes committed
-[2026-01-12 07:46:56] Progress: 36/43 stories completed
-[2026-01-12 07:46:58] === Iteration 4/50 ===
-[2026-01-12 07:46:58] Working on story: US-037
-[2026-01-12 07:46:58] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_4_US-037.log)
-[2026-01-12 07:51:38] SUCCESS: Story US-037 passed!
-[2026-01-12 07:51:38] Changes committed
-[2026-01-12 07:51:38] Progress: 37/43 stories completed
-[2026-01-12 07:51:40] === Iteration 5/50 ===
-[2026-01-12 07:51:40] Working on story: US-038
-[2026-01-12 07:51:40] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_5_US-038.log)
-[2026-01-12 07:56:08] SUCCESS: Story US-038 passed!
-[2026-01-12 07:56:08] Changes committed
-[2026-01-12 07:56:08] Progress: 38/43 stories completed
-[2026-01-12 07:56:10] === Iteration 6/50 ===
-[2026-01-12 07:56:10] Working on story: US-039
-[2026-01-12 07:56:10] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_6_US-039.log)
-[2026-01-12 08:00:37] SUCCESS: Story US-039 passed!
-[2026-01-12 08:00:37] Changes committed
-[2026-01-12 08:00:38] Progress: 39/43 stories completed
-[2026-01-12 08:00:40] === Iteration 7/50 ===
-[2026-01-12 08:00:40] Working on story: US-040
-[2026-01-12 08:00:40] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_7_US-040.log)
-[2026-01-12 08:06:20] SUCCESS: Story US-040 passed!
-[2026-01-12 08:06:20] Changes committed
-[2026-01-12 08:06:20] Progress: 40/43 stories completed
-[2026-01-12 08:06:22] === Iteration 8/50 ===
-[2026-01-12 08:06:22] Working on story: US-041
-[2026-01-12 08:06:22] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_8_US-041.log)
-[2026-01-12 08:11:12] SUCCESS: Story US-041 passed!
-[2026-01-12 08:11:12] Changes committed
-[2026-01-12 08:11:12] Progress: 41/43 stories completed
-[2026-01-12 08:11:14] === Iteration 9/50 ===
-[2026-01-12 08:11:14] Working on story: US-042
-[2026-01-12 08:11:14] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_9_US-042.log)
-[2026-01-12 08:14:53] SUCCESS: Story US-042 passed!
-[2026-01-12 08:14:53] Changes committed
-[2026-01-12 08:14:53] Progress: 42/43 stories completed
-[2026-01-12 08:14:55] === Iteration 10/50 ===
-[2026-01-12 08:14:55] Working on story: US-043
-[2026-01-12 08:14:55] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_10_US-043.log)
-[2026-01-12 08:20:33] SUCCESS: Story US-043 passed!
-[2026-01-12 08:20:33] Changes committed
-[2026-01-12 08:20:33] Progress: 43/43 stories completed
-[2026-01-12 08:20:35] === Iteration 11/50 ===
-[2026-01-12 08:20:35] SUCCESS: All stories completed! 🎉
-[2026-01-12 08:20:35] === Ralph Session Complete ===
-[2026-01-12 08:20:35] Final progress: 43/43 stories completed
-[2026-01-12 08:20:35] Branch: ralph/bulk-receipt-upload
-[2026-01-12 08:20:35] Logs: /workspace/roa2web/scripts/ralph/logs
+Mon Jan 12 09:44:54 AM UTC 2026
+[2026-01-12 09:45:00] Starting Ralph for project: unified-mobile-material-design
+[2026-01-12 09:45:00] Max iterations: 100
+[2026-01-12 09:45:00] Creating new branch: ralph/unified-mobile-md
+[2026-01-12 09:45:00] === Iteration 1/100 ===
+[2026-01-12 09:45:00] Working on story: US-101a
+[2026-01-12 09:45:00] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_1_US-101a.log)
+[2026-01-12 09:46:30] SUCCESS: Story US-101a passed!
diff --git a/src/shared/components/mobile/MobileTopBar.vue b/src/shared/components/mobile/MobileTopBar.vue
new file mode 100644
index 0000000..bb5b05a
--- /dev/null
+++ b/src/shared/components/mobile/MobileTopBar.vue
@@ -0,0 +1,218 @@
+
+
+
+
+
+
+
+
+
+
{{ title }}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tasks/prd-unified-mobile-material-design.md b/tasks/prd-unified-mobile-material-design.md
new file mode 100644
index 0000000..c4ac62c
--- /dev/null
+++ b/tasks/prd-unified-mobile-material-design.md
@@ -0,0 +1,457 @@
+# PRD: Unified Mobile Material Design Interface
+
+## 1. Introducere
+
+Aplicația ROA2WEB are deja implementată o interfață Material Design nativă Android pentru modulul de bonuri (ReceiptsListView). Acest PRD definește extinderea aceleiași interfețe unitare la toate paginile aplicației în modul mobil: Dashboard, Facturi, Balanță de Verificare, Trezorerie, Statistici, Loguri etc.
+
+Scopul este o experiență consistentă cross-module pe dispozitive mobile, cu header/footer unitar și pattern-uri de interacțiune identice.
+
+## 2. Obiective
+
+### Obiectiv Principal
+- **Consistență UI/UX**: Toate paginile mobile să aibă aceeași structură vizuală și pattern-uri de interacțiune ca lista de bonuri
+
+### Obiective Secundare
+- Eliminare cod duplicat (buton delete în header când există în footer)
+- Adăugare navigare back (← Înapoi) în editare bonuri
+- Dashboard cu carousel swipeable pentru KPI cards
+- MD3 color tokens pentru theming consistent
+
+### Metrici de Succes
+- 100% consistență vizuală între pagini pe mobil
+- Reducere CSS duplicat cu minim 30%
+- Zero regresii vizuale în modul desktop
+- Funcționare pe Android Chrome, iOS Safari, Samsung Internet
+
+## 3. User Stories
+
+### US-101: Creare sistem de componente Material Design reutilizabile
+**Ca** developer
+**Vreau** componente Vue reutilizabile pentru elementele MD comune
+**Pentru că** să evit duplicarea codului și să asigur consistența
+
+**Acceptance Criteria:**
+- [ ] Componentă `MobileTopBar.vue` extrasă din ReceiptsListView
+- [ ] Componentă `MobileBottomNav.vue` extrasă din ReceiptsListView
+- [ ] Componentă `MobileSelectionFooter.vue` pentru batch actions
+- [ ] Componentă `MobileFilterChips.vue` pentru filtre orizontale scrollable
+- [ ] Componentă `BottomSheet.vue` pentru filtre avansate
+- [ ] Props pentru customizare (title, actions, items)
+- [ ] npm run build passes
+
+### US-102: Definire MD3 color tokens în CSS
+**Ca** developer
+**Vreau** variabile CSS pentru Material Design 3 color system
+**Pentru că** să am culori consistente și dark mode automatic
+
+**Acceptance Criteria:**
+- [ ] Fișier `src/assets/css/core/md3-tokens.css` creat
+- [ ] Tokens pentru: primary, secondary, surface, on-surface, outline
+- [ ] Dark mode variants cu `[data-theme="dark"]`
+- [ ] Mapping la tokens existenți unde posibil
+- [ ] Import în main.css
+- [ ] npm run build passes
+
+### US-103: Refactor ReceiptsListView să folosească componente comune
+**Ca** developer
+**Vreau** ReceiptsListView să folosească noile componente
+**Pentru că** să validez API-ul componentelor și să reduc duplicarea
+
+**Acceptance Criteria:**
+- [ ] Import MobileTopBar, MobileBottomNav, MobileSelectionFooter
+- [ ] Ștergere CSS duplicat din ReceiptsListView
+- [ ] Funcționalitate identică cu implementarea actuală
+- [ ] Verify in browser că lista bonuri funcționează identic pe mobil
+- [ ] npm run build passes
+
+### US-104: Eliminare buton delete duplicat din header tabel bonuri
+**Ca** utilizator
+**Vreau** să văd butonul de ștergere doar în footer când am selecție activă
+**Pentru că** afișarea în ambele locuri e confuză și ocupă spațiu inutil
+
+**Acceptance Criteria:**
+- [ ] Desktop: bulk-actions-bar NU mai afișează buton Șterge când e pe mobil
+- [ ] Desktop: bulk-actions-bar afișează doar când `!isMobile`
+- [ ] Mobile: delete apare DOAR în `mobile-selection-bottom-bar`
+- [ ] Verify in browser: pe mobil, delete e doar în footer
+- [ ] Verify in browser: pe desktop, delete e în header table
+- [ ] npm run build passes
+
+### US-105: Adăugare buton Înapoi în editare bon (mobile)
+**Ca** utilizator
+**Vreau** să pot reveni la lista de bonuri din pagina de editare
+**Pentru că** navigarea back prin browser nu e intuitivă pe mobil
+
+**Acceptance Criteria:**
+- [ ] MobileTopBar în ReceiptCreateView/ReceiptCreateUnifiedView
+- [ ] Iconiță ← în stânga header-ului
+- [ ] Click pe ← navighează la `/data-entry`
+- [ ] Title: "Editare Bon" sau "Bon nou" în funcție de context
+- [ ] Verify in browser: butonul funcționează corect
+- [ ] npm run build passes
+
+### US-106: Dashboard Mobile cu Swipeable KPI Cards
+**Ca** utilizator
+**Vreau** să văd KPI-urile ca un carousel swipeable pe mobil
+**Pentru că** cardurile stacked ocupă prea mult spațiu vertical
+
+**Acceptance Criteria:**
+- [ ] Componentă `SwipeableCards.vue` creată
+- [ ] Dots indicator pentru poziție
+- [ ] Touch swipe left/right funcțional
+- [ ] DashboardView.vue folosește componenta pe mobil
+- [ ] Fallback la layout normal pe desktop
+- [ ] Verify in browser: swipe funcționează pe touch devices
+- [ ] npm run build passes
+
+### US-107: InvoicesView Mobile Material Design Header
+**Ca** utilizator
+**Vreau** pagina de facturi să aibă același header Material ca lista bonuri
+**Pentru că** interfața trebuie să fie unitară
+
+**Acceptance Criteria:**
+- [ ] MobileTopBar cu title "Facturi"
+- [ ] App Bar Actions: refresh, export în header (iconițe dreapta)
+- [ ] MobileBottomNav identic cu cel din bonuri
+- [ ] Filtre în Bottom Sheet (nu inline pe mobil)
+- [ ] Verify in browser: header arată ca la bonuri
+- [ ] npm run build passes
+
+### US-108: TrialBalanceView Mobile Material Design Header
+**Ca** utilizator
+**Vreau** pagina de balanță să aibă același header Material
+**Pentru că** interfața trebuie să fie unitară
+
+**Acceptance Criteria:**
+- [ ] MobileTopBar cu title "Balanță de Verificare"
+- [ ] App Bar Actions: export în header
+- [ ] MobileBottomNav identic
+- [ ] Bottom Sheet pentru filtre complexe (perioadă, conturi)
+- [ ] Verify in browser că arată consistent
+- [ ] npm run build passes
+
+### US-109: BankCashRegisterView (Trezorerie) Mobile Material Design
+**Ca** utilizator
+**Vreau** pagina de trezorerie să aibă același header Material
+**Pentru că** interfața trebuie să fie unitară
+
+**Acceptance Criteria:**
+- [ ] MobileTopBar cu title "Trezorerie"
+- [ ] App Bar Actions: refresh, export
+- [ ] MobileBottomNav identic
+- [ ] Bottom Sheet pentru filtre
+- [ ] Verify in browser
+- [ ] npm run build passes
+
+### US-110: ServerLogsView Mobile Material Design
+**Ca** admin
+**Vreau** pagina de loguri să aibă interfață Material
+**Pentru că** și paginile admin trebuie să fie unitare
+
+**Acceptance Criteria:**
+- [ ] MobileTopBar cu title "Loguri Server"
+- [ ] App Bar Actions: refresh, export
+- [ ] MobileBottomNav (fără link-ul de setări OCR pentru non-admin)
+- [ ] Verify in browser
+- [ ] npm run build passes
+
+### US-111: CacheStatsView Mobile Material Design
+**Ca** admin
+**Vreau** pagina de statistici cache să aibă interfață Material
+**Pentru că** și paginile admin trebuie să fie unitare
+
+**Acceptance Criteria:**
+- [ ] MobileTopBar cu title "Statistici Cache"
+- [ ] App Bar Actions: refresh
+- [ ] MobileBottomNav
+- [ ] Verify in browser
+- [ ] npm run build passes
+
+### US-112: Bottom Sheet Component pentru Filtre
+**Ca** utilizator
+**Vreau** să pot accesa filtrele într-un bottom sheet pe mobil
+**Pentru că** ocupă mai puțin spațiu și e pattern MD familiar
+
+**Acceptance Criteria:**
+- [ ] Componentă `BottomSheet.vue` cu animație slide-up
+- [ ] Drag handle în partea de sus
+- [ ] Close pe tap outside sau swipe down
+- [ ] Slot pentru conținut
+- [ ] Suport pentru visible v-model
+- [ ] Verify in browser: animația e smooth
+- [ ] npm run build passes
+
+### US-113: Batch Actions per Module (contextuale)
+**Ca** utilizator
+**Vreau** acțiuni batch diferite în funcție de modulul curent
+**Pentru că** bonurile au ștergere, facturile au export+print, balanța doar export
+
+**Acceptance Criteria:**
+- [ ] MobileSelectionFooter acceptă prop `actions` array
+- [ ] Bonuri: Delete button (existent) + Export
+- [ ] Facturi: Export + Print
+- [ ] Balanță: Export only
+- [ ] Verify in browser pentru fiecare modul
+- [ ] npm run build passes
+
+### US-114: Integrare și testare completă
+**Ca** QA
+**Vreau** toate paginile testate pe multiple device-uri
+**Pentru că** trebuie să fim siguri că nu sunt regresii
+
+**Acceptance Criteria:**
+- [ ] Test pe Chrome Android (real device sau emulator)
+- [ ] Test pe Safari iOS (simulator sau real)
+- [ ] Test desktop Chrome/Firefox/Safari
+- [ ] Verify dark mode funcționează peste tot
+- [ ] Verify landscape orientation
+- [ ] npm run build passes
+- [ ] Zero erori în console
+
+---
+
+## User Stories: Documentație și Reguli (Faza 7)
+
+### US-115: Actualizare CSS_PATTERNS.md cu Mobile Material Design
+**Ca** developer viitor
+**Vreau** documentație completă pentru pattern-urile Mobile Material Design
+**Pentru că** să pot implementa pagini noi consistent fără a citi codul existent
+
+**Acceptance Criteria:**
+- [ ] Secțiune nouă "Mobile Material Design Components" în CSS_PATTERNS.md
+- [ ] Documentat MobileTopBar: structură HTML, clase CSS, props
+- [ ] Documentat MobileBottomNav: linkuri, iconițe, structură
+- [ ] Documentat MobileSelectionFooter: când se afișează, acțiuni
+- [ ] Documentat BottomSheet: usage, v-model, slots
+- [ ] Documentat SwipeableCards: props, dots indicator
+- [ ] Exemple de cod copy-paste ready pentru fiecare componentă
+- [ ] Screenshots/ASCII diagrams pentru layout-uri
+
+### US-116: Actualizare DESIGN_TOKENS.md cu MD3 Tokens
+**Ca** developer viitor
+**Vreau** documentație pentru noile MD3 color tokens
+**Pentru că** să știu ce variabile CSS să folosesc pentru Material Design
+
+**Acceptance Criteria:**
+- [ ] Secțiune nouă "Material Design 3 Tokens" în DESIGN_TOKENS.md
+- [ ] Tabel cu toate variabilele MD3: `--md-sys-color-*`
+- [ ] Mapping la tokens existenți (ex: `--md-sys-color-primary` → `--primary-color`)
+- [ ] Exemple dark mode: cum se schimbă valorile
+- [ ] Reguli când să folosești MD3 tokens vs tokens existenți
+- [ ] Color swatches vizuale (ASCII sau referință la Figma)
+
+### US-117: Actualizare CLAUDE.md cu Reguli Mobile Development
+**Ca** Claude Code (AI)
+**Vreau** reguli clare în CLAUDE.md pentru dezvoltare mobilă
+**Pentru că** să respect pattern-urile stabilite la generarea automată de cod
+
+**Acceptance Criteria:**
+- [ ] Secțiune nouă "### Mobile Development Rules" în CLAUDE.md
+- [ ] Regulă: "Toate paginile mobile TREBUIE să folosească MobileTopBar"
+- [ ] Regulă: "Filtrele pe mobil se pun în BottomSheet, NU inline"
+- [ ] Regulă: "Selecția multiplă afișează acțiuni în footer, NU în header"
+- [ ] Regulă: "Touch targets minim 44x44px"
+- [ ] Regulă: "Folosește isMobile composable pentru condiționare"
+- [ ] Checklist rapid pentru code review mobile
+
+### US-118: Creare MOBILE_PATTERNS.md dedicat
+**Ca** developer
+**Vreau** un fișier dedicat pentru documentația mobilă
+**Pentru că** e prea mult pentru CSS_PATTERNS.md și merită propriul fișier
+
+**Acceptance Criteria:**
+- [ ] Fișier `docs/MOBILE_PATTERNS.md` creat
+- [ ] Table of Contents cu linkuri rapide
+- [ ] Secțiuni pentru fiecare componentă
+- [ ] Secțiune "Quick Start" pentru devs noi
+- [ ] Secțiune "Do's and Don'ts" cu exemple concrete
+- [ ] Diagrame ASCII pentru layout mobile
+- [ ] Linkuri către fișierele sursă componente
+- [ ] Referință adăugată în CSS_PATTERNS.md și CLAUDE.md
+
+### US-119: Actualizare claude-learn-frontend.md cu Pattern-uri Noi
+**Ca** Claude Code (AI)
+**Vreau** pattern-urile noi salvate în memoria Claude
+**Pentru că** să le pot aplica automat în sesiuni viitoare
+
+**Acceptance Criteria:**
+- [ ] Pattern nou: "Mobile Material Design Component Architecture"
+- [ ] Pattern nou: "Bottom Sheet Filter Pattern"
+- [ ] Pattern nou: "Mobile Selection Mode Flow"
+- [ ] Gotcha: "Nu duplica delete button în header și footer"
+- [ ] Gotcha: "Filtrele mobile trebuie în BottomSheet"
+- [ ] Format corect cu @date și tags
+
+### US-120: Validare Documentație cu Fresh Developer Test
+**Ca** lead developer
+**Vreau** să validez că documentația e suficientă
+**Pentru că** să mă asigur că un dev nou poate implementa o pagină mobilă fără ajutor
+
+**Acceptance Criteria:**
+- [ ] Un developer (sau AI) poate crea o pagină mobilă nouă doar din docs
+- [ ] Toate componentele sunt documentate cu exemple
+- [ ] Nu sunt referințe circulare sau documente lipsă
+- [ ] Documentația e consistentă între fișiere
+- [ ] npm run build passes după ce dev-ul urmează docs
+
+## 4. Cerințe Funcționale
+
+1. [REQ-001] Toate paginile mobile trebuie să aibă MobileTopBar cu structură identică
+2. [REQ-002] MobileBottomNav trebuie să fie consistent între pagini (aceleași linkuri)
+3. [REQ-003] Selecția multiplă trebuie să folosească footer fix, nu header tabel
+4. [REQ-004] Filtrele pe mobil trebuie să fie în Bottom Sheet, nu inline
+5. [REQ-005] App Bar Actions (iconițe) trebuie să respecte ordinea: refresh, export, print, more
+6. [REQ-006] Dashboard KPI cards trebuie să fie swipeable cu dots indicator
+7. [REQ-007] Navigarea înapoi trebuie să fie vizibilă în app bar pentru pagini secundare
+8. [REQ-008] MD3 tokens trebuie să suporte toate cele 3 theme modes (auto/light/dark)
+9. [REQ-009] Documentația trebuie actualizată ÎNAINTE de merge în main
+10. [REQ-010] CLAUDE.md trebuie să conțină reguli explicite pentru mobile development
+11. [REQ-011] Orice developer nou trebuie să poată implementa o pagină mobilă doar din documentație
+
+## 5. Non-Goals (Ce NU facem)
+
+- ❌ Nu modificăm layout-ul desktop (doar mobile)
+- ❌ Nu schimbăm structura tabelelor existente (sunt deja optimizate)
+- ❌ Nu implementăm gesture navigation nativă (back swipe) - folosim buton explicit
+- ❌ Nu adăugăm animații complexe (transform, spring physics)
+- ❌ Nu diferențiem comportamentul iOS vs Android (identic cross-platform)
+- ❌ Nu modificăm logica backend sau API calls
+- ❌ Nu implementăm pull-to-refresh (complexitate excesivă)
+
+## 6. Considerații Tehnice
+
+### Stack/Tehnologii
+- Vue 3 Composition API
+- PrimeVue components (Button, Dialog, Menu, Sidebar)
+- CSS custom cu design tokens
+- Touch events native (touchstart, touchmove, touchend)
+
+### Patterns de Urmat
+- Pattern existent din `ReceiptsListView.vue` (US-038, US-039, US-040)
+- CSS tokens din `src/assets/css/core/tokens.css`
+- Mobile breakpoint: `max-width: 768px`
+- Touch target minimum: 44px
+
+### Dependențe
+- `useMediaQuery` composable pentru `isMobile`
+- Router pentru navigare
+- Design tokens existenți
+
+### Riscuri Tehnice
+- **Risc mediu**: Bottom Sheet poate avea probleme cu keyboard pe iOS
+ - Mitigare: Testare extensivă, fallback la modal simplu
+- **Risc scăzut**: Swipe carousel poate conflicta cu scroll lateral pe tabele
+ - Mitigare: Disable swipe când e în tabel
+
+## 7. Considerații UI/UX
+
+### Layout Structure (Mobile)
+```
+┌─────────────────────────────────────┐
+│ [☰/←] Title [🔍][⚙][⋮]│ ← MobileTopBar
+├─────────────────────────────────────┤
+│ [Filter Chips scrollable...] │ ← Optional, per page
+├─────────────────────────────────────┤
+│ │
+│ Page Content │
+│ (scrollable) │
+│ │
+├─────────────────────────────────────┤
+│ [🏠] [📤] [📊] [⚙] │ ← MobileBottomNav
+└─────────────────────────────────────┘
+
+ OR (when selection active):
+
+├─────────────────────────────────────┤
+│ [🗑️ Șterge selectate] │ ← MobileSelectionFooter
+└─────────────────────────────────────┘
+```
+
+### Stări (States)
+- **Normal**: Header cu hamburger, content, bottom nav
+- **Selection Mode**: Header cu X și count, content cu checkmarks, footer cu delete
+- **Filters Open**: Bottom sheet overlay cu filtre
+- **Loading**: Skeleton sau spinner în content area
+- **Empty**: Empty state centrat în content area
+- **Error**: Toast notification
+
+### Accesibilitate
+- Touch targets minim 44x44px
+- Focus visible pentru keyboard navigation
+- ARIA labels pe butoanele icon-only
+- Color contrast minim 4.5:1
+
+## 8. Success Metrics
+
+- **Consistență vizuală**: 100% pagini cu header identic
+- **Code reuse**: Min 70% CSS din componente comune
+- **Performance**: First Contentful Paint < 1.5s pe 3G
+- **Bundle size**: Creștere max 10KB gzipped
+
+## 9. Open Questions
+
+- [ ] TelegramView are nevoie de interfață Material? (e admin-only)
+- [ ] Cum gestionăm paginile cu mai mult de 4 acțiuni în app bar?
+- [ ] OCRMetricsView necesită bottom nav sau e pagină secundară?
+
+---
+
+## Implementare Sugerată (Ordinea User Stories)
+
+### Faza 1: Fundație (US-101, US-102)
+1. Extract componente comune
+2. Definire MD3 tokens
+
+### Faza 2: Refactor Bonuri (US-103, US-104, US-105)
+3. Validare API componente pe bonuri
+4. Fix buton delete duplicat
+5. Adaugă navigare înapoi
+
+### Faza 3: Dashboard (US-106)
+6. Implement swipeable cards
+
+### Faza 4: Reports Module (US-107, US-108, US-109, US-110, US-111)
+7. Apply pattern la fiecare pagină Reports
+
+### Faza 5: Shared Components (US-112, US-113)
+8. Bottom Sheet pentru filtre
+9. Batch actions contextuale
+
+### Faza 6: Testing (US-114)
+10. Cross-device testing
+
+### Faza 7: Documentație (US-115, US-116, US-117, US-118, US-119, US-120)
+11. Creare MOBILE_PATTERNS.md dedicat
+12. Actualizare CSS_PATTERNS.md cu referințe
+13. Actualizare DESIGN_TOKENS.md cu MD3
+14. Actualizare CLAUDE.md cu reguli mobile
+15. Actualizare claude-learn-frontend.md cu patterns
+16. Validare documentație cu fresh developer test
+
+---
+
+## Anexa A: Fișiere de Documentație Afectate
+
+| Fișier | Tip Modificare | User Story |
+|--------|---------------|------------|
+| `docs/MOBILE_PATTERNS.md` | NOU | US-118 |
+| `docs/CSS_PATTERNS.md` | Update | US-115 |
+| `docs/DESIGN_TOKENS.md` | Update | US-116 |
+| `CLAUDE.md` | Update | US-117 |
+| `.claude/rules/claude-learn-frontend.md` | Update | US-119 |
+
+## Anexa B: Structura Documentație Finală
+
+```
+docs/
+├── MOBILE_PATTERNS.md # NOU - ghid complet mobile MD
+├── CSS_PATTERNS.md # + link la MOBILE_PATTERNS.md
+├── DESIGN_TOKENS.md # + secțiune MD3 tokens
+├── ONBOARDING_CSS.md # + menționare mobile patterns
+└── ...
+
+CLAUDE.md # + secțiune Mobile Development Rules
+
+.claude/rules/
+└── claude-learn-frontend.md # + patterns & gotchas noi
+```