From 109ef50fb2972fffe9d7d467bd1efc55abb278f0 Mon Sep 17 00:00:00 2001 From: Claude Agent Date: Tue, 13 Jan 2026 16:38:01 +0000 Subject: [PATCH] =?UTF-8?q?feat(ui-fixes-phase6):=20Complete=20US-608=20-?= =?UTF-8?q?=20Fix=20Buton=20FAB=20SpeedDial=20=C3=AEn=20Lista=20Bonuri?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implemented by Ralph autonomous loop. Iteration: 9 Co-Authored-By: Claude --- scripts/ralph/prd.json | 4 +- scripts/ralph/progress.txt | 6 + src/main.js | 2 + .../views/receipts/ReceiptsListView.vue | 386 ++++++++---------- 4 files changed, 184 insertions(+), 214 deletions(-) diff --git a/scripts/ralph/prd.json b/scripts/ralph/prd.json index 1267d57..967f036 100644 --- a/scripts/ralph/prd.json +++ b/scripts/ralph/prd.json @@ -162,8 +162,8 @@ "npm run typecheck passes", "Verify in browser: FAB shows SpeedDial menu with 3 options on tap" ], - "passes": false, - "notes": "Bug în ReceiptsListView.vue - SpeedDial probabil are probleme CSS sau z-index" + "passes": true, + "notes": "Completed in iteration 9" }, { "id": "US-609", diff --git a/scripts/ralph/progress.txt b/scripts/ralph/progress.txt index 96b91e9..ce06d55 100644 --- a/scripts/ralph/progress.txt +++ b/scripts/ralph/progress.txt @@ -290,3 +290,9 @@ PRD: tasks/prd-ui-fixes-phase6.md [2026-01-13 16:29:50] Working on story: US-607 [2026-01-13 16:29:50] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_8_US-607.log) [2026-01-13 16:33:08] SUCCESS: Story US-607 passed! +[2026-01-13 16:33:08] Changes committed +[2026-01-13 16:33:08] Progress: 7/10 stories completed +[2026-01-13 16:33:10] === Iteration 9/30 === +[2026-01-13 16:33:10] Working on story: US-608 +[2026-01-13 16:33:10] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_9_US-608.log) +[2026-01-13 16:38:01] SUCCESS: Story US-608 passed! diff --git a/src/main.js b/src/main.js index 3259800..7738e82 100644 --- a/src/main.js +++ b/src/main.js @@ -37,6 +37,7 @@ import RadioButton from 'primevue/radiobutton' import Toolbar from 'primevue/toolbar' import Divider from 'primevue/divider' import Message from 'primevue/message' +import SpeedDial from 'primevue/speeddial' // PrimeVue CSS (saga-blue theme) import 'primevue/resources/themes/saga-blue/theme.css' @@ -91,5 +92,6 @@ app.component('RadioButton', RadioButton) app.component('Toolbar', Toolbar) app.component('Divider', Divider) app.component('Message', Message) +app.component('SpeedDial', SpeedDial) app.mount('#app') diff --git a/src/modules/data-entry/views/receipts/ReceiptsListView.vue b/src/modules/data-entry/views/receipts/ReceiptsListView.vue index 14395df..882fd2b 100644 --- a/src/modules/data-entry/views/receipts/ReceiptsListView.vue +++ b/src/modules/data-entry/views/receipts/ReceiptsListView.vue @@ -661,28 +661,26 @@ /> - - - - - - - + @@ -1171,9 +1169,7 @@ const fabVisible = ref(true) // US-502: Export Menu ref and items for desktop header actions const exportMenuRef = ref(null) -// US-303: FAB Menu State -const fabMenuRef = ref(null) -const fabMenuOpen = ref(false) +// US-608: FAB scroll hide/show state let lastScrollY = 0 let scrollTimeout = null @@ -1230,30 +1226,31 @@ const exportMenuItems = computed(() => [ } ]) -// US-303/US-515: FAB Menu Items (Bon Nou | Upload Bulk) - Material Design 3 -const fabMenuItems = [ +// US-608: SpeedDial Items - Bon Nou Manual, Scanare Bon OCR, Upload în Masă +const speedDialItems = [ { - label: 'Bon Nou', - icon: 'pi pi-plus', - command: () => { - fabMenuOpen.value = false - goToCreate() - } + label: 'Bon Nou Manual', + icon: 'pi pi-pencil', + command: () => goToCreate() }, { - label: 'Upload Bulk', + label: 'Scanare Bon OCR', + icon: 'pi pi-camera', + command: () => goToOCRScan() + }, + { + label: 'Upload în Masă', icon: 'pi pi-upload', - command: () => { - fabMenuOpen.value = false - openBulkFileInput() - } + command: () => openBulkFileInput() } ] -// US-303: Toggle FAB Menu -const toggleFabMenu = (event) => { - fabMenuOpen.value = !fabMenuOpen.value - fabMenuRef.value?.toggle(event) +// US-608: Navigate to OCR scan page +const goToOCRScan = () => { + console.log('[ReceiptsList] Navigating to OCR scan...') + router.push({ path: '/data-entry/create', query: { mode: 'scan' } }).catch(err => { + console.error('[ReceiptsList] Navigation error:', err) + }) } // US-103/US-306: Top bar actions for MobileTopBar component @@ -4800,61 +4797,89 @@ const cleanupCompletedBatches = (storedBatchIds) => { /* US-103: Mobile Bottom Navigation styles now in MobileBottomNav.vue */ -/* Mobile FAB - Floating Action Button */ -.mobile-fab { - position: fixed; +/* US-608: Mobile SpeedDial - Floating Action Button with animated options */ +.mobile-speed-dial { + position: fixed !important; bottom: 72px; /* 56px bottom nav + 16px spacing */ right: var(--space-md); - width: 56px; - height: 56px; - border-radius: var(--radius-xl); - background: var(--color-primary); - color: var(--color-text-inverse); - border: none; - box-shadow: var(--shadow-lg); - display: flex; - align-items: center; - justify-content: center; - cursor: pointer; z-index: 999; - transition: all var(--transition-fast); } -.mobile-fab:active { - transform: scale(0.95); - box-shadow: var(--shadow-md); +/* SpeedDial main button styling */ +.mobile-speed-dial .p-speeddial-button { + width: 56px !important; + height: 56px !important; + border-radius: 50% !important; + background: var(--color-primary) !important; + border: none !important; + box-shadow: var(--shadow-lg) !important; + transition: all var(--transition-fast) !important; } -.mobile-fab i { - font-size: var(--text-2xl); - transition: transform var(--transition-fast); +.mobile-speed-dial .p-speeddial-button:hover, +.mobile-speed-dial .p-speeddial-button:focus { + background: var(--color-primary-dark) !important; + box-shadow: var(--shadow-xl) !important; } -/* US-303: FAB active state when menu is open */ -.mobile-fab.fab-active { - background: var(--color-primary-dark); +.mobile-speed-dial .p-speeddial-button:active { + transform: scale(0.95) !important; } -.mobile-fab .fab-icon-rotate { - transform: rotate(45deg); +.mobile-speed-dial .p-speeddial-button .p-button-icon { + font-size: var(--text-2xl) !important; + color: var(--color-text-inverse) !important; } -/* FAB slide animation */ -.fab-slide-enter-active, -.fab-slide-leave-active { - transition: transform var(--transition-normal), opacity var(--transition-normal); +/* SpeedDial action buttons styling */ +.mobile-speed-dial .p-speeddial-action { + width: 48px !important; + height: 48px !important; + background: var(--surface-card) !important; + border: 1px solid var(--surface-border) !important; + box-shadow: var(--shadow-md) !important; + transition: all var(--transition-fast) !important; } -.fab-slide-enter-from, -.fab-slide-leave-to { - transform: translateY(100px); +.mobile-speed-dial .p-speeddial-action:hover, +.mobile-speed-dial .p-speeddial-action:focus { + background: var(--surface-hover) !important; + transform: scale(1.1) !important; +} + +.mobile-speed-dial .p-speeddial-action .p-speeddial-action-icon { + color: var(--color-primary) !important; + font-size: var(--text-lg) !important; +} + +/* SpeedDial mask overlay (background when open) */ +.mobile-speed-dial .p-speeddial-mask { + background: rgba(0, 0, 0, 0.4) !important; +} + +/* SpeedDial tooltip labels */ +.mobile-speed-dial .p-speeddial-action::before { + content: attr(aria-label); + position: absolute; + right: 60px; + white-space: nowrap; + background: var(--surface-card); + color: var(--text-color); + padding: var(--space-xs) var(--space-sm); + border-radius: var(--radius-sm); + font-size: var(--text-sm); + font-weight: var(--font-medium); + box-shadow: var(--shadow-sm); + border: 1px solid var(--surface-border); opacity: 0; + transform: translateX(10px); + transition: all var(--transition-fast); + pointer-events: none; } -.fab-slide-enter-to, -.fab-slide-leave-from { - transform: translateY(0); +.mobile-speed-dial.p-speeddial-opened .p-speeddial-action::before { opacity: 1; + transform: translateX(0); } /* Mobile Sidebar (Hamburger Menu) */ @@ -4957,22 +4982,35 @@ const cleanupCompletedBatches = (storedBatchIds) => { /* US-103: Dark mode for MobileBottomNav now in component */ -[data-theme="dark"] .mobile-fab { - background: var(--blue-600); - box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4); +/* US-608: Dark mode for SpeedDial */ +[data-theme="dark"] .mobile-speed-dial .p-speeddial-button { + background: var(--blue-600) !important; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4) !important; } -[data-theme="dark"] .mobile-fab.fab-active { - background: var(--blue-700); +[data-theme="dark"] .mobile-speed-dial .p-speeddial-button:hover, +[data-theme="dark"] .mobile-speed-dial .p-speeddial-button:focus { + background: var(--blue-700) !important; } -[data-theme="dark"] .fab-popup-menu { +[data-theme="dark"] .mobile-speed-dial .p-speeddial-action { + background: var(--surface-card) !important; + border-color: var(--surface-border) !important; +} + +[data-theme="dark"] .mobile-speed-dial .p-speeddial-action:hover, +[data-theme="dark"] .mobile-speed-dial .p-speeddial-action:focus { + background: var(--surface-hover) !important; +} + +[data-theme="dark"] .mobile-speed-dial .p-speeddial-action .p-speeddial-action-icon { + color: var(--blue-400) !important; +} + +[data-theme="dark"] .mobile-speed-dial .p-speeddial-action::before { background: var(--surface-card); - border: 1px solid var(--surface-border); -} - -[data-theme="dark"] .fab-popup-menu .p-menuitem-icon { - color: var(--blue-400); + color: var(--text-color); + border-color: var(--surface-border); } [data-theme="dark"] .sidebar-item.active, @@ -5015,22 +5053,35 @@ const cleanupCompletedBatches = (storedBatchIds) => { /* US-103: Auto dark mode for MobileBottomNav now in component */ - :root:not([data-theme]) .mobile-fab { - background: var(--blue-600); - box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4); + /* US-608: Auto dark mode for SpeedDial */ + :root:not([data-theme]) .mobile-speed-dial .p-speeddial-button { + background: var(--blue-600) !important; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4) !important; } - :root:not([data-theme]) .mobile-fab.fab-active { - background: var(--blue-700); + :root:not([data-theme]) .mobile-speed-dial .p-speeddial-button:hover, + :root:not([data-theme]) .mobile-speed-dial .p-speeddial-button:focus { + background: var(--blue-700) !important; } - :root:not([data-theme]) .fab-popup-menu { + :root:not([data-theme]) .mobile-speed-dial .p-speeddial-action { + background: var(--surface-card) !important; + border-color: var(--surface-border) !important; + } + + :root:not([data-theme]) .mobile-speed-dial .p-speeddial-action:hover, + :root:not([data-theme]) .mobile-speed-dial .p-speeddial-action:focus { + background: var(--surface-hover) !important; + } + + :root:not([data-theme]) .mobile-speed-dial .p-speeddial-action .p-speeddial-action-icon { + color: var(--blue-400) !important; + } + + :root:not([data-theme]) .mobile-speed-dial .p-speeddial-action::before { background: var(--surface-card); - border: 1px solid var(--surface-border); - } - - :root:not([data-theme]) .fab-popup-menu .p-menuitem-icon { - color: var(--blue-400); + color: var(--text-color); + border-color: var(--surface-border); } :root:not([data-theme]) .sidebar-item.active, @@ -5073,123 +5124,34 @@ const cleanupCompletedBatches = (storedBatchIds) => { } - +