fix(reports): neutralize totals color and fix dark mode button contrast
- Remove green/red/blue coloring from summary totals on all report pages (Facturi, Facturi pe Parteneri, Casă, Bancă) — mobile and desktop, light and dark mode; totals now use --text-color like TrialBalance - Fix SplitButton (Export) dark mode: was blue (--color-primary), now matches secondary outlined style (--text-color / --surface-border) - Update button syntax: severity="secondary" outlined instead of legacy class="p-button-outlined p-button-secondary" - DetailedInvoices: partner-meta (8 facturi) inline with partner name via flex-direction row instead of column - TrialBalance: mobile flat-row list layout replacing card layout - Dashboard mobile title: shows company name + period instead of static "Dashboard" - Navigation: move Facturi pe Parteneri to RAPOARTE section; update MobileBottomNav default items (Detalii replaces Facturi) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
117
src/assets/css/vendor/primevue-overrides.css
vendored
117
src/assets/css/vendor/primevue-overrides.css
vendored
@@ -184,6 +184,11 @@
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* DataTable body text - override saga-blue hardcoded #495057 */
|
||||
.p-datatable .p-datatable-tbody > tr {
|
||||
color: var(--text-color) !important;
|
||||
}
|
||||
|
||||
/* Compact DataTable variant (p-datatable-sm) */
|
||||
.p-datatable-sm .p-datatable-thead > tr > th {
|
||||
padding: 0.5rem 0.75rem !important;
|
||||
@@ -683,9 +688,121 @@
|
||||
}
|
||||
}
|
||||
|
||||
/* ===== Menu (popup/SplitButton dropdown) ===== */
|
||||
.p-menu {
|
||||
background: var(--surface-card);
|
||||
border-color: var(--surface-border);
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
.p-menu .p-menuitem > .p-menuitem-content .p-menuitem-link {
|
||||
color: var(--text-color);
|
||||
padding: var(--space-sm) var(--space-md);
|
||||
gap: var(--space-sm);
|
||||
}
|
||||
|
||||
.p-menu .p-menuitem > .p-menuitem-content .p-menuitem-link .p-menuitem-text {
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
.p-menu .p-menuitem > .p-menuitem-content .p-menuitem-link .p-menuitem-icon {
|
||||
color: var(--text-color-secondary);
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.p-menu .p-menuitem > .p-menuitem-content:hover,
|
||||
.p-menu .p-menuitem > .p-menuitem-content:not(.p-highlight):not(.p-disabled).p-focus {
|
||||
background: var(--surface-hover);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .p-menu {
|
||||
background: var(--surface-card);
|
||||
border-color: var(--surface-border);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .p-menu .p-menuitem > .p-menuitem-content .p-menuitem-link {
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .p-menu .p-menuitem > .p-menuitem-content:hover {
|
||||
background: var(--surface-hover);
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root:not([data-theme]) .p-menu {
|
||||
background: var(--surface-card);
|
||||
border-color: var(--surface-border);
|
||||
}
|
||||
:root:not([data-theme]) .p-menu .p-menuitem > .p-menuitem-content .p-menuitem-link {
|
||||
color: var(--text-color);
|
||||
}
|
||||
:root:not([data-theme]) .p-menu .p-menuitem > .p-menuitem-content:hover {
|
||||
background: var(--surface-hover);
|
||||
}
|
||||
}
|
||||
|
||||
/* Server dropdown in login form uses default styling (inherits from global rules above) */
|
||||
/* Server dropdown in header is styled in header.css to match CompanySelector */
|
||||
|
||||
/* ===== Dark Mode Outlined Button Contrast Fix ===== */
|
||||
/* PrimeVue saga-blue (light) theme doesn't adapt outlined buttons for dark mode.
|
||||
Secondary outlined buttons become invisible (grey on dark bg).
|
||||
SplitButton outlined also needs explicit dark-mode color. */
|
||||
|
||||
[data-theme="dark"] .p-button.p-button-outlined.p-button-secondary {
|
||||
color: var(--text-color) !important;
|
||||
border-color: var(--surface-border) !important;
|
||||
background: transparent !important;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .p-button.p-button-outlined.p-button-secondary:hover {
|
||||
background: var(--surface-hover) !important;
|
||||
color: var(--text-color) !important;
|
||||
border-color: var(--text-color-secondary) !important;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .p-splitbutton .p-splitbutton-defaultbutton.p-button-outlined,
|
||||
[data-theme="dark"] .p-splitbutton .p-splitbutton-menubutton.p-button-outlined {
|
||||
color: var(--text-color) !important;
|
||||
border-color: var(--surface-border) !important;
|
||||
background: transparent !important;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .p-splitbutton .p-splitbutton-defaultbutton.p-button-outlined:hover,
|
||||
[data-theme="dark"] .p-splitbutton .p-splitbutton-menubutton.p-button-outlined:hover {
|
||||
background: var(--surface-hover) !important;
|
||||
color: var(--text-color) !important;
|
||||
border-color: var(--text-color-secondary) !important;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root:not([data-theme]) .p-button.p-button-outlined.p-button-secondary {
|
||||
color: var(--text-color) !important;
|
||||
border-color: var(--surface-border) !important;
|
||||
background: transparent !important;
|
||||
}
|
||||
|
||||
:root:not([data-theme]) .p-button.p-button-outlined.p-button-secondary:hover {
|
||||
background: var(--surface-hover) !important;
|
||||
color: var(--text-color) !important;
|
||||
border-color: var(--text-color-secondary) !important;
|
||||
}
|
||||
|
||||
:root:not([data-theme]) .p-splitbutton .p-splitbutton-defaultbutton.p-button-outlined,
|
||||
:root:not([data-theme]) .p-splitbutton .p-splitbutton-menubutton.p-button-outlined {
|
||||
color: var(--text-color) !important;
|
||||
border-color: var(--surface-border) !important;
|
||||
background: transparent !important;
|
||||
}
|
||||
|
||||
:root:not([data-theme]) .p-splitbutton .p-splitbutton-defaultbutton.p-button-outlined:hover,
|
||||
:root:not([data-theme]) .p-splitbutton .p-splitbutton-menubutton.p-button-outlined:hover {
|
||||
background: var(--surface-hover) !important;
|
||||
color: var(--text-color) !important;
|
||||
border-color: var(--text-color-secondary) !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* ===== All Dialogs - Dark Mode ===== */
|
||||
/* Dialog background + content folosesc design tokens */
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ export const menuSections = [
|
||||
items: [
|
||||
{ to: '/reports/dashboard', icon: 'pi pi-home', label: 'Dashboard' },
|
||||
{ to: '/reports/invoices', icon: 'pi pi-file', label: 'Facturi' },
|
||||
{ to: '/reports/detailed-invoices', icon: 'pi pi-list', label: 'Facturi pe Parteneri' },
|
||||
{ to: '/reports/cash', icon: 'pi pi-wallet', label: 'Casă' },
|
||||
{ to: '/reports/bank', icon: 'pi pi-building', label: 'Bancă' },
|
||||
{ to: '/reports/trial-balance', icon: 'pi pi-calculator', label: 'Balanță de Verificare' }
|
||||
@@ -12,8 +13,7 @@ export const menuSections = [
|
||||
{
|
||||
title: 'Analize',
|
||||
items: [
|
||||
{ to: '/reports/maturity-analysis', icon: 'pi pi-clock', label: 'Scadențe' },
|
||||
{ to: '/reports/detailed-invoices', icon: 'pi pi-list', label: 'Facturi Detaliate' }
|
||||
{ to: '/reports/maturity-analysis', icon: 'pi pi-clock', label: 'Scadențe' }
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -74,7 +74,8 @@
|
||||
<Button
|
||||
icon="pi pi-filter-slash"
|
||||
label="Resetează"
|
||||
class="p-button-outlined p-button-secondary"
|
||||
severity="secondary"
|
||||
outlined
|
||||
@click="resetFilters(); showFilters = false"
|
||||
/>
|
||||
<Button
|
||||
@@ -124,11 +125,11 @@
|
||||
</div>
|
||||
<div class="total-item">
|
||||
<span class="total-label">Încasări:</span>
|
||||
<span class="total-value incasari">{{ formatCompact(treasuryStore.totals.total_incasari_all) }}</span>
|
||||
<span class="total-value">{{ formatCompact(treasuryStore.totals.total_incasari_all) }}</span>
|
||||
</div>
|
||||
<div class="total-item">
|
||||
<span class="total-label">Plăți:</span>
|
||||
<span class="total-value plati">{{ formatCompact(treasuryStore.totals.total_plati_all) }}</span>
|
||||
<span class="total-value">{{ formatCompact(treasuryStore.totals.total_plati_all) }}</span>
|
||||
</div>
|
||||
<div class="total-item">
|
||||
<span class="total-label">Sold Final:</span>
|
||||
@@ -190,7 +191,8 @@
|
||||
<Button
|
||||
icon="pi pi-filter-slash"
|
||||
label="Resetează Filtre"
|
||||
class="p-button-outlined p-button-secondary"
|
||||
severity="secondary"
|
||||
outlined
|
||||
@click="resetFilters"
|
||||
/>
|
||||
<SplitButton
|
||||
@@ -198,7 +200,7 @@
|
||||
icon="pi pi-download"
|
||||
:model="desktopExportItems"
|
||||
@click="exportPDF"
|
||||
class="p-button-outlined"
|
||||
outlined
|
||||
:disabled="!hasData"
|
||||
/>
|
||||
<Button
|
||||
@@ -216,55 +218,49 @@
|
||||
<div v-if="!isMobile && companyStore.selectedCompany" class="summary-stats-inline">
|
||||
<div class="stat-item">
|
||||
<span class="stat-label">Sold Precedent:</span>
|
||||
<span
|
||||
class="stat-value"
|
||||
:class="treasuryStore.totals.sold_precedent_all >= 0 ? 'incasari' : 'plati'"
|
||||
>{{ formatCurrency(treasuryStore.totals.sold_precedent_all) }}</span
|
||||
>
|
||||
<span class="stat-value">{{ formatCurrency(treasuryStore.totals.sold_precedent_all) }}</span>
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<span class="stat-label">Încasări:</span>
|
||||
<span class="stat-value incasari">{{
|
||||
formatCurrency(treasuryStore.totals.total_incasari_all)
|
||||
}}</span>
|
||||
<span class="stat-value">{{ formatCurrency(treasuryStore.totals.total_incasari_all) }}</span>
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<span class="stat-label">Plăți:</span>
|
||||
<span class="stat-value plati">{{
|
||||
formatCurrency(treasuryStore.totals.total_plati_all)
|
||||
}}</span>
|
||||
<span class="stat-value">{{ formatCurrency(treasuryStore.totals.total_plati_all) }}</span>
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<span class="stat-label">Sold Final:</span>
|
||||
<span
|
||||
class="stat-value"
|
||||
:class="treasuryStore.totals.sold_final_all >= 0 ? 'incasari' : 'plati'"
|
||||
>{{ formatCurrency(treasuryStore.totals.sold_final_all) }}</span
|
||||
>
|
||||
<span class="stat-value">{{ formatCurrency(treasuryStore.totals.sold_final_all) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Data Table -->
|
||||
<Card v-if="companyStore.selectedCompany" class="data-card">
|
||||
<template #content>
|
||||
<!-- Mobile: Card Layout -->
|
||||
<!-- Mobile: Compact Rows with Collapsible Meta -->
|
||||
<div v-if="isMobile" class="mobile-card-list">
|
||||
<div
|
||||
v-for="reg in treasuryStore.registers"
|
||||
v-for="(reg, index) in treasuryStore.registers"
|
||||
:key="`${reg.dataact}-${reg.nract}`"
|
||||
class="mobile-data-card"
|
||||
class="mobile-compact-row"
|
||||
>
|
||||
<div class="card-header">{{ reg.nume || 'Fără partener' }}</div>
|
||||
<div class="card-row">
|
||||
<span class="card-meta">{{ formatDateShort(reg.dataact) }} · {{ reg.nume_cont_bancar }}</span>
|
||||
<div class="compact-main" @click="toggleMeta(index)">
|
||||
<span class="compact-date">{{ formatDateShort(reg.dataact) }}</span>
|
||||
<span class="compact-partner">{{ reg.nume || 'Fără partener' }}</span>
|
||||
<span
|
||||
class="card-amount"
|
||||
class="compact-amount"
|
||||
:class="reg.incasari > 0 ? 'positive' : (reg.plati > 0 ? 'negative' : '')"
|
||||
>
|
||||
<template v-if="reg.incasari > 0">+{{ formatNumber(reg.incasari) }}</template>
|
||||
<template v-else-if="reg.plati > 0">-{{ formatNumber(reg.plati) }}</template>
|
||||
<template v-else>{{ formatNumber(0) }}</template>
|
||||
<template v-else>0</template>
|
||||
</span>
|
||||
<i :class="expandedMeta.has(index) ? 'pi pi-chevron-up' : 'pi pi-chevron-down'" class="meta-chevron"></i>
|
||||
</div>
|
||||
<div v-if="expandedMeta.has(index)" class="compact-meta">
|
||||
<span v-if="reg.nume_cont_bancar" class="meta-item">{{ reg.nume_cont_bancar }}</span>
|
||||
<span v-if="reg.nract" class="meta-item">Nr: {{ reg.nract }}</span>
|
||||
<span v-if="reg.explicatia" class="meta-item">{{ truncateText(reg.explicatia, 80) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="treasuryStore.registers.length === 0" class="mobile-empty">
|
||||
@@ -419,6 +415,14 @@ const selectedCompanyId = ref(companyStore.selectedCompany?.id_firma || null);
|
||||
const isMobile = ref(window.innerWidth < 768);
|
||||
const showFilters = ref(false);
|
||||
const showDrawer = ref(false);
|
||||
const expandedMeta = ref(new Set());
|
||||
|
||||
const toggleMeta = (index) => {
|
||||
const s = new Set(expandedMeta.value);
|
||||
if (s.has(index)) s.delete(index);
|
||||
else s.add(index);
|
||||
expandedMeta.value = s;
|
||||
};
|
||||
|
||||
// Handle logout from drawer menu
|
||||
const handleLogout = async () => {
|
||||
@@ -527,11 +531,11 @@ const pagination = ref({
|
||||
rows: 50,
|
||||
});
|
||||
|
||||
const formatCurrency = (amount, currency = "RON") => {
|
||||
if (!amount) return "0,00 " + currency;
|
||||
const formatCurrency = (amount) => {
|
||||
if (!amount || amount === 0) return "0,00";
|
||||
return new Intl.NumberFormat("ro-RO", {
|
||||
style: "currency",
|
||||
currency: currency,
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
}).format(amount);
|
||||
};
|
||||
|
||||
@@ -943,6 +947,12 @@ watch(
|
||||
},
|
||||
{ immediate: true },
|
||||
);
|
||||
|
||||
// Reset expanded meta when data changes
|
||||
watch(
|
||||
() => treasuryStore.registers,
|
||||
() => { expandedMeta.value = new Set(); }
|
||||
);
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
@@ -1025,63 +1035,83 @@ watch(
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
.mobile-totals-bar .total-value.incasari {
|
||||
color: var(--green-600);
|
||||
}
|
||||
|
||||
.mobile-totals-bar .total-value.plati {
|
||||
color: var(--red-600);
|
||||
}
|
||||
/* Colors removed - totals use neutral --text-color like TrialBalance */
|
||||
|
||||
/* ================================================
|
||||
Mobile Card List
|
||||
Mobile Compact Rows with Collapsible Meta
|
||||
================================================ */
|
||||
|
||||
.mobile-card-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--space-sm);
|
||||
}
|
||||
|
||||
.mobile-data-card {
|
||||
background: var(--surface-card);
|
||||
border: 1px solid var(--surface-border);
|
||||
border-radius: var(--radius-md);
|
||||
padding: var(--space-md);
|
||||
.mobile-compact-row {
|
||||
border-bottom: 1px solid var(--surface-border);
|
||||
}
|
||||
|
||||
.mobile-data-card .card-header {
|
||||
font-weight: var(--font-semibold);
|
||||
color: var(--text-color);
|
||||
margin-bottom: var(--space-xs);
|
||||
font-size: var(--text-base);
|
||||
}
|
||||
|
||||
.mobile-data-card .card-row {
|
||||
.compact-main {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
font-size: var(--text-sm);
|
||||
color: var(--text-color-secondary);
|
||||
min-height: 44px;
|
||||
padding: var(--space-sm) var(--space-md);
|
||||
gap: var(--space-sm);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.mobile-data-card .card-meta {
|
||||
.compact-main:active {
|
||||
background: var(--surface-hover);
|
||||
}
|
||||
|
||||
.compact-date {
|
||||
font-size: var(--text-xs);
|
||||
color: var(--text-color-secondary);
|
||||
min-width: 40px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.compact-partner {
|
||||
flex: 1;
|
||||
font-size: var(--text-sm);
|
||||
color: var(--text-color);
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.compact-amount {
|
||||
font-weight: var(--font-semibold);
|
||||
font-variant-numeric: tabular-nums;
|
||||
font-size: var(--text-sm);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.compact-amount.positive {
|
||||
color: var(--green-600);
|
||||
}
|
||||
|
||||
.compact-amount.negative {
|
||||
color: var(--red-600);
|
||||
}
|
||||
|
||||
.meta-chevron {
|
||||
font-size: var(--text-xs);
|
||||
color: var(--text-color-secondary);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.compact-meta {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--space-xs);
|
||||
padding: var(--space-xs) var(--space-md) var(--space-sm) calc(40px + var(--space-md) + var(--space-sm));
|
||||
background: var(--surface-hover);
|
||||
font-size: var(--text-xs);
|
||||
color: var(--text-color-secondary);
|
||||
}
|
||||
|
||||
.mobile-data-card .card-amount {
|
||||
font-weight: var(--font-semibold);
|
||||
color: var(--text-color);
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
|
||||
.mobile-data-card .card-amount.positive {
|
||||
color: var(--green-600);
|
||||
}
|
||||
|
||||
.mobile-data-card .card-amount.negative {
|
||||
color: var(--red-600);
|
||||
.meta-item {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.mobile-empty {
|
||||
@@ -1126,41 +1156,33 @@ watch(
|
||||
Dark Mode Support
|
||||
================================================ */
|
||||
|
||||
[data-theme="dark"] .mobile-totals-bar .total-value.incasari {
|
||||
[data-theme="dark"] .compact-amount.positive {
|
||||
color: var(--green-400);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .mobile-totals-bar .total-value.plati {
|
||||
color: var(--red-400);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .mobile-data-card .card-amount.positive {
|
||||
color: var(--green-400);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .mobile-data-card .card-amount.negative {
|
||||
[data-theme="dark"] .compact-amount.negative {
|
||||
color: var(--red-400);
|
||||
}
|
||||
|
||||
/* Auto dark mode */
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root:not([data-theme]) .mobile-totals-bar .total-value.incasari {
|
||||
:root:not([data-theme]) .compact-amount.positive {
|
||||
color: var(--green-400);
|
||||
}
|
||||
|
||||
:root:not([data-theme]) .mobile-totals-bar .total-value.plati {
|
||||
:root:not([data-theme]) .compact-amount.negative {
|
||||
color: var(--red-400);
|
||||
}
|
||||
|
||||
:root:not([data-theme]) .mobile-data-card .card-amount.positive {
|
||||
color: var(--green-400);
|
||||
}
|
||||
|
||||
:root:not([data-theme]) .mobile-data-card .card-amount.negative {
|
||||
:root:not([data-theme]) .numeric-value.negative {
|
||||
color: var(--red-400);
|
||||
}
|
||||
}
|
||||
|
||||
[data-theme="dark"] .numeric-value.negative {
|
||||
color: var(--red-400);
|
||||
}
|
||||
|
||||
/* ================================================
|
||||
Responsive Design
|
||||
================================================ */
|
||||
|
||||
@@ -74,7 +74,8 @@
|
||||
<Button
|
||||
icon="pi pi-filter-slash"
|
||||
label="Resetează"
|
||||
class="p-button-outlined p-button-secondary"
|
||||
severity="secondary"
|
||||
outlined
|
||||
@click="resetFilters(); showFilters = false"
|
||||
/>
|
||||
<Button
|
||||
@@ -124,11 +125,11 @@
|
||||
</div>
|
||||
<div class="total-item">
|
||||
<span class="total-label">Încasări:</span>
|
||||
<span class="total-value incasari">{{ formatCompact(treasuryStore.totals.total_incasari_all) }}</span>
|
||||
<span class="total-value">{{ formatCompact(treasuryStore.totals.total_incasari_all) }}</span>
|
||||
</div>
|
||||
<div class="total-item">
|
||||
<span class="total-label">Plăți:</span>
|
||||
<span class="total-value plati">{{ formatCompact(treasuryStore.totals.total_plati_all) }}</span>
|
||||
<span class="total-value">{{ formatCompact(treasuryStore.totals.total_plati_all) }}</span>
|
||||
</div>
|
||||
<div class="total-item">
|
||||
<span class="total-label">Sold Final:</span>
|
||||
@@ -190,7 +191,8 @@
|
||||
<Button
|
||||
icon="pi pi-filter-slash"
|
||||
label="Resetează Filtre"
|
||||
class="p-button-outlined p-button-secondary"
|
||||
severity="secondary"
|
||||
outlined
|
||||
@click="resetFilters"
|
||||
/>
|
||||
<SplitButton
|
||||
@@ -198,7 +200,7 @@
|
||||
icon="pi pi-download"
|
||||
:model="desktopExportItems"
|
||||
@click="exportPDF"
|
||||
class="p-button-outlined"
|
||||
outlined
|
||||
:disabled="!hasData"
|
||||
/>
|
||||
<Button
|
||||
@@ -216,55 +218,49 @@
|
||||
<div v-if="!isMobile && companyStore.selectedCompany" class="summary-stats-inline">
|
||||
<div class="stat-item">
|
||||
<span class="stat-label">Sold Precedent:</span>
|
||||
<span
|
||||
class="stat-value"
|
||||
:class="treasuryStore.totals.sold_precedent_all >= 0 ? 'incasari' : 'plati'"
|
||||
>{{ formatCurrency(treasuryStore.totals.sold_precedent_all) }}</span
|
||||
>
|
||||
<span class="stat-value">{{ formatCurrency(treasuryStore.totals.sold_precedent_all) }}</span>
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<span class="stat-label">Încasări:</span>
|
||||
<span class="stat-value incasari">{{
|
||||
formatCurrency(treasuryStore.totals.total_incasari_all)
|
||||
}}</span>
|
||||
<span class="stat-value">{{ formatCurrency(treasuryStore.totals.total_incasari_all) }}</span>
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<span class="stat-label">Plăți:</span>
|
||||
<span class="stat-value plati">{{
|
||||
formatCurrency(treasuryStore.totals.total_plati_all)
|
||||
}}</span>
|
||||
<span class="stat-value">{{ formatCurrency(treasuryStore.totals.total_plati_all) }}</span>
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<span class="stat-label">Sold Final:</span>
|
||||
<span
|
||||
class="stat-value"
|
||||
:class="treasuryStore.totals.sold_final_all >= 0 ? 'incasari' : 'plati'"
|
||||
>{{ formatCurrency(treasuryStore.totals.sold_final_all) }}</span
|
||||
>
|
||||
<span class="stat-value">{{ formatCurrency(treasuryStore.totals.sold_final_all) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Data Table -->
|
||||
<Card v-if="companyStore.selectedCompany" class="data-card">
|
||||
<template #content>
|
||||
<!-- Mobile: Card Layout -->
|
||||
<!-- Mobile: Compact Rows with Collapsible Meta -->
|
||||
<div v-if="isMobile" class="mobile-card-list">
|
||||
<div
|
||||
v-for="reg in treasuryStore.registers"
|
||||
v-for="(reg, index) in treasuryStore.registers"
|
||||
:key="`${reg.dataact}-${reg.nract}`"
|
||||
class="mobile-data-card"
|
||||
class="mobile-compact-row"
|
||||
>
|
||||
<div class="card-header">{{ reg.nume || 'Fără partener' }}</div>
|
||||
<div class="card-row">
|
||||
<span class="card-meta">{{ formatDateShort(reg.dataact) }} · {{ reg.nume_cont_bancar }}</span>
|
||||
<div class="compact-main" @click="toggleMeta(index)">
|
||||
<span class="compact-date">{{ formatDateShort(reg.dataact) }}</span>
|
||||
<span class="compact-partner">{{ reg.nume || 'Fără partener' }}</span>
|
||||
<span
|
||||
class="card-amount"
|
||||
class="compact-amount"
|
||||
:class="reg.incasari > 0 ? 'positive' : (reg.plati > 0 ? 'negative' : '')"
|
||||
>
|
||||
<template v-if="reg.incasari > 0">+{{ formatNumber(reg.incasari) }}</template>
|
||||
<template v-else-if="reg.plati > 0">-{{ formatNumber(reg.plati) }}</template>
|
||||
<template v-else>{{ formatNumber(0) }}</template>
|
||||
<template v-else>0</template>
|
||||
</span>
|
||||
<i :class="expandedMeta.has(index) ? 'pi pi-chevron-up' : 'pi pi-chevron-down'" class="meta-chevron"></i>
|
||||
</div>
|
||||
<div v-if="expandedMeta.has(index)" class="compact-meta">
|
||||
<span v-if="reg.nume_cont_bancar" class="meta-item">{{ reg.nume_cont_bancar }}</span>
|
||||
<span v-if="reg.nract" class="meta-item">Nr: {{ reg.nract }}</span>
|
||||
<span v-if="reg.explicatia" class="meta-item">{{ truncateText(reg.explicatia, 80) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="treasuryStore.registers.length === 0" class="mobile-empty">
|
||||
@@ -419,6 +415,14 @@ const selectedCompanyId = ref(companyStore.selectedCompany?.id_firma || null);
|
||||
const isMobile = ref(window.innerWidth < 768);
|
||||
const showFilters = ref(false);
|
||||
const showDrawer = ref(false);
|
||||
const expandedMeta = ref(new Set());
|
||||
|
||||
const toggleMeta = (index) => {
|
||||
const s = new Set(expandedMeta.value);
|
||||
if (s.has(index)) s.delete(index);
|
||||
else s.add(index);
|
||||
expandedMeta.value = s;
|
||||
};
|
||||
|
||||
// Handle logout from drawer menu
|
||||
const handleLogout = async () => {
|
||||
@@ -527,11 +531,11 @@ const pagination = ref({
|
||||
rows: 50,
|
||||
});
|
||||
|
||||
const formatCurrency = (amount, currency = "RON") => {
|
||||
if (!amount) return "0,00 " + currency;
|
||||
const formatCurrency = (amount) => {
|
||||
if (!amount || amount === 0) return "0,00";
|
||||
return new Intl.NumberFormat("ro-RO", {
|
||||
style: "currency",
|
||||
currency: currency,
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
}).format(amount);
|
||||
};
|
||||
|
||||
@@ -943,6 +947,12 @@ watch(
|
||||
},
|
||||
{ immediate: true },
|
||||
);
|
||||
|
||||
// Reset expanded meta when data changes
|
||||
watch(
|
||||
() => treasuryStore.registers,
|
||||
() => { expandedMeta.value = new Set(); }
|
||||
);
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
@@ -1025,63 +1035,83 @@ watch(
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
.mobile-totals-bar .total-value.incasari {
|
||||
color: var(--green-600);
|
||||
}
|
||||
|
||||
.mobile-totals-bar .total-value.plati {
|
||||
color: var(--red-600);
|
||||
}
|
||||
/* Colors removed - totals use neutral --text-color like TrialBalance */
|
||||
|
||||
/* ================================================
|
||||
Mobile Card List
|
||||
Mobile Compact Rows with Collapsible Meta
|
||||
================================================ */
|
||||
|
||||
.mobile-card-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--space-sm);
|
||||
}
|
||||
|
||||
.mobile-data-card {
|
||||
background: var(--surface-card);
|
||||
border: 1px solid var(--surface-border);
|
||||
border-radius: var(--radius-md);
|
||||
padding: var(--space-md);
|
||||
.mobile-compact-row {
|
||||
border-bottom: 1px solid var(--surface-border);
|
||||
}
|
||||
|
||||
.mobile-data-card .card-header {
|
||||
font-weight: var(--font-semibold);
|
||||
color: var(--text-color);
|
||||
margin-bottom: var(--space-xs);
|
||||
font-size: var(--text-base);
|
||||
}
|
||||
|
||||
.mobile-data-card .card-row {
|
||||
.compact-main {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
font-size: var(--text-sm);
|
||||
color: var(--text-color-secondary);
|
||||
min-height: 44px;
|
||||
padding: var(--space-sm) var(--space-md);
|
||||
gap: var(--space-sm);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.mobile-data-card .card-meta {
|
||||
.compact-main:active {
|
||||
background: var(--surface-hover);
|
||||
}
|
||||
|
||||
.compact-date {
|
||||
font-size: var(--text-xs);
|
||||
color: var(--text-color-secondary);
|
||||
min-width: 40px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.compact-partner {
|
||||
flex: 1;
|
||||
font-size: var(--text-sm);
|
||||
color: var(--text-color);
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.compact-amount {
|
||||
font-weight: var(--font-semibold);
|
||||
font-variant-numeric: tabular-nums;
|
||||
font-size: var(--text-sm);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.compact-amount.positive {
|
||||
color: var(--green-600);
|
||||
}
|
||||
|
||||
.compact-amount.negative {
|
||||
color: var(--red-600);
|
||||
}
|
||||
|
||||
.meta-chevron {
|
||||
font-size: var(--text-xs);
|
||||
color: var(--text-color-secondary);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.compact-meta {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--space-xs);
|
||||
padding: var(--space-xs) var(--space-md) var(--space-sm) calc(40px + var(--space-md) + var(--space-sm));
|
||||
background: var(--surface-hover);
|
||||
font-size: var(--text-xs);
|
||||
color: var(--text-color-secondary);
|
||||
}
|
||||
|
||||
.mobile-data-card .card-amount {
|
||||
font-weight: var(--font-semibold);
|
||||
color: var(--text-color);
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
|
||||
.mobile-data-card .card-amount.positive {
|
||||
color: var(--green-600);
|
||||
}
|
||||
|
||||
.mobile-data-card .card-amount.negative {
|
||||
color: var(--red-600);
|
||||
.meta-item {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.mobile-empty {
|
||||
@@ -1126,41 +1156,33 @@ watch(
|
||||
Dark Mode Support
|
||||
================================================ */
|
||||
|
||||
[data-theme="dark"] .mobile-totals-bar .total-value.incasari {
|
||||
[data-theme="dark"] .compact-amount.positive {
|
||||
color: var(--green-400);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .mobile-totals-bar .total-value.plati {
|
||||
color: var(--red-400);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .mobile-data-card .card-amount.positive {
|
||||
color: var(--green-400);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .mobile-data-card .card-amount.negative {
|
||||
[data-theme="dark"] .compact-amount.negative {
|
||||
color: var(--red-400);
|
||||
}
|
||||
|
||||
/* Auto dark mode */
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root:not([data-theme]) .mobile-totals-bar .total-value.incasari {
|
||||
:root:not([data-theme]) .compact-amount.positive {
|
||||
color: var(--green-400);
|
||||
}
|
||||
|
||||
:root:not([data-theme]) .mobile-totals-bar .total-value.plati {
|
||||
:root:not([data-theme]) .compact-amount.negative {
|
||||
color: var(--red-400);
|
||||
}
|
||||
|
||||
:root:not([data-theme]) .mobile-data-card .card-amount.positive {
|
||||
color: var(--green-400);
|
||||
}
|
||||
|
||||
:root:not([data-theme]) .mobile-data-card .card-amount.negative {
|
||||
:root:not([data-theme]) .numeric-value.negative {
|
||||
color: var(--red-400);
|
||||
}
|
||||
}
|
||||
|
||||
[data-theme="dark"] .numeric-value.negative {
|
||||
color: var(--red-400);
|
||||
}
|
||||
|
||||
/* ================================================
|
||||
Responsive Design
|
||||
================================================ */
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<!-- Mobile Top Bar -->
|
||||
<MobileTopBar
|
||||
v-if="isMobile"
|
||||
title="Dashboard"
|
||||
:title="dashboardTitle"
|
||||
:show-menu="true"
|
||||
:actions="mobileTopBarActions"
|
||||
@menu-click="showDrawer = true"
|
||||
@@ -775,6 +775,17 @@ const bancaPreviousSparkline = computed(() => {
|
||||
const windowWidth = ref(window.innerWidth);
|
||||
const isMobile = computed(() => windowWidth.value < 768);
|
||||
|
||||
const dashboardTitle = computed(() => {
|
||||
const company = companyStore.selectedCompany?.name;
|
||||
const period = periodStore.selectedPeriod;
|
||||
if (!company) return 'Dashboard';
|
||||
if (period) {
|
||||
const lunaStr = String(period.luna).padStart(2, '0');
|
||||
return `${company} · ${lunaStr}/${period.an}`;
|
||||
}
|
||||
return company;
|
||||
});
|
||||
|
||||
// Handle window resize for mobile detection
|
||||
const handleResize = () => {
|
||||
windowWidth.value = window.innerWidth;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<!-- US-703: Mobile Top Bar with Hamburger Menu (not back button) -->
|
||||
<MobileTopBar
|
||||
v-if="isMobile"
|
||||
title="Facturi Detaliate"
|
||||
title="Facturi pe Parteneri"
|
||||
:show-menu="true"
|
||||
:actions="topBarActions"
|
||||
@menu-click="showDrawer = true"
|
||||
@@ -52,8 +52,8 @@
|
||||
<!-- Page Header - only on desktop -->
|
||||
<!-- US-603: Desktop header with tabs -->
|
||||
<div v-if="!isMobile" class="page-header">
|
||||
<h1 class="page-title">Facturi Detaliate</h1>
|
||||
<p class="page-subtitle">Vizualizare detaliată a facturilor clienți și furnizori</p>
|
||||
<h1 class="page-title">Facturi pe Parteneri</h1>
|
||||
<p class="page-subtitle">Vizualizare facturi grupate pe clienți și furnizori</p>
|
||||
|
||||
<!-- US-603: Desktop Tabs for Clienți/Furnizori -->
|
||||
<div class="desktop-tabs">
|
||||
@@ -106,18 +106,6 @@
|
||||
@input="handleSearch"
|
||||
/>
|
||||
</div>
|
||||
<div class="filter-group">
|
||||
<label class="form-label">Perioadă</label>
|
||||
<Dropdown
|
||||
v-model="selectedPeriod"
|
||||
:options="periodOptions"
|
||||
optionLabel="label"
|
||||
optionValue="value"
|
||||
placeholder="Selectați perioada"
|
||||
class="w-full"
|
||||
@change="loadDetailedData"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<!-- US-501: Desktop Action buttons with Export dropdown -->
|
||||
<div class="filters-actions">
|
||||
@@ -152,11 +140,6 @@
|
||||
<span>{{ searchTerm }}</span>
|
||||
<i class="pi pi-times" @click="clearSearch"></i>
|
||||
</div>
|
||||
<div v-if="selectedPeriod !== 'all'" class="filter-chip active">
|
||||
<i class="pi pi-calendar"></i>
|
||||
<span>{{ getPeriodLabel(selectedPeriod) }}</span>
|
||||
<i class="pi pi-times" @click="clearPeriod"></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Loading State -->
|
||||
@@ -174,6 +157,26 @@
|
||||
|
||||
<!-- Data Table / Cards -->
|
||||
<div v-else class="data-section">
|
||||
<!-- Desktop Totals - above table -->
|
||||
<div v-if="!isMobile && filteredData.length > 0" class="summary-stats-inline">
|
||||
<div class="stat-item">
|
||||
<span class="stat-label">Total Sold:</span>
|
||||
<span class="stat-value">{{ formatCurrency(calculateTotal('sold')) }}</span>
|
||||
</div>
|
||||
<div v-if="invoiceType !== 'treasury'" class="stat-item">
|
||||
<span class="stat-label">Total Facturat:</span>
|
||||
<span class="stat-value">{{ formatCurrency(calculateTotal('facturat')) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Mobile Totals - above cards -->
|
||||
<div v-if="isMobile && filteredData.length > 0" class="mobile-totals-bar">
|
||||
<div class="mobile-totals-content">
|
||||
<span class="total-label">Sold Total:</span>
|
||||
<span class="total-value">{{ formatCurrency(calculateTotal('sold')) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Desktop Table -->
|
||||
<div v-if="!isMobile" class="table-wrapper">
|
||||
<!-- Treasury DataTable (no expansion needed) -->
|
||||
@@ -314,103 +317,56 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Mobile Cards -->
|
||||
<div v-if="isMobile" class="mobile-cards">
|
||||
<!-- Treasury Cards -->
|
||||
<!-- Mobile: Collapsible Rows -->
|
||||
<div v-if="isMobile" class="mobile-partner-list">
|
||||
<!-- Treasury: simple flat rows -->
|
||||
<template v-if="invoiceType === 'treasury'">
|
||||
<div
|
||||
v-for="row in paginatedData"
|
||||
:key="row.id"
|
||||
class="invoice-card"
|
||||
class="mobile-partner-row treasury-row"
|
||||
>
|
||||
<div class="card-header-row">
|
||||
<strong>{{ row.cont }}</strong>
|
||||
<span class="card-badge">{{ row.valuta }}</span>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="card-field">
|
||||
<span class="field-label">Nume Cont</span>
|
||||
<span class="field-value">{{ row.nume_cont }}</span>
|
||||
</div>
|
||||
<div class="card-field highlight">
|
||||
<span class="field-label">Sold</span>
|
||||
<span class="field-value sold-value">{{ formatCurrency(row.sold) }}</span>
|
||||
<div class="partner-header">
|
||||
<div class="partner-info">
|
||||
<span class="partner-name">{{ row.cont }}</span>
|
||||
<span class="partner-meta">{{ row.nume_cont }}</span>
|
||||
</div>
|
||||
<span class="partner-sold">{{ formatCurrency(row.sold) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- Client/Supplier Cards -->
|
||||
<!-- Clients/Suppliers: collapsible partner rows -->
|
||||
<template v-else>
|
||||
<div
|
||||
v-for="group in paginatedGroups"
|
||||
:key="group.name"
|
||||
class="invoice-card"
|
||||
:class="{ 'has-multiple': group.facturi.length > 1 }"
|
||||
@click="group.facturi.length > 1 && toggleGroup(group.name)"
|
||||
class="mobile-partner-row"
|
||||
>
|
||||
<div class="card-header-row">
|
||||
<div class="header-left">
|
||||
<strong>{{ group.name }}</strong>
|
||||
<span v-if="group.facturi.length > 1" class="count-badge">
|
||||
({{ group.facturi.length }})
|
||||
</span>
|
||||
<div class="partner-header" @click="toggleGroup(group.name)">
|
||||
<div class="partner-info">
|
||||
<span class="partner-name">{{ group.name }}</span>
|
||||
<span class="partner-meta">({{ group.facturi.length }})</span>
|
||||
</div>
|
||||
<div class="header-right">
|
||||
<span
|
||||
class="sold-value"
|
||||
:class="{ 'sold-restant': group.hasRestant }"
|
||||
>
|
||||
<div class="partner-total">
|
||||
<span class="partner-sold" :class="{ overdue: group.hasRestant }">
|
||||
{{ formatCurrency(group.totalSold) }}
|
||||
</span>
|
||||
<i
|
||||
v-if="group.facturi.length > 1"
|
||||
:class="['pi', isGroupExpanded(group.name) ? 'pi-chevron-up' : 'pi-chevron-down']"
|
||||
></i>
|
||||
<i :class="isGroupExpanded(group.name) ? 'pi pi-chevron-up' : 'pi pi-chevron-down'" class="partner-chevron"></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Single invoice details -->
|
||||
<div v-if="group.facturi.length === 1" class="card-body">
|
||||
<div class="card-field">
|
||||
<span class="field-label">Nr. Document</span>
|
||||
<span class="field-value">{{ group.facturi[0].numar_document }}</span>
|
||||
</div>
|
||||
<div class="card-row-inline">
|
||||
<div class="card-field">
|
||||
<span class="field-label">Data Doc.</span>
|
||||
<span class="field-value">{{ formatDate(group.facturi[0].data_document) }}</span>
|
||||
</div>
|
||||
<div class="card-field">
|
||||
<span class="field-label">Scadență</span>
|
||||
<span class="field-value">{{ formatDate(group.facturi[0].data_scadenta) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-status" :class="getStatusClass(group.facturi[0].status)">
|
||||
{{ group.facturi[0].status }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Multiple invoices expanded -->
|
||||
<div v-if="group.facturi.length > 1 && isGroupExpanded(group.name)" class="card-sub-items">
|
||||
<div v-if="isGroupExpanded(group.name)" class="partner-invoices">
|
||||
<div
|
||||
v-for="(factura, idx) in group.facturi"
|
||||
:key="`${group.name}-${idx}`"
|
||||
class="sub-item"
|
||||
class="invoice-line"
|
||||
>
|
||||
<div class="sub-item-header">
|
||||
<span>{{ factura.numar_document }}</span>
|
||||
<span
|
||||
class="sub-item-sold"
|
||||
:class="{ 'sold-restant': factura.status === 'Restant' }"
|
||||
>
|
||||
{{ formatCurrency(factura.sold) }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="sub-item-dates">
|
||||
<span>{{ formatDate(factura.data_scadenta) }}</span>
|
||||
<span :class="getStatusClass(factura.status)">{{ factura.status }}</span>
|
||||
</div>
|
||||
<span class="invoice-ref">
|
||||
{{ factura.numar_document }} · {{ formatDate(factura.data_document) }} · sc:{{ formatDate(factura.data_scadenta) }}
|
||||
</span>
|
||||
<span class="invoice-sold" :class="{ overdue: factura.status === 'Restant' }">
|
||||
{{ formatCurrency(factura.sold) }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -434,17 +390,6 @@
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Totals Summary -->
|
||||
<div v-if="filteredData.length > 0" class="totals-summary">
|
||||
<div class="total-item">
|
||||
<span class="total-label">Total Sold:</span>
|
||||
<span class="total-value">{{ formatCurrency(calculateTotal('sold')) }}</span>
|
||||
</div>
|
||||
<div v-if="invoiceType !== 'treasury'" class="total-item">
|
||||
<span class="total-label">Total Facturat:</span>
|
||||
<span class="total-value">{{ formatCurrency(calculateTotal('facturat')) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -468,18 +413,6 @@
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="filter-sheet-group">
|
||||
<label class="form-label">Perioadă</label>
|
||||
<Dropdown
|
||||
v-model="selectedPeriod"
|
||||
:options="periodOptions"
|
||||
optionLabel="label"
|
||||
optionValue="value"
|
||||
placeholder="Selectați perioada"
|
||||
class="w-full"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="filter-sheet-actions">
|
||||
<Button
|
||||
label="Resetează"
|
||||
@@ -504,7 +437,6 @@
|
||||
import { ref, computed, onMounted, onUnmounted, watch, Transition } from 'vue'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import Button from 'primevue/button'
|
||||
import Dropdown from 'primevue/dropdown'
|
||||
import InputText from 'primevue/inputtext'
|
||||
import DataTable from 'primevue/datatable'
|
||||
import Column from 'primevue/column'
|
||||
@@ -519,8 +451,8 @@ import SplitButton from 'primevue/splitbutton'
|
||||
import { useDashboardStore } from '@reports/stores/dashboard'
|
||||
import { useCompanyStore, useAccountingPeriodStore, useAuthStore } from '@reports/stores/sharedStores'
|
||||
import * as XLSX from 'xlsx'
|
||||
import jsPDF from 'jspdf'
|
||||
import 'jspdf-autotable'
|
||||
import { jsPDF } from 'jspdf'
|
||||
import autoTable from 'jspdf-autotable'
|
||||
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
@@ -572,7 +504,6 @@ const isLoading = ref(false)
|
||||
const error = ref(null)
|
||||
// US-510: Removed selectedType - now using invoiceType from route
|
||||
const searchTerm = ref('')
|
||||
const selectedPeriod = ref('all')
|
||||
const detailedData = ref([])
|
||||
const firstRow = ref(0)
|
||||
const rowsPerPage = ref(25)
|
||||
@@ -582,20 +513,10 @@ const isFilterSheetOpen = ref(false)
|
||||
// Options
|
||||
// US-510: Removed typeOptions - type is now determined by route
|
||||
|
||||
const periodOptions = [
|
||||
{ label: 'Toate', value: 'all' },
|
||||
{ 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' }
|
||||
]
|
||||
|
||||
// US-501: Check if filters have non-default values
|
||||
// US-510: Removed selectedType check - type is now route-based
|
||||
const hasActiveFilters = computed(() => {
|
||||
return searchTerm.value !== '' ||
|
||||
selectedPeriod.value !== 'all'
|
||||
return searchTerm.value !== ''
|
||||
})
|
||||
|
||||
// US-501: Mobile TopBar actions (filter, reset, export dropdown)
|
||||
@@ -729,16 +650,6 @@ const totalRecords = computed(() => {
|
||||
// Helper functions
|
||||
// US-510: Removed getTypeLabel - no longer needed
|
||||
|
||||
const getPeriodLabel = (period) => {
|
||||
const option = periodOptions.find(o => o.value === period)
|
||||
return option?.label || period
|
||||
}
|
||||
|
||||
const getStatusClass = (status) => {
|
||||
if (status === 'Restant') return 'status-restant'
|
||||
return 'status-ok'
|
||||
}
|
||||
|
||||
const toggleGroup = (groupName) => {
|
||||
if (expandedGroups.value.has(groupName)) {
|
||||
expandedGroups.value.delete(groupName)
|
||||
@@ -811,12 +722,6 @@ const clearSearch = () => {
|
||||
handleSearch()
|
||||
}
|
||||
|
||||
// US-511: Clear period filter from chip
|
||||
const clearPeriod = () => {
|
||||
selectedPeriod.value = 'all'
|
||||
loadDetailedData()
|
||||
}
|
||||
|
||||
const handleSearch = () => {
|
||||
firstRow.value = 0
|
||||
expandedGroups.value.clear()
|
||||
@@ -825,7 +730,6 @@ const handleSearch = () => {
|
||||
const resetFilters = () => {
|
||||
// US-510: Removed type reset - type is now determined by route
|
||||
searchTerm.value = ''
|
||||
selectedPeriod.value = 'all'
|
||||
firstRow.value = 0
|
||||
expandedGroups.value.clear()
|
||||
loadDetailedData()
|
||||
@@ -923,7 +827,7 @@ const exportPDF = () => {
|
||||
]
|
||||
})
|
||||
|
||||
doc.autoTable({
|
||||
autoTable(doc, {
|
||||
head: [columns],
|
||||
body: rows,
|
||||
theme: 'grid',
|
||||
@@ -1537,154 +1441,125 @@ onUnmounted(() => {
|
||||
color: var(--color-error) !important;
|
||||
}
|
||||
|
||||
/* Mobile Cards */
|
||||
.mobile-cards {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--space-md);
|
||||
[data-theme="dark"] .sold-restant {
|
||||
color: var(--red-400) !important;
|
||||
}
|
||||
|
||||
.invoice-card {
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root:not([data-theme]) .sold-restant {
|
||||
color: var(--red-400) !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* Mobile Partner List */
|
||||
.mobile-partner-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--space-sm);
|
||||
}
|
||||
|
||||
.mobile-partner-row {
|
||||
background: var(--surface-card);
|
||||
border: 1px solid var(--surface-border);
|
||||
border-radius: var(--radius-md);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.invoice-card.has-multiple {
|
||||
.partner-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: var(--space-sm) var(--space-md);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.card-header-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: var(--space-md);
|
||||
background: var(--surface-hover);
|
||||
border-bottom: 1px solid var(--surface-border);
|
||||
}
|
||||
|
||||
.header-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--space-sm);
|
||||
min-height: 44px;
|
||||
}
|
||||
|
||||
.header-right {
|
||||
.treasury-row .partner-header {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.partner-info {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: var(--space-sm);
|
||||
}
|
||||
|
||||
.card-badge {
|
||||
font-size: var(--text-xs);
|
||||
padding: 2px var(--space-xs);
|
||||
background: var(--primary-100);
|
||||
color: var(--color-primary);
|
||||
border-radius: var(--radius-sm);
|
||||
}
|
||||
|
||||
.card-body {
|
||||
padding: var(--space-md);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--space-sm);
|
||||
}
|
||||
|
||||
.card-field {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.card-field.highlight {
|
||||
padding-top: var(--space-sm);
|
||||
border-top: 1px solid var(--surface-border);
|
||||
margin-top: var(--space-xs);
|
||||
}
|
||||
|
||||
.card-row-inline {
|
||||
display: flex;
|
||||
gap: var(--space-md);
|
||||
}
|
||||
|
||||
.card-row-inline .card-field {
|
||||
gap: var(--space-xs);
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: 2px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.field-label {
|
||||
.partner-name {
|
||||
font-size: var(--text-sm);
|
||||
font-weight: var(--font-semibold);
|
||||
color: var(--text-color);
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.partner-meta {
|
||||
font-size: var(--text-xs);
|
||||
color: var(--text-color-secondary);
|
||||
}
|
||||
|
||||
.field-value {
|
||||
font-size: var(--text-sm);
|
||||
color: var(--text-color);
|
||||
font-weight: var(--font-medium);
|
||||
.partner-total {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--space-xs);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.sold-value {
|
||||
.partner-sold {
|
||||
font-family: var(--font-mono);
|
||||
font-size: var(--text-sm);
|
||||
font-weight: var(--font-bold);
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
.card-status {
|
||||
display: inline-flex;
|
||||
align-self: flex-start;
|
||||
font-size: var(--text-xs);
|
||||
padding: 2px var(--space-sm);
|
||||
border-radius: var(--radius-full);
|
||||
font-weight: var(--font-medium);
|
||||
}
|
||||
|
||||
.status-ok {
|
||||
background: var(--green-100);
|
||||
color: var(--green-600);
|
||||
}
|
||||
|
||||
.status-restant {
|
||||
background: var(--red-100);
|
||||
.partner-sold.overdue {
|
||||
color: var(--red-600);
|
||||
}
|
||||
|
||||
/* Sub items for expanded groups */
|
||||
.card-sub-items {
|
||||
.partner-chevron {
|
||||
font-size: 12px;
|
||||
color: var(--text-color-secondary);
|
||||
}
|
||||
|
||||
.partner-invoices {
|
||||
border-top: 1px solid var(--surface-border);
|
||||
padding: var(--space-sm) var(--space-md) var(--space-md);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--space-sm);
|
||||
}
|
||||
|
||||
.sub-item {
|
||||
padding: var(--space-sm);
|
||||
background: var(--surface-hover);
|
||||
border-radius: var(--radius-sm);
|
||||
}
|
||||
|
||||
.sub-item-header {
|
||||
.invoice-line {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
font-size: var(--text-sm);
|
||||
font-weight: var(--font-medium);
|
||||
margin-bottom: 4px;
|
||||
padding: var(--space-xs) var(--space-md);
|
||||
border-bottom: 1px solid var(--surface-border);
|
||||
gap: var(--space-sm);
|
||||
}
|
||||
|
||||
.sub-item-sold {
|
||||
font-family: var(--font-mono);
|
||||
font-weight: var(--font-bold);
|
||||
.invoice-line:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.sub-item-dates {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
.invoice-ref {
|
||||
font-size: var(--text-xs);
|
||||
color: var(--text-color-secondary);
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.invoice-sold {
|
||||
font-family: var(--font-mono);
|
||||
font-size: var(--text-xs);
|
||||
font-weight: var(--font-semibold);
|
||||
color: var(--text-color);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.invoice-sold.overdue {
|
||||
color: var(--red-600);
|
||||
}
|
||||
|
||||
/* Empty data state */
|
||||
@@ -1710,39 +1585,34 @@ onUnmounted(() => {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
/* Totals Summary */
|
||||
.totals-summary {
|
||||
display: flex;
|
||||
gap: var(--space-lg);
|
||||
padding: var(--space-md);
|
||||
/* Desktop Totals - uses global stats.css (src/assets/css/components/stats.css) */
|
||||
|
||||
/* Mobile Totals Bar */
|
||||
.mobile-totals-bar {
|
||||
background: var(--surface-card);
|
||||
border: 1px solid var(--surface-border);
|
||||
padding: var(--space-sm) var(--space-md);
|
||||
margin-bottom: var(--space-md);
|
||||
border-radius: var(--radius-md);
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.totals-summary {
|
||||
flex-direction: column;
|
||||
gap: var(--space-sm);
|
||||
}
|
||||
}
|
||||
|
||||
.total-item {
|
||||
.mobile-totals-content {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
gap: var(--space-sm);
|
||||
}
|
||||
|
||||
.total-label {
|
||||
.mobile-totals-bar .total-label {
|
||||
font-size: var(--text-sm);
|
||||
color: var(--text-color-secondary);
|
||||
font-weight: var(--font-medium);
|
||||
}
|
||||
|
||||
.total-value {
|
||||
.mobile-totals-bar .total-value {
|
||||
font-size: var(--text-lg);
|
||||
font-weight: var(--font-bold);
|
||||
font-family: var(--font-mono);
|
||||
color: var(--color-primary);
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
/* Filter Sheet Content */
|
||||
@@ -1787,18 +1657,9 @@ onUnmounted(() => {
|
||||
background: var(--primary-800);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .card-badge {
|
||||
background: var(--primary-800);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .status-ok {
|
||||
background: var(--green-900);
|
||||
color: var(--green-300);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .status-restant {
|
||||
background: var(--red-900);
|
||||
color: var(--red-300);
|
||||
[data-theme="dark"] .partner-sold.overdue,
|
||||
[data-theme="dark"] .invoice-sold.overdue {
|
||||
color: var(--red-400);
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
@@ -1810,18 +1671,9 @@ onUnmounted(() => {
|
||||
background: var(--primary-800);
|
||||
}
|
||||
|
||||
:root:not([data-theme]) .card-badge {
|
||||
background: var(--primary-800);
|
||||
}
|
||||
|
||||
:root:not([data-theme]) .status-ok {
|
||||
background: var(--green-900);
|
||||
color: var(--green-300);
|
||||
}
|
||||
|
||||
:root:not([data-theme]) .status-restant {
|
||||
background: var(--red-900);
|
||||
color: var(--red-300);
|
||||
:root:not([data-theme]) .partner-sold.overdue,
|
||||
:root:not([data-theme]) .invoice-sold.overdue {
|
||||
color: var(--red-400);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -104,7 +104,8 @@
|
||||
<Button
|
||||
icon="pi pi-filter-slash"
|
||||
label="Resetează"
|
||||
class="p-button-outlined p-button-secondary"
|
||||
severity="secondary"
|
||||
outlined
|
||||
@click="clearFilters(); showFilters = false"
|
||||
/>
|
||||
<Button
|
||||
@@ -149,7 +150,7 @@
|
||||
<div v-if="isMobile && companyStore.selectedCompany && invoicesStore.hasInvoices" class="mobile-totals-bar">
|
||||
<div class="mobile-totals-content">
|
||||
<span class="total-label">Sold Total:</span>
|
||||
<span class="total-value" :class="invoicesStore.totalSoldAll > 0 ? 'positive' : 'negative'">
|
||||
<span class="total-value">
|
||||
{{ formatCompact(invoicesStore.totalSoldAll) }}
|
||||
</span>
|
||||
</div>
|
||||
@@ -224,21 +225,16 @@
|
||||
<Button
|
||||
icon="pi pi-filter-slash"
|
||||
label="Resetează Filtre"
|
||||
class="p-button-outlined p-button-secondary"
|
||||
severity="secondary"
|
||||
outlined
|
||||
@click="clearFilters"
|
||||
/>
|
||||
<Button
|
||||
icon="pi pi-file-excel"
|
||||
label="Export Excel"
|
||||
class="p-button-outlined p-button-success"
|
||||
<SplitButton
|
||||
label="Export"
|
||||
icon="pi pi-download"
|
||||
:model="desktopExportItems"
|
||||
@click="exportExcel"
|
||||
:disabled="!invoicesStore.hasInvoices"
|
||||
/>
|
||||
<Button
|
||||
icon="pi pi-file-pdf"
|
||||
label="Export PDF"
|
||||
class="p-button-outlined p-button-danger"
|
||||
@click="exportPDF"
|
||||
outlined
|
||||
:disabled="!invoicesStore.hasInvoices"
|
||||
/>
|
||||
<Button
|
||||
@@ -257,7 +253,7 @@
|
||||
<div v-if="!isMobile && companyStore.selectedCompany && invoicesStore.hasInvoices" class="summary-stats-inline">
|
||||
<div class="stat-item">
|
||||
<span class="stat-label">Total Sold:</span>
|
||||
<span class="stat-value" :class="invoicesStore.totalSoldAll > 0 ? 'plati' : 'incasari'">
|
||||
<span class="stat-value">
|
||||
{{ formatCurrency(invoicesStore.totalSoldAll) }}
|
||||
</span>
|
||||
</div>
|
||||
@@ -266,23 +262,19 @@
|
||||
<!-- Invoices Table -->
|
||||
<Card v-if="companyStore.selectedCompany" class="table-card">
|
||||
<template #content>
|
||||
<!-- Mobile: Card Layout -->
|
||||
<div v-if="isMobile" class="mobile-card-list">
|
||||
<!-- Mobile: Flat List (compact, table-like) -->
|
||||
<div v-if="isMobile" class="mobile-flat-list">
|
||||
<div
|
||||
v-for="invoice in invoicesStore.invoiceList"
|
||||
:key="invoice.nract"
|
||||
class="mobile-data-card"
|
||||
class="flat-row"
|
||||
>
|
||||
<div class="card-header">{{ invoice.nume }}</div>
|
||||
<div class="card-row">
|
||||
<span>{{ formatDate(invoice.dataact) }} · {{ invoice.nract }}</span>
|
||||
<span
|
||||
class="card-amount"
|
||||
:class="{ positive: invoice.soldfinal > 0 }"
|
||||
>
|
||||
{{ formatNumber(invoice.soldfinal) }}
|
||||
</span>
|
||||
<div class="flat-row-left">
|
||||
<span class="flat-cont">{{ invoice.nract }}</span>
|
||||
<span class="flat-date">{{ formatDateShort(invoice.dataact) }}</span>
|
||||
<span class="flat-denumire">{{ invoice.nume || '–' }}</span>
|
||||
</div>
|
||||
<span class="flat-sold">{{ formatNumber(invoice.soldfinal) }}</span>
|
||||
</div>
|
||||
<div v-if="invoicesStore.invoiceList.length === 0" class="mobile-empty">
|
||||
<i class="pi pi-info-circle"></i>
|
||||
@@ -412,6 +404,7 @@ 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 SplitButton from "primevue/splitbutton";
|
||||
import { useRouter, useRoute } from "vue-router";
|
||||
|
||||
const toast = useToast();
|
||||
@@ -591,12 +584,26 @@ const paymentStatusOptions = [
|
||||
{ label: "Toate", value: "toate" },
|
||||
];
|
||||
|
||||
// Desktop export dropdown items (SplitButton)
|
||||
const desktopExportItems = [
|
||||
{
|
||||
label: "Export Excel",
|
||||
icon: "pi pi-file-excel",
|
||||
command: () => exportExcel(),
|
||||
},
|
||||
{
|
||||
label: "Export PDF",
|
||||
icon: "pi pi-file-pdf",
|
||||
command: () => exportPDF(),
|
||||
},
|
||||
];
|
||||
|
||||
// Methods
|
||||
const formatCurrency = (amount) => {
|
||||
if (!amount) return "0,00 RON";
|
||||
if (!amount || amount === 0) return "0,00";
|
||||
return new Intl.NumberFormat("ro-RO", {
|
||||
style: "currency",
|
||||
currency: "RON",
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
}).format(amount);
|
||||
};
|
||||
|
||||
@@ -631,6 +638,16 @@ const formatDate = (dateString) => {
|
||||
}
|
||||
};
|
||||
|
||||
// Short date format for mobile (DD/MM only)
|
||||
const formatDateShort = (dateString) => {
|
||||
if (!dateString) return "";
|
||||
try {
|
||||
return format(new Date(dateString), "dd/MM", { locale: ro });
|
||||
} catch (error) {
|
||||
return "";
|
||||
}
|
||||
};
|
||||
|
||||
const handleCompanyChange = async () => {
|
||||
if (!selectedCompanyId.value) return;
|
||||
|
||||
@@ -1157,55 +1174,66 @@ watch(
|
||||
.mobile-totals-bar .total-value {
|
||||
font-size: var(--text-lg);
|
||||
font-weight: var(--font-bold);
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
.mobile-totals-bar .total-value.positive {
|
||||
color: var(--green-600);
|
||||
}
|
||||
|
||||
.mobile-totals-bar .total-value.negative {
|
||||
color: var(--red-600);
|
||||
}
|
||||
/* Colors removed - totals use neutral --text-color like TrialBalance */
|
||||
|
||||
/* ================================================
|
||||
US-107: Mobile Card List (Invoice Cards)
|
||||
Mobile Flat List (Compact Invoice Rows - like TrialBalance)
|
||||
================================================ */
|
||||
|
||||
.mobile-card-list {
|
||||
.mobile-flat-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--space-sm);
|
||||
}
|
||||
|
||||
.mobile-data-card {
|
||||
background: var(--surface-card);
|
||||
border: 1px solid var(--surface-border);
|
||||
border-radius: var(--radius-md);
|
||||
padding: var(--space-md);
|
||||
}
|
||||
|
||||
.mobile-data-card .card-header {
|
||||
font-weight: var(--font-semibold);
|
||||
color: var(--text-color);
|
||||
margin-bottom: var(--space-xs);
|
||||
font-size: var(--text-base);
|
||||
}
|
||||
|
||||
.mobile-data-card .card-row {
|
||||
.flat-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
font-size: var(--text-sm);
|
||||
color: var(--text-color-secondary);
|
||||
border-bottom: 1px solid var(--surface-border);
|
||||
min-height: 44px;
|
||||
padding: var(--space-sm) var(--space-md);
|
||||
gap: var(--space-sm);
|
||||
}
|
||||
|
||||
.mobile-data-card .card-amount {
|
||||
font-weight: var(--font-semibold);
|
||||
.flat-row-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--space-sm);
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.flat-cont {
|
||||
font-weight: var(--font-bold);
|
||||
color: var(--text-color);
|
||||
font-size: var(--text-sm);
|
||||
min-width: 48px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.mobile-data-card .card-amount.positive {
|
||||
color: var(--green-600);
|
||||
.flat-date {
|
||||
font-size: var(--text-xs);
|
||||
color: var(--text-color-secondary);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.flat-denumire {
|
||||
color: var(--text-color-secondary);
|
||||
font-size: var(--text-sm);
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.flat-sold {
|
||||
font-weight: var(--font-semibold);
|
||||
font-variant-numeric: tabular-nums;
|
||||
font-size: var(--text-sm);
|
||||
color: var(--text-color);
|
||||
text-align: right;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.mobile-empty {
|
||||
@@ -1293,83 +1321,19 @@ watch(
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* ================================================
|
||||
Summary Stats
|
||||
================================================ */
|
||||
|
||||
.summary-stats-inline {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin-bottom: var(--space-md);
|
||||
}
|
||||
|
||||
.stat-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--space-sm);
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
font-size: var(--text-sm);
|
||||
color: var(--text-color-secondary);
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
font-size: var(--text-lg);
|
||||
font-weight: var(--font-bold);
|
||||
}
|
||||
|
||||
.stat-value.plati {
|
||||
color: var(--red-600);
|
||||
}
|
||||
|
||||
.stat-value.incasari {
|
||||
color: var(--green-600);
|
||||
}
|
||||
/* Summary Stats - uses global stats.css (src/assets/css/components/stats.css) */
|
||||
|
||||
/* ================================================
|
||||
Dark Mode Support
|
||||
================================================ */
|
||||
|
||||
[data-theme="dark"] .mobile-totals-bar .total-value.positive {
|
||||
color: var(--green-400);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .mobile-totals-bar .total-value.negative {
|
||||
color: var(--red-400);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .mobile-data-card .card-amount.positive {
|
||||
color: var(--green-400);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .sidebar-item.active {
|
||||
background: var(--blue-900);
|
||||
color: var(--blue-400);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .stat-value.plati {
|
||||
color: var(--red-400);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .stat-value.incasari {
|
||||
color: var(--green-400);
|
||||
}
|
||||
|
||||
/* Auto dark mode */
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root:not([data-theme]) .mobile-totals-bar .total-value.positive {
|
||||
color: var(--green-400);
|
||||
}
|
||||
|
||||
:root:not([data-theme]) .mobile-totals-bar .total-value.negative {
|
||||
color: var(--red-400);
|
||||
}
|
||||
|
||||
:root:not([data-theme]) .mobile-data-card .card-amount.positive {
|
||||
color: var(--green-400);
|
||||
}
|
||||
|
||||
:root:not([data-theme]) .sidebar-item.active {
|
||||
background: var(--blue-900);
|
||||
color: var(--blue-400);
|
||||
|
||||
@@ -57,7 +57,8 @@
|
||||
<Button
|
||||
icon="pi pi-filter-slash"
|
||||
label="Resetează"
|
||||
class="p-button-outlined p-button-secondary"
|
||||
severity="secondary"
|
||||
outlined
|
||||
@click="clearFilters(); showFilters = false"
|
||||
/>
|
||||
<Button
|
||||
@@ -151,7 +152,8 @@
|
||||
<Button
|
||||
icon="pi pi-filter-slash"
|
||||
label="Resetează Filtre"
|
||||
class="p-button-outlined p-button-secondary"
|
||||
severity="secondary"
|
||||
outlined
|
||||
@click="clearFilters"
|
||||
/>
|
||||
<SplitButton
|
||||
@@ -159,7 +161,7 @@
|
||||
icon="pi pi-download"
|
||||
:model="desktopExportItems"
|
||||
@click="exportPDF"
|
||||
class="p-button-outlined"
|
||||
outlined
|
||||
:disabled="!trialBalanceStore.hasData"
|
||||
/>
|
||||
<Button
|
||||
@@ -205,26 +207,24 @@
|
||||
<!-- Trial Balance Table -->
|
||||
<Card v-if="companyStore.selectedCompany" class="table-card">
|
||||
<template #content>
|
||||
<!-- Mobile: Card Layout -->
|
||||
<div v-if="isMobile" class="mobile-card-list">
|
||||
<!-- Mobile: Flat Single-Row List -->
|
||||
<div v-if="isMobile" class="mobile-flat-list">
|
||||
<div
|
||||
v-for="account in trialBalanceStore.trialBalanceData.filter(a => a.sold_final_debit > 0 || a.sold_final_credit > 0)"
|
||||
v-for="account in filteredMobileAccounts"
|
||||
:key="account.cont"
|
||||
class="mobile-data-card"
|
||||
class="flat-row"
|
||||
>
|
||||
<div class="card-header">
|
||||
<strong>{{ account.cont }}</strong> {{ truncate(account.denumire, 30) }}
|
||||
</div>
|
||||
<div class="card-row">
|
||||
<span></span>
|
||||
<span class="card-amount">
|
||||
{{ account.sold_final_debit > 0
|
||||
? formatCurrency(account.sold_final_debit) + ' D'
|
||||
: formatCurrency(account.sold_final_credit) + ' C' }}
|
||||
</span>
|
||||
<div class="flat-row-left">
|
||||
<span class="flat-cont">{{ account.cont }}</span>
|
||||
<span class="flat-denumire">{{ account.denumire }}</span>
|
||||
</div>
|
||||
<span class="flat-sold">
|
||||
{{ account.sold_final_debit > 0
|
||||
? formatCompact(account.sold_final_debit) + ' D'
|
||||
: formatCompact(account.sold_final_credit) + ' C' }}
|
||||
</span>
|
||||
</div>
|
||||
<div v-if="trialBalanceStore.trialBalanceData.filter(a => a.sold_final_debit > 0 || a.sold_final_credit > 0).length === 0" class="mobile-empty">
|
||||
<div v-if="filteredMobileAccounts.length === 0" class="mobile-empty">
|
||||
<i class="pi pi-info-circle"></i>
|
||||
<p>Nu au fost găsite date</p>
|
||||
</div>
|
||||
@@ -506,6 +506,11 @@ const hasActiveFilters = computed(() => {
|
||||
return localFilters.value.cont !== "" || localFilters.value.denumire !== "";
|
||||
});
|
||||
|
||||
// Mobile: Accounts with non-zero final balance (avoids inline .filter() in template)
|
||||
const filteredMobileAccounts = computed(() =>
|
||||
trialBalanceStore.trialBalanceData.filter(a => a.sold_final_debit > 0 || a.sold_final_credit > 0)
|
||||
);
|
||||
|
||||
// Mobile: Actions menu items
|
||||
const actionMenuItems = computed(() => [
|
||||
{
|
||||
@@ -1123,40 +1128,55 @@ watch(
|
||||
}
|
||||
|
||||
/* ================================================
|
||||
US-108: Mobile Card List (Account Cards)
|
||||
Mobile Flat List (Account Rows)
|
||||
================================================ */
|
||||
|
||||
.mobile-card-list {
|
||||
.mobile-flat-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--space-sm);
|
||||
}
|
||||
|
||||
.mobile-data-card {
|
||||
background: var(--surface-card);
|
||||
border: 1px solid var(--surface-border);
|
||||
border-radius: var(--radius-md);
|
||||
padding: var(--space-md);
|
||||
}
|
||||
|
||||
.mobile-data-card .card-header {
|
||||
font-weight: var(--font-semibold);
|
||||
color: var(--text-color);
|
||||
margin-bottom: var(--space-xs);
|
||||
font-size: var(--text-base);
|
||||
}
|
||||
|
||||
.mobile-data-card .card-row {
|
||||
.flat-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
font-size: var(--text-sm);
|
||||
color: var(--text-color-secondary);
|
||||
border-bottom: 1px solid var(--surface-border);
|
||||
min-height: 44px;
|
||||
padding: var(--space-sm) var(--space-md);
|
||||
gap: var(--space-sm);
|
||||
}
|
||||
|
||||
.mobile-data-card .card-amount {
|
||||
font-weight: var(--font-semibold);
|
||||
.flat-row-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--space-sm);
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.flat-cont {
|
||||
font-weight: var(--font-bold);
|
||||
color: var(--text-color);
|
||||
font-size: var(--text-sm);
|
||||
min-width: 48px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.flat-denumire {
|
||||
color: var(--text-color-secondary);
|
||||
font-size: var(--text-sm);
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.flat-sold {
|
||||
font-weight: var(--font-semibold);
|
||||
font-variant-numeric: tabular-nums;
|
||||
font-size: var(--text-sm);
|
||||
color: var(--text-color);
|
||||
text-align: right;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.mobile-empty {
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
* Default items (4 links):
|
||||
* - Dashboard (/dashboard)
|
||||
* - Bonuri (/data-entry)
|
||||
* - Facturi (/reports/invoices)
|
||||
* - Detalii (/reports/detailed-invoices)
|
||||
* - Setări (/settings)
|
||||
*/
|
||||
|
||||
@@ -58,7 +58,7 @@ defineProps({
|
||||
default: () => [
|
||||
{ to: '/dashboard', icon: 'pi pi-home', label: 'Dashboard' },
|
||||
{ to: '/data-entry', icon: 'pi pi-shopping-bag', label: 'Bonuri' },
|
||||
{ to: '/reports/invoices', icon: 'pi pi-file-edit', label: 'Facturi' },
|
||||
{ to: '/reports/detailed-invoices', icon: 'pi pi-file-edit', label: 'Detalii' },
|
||||
{ to: '/settings', icon: 'pi pi-cog', label: 'Setări' }
|
||||
],
|
||||
validator: (items) => {
|
||||
|
||||
@@ -715,18 +715,18 @@ const principaleItems = [
|
||||
{ to: '/data-entry', icon: 'pi pi-shopping-bag', label: 'Bonuri', exactMatch: false }
|
||||
]
|
||||
|
||||
// RAPOARTE: Facturi, Balanță, Casă, Bancă (US-519: separate pages)
|
||||
// RAPOARTE: Facturi, Facturi Detaliate, Balanță, Casă, Bancă (US-519: separate pages)
|
||||
const rapoarteItems = [
|
||||
{ to: '/reports/invoices', icon: 'pi pi-file', label: 'Facturi', exactMatch: true },
|
||||
{ to: '/reports/detailed-invoices', icon: 'pi pi-list', label: 'Facturi Detaliate', exactMatch: true },
|
||||
{ to: '/reports/trial-balance', icon: 'pi pi-calculator', label: 'Balanță', exactMatch: true },
|
||||
{ to: '/reports/cash', icon: 'pi pi-wallet', label: 'Casă', exactMatch: true },
|
||||
{ to: '/reports/bank', icon: 'pi pi-building', label: 'Bancă', exactMatch: true }
|
||||
]
|
||||
|
||||
// ANALIZE: Scadențe, Facturi Detaliate
|
||||
// ANALIZE: Scadențe
|
||||
const analizeItems = [
|
||||
{ to: '/reports/maturity-analysis', icon: 'pi pi-clock', label: 'Scadențe', exactMatch: true },
|
||||
{ to: '/reports/detailed-invoices', icon: 'pi pi-list', label: 'Facturi Detaliate', exactMatch: true }
|
||||
{ to: '/reports/maturity-analysis', icon: 'pi pi-clock', label: 'Scadențe', exactMatch: true }
|
||||
]
|
||||
|
||||
// ADMINISTRARE: Setări
|
||||
|
||||
Reference in New Issue
Block a user