# 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:**
```css
.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:**
```css
.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
```javascript
// 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
5. **US-036**: Afișare Nume Fișier pentru Toate Bonurile
6. **US-038**: Mobile - Selecție Multiplă prin Long-Press
7. **US-039**: Mobile - Select All și Buton Ștergere

### Faza 3: Mobile Native Layout
8. **US-040**: Mobile - Layout Android pentru Lista Bonuri
9. **US-041**: Mobile - Layout Android pentru Editare/Creare
10. **US-042**: Mobile - Layout Android pentru Vizualizare

---

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