feat(mobile-fixes-phase3): Complete US-306 - Restaurare Butoane Export și Filtrare pe Rapoarte
Implemented by Ralph autonomous loop. Iteration: 6 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -977,6 +977,17 @@ onMounted(() => {
|
||||
loadMaturityData();
|
||||
}
|
||||
});
|
||||
|
||||
// US-306: Expose methods for parent component (MobileTopBar actions)
|
||||
defineExpose({
|
||||
exportExcel,
|
||||
exportPDF,
|
||||
selectedPeriod,
|
||||
selectedType,
|
||||
searchTerm,
|
||||
handleSearch,
|
||||
loadDetailedData
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@@ -1,12 +1,61 @@
|
||||
<template>
|
||||
<!-- Mobile Top Bar -->
|
||||
<!-- Mobile Top Bar - US-306: Added Export and Filter actions -->
|
||||
<MobileTopBar
|
||||
v-if="isMobile"
|
||||
title="Scadențe"
|
||||
:show-back="true"
|
||||
:actions="mobileTopBarActions"
|
||||
@back-click="goBack"
|
||||
@action-click="handleTopBarAction"
|
||||
/>
|
||||
|
||||
<!-- US-306: Filter BottomSheet for mobile -->
|
||||
<BottomSheet v-model="showFilters">
|
||||
<h3 class="bottom-sheet-title">Filtre</h3>
|
||||
<div class="bottom-sheet-filters">
|
||||
<!-- Period Filter -->
|
||||
<div class="form-group">
|
||||
<label class="form-label">Perioadă</label>
|
||||
<Dropdown
|
||||
v-model="filterPeriod"
|
||||
:options="periodOptions"
|
||||
optionLabel="label"
|
||||
optionValue="value"
|
||||
placeholder="Selectați perioada"
|
||||
class="w-full"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Type Filter -->
|
||||
<div class="form-group">
|
||||
<label class="form-label">Tip</label>
|
||||
<Dropdown
|
||||
v-model="filterType"
|
||||
:options="typeOptions"
|
||||
optionLabel="label"
|
||||
optionValue="value"
|
||||
placeholder="Selectați tipul"
|
||||
class="w-full"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Bottom sheet actions -->
|
||||
<div class="bottom-sheet-actions">
|
||||
<Button
|
||||
icon="pi pi-filter-slash"
|
||||
label="Resetează"
|
||||
class="p-button-outlined p-button-secondary"
|
||||
@click="resetFilters"
|
||||
/>
|
||||
<Button
|
||||
icon="pi pi-check"
|
||||
label="Aplică"
|
||||
@click="applyFilters"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</BottomSheet>
|
||||
|
||||
<!-- US-305: Mobile Tabs for Clienți/Furnizori -->
|
||||
<div v-if="isMobile" class="mobile-tabs-container">
|
||||
<div class="mobile-tabs">
|
||||
@@ -53,6 +102,7 @@
|
||||
<!-- Main content - MaturityAndDetailsCard -->
|
||||
<div v-else class="maturity-container">
|
||||
<MaturityAndDetailsCard
|
||||
ref="maturityCardRef"
|
||||
:companyId="companyStore.selectedCompany?.id_firma"
|
||||
:activeTab="activeTab"
|
||||
:isMobile="isMobile"
|
||||
@@ -70,8 +120,10 @@
|
||||
import { ref, computed, onMounted, onUnmounted } from 'vue'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import Button from 'primevue/button'
|
||||
import Dropdown from 'primevue/dropdown'
|
||||
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 MaturityAndDetailsCard from '@reports/components/dashboard/cards/MaturityAndDetailsCard.vue'
|
||||
import { useCompanyStore } from '@reports/stores/sharedStores'
|
||||
|
||||
@@ -86,9 +138,90 @@ const activeTab = ref(route.query.tab === 'suppliers' ? 'suppliers' : 'clients')
|
||||
const windowWidth = ref(window.innerWidth)
|
||||
const isMobile = computed(() => windowWidth.value < 768)
|
||||
|
||||
// US-306: Ref to MaturityAndDetailsCard for calling exposed methods
|
||||
const maturityCardRef = ref(null)
|
||||
|
||||
// US-306: Mobile filter state
|
||||
const showFilters = ref(false)
|
||||
const filterPeriod = ref('1m')
|
||||
const filterType = ref('clients')
|
||||
|
||||
// US-306: Filter options
|
||||
const periodOptions = [
|
||||
{ label: '7 zile', value: '7d' },
|
||||
{ label: '1 lună', value: '1m' },
|
||||
{ label: '3 luni', value: '3m' },
|
||||
{ label: '6 luni', value: '6m' },
|
||||
{ label: '12 luni', value: '12m' },
|
||||
{ label: 'Toate', value: 'all' }
|
||||
]
|
||||
|
||||
const typeOptions = [
|
||||
{ label: 'Clienți', value: 'clients' },
|
||||
{ label: 'Furnizori', value: 'suppliers' },
|
||||
{ label: 'Trezorerie', value: 'treasury' }
|
||||
]
|
||||
|
||||
// US-306: Check if filters have non-default values
|
||||
const hasActiveFilters = computed(() => {
|
||||
return filterPeriod.value !== '1m' || filterType.value !== 'clients'
|
||||
})
|
||||
|
||||
// US-306: Mobile TopBar actions (Export + Filter)
|
||||
const mobileTopBarActions = computed(() => [
|
||||
{
|
||||
icon: 'pi pi-filter',
|
||||
label: 'Filtre',
|
||||
tooltip: 'Filtre',
|
||||
active: hasActiveFilters.value
|
||||
},
|
||||
{
|
||||
icon: 'pi pi-download',
|
||||
label: 'Export',
|
||||
tooltip: 'Export Excel'
|
||||
}
|
||||
])
|
||||
|
||||
// US-306: Handle top bar action clicks
|
||||
const handleTopBarAction = (action) => {
|
||||
if (action.icon === 'pi pi-filter') {
|
||||
// Sync current values from child component before opening
|
||||
if (maturityCardRef.value) {
|
||||
filterPeriod.value = maturityCardRef.value.selectedPeriod
|
||||
filterType.value = maturityCardRef.value.selectedType
|
||||
}
|
||||
showFilters.value = !showFilters.value
|
||||
} else if (action.icon === 'pi pi-download') {
|
||||
// Trigger export from child component
|
||||
if (maturityCardRef.value) {
|
||||
maturityCardRef.value.exportExcel()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// US-306: Apply filters to child component
|
||||
const applyFilters = () => {
|
||||
if (maturityCardRef.value) {
|
||||
maturityCardRef.value.selectedPeriod = filterPeriod.value
|
||||
maturityCardRef.value.selectedType = filterType.value
|
||||
maturityCardRef.value.loadDetailedData()
|
||||
}
|
||||
showFilters.value = false
|
||||
}
|
||||
|
||||
// US-306: Reset filters to defaults
|
||||
const resetFilters = () => {
|
||||
filterPeriod.value = '1m'
|
||||
filterType.value = 'clients'
|
||||
applyFilters()
|
||||
}
|
||||
|
||||
// Handle window resize for mobile detection
|
||||
const handleResize = () => {
|
||||
windowWidth.value = window.innerWidth
|
||||
if (!isMobile.value) {
|
||||
showFilters.value = false // Reset when switching to desktop
|
||||
}
|
||||
}
|
||||
|
||||
// Navigation
|
||||
@@ -270,4 +403,30 @@ onUnmounted(() => {
|
||||
.empty-action {
|
||||
margin-top: var(--space-md);
|
||||
}
|
||||
|
||||
/* ================================================
|
||||
US-306: Bottom Sheet Styles
|
||||
================================================ */
|
||||
|
||||
.bottom-sheet-title {
|
||||
font-size: var(--text-lg);
|
||||
font-weight: var(--font-semibold);
|
||||
color: var(--text-color);
|
||||
margin: 0 0 var(--space-md) 0;
|
||||
}
|
||||
|
||||
.bottom-sheet-filters {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--space-md);
|
||||
}
|
||||
|
||||
.bottom-sheet-actions {
|
||||
display: flex;
|
||||
gap: var(--space-sm);
|
||||
justify-content: flex-end;
|
||||
margin-top: var(--space-md);
|
||||
padding-top: var(--space-md);
|
||||
border-top: 1px solid var(--surface-border);
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user