feat(mobile-fixes-phase4): Complete US-401 - Fix Layout Principal - Ascundere Header Desktop pe Mobil
Implemented by Ralph autonomous loop. Iteration: 1 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"projectName": "mobile-fixes-phase3",
|
||||
"projectName": "mobile-fixes-phase4",
|
||||
"branchName": "ralph/unified-mobile-md",
|
||||
"description": "Corectări navigare mobilă: footer restructurat, tab-uri Clienți/Furnizori, FAB pe Bonuri, hamburger grupat",
|
||||
"description": "Fix layout mobil: ascundere header desktop, butoane filter/export vizibile, MobileDrawerMenu cu ANALIZE, persistență bonuri cu eroare",
|
||||
"cssRules": {
|
||||
"documentation": [
|
||||
"docs/ONBOARDING_CSS.md",
|
||||
@@ -16,7 +16,8 @@
|
||||
"NICIODATĂ :deep() în componente (PrimeVue → vendor/)",
|
||||
"Mobile: toate paginile folosesc MobileTopBar + MobileBottomNav",
|
||||
"Mobile: filtrele se pun în BottomSheet, NU inline",
|
||||
"Mobile: tab-uri pentru switch Clienți/Furnizori"
|
||||
"Mobile: v-if='isMobile' pentru componente mobile-only",
|
||||
"Desktop: v-if='!isMobile' pentru componente desktop-only"
|
||||
],
|
||||
"mobileLayoutTokens": {
|
||||
"topBarHeight": "56px",
|
||||
@@ -28,189 +29,133 @@
|
||||
},
|
||||
"userStories": [
|
||||
{
|
||||
"id": "US-307",
|
||||
"title": "Restructurare Footer Nav (4 butoane noi)",
|
||||
"description": "Ca utilizator mobil vreau footer navigation cu: Dashboard | Bonuri | Facturi | Setări",
|
||||
"id": "US-401",
|
||||
"title": "Fix Layout Principal - Ascundere Header Desktop pe Mobil",
|
||||
"description": "Ca utilizator mobil vreau să văd doar MobileTopBar și MobileBottomNav, nu header-ul desktop",
|
||||
"priority": 1,
|
||||
"acceptanceCriteria": [
|
||||
"MobileBottomNav cu 4 butoane: Dashboard, Bonuri, Facturi, Setări",
|
||||
"Dashboard: icon pi-home, route /dashboard",
|
||||
"Bonuri: icon pi-receipt, route /data-entry",
|
||||
"Facturi: icon pi-file-edit, route /reports/invoices",
|
||||
"Setări: icon pi-cog, route /settings",
|
||||
"Active state corect pe fiecare pagină",
|
||||
"Ștergere link Upload din footer (mutat în FAB)",
|
||||
"npm run build passes"
|
||||
"AppHeader.vue sau componenta părinte are v-if='!isMobile' pentru a se ascunde pe mobil",
|
||||
"Sidebar-ul desktop (navigation cu Rapoarte/Introduceri Date/Sistem) este ascuns pe mobil cu v-if='!isMobile'",
|
||||
"MobileTopBar este singurul header vizibil pe viewport < 768px",
|
||||
"Nu există suprapunere între header desktop și MobileTopBar",
|
||||
"isMobile computed folosește window.innerWidth < 768 și este reactiv la resize",
|
||||
"npm run build passes",
|
||||
"Verify in browser (375x667): Header desktop cu 'Selectare perioada' și 'AXN' NU este vizibil"
|
||||
],
|
||||
"passes": true,
|
||||
"notes": "Completed in iteration 1"
|
||||
},
|
||||
{
|
||||
"id": "US-308",
|
||||
"title": "Actualizare Hamburger Menu - Grupat pe Categorii",
|
||||
"description": "Ca utilizator mobil vreau meniul hamburger organizat pe categorii clare",
|
||||
"id": "US-402",
|
||||
"title": "Fix MobileTopBar - Butoane Filter/Export Vizibile",
|
||||
"description": "Ca utilizator mobil pe pagina Facturi/Bonuri vreau să văd butoanele de filtrare și export în header",
|
||||
"priority": 2,
|
||||
"acceptanceCriteria": [
|
||||
"MobileDrawerMenu.vue restructurat cu secțiuni vizuale",
|
||||
"Secțiune PRINCIPALE: Dashboard → /dashboard, Bonuri → /data-entry",
|
||||
"Secțiune RAPOARTE: Facturi → /reports/invoices, Balanță → /reports/trial-balance, Casa și Banca → /reports/bank-cash",
|
||||
"Secțiune ANALIZE: Scadențe → /reports/maturity-analysis, Facturi Detaliate → /reports/detailed-invoices",
|
||||
"Secțiune ADMINISTRARE: Setări → /settings",
|
||||
"Separatori vizuali între secțiuni",
|
||||
"Header cu logo, Footer cu profil utilizator și logout",
|
||||
"npm run build passes"
|
||||
"După US-401, pe InvoicesView.vue butoanele Filter/Refresh/Export sunt vizibile în MobileTopBar",
|
||||
"Pe ReceiptsListView.vue butoanele Filter/Export/More sunt vizibile în MobileTopBar",
|
||||
"Butoanele au dimensiune touch target minim 48px",
|
||||
"npm run build passes",
|
||||
"Verify in browser (375x667): Butoanele sunt vizibile și clickable pe pagina Facturi"
|
||||
],
|
||||
"passes": true,
|
||||
"notes": "Completed in iteration 2"
|
||||
"passes": false,
|
||||
"notes": "Depinde de US-401 - butoanele există dar sunt acoperite de header-ul desktop"
|
||||
},
|
||||
{
|
||||
"id": "US-304",
|
||||
"title": "Tab-uri Clienți/Furnizori în Facturi",
|
||||
"description": "Ca utilizator vreau pagina Facturi să aibă tab-uri pentru Clienți și Furnizori",
|
||||
"id": "US-403",
|
||||
"title": "Fix MobileDrawerMenu - Secțiunea ANALIZE Vizibilă",
|
||||
"description": "Ca utilizator mobil vreau să văd secțiunea ANALIZE în hamburger menu",
|
||||
"priority": 3,
|
||||
"acceptanceCriteria": [
|
||||
"InvoicesView.vue modificat cu tab-uri: Clienți | Furnizori",
|
||||
"Tab-uri sub MobileTopBar (design Material, full-width)",
|
||||
"Switch între tab-uri păstrează filtrele active",
|
||||
"Default: primul tab activ (Clienți)",
|
||||
"URL query param pentru tab activ (?tab=suppliers)",
|
||||
"MobileTopBar cu title Facturi",
|
||||
"MobileBottomNav activ (Facturi highlighted)",
|
||||
"npm run build passes"
|
||||
"Click pe butonul Meniu din MobileTopBar deschide MobileDrawerMenu (nu sidebar desktop)",
|
||||
"MobileDrawerMenu afișează secțiunile: PRINCIPALE, RAPOARTE, ANALIZE, ADMINISTRARE",
|
||||
"Secțiunea ANALIZE conține: Scadențe (/reports/maturity-analysis), Facturi Detaliate (/reports/detailed-invoices)",
|
||||
"Link-urile din ANALIZE navighează corect și închid drawer-ul",
|
||||
"npm run build passes",
|
||||
"Verify in browser (375x667): Click pe Meniu → apare MobileDrawerMenu cu secțiunea ANALIZE vizibilă"
|
||||
],
|
||||
"passes": true,
|
||||
"notes": "Completed in iteration 1"
|
||||
"passes": false,
|
||||
"notes": "Depinde de US-401 - hamburger-ul deschidea sidebar-ul desktop"
|
||||
},
|
||||
{
|
||||
"id": "US-305",
|
||||
"title": "Tab-uri Clienți/Furnizori în Scadențe",
|
||||
"description": "Ca utilizator vreau pagina Scadențe să aibă tab-uri pentru Clienți și Furnizori",
|
||||
"id": "US-404",
|
||||
"title": "Fix Spațiu Blank - Padding Corect pentru Mobile",
|
||||
"description": "Ca utilizator mobil vreau ca paginile să nu aibă spațiu blank excesiv în partea de sus",
|
||||
"priority": 4,
|
||||
"acceptanceCriteria": [
|
||||
"MaturityAnalysisView.vue modificat cu tab-uri: Clienți | Furnizori",
|
||||
"Tab-uri sub MobileTopBar (design Material, full-width)",
|
||||
"Switch între tab-uri păstrează filtrele active",
|
||||
"Default: primul tab activ (Clienți)",
|
||||
"URL query param pentru tab activ (?tab=suppliers)",
|
||||
"MobileTopBar cu title Scadențe și buton ← Înapoi",
|
||||
"MobileBottomNav activ",
|
||||
"npm run build passes"
|
||||
"Paginile de rapoarte au padding-top: 56px (doar MobileTopBar height) pe mobil",
|
||||
"Nu există spațiu blank între MobileTopBar și conținut",
|
||||
"Tab-urile Clienți/Furnizori sunt imediat sub MobileTopBar pe InvoicesView",
|
||||
"Status chips sunt imediat sub MobileTopBar pe ReceiptsListView",
|
||||
"npm run build passes",
|
||||
"Verify in browser (375x667): Conținutul începe imediat sub MobileTopBar, fără gap de ~120px"
|
||||
],
|
||||
"passes": true,
|
||||
"notes": "Completed in iteration 2"
|
||||
"passes": false,
|
||||
"notes": "Depinde de US-401 - spațiul era ocupat de header-ul desktop ascuns incorect"
|
||||
},
|
||||
{
|
||||
"id": "US-301",
|
||||
"title": "Buton Înapoi în Creare/Editare/Vizualizare Bon",
|
||||
"description": "Ca utilizator mobil vreau buton ← Înapoi în MobileTopBar pe pagina de bon",
|
||||
"id": "US-405",
|
||||
"title": "Fix batchProgressStore - Restaurare Joburi Failed",
|
||||
"description": "Ca utilizator care a uploadat bonuri cu erori OCR vreau ca acestea să rămână vizibile după refresh",
|
||||
"priority": 5,
|
||||
"acceptanceCriteria": [
|
||||
"ReceiptCreateUnifiedView.vue are MobileTopBar cu showBack=true",
|
||||
"Click pe ← navighează la /data-entry (lista bonuri)",
|
||||
"Funcționează în toate modurile: create, edit, view",
|
||||
"Verify in browser: butonul apare și funcționează",
|
||||
"În batchProgressStore.js, funcția restoreJobsFromBatch() include joburi cu status 'failed' (nu doar pending/processing)",
|
||||
"Batch-ul NU este șters din localStorage dacă are joburi failed nerezolvate",
|
||||
"După refresh, bonurile cu eroare sunt afișate în listă",
|
||||
"unifiedItems computed include joburile failed pentru afișare",
|
||||
"npm run build passes"
|
||||
],
|
||||
"passes": true,
|
||||
"notes": "Completed in iteration 3"
|
||||
"passes": false,
|
||||
"notes": ""
|
||||
},
|
||||
{
|
||||
"id": "US-302",
|
||||
"title": "Footer Nav pe toate Paginile de Setări",
|
||||
"description": "Ca utilizator mobil vreau MobileBottomNav pe toate paginile din secțiunea Setări",
|
||||
"id": "US-406",
|
||||
"title": "Fix UI Bonuri cu Eroare - Afișare Corectă pe Mobil",
|
||||
"description": "Ca utilizator mobil vreau să văd clar că un bon are eroare, nu 'în procesare'",
|
||||
"priority": 6,
|
||||
"acceptanceCriteria": [
|
||||
"OCRMetricsView.vue include MobileBottomNav cu Setări activ",
|
||||
"CacheStatsView.vue include MobileBottomNav cu Setări activ",
|
||||
"ServerLogsView.vue include MobileBottomNav cu Setări activ",
|
||||
"TelegramAdminView.vue include MobileBottomNav cu Setări activ (dacă există)",
|
||||
"SettingsHubView.vue include MobileBottomNav cu Setări activ",
|
||||
"npm run build passes"
|
||||
"Bonurile cu status 'failed' afișează chip/badge 'Eroare' cu culoare roșie (var(--red-500))",
|
||||
"NU afișează 'În procesare' sau spinner pentru bonuri failed",
|
||||
"Mesajul de eroare este vizibil (truncat cu ellipsis dacă e prea lung)",
|
||||
"Utilizatorul poate vedea eroarea completă la click/hover",
|
||||
"npm run build passes",
|
||||
"Verify in browser (375x667): Bon cu eroare arată 'Eroare' nu 'În procesare'"
|
||||
],
|
||||
"passes": true,
|
||||
"notes": "Completed in iteration 4"
|
||||
"passes": false,
|
||||
"notes": "Depinde de US-405 - bonurile failed trebuie să fie în listă mai întâi"
|
||||
},
|
||||
{
|
||||
"id": "US-303",
|
||||
"title": "FAB pe Pagina Bonuri (Mutare Upload)",
|
||||
"description": "Ca utilizator mobil vreau funcția Upload să fie în butonul FAB (+) pe pagina Bonuri",
|
||||
"id": "US-407",
|
||||
"title": "Fix Editare Bonuri cu Eroare",
|
||||
"description": "Ca utilizator care are un bon cu eroare OCR vreau să pot edita bonul pentru a corecta erorile manual",
|
||||
"priority": 7,
|
||||
"acceptanceCriteria": [
|
||||
"ReceiptsListView.vue are buton FAB (+) în colțul dreapta-jos",
|
||||
"Click pe FAB deschide meniu popup: Bon Nou | Upload Bulk",
|
||||
"FAB poziționat deasupra MobileBottomNav (bottom: 72px)",
|
||||
"Bon Nou navighează la /data-entry/receipts/new",
|
||||
"Upload Bulk navighează la /data-entry/bulk-upload",
|
||||
"FAB vizibil doar pe mobil (isMobile)",
|
||||
"npm run build passes"
|
||||
"Click pe bon cu eroare deschide formularul de editare (ReceiptCreateUnifiedView)",
|
||||
"La salvare, processing_status este resetat la NULL în baza de date",
|
||||
"După salvare, bonul poate fi trimis pe workflow (Submit for Approval)",
|
||||
"Backend endpoint PATCH /receipts/{id} resetează processing_status la NULL când se salvează modificări",
|
||||
"npm run build passes",
|
||||
"Verify in browser: Editează bon cu eroare → Salvează → Statusul nu mai arată eroare"
|
||||
],
|
||||
"passes": true,
|
||||
"notes": "Completed in iteration 5"
|
||||
"passes": false,
|
||||
"notes": ""
|
||||
},
|
||||
{
|
||||
"id": "US-306",
|
||||
"title": "Restaurare Butoane Export și Filtrare pe Rapoarte",
|
||||
"description": "Ca utilizator mobil vreau butoane de export și filtrare pe toate rapoartele",
|
||||
"id": "US-408",
|
||||
"title": "Verificare Finală - Toate Fix-urile Funcționează",
|
||||
"description": "Ca developer vreau să confirm că toate fix-urile din Phase 4 funcționează corect",
|
||||
"priority": 8,
|
||||
"acceptanceCriteria": [
|
||||
"InvoicesView.vue: buton Export (pi-download) și Filtrare (pi-filter) în MobileTopBar actions",
|
||||
"TrialBalanceView.vue: buton Export și Filtrare în MobileTopBar actions",
|
||||
"BankCashRegisterView.vue: buton Export și Filtrare în MobileTopBar actions",
|
||||
"ReceiptsListView.vue: buton Export și Filtrare în MobileTopBar actions",
|
||||
"MaturityAnalysisView.vue: buton Export și Filtrare în MobileTopBar actions",
|
||||
"Click pe Filtrare deschide BottomSheet cu filtrele paginii",
|
||||
"Viewport 375x667: Header desktop (Selectare perioada, AXN) NU este vizibil",
|
||||
"Viewport 375x667: MobileTopBar cu butoane Filter/Export este vizibil",
|
||||
"Click pe Meniu deschide MobileDrawerMenu cu secțiunea ANALIZE",
|
||||
"Pagina Facturi: Tab-uri Clienți/Furnizori imediat sub header, fără spațiu blank",
|
||||
"Pagina Bonuri: Status chips imediat sub header, fără spațiu blank",
|
||||
"Upload bon cu eroare: Afișează 'Eroare' nu 'În procesare'",
|
||||
"Refresh după upload cu eroare: Bonul cu eroare rămâne vizibil în listă",
|
||||
"npm run build passes"
|
||||
],
|
||||
"passes": true,
|
||||
"notes": "Completed in iteration 6"
|
||||
},
|
||||
{
|
||||
"id": "US-309",
|
||||
"title": "Cleanup Dashboard Mobile",
|
||||
"description": "Ca utilizator mobil vreau Dashboard-ul să afișeze doar KPIs fără quick-links",
|
||||
"priority": 9,
|
||||
"acceptanceCriteria": [
|
||||
"DashboardView.vue pe mobil: ștergere quick-link cards dacă există",
|
||||
"Doar SwipeableCards cu KPIs pe mobil",
|
||||
"Desktop rămâne neschimbat",
|
||||
"MobileTopBar cu title Dashboard",
|
||||
"MobileBottomNav cu Dashboard activ",
|
||||
"npm run build passes"
|
||||
],
|
||||
"passes": true,
|
||||
"notes": "Completed in iteration 7"
|
||||
},
|
||||
{
|
||||
"id": "US-310",
|
||||
"title": "Actualizare Router cu Modificările",
|
||||
"description": "Ca developer vreau router-ul actualizat pentru a funcționa cu noile pagini",
|
||||
"priority": 10,
|
||||
"acceptanceCriteria": [
|
||||
"Rută /reports/invoices → InvoicesView funcțională",
|
||||
"Rută /reports/maturity-analysis → MaturityAnalysisView funcțională",
|
||||
"Rutele existente păstrate: /reports/trial-balance, /reports/bank-cash, /reports/detailed-invoices",
|
||||
"Cleanup rute nefolosite dacă există",
|
||||
"Toate rutele lazy loaded",
|
||||
"npm run build passes"
|
||||
],
|
||||
"passes": true,
|
||||
"notes": "Completed in iteration 8"
|
||||
},
|
||||
{
|
||||
"id": "US-311",
|
||||
"title": "Actualizare Documentație MOBILE_PATTERNS.md",
|
||||
"description": "Ca developer viitor vreau documentația actualizată cu modificările din Phase 3",
|
||||
"priority": 11,
|
||||
"acceptanceCriteria": [
|
||||
"Secțiune actualizată: Footer Navigation (Dashboard, Bonuri, Facturi, Setări)",
|
||||
"Secțiune nouă: FAB Pattern pentru acțiuni contextuale",
|
||||
"Secțiune nouă: Tab Pattern pentru switch Clienți/Furnizori",
|
||||
"Secțiune actualizată: Hamburger Menu grupat pe categorii",
|
||||
"Diagrame ASCII actualizate cu noua structură navigare",
|
||||
"npm run build passes"
|
||||
],
|
||||
"passes": true,
|
||||
"notes": "Completed in iteration 9"
|
||||
"passes": false,
|
||||
"notes": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
30
src/App.vue
30
src/App.vue
@@ -1,8 +1,8 @@
|
||||
<template>
|
||||
<div id="app">
|
||||
<!-- Header -->
|
||||
<!-- Desktop Header - hidden on mobile (viewport < 768px) -->
|
||||
<AppHeader
|
||||
v-if="authStore.isAuthenticated"
|
||||
v-if="authStore.isAuthenticated && !isMobile"
|
||||
title="ROA2WEB"
|
||||
brand-link="/reports/dashboard"
|
||||
:menu-open="menuOpen"
|
||||
@@ -15,9 +15,9 @@
|
||||
@period-changed="handlePeriodChanged"
|
||||
/>
|
||||
|
||||
<!-- Slide Menu -->
|
||||
<!-- Desktop Slide Menu - hidden on mobile (viewport < 768px) -->
|
||||
<SlideMenu
|
||||
v-if="authStore.isAuthenticated"
|
||||
v-if="authStore.isAuthenticated && !isMobile"
|
||||
:is-open="menuOpen"
|
||||
:menu-items="enabledMenuItems"
|
||||
:current-user="authStore.currentUser"
|
||||
@@ -25,8 +25,8 @@
|
||||
@logout="handleLogout"
|
||||
/>
|
||||
|
||||
<!-- Main Content -->
|
||||
<main class="main-content" :class="{ 'with-navbar': authStore.isAuthenticated }">
|
||||
<!-- Main Content - with-navbar only on desktop when authenticated -->
|
||||
<main class="main-content" :class="{ 'with-navbar': authStore.isAuthenticated && !isMobile }">
|
||||
<router-view />
|
||||
</main>
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, onMounted, watch } from 'vue'
|
||||
import { ref, computed, onMounted, onUnmounted, watch } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import AppHeader from '@shared/components/layout/AppHeader.vue'
|
||||
import SlideMenu from '@shared/components/layout/SlideMenu.vue'
|
||||
@@ -52,6 +52,14 @@ import axios from 'axios'
|
||||
|
||||
const router = useRouter()
|
||||
|
||||
// Mobile detection - reactive with resize listener
|
||||
const windowWidth = ref(typeof window !== 'undefined' ? window.innerWidth : 1024)
|
||||
const isMobile = computed(() => windowWidth.value < 768)
|
||||
|
||||
const handleResize = () => {
|
||||
windowWidth.value = window.innerWidth
|
||||
}
|
||||
|
||||
// API service for auth and shared endpoints (unified backend)
|
||||
const authApi = axios.create({
|
||||
baseURL: import.meta.env.BASE_URL + 'api',
|
||||
@@ -101,6 +109,9 @@ watch(
|
||||
|
||||
// Initialize auth and load companies on mount
|
||||
onMounted(async () => {
|
||||
// Add resize listener for mobile detection
|
||||
window.addEventListener('resize', handleResize)
|
||||
|
||||
console.log('[App] Mounted - initializing auth...')
|
||||
await authStore.initializeAuth()
|
||||
console.log('[App] Auth initialized, isAuthenticated:', authStore.isAuthenticated)
|
||||
@@ -116,6 +127,11 @@ onMounted(async () => {
|
||||
}
|
||||
})
|
||||
|
||||
// Cleanup resize listener
|
||||
onUnmounted(() => {
|
||||
window.removeEventListener('resize', handleResize)
|
||||
})
|
||||
|
||||
// Event handlers
|
||||
const handleCompanyChanged = async (company) => {
|
||||
console.log('[App] Company changed:', company)
|
||||
|
||||
188
tasks/prd-mobile-fixes-phase4.md
Normal file
188
tasks/prd-mobile-fixes-phase4.md
Normal file
@@ -0,0 +1,188 @@
|
||||
# PRD: Mobile Fixes Phase 4 - Layout & State Issues
|
||||
|
||||
## 1. Introducere
|
||||
|
||||
După completarea Phase 3 (11/11 stories), au fost identificate probleme critice în modul mobil prin testare Playwright. Cauza principală este că layout-ul desktop (AppHeader + sidebar) rămâne vizibil pe viewport mobil, acoperind componentele mobile (MobileTopBar, MobileDrawerMenu). În plus, există probleme cu persistența bonurilor cu eroare la upload.
|
||||
|
||||
## 2. Obiective
|
||||
|
||||
### Obiectiv Principal
|
||||
- Corectarea layout-ului mobil pentru a afișa DOAR componentele mobile pe viewport < 768px
|
||||
|
||||
### Obiective Secundare
|
||||
- Restaurarea corectă a bonurilor cu eroare după refresh
|
||||
- Permiterea editării bonurilor cu eroare pentru corectare
|
||||
|
||||
### Metrici de Succes
|
||||
- Playwright test: Header desktop ASCUNS pe viewport 375px
|
||||
- Playwright test: MobileTopBar cu butoane filter/export VIZIBILE
|
||||
- Playwright test: MobileDrawerMenu afișează secțiunea ANALIZE
|
||||
- Playwright test: Bonuri cu eroare rămân vizibile după refresh
|
||||
|
||||
## 3. User Stories
|
||||
|
||||
### US-401: Fix Layout Principal - Ascundere Header Desktop pe Mobil
|
||||
**Ca** utilizator mobil
|
||||
**Vreau** să văd doar MobileTopBar și MobileBottomNav
|
||||
**Pentru că** header-ul desktop ocupă spațiu și acoperă butoanele mobile
|
||||
|
||||
**Acceptance Criteria:**
|
||||
- [ ] AppHeader.vue are `v-if="!isMobile"` pentru a se ascunde pe mobil
|
||||
- [ ] Sidebar-ul desktop (navigation cu Rapoarte/Introduceri Date/Sistem) este ascuns pe mobil
|
||||
- [ ] MobileTopBar este singurul header vizibil pe viewport < 768px
|
||||
- [ ] Nu există suprapunere între header desktop și MobileTopBar
|
||||
- [ ] npm run build passes
|
||||
- [ ] Verify in browser (375x667): Header desktop NU este vizibil
|
||||
|
||||
### US-402: Fix MobileTopBar - Butoane Filter/Export Vizibile
|
||||
**Ca** utilizator mobil pe pagina Facturi/Bonuri
|
||||
**Vreau** să văd butoanele de filtrare și export în header
|
||||
**Pentru că** acum sunt ascunse/acoperite de header-ul desktop
|
||||
|
||||
**Acceptance Criteria:**
|
||||
- [ ] Pe InvoicesView.vue, butoanele Filter/Refresh/Export sunt vizibile în MobileTopBar
|
||||
- [ ] Pe ReceiptsListView.vue, butoanele Filter/Export/More sunt vizibile în MobileTopBar
|
||||
- [ ] Click pe butonul Filter deschide BottomSheet cu filtre
|
||||
- [ ] Click pe butonul Export declanșează descărcarea
|
||||
- [ ] npm run build passes
|
||||
- [ ] Verify in browser (375x667): Butoanele sunt vizibile și funcționale pe pagina Facturi
|
||||
|
||||
### US-403: Fix MobileDrawerMenu - Secțiunea ANALIZE Vizibilă
|
||||
**Ca** utilizator mobil
|
||||
**Vreau** să văd secțiunea ANALIZE în hamburger menu
|
||||
**Pentru că** acum se deschide sidebar-ul desktop în loc de MobileDrawerMenu
|
||||
|
||||
**Acceptance Criteria:**
|
||||
- [ ] Click pe butonul Meniu din MobileTopBar deschide MobileDrawerMenu (nu sidebar desktop)
|
||||
- [ ] MobileDrawerMenu afișează secțiunile: PRINCIPALE, RAPOARTE, ANALIZE, ADMINISTRARE
|
||||
- [ ] Secțiunea ANALIZE conține: Scadențe, Facturi Detaliate
|
||||
- [ ] Link-urile din ANALIZE navighează corect
|
||||
- [ ] npm run build passes
|
||||
- [ ] Verify in browser (375x667): Click pe Meniu → apare drawer cu secțiunea ANALIZE
|
||||
|
||||
### US-404: Fix Spațiu Blank - Padding Corect pentru Mobile
|
||||
**Ca** utilizator mobil
|
||||
**Vreau** ca paginile să nu aibă spațiu blank excesiv în partea de sus
|
||||
**Pentru că** acum există ~120px spațiu gol unde ar fi header-ul desktop
|
||||
|
||||
**Acceptance Criteria:**
|
||||
- [ ] Paginile de rapoarte au padding-top corect pentru MobileTopBar (56px)
|
||||
- [ ] Nu există spațiu blank între MobileTopBar și conținut
|
||||
- [ ] Tab-urile Clienți/Furnizori sunt imediat sub MobileTopBar
|
||||
- [ ] npm run build passes
|
||||
- [ ] Verify in browser (375x667): Nu există spațiu blank excesiv pe pagina Facturi
|
||||
|
||||
### US-405: Fix batchProgressStore - Restaurare Joburi Failed
|
||||
**Ca** utilizator care a uploadat bonuri cu erori OCR
|
||||
**Vreau** ca bonurile cu eroare să rămână vizibile după refresh
|
||||
**Pentru că** acum dispar și nu pot fi editate
|
||||
|
||||
**Acceptance Criteria:**
|
||||
- [ ] `restoreJobsFromBatch()` în batchProgressStore.js include joburi cu status 'failed'
|
||||
- [ ] Batch-ul NU este șters din localStorage dacă are joburi failed
|
||||
- [ ] După refresh, bonurile cu eroare sunt afișate cu status vizual "Eroare"
|
||||
- [ ] `unifiedItems` computed include joburile failed pentru afișare
|
||||
- [ ] npm run build passes
|
||||
- [ ] Verify in browser: Upload bon cu eroare → Refresh → Bonul cu eroare rămâne vizibil
|
||||
|
||||
### US-406: Fix UI Bonuri cu Eroare - Afișare Corectă pe Mobil
|
||||
**Ca** utilizator mobil
|
||||
**Vreau** să văd clar că un bon are eroare (nu "în procesare")
|
||||
**Pentru că** acum bonurile failed arată ca și cum ar fi încă în procesare
|
||||
|
||||
**Acceptance Criteria:**
|
||||
- [ ] Bonurile cu status 'failed' afișează chip/badge "Eroare" (roșu)
|
||||
- [ ] NU afișează "În procesare" pentru bonuri failed
|
||||
- [ ] Mesajul de eroare este vizibil (truncat dacă e prea lung)
|
||||
- [ ] npm run build passes
|
||||
- [ ] Verify in browser (375x667): Bon cu eroare arată "Eroare" nu "În procesare"
|
||||
|
||||
### US-407: Fix Editare Bonuri cu Eroare
|
||||
**Ca** utilizator care are un bon cu eroare OCR
|
||||
**Vreau** să pot edita bonul pentru a corecta erorile manual
|
||||
**Pentru că** acum nu pot salva modificările sau re-trimite pe workflow
|
||||
|
||||
**Acceptance Criteria:**
|
||||
- [ ] Click pe bon cu eroare deschide formularul de editare
|
||||
- [ ] La salvare, `processing_status` este resetat la NULL
|
||||
- [ ] După salvare, bonul poate fi trimis pe workflow (Submit for Approval)
|
||||
- [ ] Backend endpoint PATCH /receipts/{id} resetează processing_status
|
||||
- [ ] npm run build passes
|
||||
- [ ] Verify in browser: Editează bon cu eroare → Salvează → Poate fi trimis pe workflow
|
||||
|
||||
### US-408: Verificare Finală cu Playwright
|
||||
**Ca** developer
|
||||
**Vreau** verificare automată a tuturor fix-urilor
|
||||
**Pentru că** trebuie confirmate toate scenariile înainte de merge
|
||||
|
||||
**Acceptance Criteria:**
|
||||
- [ ] Test 1: Viewport 375x667 → Header desktop ASCUNS
|
||||
- [ ] Test 2: Viewport 375x667 → MobileTopBar cu butoane VIZIBILE
|
||||
- [ ] Test 3: Click Meniu → MobileDrawerMenu cu ANALIZE
|
||||
- [ ] Test 4: Pagina Facturi → Tab-uri + butoane imediat vizibile (fără blank)
|
||||
- [ ] Test 5: Upload bon cu eroare → Arată "Eroare" nu "În procesare"
|
||||
- [ ] Test 6: Refresh → Bonul cu eroare rămâne
|
||||
- [ ] npm run build passes
|
||||
|
||||
## 4. Cerințe Funcționale
|
||||
|
||||
1. [REQ-001] Pe viewport < 768px, AppHeader și sidebar desktop trebuie ascunse complet
|
||||
2. [REQ-002] MobileTopBar trebuie să fie singurul header vizibil pe mobil
|
||||
3. [REQ-003] MobileDrawerMenu trebuie să se deschidă la click pe butonul Meniu din MobileTopBar
|
||||
4. [REQ-004] Butoanele actions din MobileTopBar trebuie să fie vizibile și funcționale
|
||||
5. [REQ-005] batchProgressStore trebuie să restaureze și să afișeze joburi cu status 'failed'
|
||||
6. [REQ-006] Editarea unui bon cu eroare trebuie să reseteze processing_status pentru re-workflow
|
||||
|
||||
## 5. Non-Goals (Ce NU facem)
|
||||
|
||||
- NU modificăm layout-ul desktop (rămâne neschimbat)
|
||||
- NU adăugăm funcționalități noi (doar fix-uri)
|
||||
- NU modificăm stilurile cardurilor de bonuri
|
||||
- NU schimbăm structura hamburger menu (doar ne asigurăm că se deschide corect)
|
||||
|
||||
## 6. Considerații Tehnice
|
||||
|
||||
### Stack/Tehnologii
|
||||
- Vue 3 Composition API
|
||||
- PrimeVue components
|
||||
- Pinia stores (batchProgressStore)
|
||||
- CSS media queries / v-if cu isMobile computed
|
||||
|
||||
### Patterns de Urmat
|
||||
- `isMobile` computed bazat pe `window.innerWidth < 768`
|
||||
- `v-if="!isMobile"` pentru componente desktop-only
|
||||
- `v-if="isMobile"` pentru componente mobile-only
|
||||
|
||||
### Fișiere Cheie de Modificat
|
||||
| Fișier | Modificare |
|
||||
|--------|------------|
|
||||
| `src/App.vue` sau layout component | v-if pentru AppHeader/sidebar |
|
||||
| `src/shared/components/layout/AppHeader.vue` | Verificare isMobile |
|
||||
| `src/modules/reports/views/InvoicesView.vue` | CSS padding-top |
|
||||
| `src/modules/data-entry/views/ReceiptsListView.vue` | CSS padding-top |
|
||||
| `src/stores/batchProgressStore.js` | Include 'failed' în restore |
|
||||
| `backend/modules/data_entry/routers/receipts.py` | Reset processing_status |
|
||||
|
||||
### Riscuri Tehnice
|
||||
- Modificarea layout-ului principal poate afecta toate paginile - testare completă necesară
|
||||
- isMobile computed trebuie să fie reactiv la resize
|
||||
|
||||
## 7. Considerații UI/UX
|
||||
|
||||
- Mobile layout trebuie să fie curat, fără suprapuneri
|
||||
- Butoanele touch target minim 48px
|
||||
- Feedback vizual clar pentru starea bonurilor (Eroare vs În procesare)
|
||||
- Tranziție smooth pentru MobileDrawerMenu
|
||||
|
||||
## 8. Success Metrics
|
||||
|
||||
- 100% teste Playwright trec
|
||||
- 0 suprapuneri vizuale pe viewport mobil
|
||||
- Bonuri cu eroare persistent după refresh
|
||||
- Timp de încărcare pagină neschimbat
|
||||
|
||||
## 9. Open Questions
|
||||
|
||||
- [x] Cauza exactă a problemei? → Header desktop nu este ascuns pe mobil (confirmat prin Playwright)
|
||||
- [x] isMobile computed există? → Trebuie verificat în layout principal
|
||||
- [ ] Există alte pagini afectate de layout? → De verificat după fix
|
||||
Reference in New Issue
Block a user