feat(mobile-fixes-phase3): Complete US-304 - Tab-uri Clienți/Furnizori în Facturi

Implemented by Ralph autonomous loop.
Iteration: 1

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Claude Agent
2026-01-12 16:36:25 +00:00
parent 944b1c6b9e
commit edcdce58e2
3 changed files with 1099 additions and 6 deletions

View File

@@ -10,6 +10,26 @@
@action-click="handleTopBarAction"
/>
<!-- US-304: Mobile Tabs for Clienți/Furnizori -->
<div v-if="isMobile" class="mobile-tabs-container">
<div class="mobile-tabs">
<button
class="mobile-tab"
:class="{ active: activeTab === 'clients' }"
@click="switchTab('clients')"
>
<span class="tab-label">Clienți</span>
</button>
<button
class="mobile-tab"
:class="{ active: activeTab === 'suppliers' }"
@click="switchTab('suppliers')"
>
<span class="tab-label">Furnizori</span>
</button>
</div>
</div>
<!-- Mobile Drawer Menu (replaces old Sidebar) -->
<MobileDrawerMenu
v-model="showDrawer"
@@ -384,10 +404,14 @@ import MobileTopBar from "@shared/components/mobile/MobileTopBar.vue";
import MobileBottomNav from "@shared/components/mobile/MobileBottomNav.vue";
import BottomSheet from "@shared/components/mobile/BottomSheet.vue";
import MobileDrawerMenu from "@shared/components/mobile/MobileDrawerMenu.vue";
import { useRouter } from "vue-router";
import { useRouter, useRoute } from "vue-router";
const toast = useToast();
const router = useRouter();
const route = useRoute();
// US-304: Tab state synced with URL query params
const activeTab = ref(route.query.tab === 'suppliers' ? 'suppliers' : 'clients');
const companyStore = useCompanyStore();
const invoicesStore = useInvoicesStore();
const periodStore = useAccountingPeriodStore();
@@ -439,6 +463,29 @@ const handleTopBarAction = (action) => {
}
};
// US-304: Switch between Clienți/Furnizori tabs
// Preserves all filters except type, updates URL query param
const switchTab = async (tab) => {
if (tab === activeTab.value) return;
activeTab.value = tab;
// Update URL query param without full navigation
router.replace({
query: {
...route.query,
tab: tab === 'suppliers' ? 'suppliers' : undefined // Remove param if 'clients' (default)
}
});
// Update filter type based on tab (preserves other filters)
filters.value.type = tab === 'suppliers' ? 'FURNIZORI' : 'CLIENTI';
// Reload invoices with new filter
pagination.value.page = 1;
await loadInvoices();
};
// US-307: Removed custom mobileBottomNavItems - using MobileBottomNav defaults
// Handle window resize
@@ -449,8 +496,9 @@ const handleResize = () => {
}
};
// US-304: Initialize filters.type based on URL query param (tab)
const filters = ref({
type: "CLIENTI",
type: route.query.tab === 'suppliers' ? 'FURNIZORI' : 'CLIENTI',
paymentStatus: "neachitate", // Default to unpaid invoices
searchTerm: "",
cont: "",
@@ -916,14 +964,66 @@ watch(
padding: var(--space-xl);
}
/* Mobile layout adjustments for top/bottom bars */
/* Mobile layout adjustments for top/bottom bars + tabs */
.mobile-layout .invoices {
padding-top: calc(56px + var(--space-md)); /* Account for fixed MobileTopBar */
padding-top: calc(56px + 48px + var(--space-md)); /* Account for MobileTopBar + tabs */
padding-bottom: calc(56px + var(--space-md)); /* Account for fixed MobileBottomNav */
padding-left: var(--space-md);
padding-right: var(--space-md);
}
/* ================================================
US-304: Mobile Tabs (Clienți/Furnizori)
Material Design 3 inspired full-width tabs
================================================ */
.mobile-tabs-container {
position: fixed;
top: 56px; /* Below MobileTopBar */
left: 0;
right: 0;
z-index: var(--z-sticky);
background: var(--surface-card);
border-bottom: 1px solid var(--surface-border);
}
.mobile-tabs {
display: flex;
width: 100%;
}
.mobile-tab {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
padding: var(--space-md);
min-height: 48px;
background: transparent;
border: none;
border-bottom: 2px solid transparent;
cursor: pointer;
transition: all var(--transition-fast);
color: var(--text-color-secondary);
font-size: var(--text-sm);
font-weight: var(--font-medium);
}
.mobile-tab:active {
background: var(--surface-hover);
}
.mobile-tab.active {
color: var(--color-primary);
border-bottom-color: var(--color-primary);
font-weight: var(--font-semibold);
}
.tab-label {
text-transform: uppercase;
letter-spacing: 0.5px;
}
.page-header {
margin-bottom: var(--space-xl);
}