Files
roa2web-service-auto/tasks/prd-mobile-ux-improvements.md
Claude Agent 7b3541403f feat(data-entry): Bulk Receipt Upload cu Mobile UX Android Nativ
## Funcționalități Principale

### Bulk Upload & Processing
- Drag & drop pentru upload bonuri multiple oriunde pe pagină
- Batch processing cu job queue și worker pool
- Real-time updates via SSE (Server-Sent Events) cu fallback polling
- Duplicate detection via SHA-256 file hash
- Auto-retry pentru job-uri failed
- Cancel individual jobs sau batch complet

### Mobile UX - Android Native Style
- Top bar fixă cu hamburger, titlu centrat, acțiuni (search/filter)
- Bottom navigation cu 4 tab-uri (Bonuri, Upload, Rapoarte, Setări)
- FAB (Floating Action Button) cu hide/show on scroll
- Filter chips orizontal scrollabile
- Selecție multiplă prin long-press (500ms)
- Select All + Bulk Delete cu confirmare
- Layout Android pentru Create/Edit/View bon (Gmail compose style)

### Bug Fixes
- Refresh individual via SSE în loc de refresh total pagină
- Bonurile cu eroare OCR rămân vizibile pentru editare manuală
- Afișare nume fișier original pentru toate bonurile
- Upload stabil pe mobil (fix race condition File API)
- Păstrare ordine bonuri la refresh (nu se reordonează)

### Backend
- SSE endpoint pentru status updates real-time
- Bulk delete endpoint cu partial success
- Auto-cleanup bonuri failed după 7 zile
- Batch model cu tracking complet

### Testing
- E2E tests cu Playwright
- Unit tests pentru bulk upload, auto-create, cleanup

## Commits Squashed: 43 user stories (US-001 → US-043)
## Branch: ralph/bulk-receipt-upload
## Timp dezvoltare: ~3 zile (Ralph autonomous)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-12 08:33:17 +00:00

16 KiB

PRD: Mobile UX Improvements & Bulk Upload Bug Fixes

1. Introducere

Acest PRD adresează multiple probleme identificate în modulul de bulk upload bonuri și îmbunătățiri UX pentru interfața mobilă. Problemele includ refresh incorect al listei, pierderea bonurilor cu eroare, lipsa selecției multiple pe mobil, și nevoia unei interfețe mai native pentru Android.

Branch de lucru: ralph/bulk-receipt-upload (continuăm în același branch)

Context: PRD-ul anterior (prd-bulk-receipt-upload.md) a implementat funcționalitatea de bază, dar testarea în producție a evidențiat probleme de UX și bugs ce necesită rezolvare.

2. Obiective

Obiectiv Principal

  • Corectarea comportamentului de refresh pentru a păstra bonurile cu eroare în listă și a menține ordinea

Obiective Secundare

  • Implementarea selecției multiple pe mobil cu interfață în stil Android nativ
  • Afișarea numelui fișierului pentru toate bonurile (nu doar cele în procesare)
  • Rezolvarea bug-ului de refresh automat la selectarea fișierelor

Metrici de Succes

  • Zero bonuri "pierdute" după procesare bulk
  • Timp de selecție multiple pe mobil < 3 secunde pentru 10 bonuri
  • User satisfaction score > 4/5 pentru interfața mobilă

3. User Stories

US-034: Fix - Refresh Individual vs Refresh Total

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 în listă

Acceptance Criteria:

  • SSE handler NU apelează store.fetchReceipts() când un receipt nu este în pagina curentă
  • În schimb, verifică dacă receipt-ul aparține unui batch activ și îl adaugă local
  • Ordinea bonurilor din batch rămâne stabilă (nu se reordonează)
  • Bonurile noi din procesare se inserează în poziția corectă
  • npm run typecheck passes
  • Verify in browser: uploadează 5 bonuri, nu se reîncarcă pagina între procesări

Technical Notes:

  • 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

US-035: Fix - Bonuri cu Eroare Rămân în Listă

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

Acceptance Criteria:

  • 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

Technical Notes:

  • Bonurile cu eroare ar trebui să aibă status='draft' și processing_status='failed'
  • Nu se șterg la refresh, doar se actualizează in-place

US-036: Afișare Nume Fișier pentru Toate Bonurile

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

Acceptance Criteria:

  • Coloana "Fișier" afișează original_filename și pentru receipt-uri completate, nu doar pentru job-uri
  • Pe mobil, numele fișierului apare sub partenăr (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

Technical Notes:

  • Backend trebuie să populeze original_filename pe receipt din job-ul OCR
  • Verifică că auto-save service copiază filename din job la receipt

US-037: Fix - Upload Nu Mai Face Refresh Automat

Ca utilizator Vreau ca selectarea fișierelor să nu reîncarce pagina Pentru că pierd fișierele selectate înainte să apăs "Procesează"

Acceptance Criteria:

  • 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ă

Technical Notes:

  • 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

US-038: Mobile - Selecție Multiplă prin Long-Press

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

Acceptance Criteria:

  • Long-press (500ms) pe un card activează modul de selecție
  • Card-ul selectat primește checkmark și background diferit
  • După activare, tap simplu pe alte carduri le adaugă/elimină din selecție
  • Tap în afara cardurilor (pe background) 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

CSS Requirements:

  • .receipt-card.selected { background: var(--blue-50); border-color: var(--blue-500); }
  • .receipt-card .selection-check { position: absolute; top: 8px; right: 8px; }
  • Testează dark mode: background selectat vizibil

US-039: Mobile - Select All și Buton Ștergere

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

Acceptance Criteria:

  • În modul selecție, apare top bar contextual cu:
    • Numărul de selectate: "X selectate"
    • Buton "Selectează tot"
    • Buton X pentru a ieși din modul selecție
  • 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ă

CSS Requirements:

  • Top bar: position: sticky; top: 0; z-index: 100;
  • Bottom bar: position: fixed; bottom: 0; left: 0; right: 0;
  • Animație slide-in pentru bars

US-040: Mobile - Layout Android Nativ pentru Lista Bonuri

Ca utilizator mobil Vreau o interfață similară cu aplicațiile Android native Pentru că vreau experiență familiară și intuitivă

Acceptance Criteria:

  • Top Bar fixă cu:
    • Stânga: Hamburger menu / Back arrow
    • Centru: Titlu "Bonuri Fiscale"
    • Dreapta: Search icon, Filter icon, More options (3 dots)
  • Filter Chips sub top bar (orizontal scrollabil):
    • Toate, Ciorne, În așteptare, Validate, Respinse
    • Chip activ are background primary color
  • Bottom Navigation fixă cu 4 tab-uri:
    • Bonuri (icon receipt, activ)
    • Upload (icon cloud-upload)
    • Rapoarte (icon chart)
    • Setări (icon cog)
  • FAB (Floating Action Button) în colț dreapta jos:
    • Icon "+" pentru adăugare bon nou
    • Se ascunde când se face 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

CSS Requirements:

.mobile-top-bar {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: 56px;
  background: var(--surface-card);
  border-bottom: 1px solid var(--surface-border);
  z-index: 1000;
}

.mobile-bottom-nav {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  height: 56px;
  background: var(--surface-card);
  border-top: 1px solid var(--surface-border);
  z-index: 1000;
}

.mobile-fab {
  position: fixed;
  bottom: 72px; /* above bottom nav */
  right: 16px;
  width: 56px;
  height: 56px;
  border-radius: 16px;
  background: var(--primary-500);
  box-shadow: var(--shadow-lg);
}

US-041: Mobile - Layout Android pentru Editare/Creare Bon

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

Acceptance Criteria:

  • Top Bar cu:
    • Stânga: X (close) sau Back arrow
    • Centru: "Bon Nou" / "Editare Bon #123"
    • Dreapta: Attach icon, Save/Submit icon
  • Content Area scrollabilă cu form fields
  • Bottom Action Bar fixă cu butoane:
    • "Salvează Ciornă" (secondary)
    • "Trimite pentru Validare" (primary)
  • Form fields ocupă 100% width pe mobil
  • Keyboard-aware: bottom bar se mută deasupra tastaturii
  • npm run typecheck passes
  • Verify on mobile: layout similar cu Gmail compose

CSS Requirements:

.mobile-receipt-form {
  padding-bottom: 80px; /* space for bottom bar */
}

.mobile-form-bottom-bar {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  padding: var(--space-sm) var(--space-md);
  background: var(--surface-card);
  border-top: 1px solid var(--surface-border);
  display: flex;
  gap: var(--space-sm);
}

.mobile-form-bottom-bar .p-button {
  flex: 1;
}

US-042: Mobile - Layout Android pentru Vizualizare Bon

Ca utilizator mobil Vreau interfață de vizualizare bon similară cu view email în Gmail Pentru că vreau acțiuni rapide și navigare ușoară

Acceptance Criteria:

  • Top Bar cu:
    • Stânga: Back arrow
    • Dreapta: Edit icon, Delete icon, More options
  • Content Area cu detalii bon (read-only)
  • Bottom Action Bar cu butoane contextuale:
    • Pentru DRAFT: "Editează", "Trimite"
    • Pentru PENDING: "Validează", "Respinge" (dacă are permisiuni)
    • Pentru APPROVED: "Anulează validare" (dacă are permisiuni)
  • Swipe left/right pentru navigare între bonuri (optional, nice-to-have)
  • npm run typecheck passes
  • Verify on mobile: acțiuni accesibile din bottom bar

US-043: Păstrare Ordine Bonuri la Refresh

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

Acceptance Criteria:

  • Bonurile din același batch păstrează ordinea de upload (nu se reordonează alfabetic sau by date)
  • 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 (pull-to-refresh) poate reordona, dar SSE updates nu
  • npm run typecheck passes
  • Verify in browser: bon procesat nu își schimbă poziția în listă

Technical Notes:

  • Lista trebuie sortată by created_at DESC sau by batch order, nu by last_modified
  • updateReceiptInPlace din store NU trebuie să reordoneze array-ul

4. Cerințe Funcționale

  1. [REQ-011] Bonurile cu eroare OCR rămân vizibile în listă cu status "Eroare"
  2. [REQ-012] Refresh via SSE NU reîncarcă toată lista, doar actualizează individual
  3. [REQ-013] Numele fișierului original e afișat pentru toate bonurile
  4. [REQ-014] Selecția multiplă pe mobil funcționează via long-press
  5. [REQ-015] Interfața mobilă urmează design patterns Android Material
  6. [REQ-016] Bottom navigation are 4 tab-uri: Bonuri, Upload, Rapoarte, Setări
  7. [REQ-017] FAB pentru "Bon Nou" în colț dreapta jos pe mobil
  8. [REQ-018] Ordinea bonurilor rămâne stabilă în cadrul unui batch

5. Non-Goals (Ce NU facem)

  • NU facem swipe gestures pentru acțiuni (delete/archive) - prea complex
  • NU facem animații complexe de tranziție între pagini
  • NU schimbăm layout-ul desktop - doar mobil
  • NU facem tab-uri funcționale pentru Rapoarte/Setări (placeholder pentru moment)
  • NU facem pull-to-refresh - refresh via SSE e suficient
  • NU facem offline mode sau caching local

6. Considerații Tehnice

Stack/Tehnologii

  • Frontend: Vue 3 Composition API, PrimeVue
  • Mobile Detection: window.innerWidth < 768 sau navigator.userAgent
  • Touch Events: Native touchstart/touchend pentru long-press

Patterns de Urmat

  • Design tokens din docs/DESIGN_TOKENS.md
  • CSS patterns din docs/CSS_PATTERNS.md
  • Mobile-first responsive approach

⚠️ Mobile Long-Press Implementation

// Long-press detection (500ms)
let pressTimer = null

const onTouchStart = (item) => {
  pressTimer = setTimeout(() => {
    enterSelectionMode(item)
  }, 500)
}

const onTouchEnd = () => {
  clearTimeout(pressTimer)
}

const onTouchMove = () => {
  clearTimeout(pressTimer) // Cancel if user drags
}

Dependențe

  • Store existent: receiptsStore.js
  • SSE Service: sseService.js
  • Batch Progress Store: batchProgressStore.js

Riscuri Tehnice

  • Touch event conflicts: Long-press poate conflicta cu scroll pe mobile
    • Mitigare: Setează threshold mic pentru detectare scroll vs. hold
  • Performance: Lista mare poate încetini selecția
    • Mitigare: Virtual scrolling dacă > 100 items
  • Cross-browser: Safari iOS poate avea comportament diferit
    • Mitigare: Test explicit pe Safari iOS

7. Considerații UI/UX

Mobile Layout Reference (din imagini)

img1.jpg & img2.jpg (WhatsApp style):

  • Top bar contextual cu count și acțiuni
  • Filter chips orizontal scrollabile
  • Bottom navigation cu 4 tabs
  • FAB în colț dreapta jos

img3.jpg & img4.jpg (Gmail style):

  • Top bar minimalist cu back + acțiuni
  • Bottom action bar cu butoane contextuale
  • Full-width content area

Stări Mobile

Stare Top Bar Content Bottom
Normal Title + Search + Filter Lista carduri Bottom Nav + FAB
Selection Mode "X selectate" + Select All + Close Carduri cu checkmarks Delete button
View Receipt Back + Edit + Delete Detalii bon Acțiuni contextuale
Edit Receipt Close + Attach + Save Form fields Save Draft + Submit

Accesibilitate

  • Touch targets minim 48x48px
  • Contrast suficient pentru badges și text secundar
  • Screen reader support pentru selection mode

8. Success Metrics

  • Bug Fixes: 0 bonuri pierdute la procesare bulk
  • Upload Success: 0 refresh-uri neintenționate la selectare fișiere
  • Selection Time: < 2 secunde pentru selectare 5 bonuri
  • User Feedback: Score > 4/5 pentru "Interfața mobilă e intuitivă"

9. Open Questions

  • FAB-ul trebuie să aibă sub-menu (speed dial) pentru "Bon Nou" + "Upload Bulk"?
  • Bottom navigation tab "Upload" deschide file picker direct sau navighează la pagină separată?
  • Swipe gestures pentru delete/archive - implementăm în versiunea inițială sau amânăm?
  • Animație de highlight când un bon termină procesarea - fade green sau pulse?

10. Dependențe între User Stories

US-034 (Fix Refresh) ─┬─→ US-035 (Erori rămân) → US-036 (Filename)
                      │
US-037 (Fix Upload) ──┘

US-038 (Long-press) → US-039 (Select All + Delete)
                              ↓
US-040 (Mobile List Layout) ←─┘
         ↓
US-041 (Mobile Edit Layout) → US-042 (Mobile View Layout)

US-043 (Ordine) - independent, poate fi făcut oricând

Ordine recomandată de implementare:

Faza 1: Bug Fixes (Critice)

  1. US-037: Fix Upload Nu Mai Face Refresh Automat
  2. US-034: Fix Refresh Individual vs Total
  3. US-035: Bonuri cu Eroare Rămân în Listă
  4. US-043: Păstrare Ordine Bonuri

Faza 2: Mobile Enhancements

  1. US-036: Afișare Nume Fișier pentru Toate Bonurile
  2. US-038: Mobile - Selecție Multiplă prin Long-Press
  3. US-039: Mobile - Select All și Buton Ștergere

Faza 3: Mobile Native Layout

  1. US-040: Mobile - Layout Android pentru Lista Bonuri
  2. US-041: Mobile - Layout Android pentru Editare/Creare
  3. US-042: Mobile - Layout Android pentru Vizualizare

Last Updated: 2026-01-12 Author: Claude Code Status: Draft - Pending Review