feat(mobile-fixes-phase3): Complete US-303 - FAB pe Pagina Bonuri (Mutare Upload)

Implemented by Ralph autonomous loop.
Iteration: 5

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Claude Agent
2026-01-12 16:46:26 +00:00
parent f272d55ba4
commit 3afd3cd0ec
3 changed files with 124 additions and 6 deletions

View File

@@ -144,8 +144,8 @@
"FAB vizibil doar pe mobil (isMobile)",
"npm run build passes"
],
"passes": false,
"notes": ""
"passes": true,
"notes": "Completed in iteration 5"
},
{
"id": "US-306",

View File

@@ -1044,3 +1044,9 @@ User Stories: 11 (US-301 to US-311)
[2026-01-12 16:40:03] Working on story: US-302
[2026-01-12 16:40:03] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_4_US-302.log)
[2026-01-12 16:42:59] SUCCESS: Story US-302 passed!
[2026-01-12 16:42:59] Changes committed
[2026-01-12 16:42:59] Progress: 6/11 stories completed
[2026-01-12 16:43:01] === Iteration 5/100 ===
[2026-01-12 16:43:01] Working on story: US-303
[2026-01-12 16:43:01] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_5_US-303.log)
[2026-01-12 16:46:26] SUCCESS: Story US-303 passed!

View File

@@ -545,18 +545,30 @@
/>
</div>
<!-- US-040: Mobile FAB (Floating Action Button) -->
<!-- US-303: Mobile FAB (Floating Action Button) with Popup Menu -->
<Transition name="fab-slide">
<button
v-if="isMobile && !mobileSelectionMode && fabVisible"
class="mobile-fab"
@click="goToCreate"
aria-label="Adaugă bon nou"
:class="{ 'fab-active': fabMenuOpen }"
@click="toggleFabMenu"
aria-label="Meniu acțiuni"
aria-haspopup="true"
:aria-expanded="fabMenuOpen"
>
<i class="pi pi-plus"></i>
<i class="pi pi-plus" :class="{ 'fab-icon-rotate': fabMenuOpen }"></i>
</button>
</Transition>
<!-- US-303: FAB Popup Menu -->
<Menu
ref="fabMenuRef"
:model="fabMenuItems"
:popup="true"
class="fab-popup-menu"
@hide="fabMenuOpen = false"
/>
<!-- US-103: Mobile Bottom Navigation (using shared component) -->
<!-- US-307: Using default nav items (Dashboard, Bonuri, Facturi, Setări) -->
<MobileBottomNav v-if="isMobile && !mobileSelectionMode" />
@@ -1038,6 +1050,10 @@ const handleResize = () => {
const showDrawer = ref(false)
const moreMenuRef = ref(null)
const fabVisible = ref(true)
// US-303: FAB Menu State
const fabMenuRef = ref(null)
const fabMenuOpen = ref(false)
let lastScrollY = 0
let scrollTimeout = null
@@ -1075,6 +1091,32 @@ const moreMenuItems = computed(() => [
}
])
// US-303: FAB Menu Items (Bon Nou | Upload Bulk)
const fabMenuItems = [
{
label: 'Bon Nou',
icon: 'pi pi-plus',
command: () => {
fabMenuOpen.value = false
goToCreate()
}
},
{
label: 'Upload Bulk',
icon: 'pi pi-cloud-upload',
command: () => {
fabMenuOpen.value = false
openBulkFileInput()
}
}
]
// US-303: Toggle FAB Menu
const toggleFabMenu = (event) => {
fabMenuOpen.value = !fabMenuOpen.value
fabMenuRef.value?.toggle(event)
}
// US-103: Top bar actions for MobileTopBar component
const mobileTopBarActions = computed(() => {
if (mobileSelectionMode.value) {
@@ -4398,6 +4440,50 @@ const cleanupCompletedBatches = (storedBatchIds) => {
.mobile-fab i {
font-size: var(--text-2xl);
transition: transform var(--transition-fast);
}
/* US-303: FAB active state when menu is open */
.mobile-fab.fab-active {
background: var(--color-primary-dark);
}
.mobile-fab .fab-icon-rotate {
transform: rotate(45deg);
}
/* US-303: FAB Popup Menu positioning */
.fab-popup-menu {
/* Position above FAB, aligned to right */
position: fixed !important;
bottom: 140px !important; /* 72px FAB position + 56px FAB height + 12px spacing */
right: var(--space-md) !important;
left: auto !important;
top: auto !important;
min-width: 180px;
z-index: 1000 !important;
border-radius: var(--radius-lg);
box-shadow: var(--shadow-xl);
}
.fab-popup-menu .p-menuitem {
padding: 0;
}
.fab-popup-menu .p-menuitem-link {
padding: var(--space-md) var(--space-lg);
gap: var(--space-sm);
font-size: var(--text-base);
min-height: 48px; /* Touch-friendly */
}
.fab-popup-menu .p-menuitem-icon {
font-size: var(--text-lg);
color: var(--color-primary);
}
.fab-popup-menu .p-menuitem-text {
font-weight: var(--font-medium);
}
/* FAB slide animation */
@@ -4523,6 +4609,19 @@ const cleanupCompletedBatches = (storedBatchIds) => {
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4);
}
[data-theme="dark"] .mobile-fab.fab-active {
background: var(--blue-700);
}
[data-theme="dark"] .fab-popup-menu {
background: var(--surface-card);
border: 1px solid var(--surface-border);
}
[data-theme="dark"] .fab-popup-menu .p-menuitem-icon {
color: var(--blue-400);
}
[data-theme="dark"] .sidebar-item.active,
[data-theme="dark"] .sidebar-item.router-link-active {
color: var(--blue-400);
@@ -4568,6 +4667,19 @@ const cleanupCompletedBatches = (storedBatchIds) => {
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4);
}
:root:not([data-theme]) .mobile-fab.fab-active {
background: var(--blue-700);
}
:root:not([data-theme]) .fab-popup-menu {
background: var(--surface-card);
border: 1px solid var(--surface-border);
}
:root:not([data-theme]) .fab-popup-menu .p-menuitem-icon {
color: var(--blue-400);
}
:root:not([data-theme]) .sidebar-item.active,
:root:not([data-theme]) .sidebar-item.router-link-active {
color: var(--blue-400);