diff --git a/index.html b/index.html
index 0771e31..7dccfe2 100644
--- a/index.html
+++ b/index.html
@@ -14,6 +14,15 @@
+
+
+
+
diff --git a/src/modules/reports/views/DashboardView.vue b/src/modules/reports/views/DashboardView.vue
index 80ae651..04dfb4e 100644
--- a/src/modules/reports/views/DashboardView.vue
+++ b/src/modules/reports/views/DashboardView.vue
@@ -4,7 +4,9 @@
v-if="isMobile"
title="Dashboard"
:show-menu="true"
+ :actions="mobileTopBarActions"
@menu-click="showDrawer = true"
+ @action-click="handleMobileAction"
/>
@@ -21,6 +23,16 @@
@@ -28,8 +40,36 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
-
+
+
-
+
+
-
-
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
@@ -161,13 +217,14 @@
import { ref, computed, onMounted, onUnmounted, watch } from "vue";
import { useRouter } from "vue-router";
import { useToast } from "primevue/usetoast";
+import Button from "primevue/button";
// Import componente noi
import MetricCard from "@reports/components/dashboard/cards/MetricCard.vue";
import CashFlowMetricCard from "@reports/components/dashboard/cards/CashFlowMetricCard.vue";
-import MaturityAndDetailsCard from "@reports/components/dashboard/cards/MaturityAndDetailsCard.vue";
import ClientiBalanceCard from "@reports/components/dashboard/cards/ClientiBalanceCard.vue";
import FurnizoriBalanceCard from "@reports/components/dashboard/cards/FurnizoriBalanceCard.vue";
import TreasuryDualCard from "@reports/components/dashboard/cards/TreasuryDualCard.vue";
+import SolduriCompactCard from "@reports/components/solduri/SolduriCompactCard.vue";
// Mobile components
import SwipeableCards from "@shared/components/mobile/SwipeableCards.vue";
import MobileTopBar from "@shared/components/mobile/MobileTopBar.vue";
@@ -205,12 +262,6 @@ const netBalanceData = ref(null);
const selectedPeriod = ref("12m");
const selectedChartType = ref("line");
-// Handlers pentru schimbare perioadă
-const handleMaturityPeriodChange = (period) => {
- console.log("Maturity period changed:", period);
- // Trigger reload cu noua perioadă
-};
-
// Calculare trend bazată pe date reale din trends.raw
const calculateTrend = (metric) => {
if (!dashboardStore.trends?.raw) return null;
@@ -406,6 +457,18 @@ const treasuryPreviousSparkline = computed(() =>
const sparklineLabels = computed(() => getSparklineLabels());
const previousSparklineLabels = computed(() => getPreviousSparklineLabels());
+// US-2002: Computed properties for SolduriCompactCard grid
+const totalTrezorerie = computed(() => {
+ const casaTotal = treasuryData.value?.breakdown?.casa?.total || 0;
+ const bancaTotal = treasuryData.value?.breakdown?.banca?.total || 0;
+ return casaTotal + bancaTotal;
+});
+
+const tvaTotal = computed(() => {
+ // TVA from dashboard summary if available, otherwise default to 0
+ return dashboardStore.summary?.tva_sold || 0;
+});
+
// Casa and Bancă specific trends and sparklines
const casaTrend = computed(() => {
// Calculate trend based on Casa proportion of treasury
@@ -522,6 +585,29 @@ const handleLogout = async () => {
router.push('/login');
};
+// US-2008: Mobile top bar actions with refresh button
+const mobileTopBarActions = computed(() => [
+ {
+ id: 'refresh',
+ icon: isLoading.value ? 'pi pi-spin pi-refresh' : 'pi pi-refresh',
+ label: 'Actualizează',
+ tooltip: 'Actualizează datele'
+ }
+]);
+
+// US-2008: Handle mobile action clicks
+const handleMobileAction = async (action) => {
+ if (action.id === 'refresh') {
+ await handleRefresh();
+ }
+};
+
+// US-2008: Handle refresh button click (shared between mobile and desktop)
+const handleRefresh = async () => {
+ if (isLoading.value) return; // Prevent multiple clicks during loading
+ await loadDashboardData();
+};
+
// Computed property pentru luna curentă - folosește perioada din period selector
const currentMonthLabel = computed(() => {
// Prioritate: period selector > dashboard current period > loading
@@ -990,6 +1076,30 @@ onUnmounted(() => {
padding-bottom: 56px; /* MobileBottomNav height */
}
+/* US-2008: Refresh Button Styles */
+.refresh-btn {
+ color: var(--color-text-secondary);
+ transition: color var(--transition-fast), transform var(--transition-fast);
+}
+
+.refresh-btn:hover {
+ color: var(--color-primary);
+}
+
+/* US-2008: Rotating animation during loading */
+.refresh-btn.is-loading .pi-refresh {
+ animation: spin 1s linear infinite;
+}
+
+@keyframes spin {
+ from {
+ transform: rotate(0deg);
+ }
+ to {
+ transform: rotate(360deg);
+ }
+}
+
/* Company Selection */
.company-selection {
max-width: 500px;
@@ -1006,13 +1116,6 @@ onUnmounted(() => {
font-style: italic;
}
-/* Dashboard Content */
-.dashboard-content {
- display: flex;
- flex-direction: column;
- gap: var(--space-xl);
-}
-
/* Dashboard Sections */
.dashboard-section {
background: var(--color-bg);
@@ -1273,27 +1376,29 @@ onUnmounted(() => {
padding: 0 var(--space-md);
}
+/* US-2004: Desktop Solduri Section - 2x2 grid (2 cards per row) */
+.desktop-solduri-section {
+ display: grid;
+ grid-template-columns: repeat(2, 1fr);
+ gap: var(--space-md);
+ margin-bottom: var(--space-lg);
+}
+
/* Metrics Cards Layout - Component-specific grid layouts */
.metrics-row {
display: grid;
grid-template-columns: repeat(2, 1fr);
- gap: 1rem;
- margin-bottom: 1.5rem;
+ gap: var(--space-md);
+ margin-bottom: var(--space-lg);
}
.analysis-row {
display: grid;
grid-template-columns: 1fr 1fr;
- gap: 1rem;
- margin-bottom: 1.5rem;
+ gap: var(--space-md);
+ margin-bottom: var(--space-lg);
}
-.comparison-row {
- display: grid;
- grid-template-columns: 1fr;
- gap: 1rem;
- margin-bottom: 1.5rem;
-}
/* Responsive - All breakpoints consolidated */
@media (max-width: 1200px) {
@@ -1325,4 +1430,17 @@ onUnmounted(() => {
.mobile-kpi-carousel {
margin-bottom: var(--space-lg);
}
+
+/* US-2002: Solduri list for mobile first page - 1 card per row */
+.solduri-grid-2x2 {
+ display: flex;
+ flex-direction: column;
+ gap: var(--space-sm);
+ padding: var(--space-xs);
+}
+
+/* Touch target compliance - SolduriCompactCard handles its own min-height */
+.solduri-grid-2x2 > * {
+ /* Height auto - only as tall as content needs */
+}
diff --git a/src/shared/components/mobile/MobileBottomNav.vue b/src/shared/components/mobile/MobileBottomNav.vue
index 94bb408..8c91ab9 100644
--- a/src/shared/components/mobile/MobileBottomNav.vue
+++ b/src/shared/components/mobile/MobileBottomNav.vue
@@ -57,7 +57,7 @@ defineProps({
type: Array,
default: () => [
{ to: '/dashboard', icon: 'pi pi-home', label: 'Dashboard' },
- { to: '/data-entry', icon: 'pi pi-receipt', label: 'Bonuri' },
+ { to: '/data-entry', icon: 'pi pi-shopping-bag', label: 'Bonuri' },
{ to: '/reports/invoices', icon: 'pi pi-file-edit', label: 'Facturi' },
{ to: '/settings', icon: 'pi pi-cog', label: 'Setări' }
],
diff --git a/src/shared/components/mobile/MobileDrawerMenu.vue b/src/shared/components/mobile/MobileDrawerMenu.vue
index d1dbc1f..912b553 100644
--- a/src/shared/components/mobile/MobileDrawerMenu.vue
+++ b/src/shared/components/mobile/MobileDrawerMenu.vue
@@ -407,7 +407,7 @@ watch(() => props.modelValue, (isOpen) => {
// PRINCIPALE: Dashboard, Bonuri
const principaleItems = [
{ to: '/dashboard', icon: 'pi pi-home', label: 'Dashboard', exactMatch: true },
- { to: '/data-entry', icon: 'pi pi-receipt', label: 'Bonuri', exactMatch: false }
+ { to: '/data-entry', icon: 'pi pi-shopping-bag', label: 'Bonuri', exactMatch: false }
]
// RAPOARTE: Facturi, Balanță, Casă, Bancă (US-519: separate pages)
diff --git a/tasks/prd-dashboard-solduri-v2.md b/tasks/prd-dashboard-solduri-v2.md
new file mode 100644
index 0000000..2e60276
--- /dev/null
+++ b/tasks/prd-dashboard-solduri-v2.md
@@ -0,0 +1,176 @@
+# PRD: Dashboard cu Solduri - Versiunea 2 (Corectă)
+
+## 1. Introducere
+Adăugare secțiune Solduri în Dashboard păstrând paginile originale cu grafice. Pe mobil, soldurile sunt prima pagină din swipe (grid 2x2), iar graficele sunt paginile 2-5 (ca în main). Pe desktop, două secțiuni separate: Solduri sus, Grafice jos.
+
+## 2. Obiective
+
+### Obiectiv Principal
+- Prima pagină din swipe pe mobil = 4 carduri compacte cu solduri
+- Paginile 2-5 din swipe = cardurile originale cu grafice (păstrate exact ca în main)
+
+### Obiective Secundare
+- Desktop: Secțiune Solduri + Secțiune Grafice (fără titluri vizibile)
+- Eliminare MaturityAndDetailsCard de pe Dashboard
+- Carduri solduri compacte cu expand pentru detalii
+
+### Metrici de Succes
+- Mobil: 5 pagini de swipe (Solduri + 4 grafice)
+- Desktop: 2 secțiuni vizual separate
+- Cardurile grafice rămân IDENTICE cu cele din main
+
+## 3. User Stories
+
+### US-2001: Creare componentă SolduriCompactCard (reutilizabilă)
+**Ca** dezvoltator
+**Vreau** o componentă card compactă pentru solduri
+**Pentru că** o voi folosi în grid 2x2 pe mobil și desktop
+
+**Acceptance Criteria:**
+- [ ] Creează SolduriCompactCard.vue în src/modules/reports/components/solduri/
+- [ ] Props: type (trezorerie|clienti|furnizori|tva), total, breakdown (object)
+- [ ] Afișează: icon + label + valoare principală
+- [ ] Click expandează/colapsează breakdown-ul (conturi, buckets)
+- [ ] Folosește design tokens pentru culori și spațiere
+- [ ] npm run typecheck passes
+
+### US-2002: Grid 2x2 Solduri pentru prima pagină swipe pe mobil
+**Ca** utilizator pe mobil
+**Vreau** prima pagină din swipe să fie un grid 2x2 cu 4 carduri solduri
+**Pentru că** văd toate soldurile dintr-o privire
+
+**Acceptance Criteria:**
+- [ ] Prima pagină din SwipeableCards conține un grid 2x2
+- [ ] Ordinea: Trezorerie | Clienți / Furnizori | TVA
+- [ ] Fiecare card e SolduriCompactCard cu props corecte
+- [ ] Touch target minim 44x44px
+- [ ] npm run typecheck passes
+- [ ] Verify in browser mobil că prima pagină e grid-ul cu solduri
+
+### US-2003: Păstrare carduri grafice originale pe paginile 2-5 mobil
+**Ca** utilizator pe mobil
+**Vreau** paginile 2-5 din swipe să fie cardurile cu grafice originale
+**Pentru că** vreau să le văd individual cu toate detaliile
+
+**Acceptance Criteria:**
+- [ ] Pagina 2: TreasuryDualCard (exact ca în main)
+- [ ] Pagina 3: CashFlowMetricCard (exact ca în main)
+- [ ] Pagina 4: ClientiBalanceCard (exact ca în main)
+- [ ] Pagina 5: FurnizoriBalanceCard (exact ca în main)
+- [ ] SwipeableCards folosește totalCards=5 sau similar
+- [ ] npm run typecheck passes
+- [ ] Verify în browser că swipe funcționează între toate 5 paginile
+
+### US-2004: Secțiune Solduri pe Desktop (grid 2x2 sau 4 în linie)
+**Ca** utilizator pe desktop
+**Vreau** să văd soldurile într-o secțiune separată sus
+**Pentru că** sunt cele mai importante informații
+
+**Acceptance Criteria:**
+- [ ] Secțiune Solduri în partea de sus a Dashboard-ului
+- [ ] Fără titlu vizibil (doar layout)
+- [ ] 4 SolduriCompactCard în grid responsive (2x2 sau 4 în linie pe ecran lat)
+- [ ] Sub solduri: cardurile originale cu grafice
+- [ ] npm run typecheck passes
+- [ ] Verify în browser desktop că ambele secțiuni sunt vizibile
+
+### US-2005: Eliminare MaturityAndDetailsCard de pe Dashboard
+**Ca** utilizator
+**Vreau** Dashboard-ul să nu mai aibă tabelul detaliat de scadențe
+**Pentru că** există deja pagina Maturity Analysis separată
+
+**Acceptance Criteria:**
+- [ ] Șterge MaturityAndDetailsCard din DashboardView.vue
+- [ ] Șterge div-ul .comparison-row
+- [ ] Șterge importul componentei
+- [ ] npm run typecheck passes
+- [ ] Verify: Dashboard nu mai are tabel
+
+### US-2006: Integrare date Solduri din dashboardStore
+**Ca** dezvoltator
+**Vreau** cardurile solduri să folosească datele existente din store
+**Pentru că** nu vreau request-uri API duplicate
+
+**Acceptance Criteria:**
+- [ ] Trezorerie: dashboardStore.treasuryData (casa.total, banca.total, items)
+- [ ] Clienți: dashboardStore.netBalanceData.clienti_total + breakdown
+- [ ] Furnizori: dashboardStore.netBalanceData.furnizori_total + breakdown
+- [ ] TVA: dashboardStore (calculat din summary sau endpoint)
+- [ ] npm run typecheck passes
+
+### US-2007: Indicatori vizuali pentru starea financiară
+**Ca** utilizator
+**Vreau** să văd indicatori de avertizare pe carduri
+**Pentru că** identific rapid problemele
+
+**Acceptance Criteria:**
+- [ ] Indicator roșu pe Clienți/Furnizori dacă restanță > 20%
+- [ ] TVA roșu dacă e de plată, verde dacă e de recuperat
+- [ ] Folosește var(--red-500), var(--green-500)
+- [ ] npm run typecheck passes
+
+### US-2008: Buton Refresh în header Dashboard
+**Ca** utilizator
+**Vreau** un buton de refresh în header
+**Pentru că** vreau să actualizez manual datele
+
+**Acceptance Criteria:**
+- [ ] Pe mobil: icon refresh în MobileTopBar actions
+- [ ] Pe desktop: buton lângă titlu Dashboard
+- [ ] Animație spinner în timpul încărcării
+- [ ] npm run typecheck passes
+
+## 4. Cerințe Funcționale
+1. [REQ-001] Cardurile grafice rămân IDENTICE cu cele din main
+2. [REQ-002] Swipe pe mobil funcționează fluid între toate 5 paginile
+3. [REQ-003] Desktop layout responsive (secțiunile se adaptează la lățime)
+4. [REQ-004] Funcționează în dark mode
+
+## 5. Non-Goals (Ce NU facem)
+- NU modificăm cardurile cu grafice (TreasuryDualCard, etc.)
+- NU adăugăm funcționalități noi de analiză
+- NU schimbăm API-ul backend
+- NU facem KPIStrip (bandă compactă) - facem carduri individuale
+
+## 6. Layout Vizual
+
+### MOBIL (5 pagini swipe):
+```
+[Pagina 1 - Solduri Grid 2x2]
+┌──────────┬──────────┐
+│TREZORERIE│ CLIENȚI │
+│ 150.000 │ 89.000 │
+│[expand] │[expand] │
+├──────────┼──────────┤
+│FURNIZORI │ TVA │
+│ 45.000 │ +15.000 │
+│[expand] │[expand] │
+└──────────┴──────────┘
+ • ○ ○ ○ ○ (dot indicator)
+
+[Pagina 2] TreasuryDualCard (grafice)
+[Pagina 3] CashFlowMetricCard (grafice)
+[Pagina 4] ClientiBalanceCard (grafice)
+[Pagina 5] FurnizoriBalanceCard (grafice)
+```
+
+### DESKTOP:
+```
+┌─────────────────────────────────────────────────────────────┐
+│ Dashboard [↻ Refresh] │
+├─────────────────────────────────────────────────────────────┤
+│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
+│ │TREZORERIE│ │ CLIENȚI │ │FURNIZORI│ │ TVA │ ← Solduri │
+│ │ 150.000 │ │ 89.000 ●│ │ 45.000 │ │+15.000 │ │
+│ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │
+├─────────────────────────────────────────────────────────────┤
+│ ┌───────────────────┐ ┌───────────────────┐ │
+│ │ Treasury Trend │ │ Cash Flow │ ← Grafice │
+│ │ [sparkline] │ │ [sparkline] │ │
+│ └───────────────────┘ └───────────────────┘ │
+│ ┌───────────────────┐ ┌───────────────────┐ │
+│ │ Clienți Balance │ │ Furnizori Balance │ │
+│ │ [sparkline] │ │ [sparkline] │ │
+│ └───────────────────┘ └───────────────────┘ │
+└─────────────────────────────────────────────────────────────┘
+```