## Features - US-2001: Create reusable SolduriCompactCard component - US-2004: Solduri section on Desktop (top, without title) - US-2005: Remove MaturityAndDetailsCard from Dashboard - US-2006: Integrate Solduri data from dashboardStore - US-2007: Visual indicators for financial status - US-2008: Refresh button in Dashboard header ## UI Improvements - Desktop: 2x2 grid for solduri cards with larger breakdown fonts - Mobile: Single column layout with auto height - Theme persistence: synchronous initialization to prevent flash - Unified "Bonuri" icon (pi-shopping-bag) across all navigation ## Files Changed - New: SolduriCompactCard.vue - expandable cards for Trezorerie/Clienți/Furnizori/TVA - Modified: DashboardView.vue - integrated solduri section - Modified: index.html - theme init script - Modified: Mobile navigation components - icon consistency Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
233 lines
6.4 KiB
Vue
233 lines
6.4 KiB
Vue
<template>
|
|
<div>
|
|
<!-- Menu Overlay -->
|
|
<div
|
|
class="slide-menu-overlay"
|
|
:class="{ open: isOpen }"
|
|
@click="closeMenu"
|
|
></div>
|
|
|
|
<!-- Slide Menu - Unified structure matching MobileDrawerMenu -->
|
|
<nav class="slide-menu" :class="{ open: isOpen }">
|
|
<!-- PRINCIPALE Section -->
|
|
<div class="menu-section">
|
|
<h3 class="menu-title">Principale</h3>
|
|
<ul class="menu-list">
|
|
<li class="menu-item" v-for="item in principaleItems" :key="item.to">
|
|
<router-link
|
|
:to="item.to"
|
|
class="menu-link"
|
|
:class="{ active: isActive(item.to, item.exactMatch) }"
|
|
@click="closeMenu"
|
|
>
|
|
<i :class="['menu-icon', item.icon]"></i>
|
|
<span>{{ item.label }}</span>
|
|
</router-link>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
|
|
<!-- RAPOARTE Section -->
|
|
<div class="menu-section">
|
|
<h3 class="menu-title">Rapoarte</h3>
|
|
<ul class="menu-list">
|
|
<li class="menu-item" v-for="item in rapoarteItems" :key="item.to">
|
|
<router-link
|
|
:to="item.to"
|
|
class="menu-link"
|
|
:class="{ active: isActive(item.to, item.exactMatch) }"
|
|
@click="closeMenu"
|
|
>
|
|
<i :class="['menu-icon', item.icon]"></i>
|
|
<span>{{ item.label }}</span>
|
|
</router-link>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
|
|
<!-- ANALIZE Section -->
|
|
<div class="menu-section">
|
|
<h3 class="menu-title">Analize</h3>
|
|
<ul class="menu-list">
|
|
<li class="menu-item" v-for="item in analizeItems" :key="item.to">
|
|
<router-link
|
|
:to="item.to"
|
|
class="menu-link"
|
|
:class="{ active: isActive(item.to, item.exactMatch) }"
|
|
@click="closeMenu"
|
|
>
|
|
<i :class="['menu-icon', item.icon]"></i>
|
|
<span>{{ item.label }}</span>
|
|
</router-link>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
|
|
<!-- ADMINISTRARE Section -->
|
|
<div class="menu-section">
|
|
<h3 class="menu-title">Administrare</h3>
|
|
<ul class="menu-list">
|
|
<li class="menu-item" v-for="item in administrareItems" :key="item.to">
|
|
<router-link
|
|
:to="item.to"
|
|
class="menu-link"
|
|
:class="{ active: isActive(item.to, item.exactMatch) }"
|
|
@click="closeMenu"
|
|
>
|
|
<i :class="['menu-icon', item.icon]"></i>
|
|
<span>{{ item.label }}</span>
|
|
</router-link>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
|
|
<!-- Profile Section (at bottom) -->
|
|
<div class="menu-section menu-profile">
|
|
<div class="profile-info">
|
|
<i class="pi pi-user"></i>
|
|
<span>{{ currentUser?.username || 'Utilizator' }}</span>
|
|
</div>
|
|
<ul class="menu-list">
|
|
<li class="menu-item">
|
|
<a href="#" class="menu-link menu-link-logout" @click.prevent="handleLogout">
|
|
<i class="menu-icon pi pi-sign-out"></i>
|
|
<span>Deconectare</span>
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</nav>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import { computed, ref } from "vue";
|
|
import { useRoute, useRouter } from "vue-router";
|
|
import { useAuthStore } from "@reports/stores/sharedStores";
|
|
|
|
export default {
|
|
name: "HamburgerMenu",
|
|
props: {
|
|
isOpen: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
},
|
|
emits: ["close"],
|
|
setup(props, { emit }) {
|
|
const route = useRoute();
|
|
const router = useRouter();
|
|
const authStore = useAuthStore();
|
|
|
|
const currentUser = computed(() => authStore.currentUser);
|
|
|
|
/**
|
|
* Navigation items organized by category - matching MobileDrawerMenu structure
|
|
*/
|
|
|
|
// PRINCIPALE: Dashboard, Bonuri
|
|
const principaleItems = ref([
|
|
{ to: '/dashboard', icon: 'pi pi-home', label: 'Dashboard', exactMatch: true },
|
|
{ to: '/data-entry', icon: 'pi pi-shopping-bag', label: 'Bonuri', exactMatch: false }
|
|
]);
|
|
|
|
// RAPOARTE: Facturi, Balanță, Casa și Banca
|
|
const rapoarteItems = ref([
|
|
{ to: '/reports/invoices', icon: 'pi pi-file', label: 'Facturi', exactMatch: true },
|
|
{ to: '/reports/trial-balance', icon: 'pi pi-calculator', label: 'Balanță', exactMatch: true },
|
|
{ to: '/reports/bank-cash', icon: 'pi pi-money-bill', label: 'Casa și Banca', exactMatch: true }
|
|
]);
|
|
|
|
// ANALIZE: Scadențe, Facturi Detaliate
|
|
const analizeItems = ref([
|
|
{ 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 }
|
|
]);
|
|
|
|
// ADMINISTRARE: Setări
|
|
const administrareItems = ref([
|
|
{ to: '/settings', icon: 'pi pi-cog', label: 'Setări', exactMatch: false }
|
|
]);
|
|
|
|
/**
|
|
* Check if a navigation item is active based on current route
|
|
*/
|
|
const isActive = (to, exactMatch) => {
|
|
if (exactMatch) {
|
|
return route.path === to;
|
|
}
|
|
// For non-exact match, check if current path starts with the route
|
|
return route.path.startsWith(to);
|
|
};
|
|
|
|
const closeMenu = () => {
|
|
emit("close");
|
|
};
|
|
|
|
const handleLogout = async () => {
|
|
try {
|
|
authStore.logout();
|
|
closeMenu();
|
|
await router.push("/login");
|
|
} catch (error) {
|
|
console.error("Logout error:", error);
|
|
}
|
|
};
|
|
|
|
return {
|
|
currentUser,
|
|
principaleItems,
|
|
rapoarteItems,
|
|
analizeItems,
|
|
administrareItems,
|
|
isActive,
|
|
closeMenu,
|
|
handleLogout,
|
|
};
|
|
},
|
|
};
|
|
</script>
|
|
|
|
<style scoped>
|
|
/* Logout link styling - matches MobileDrawerMenu */
|
|
.menu-link-logout {
|
|
color: var(--color-error);
|
|
}
|
|
|
|
.menu-link-logout .menu-icon {
|
|
color: var(--color-error);
|
|
}
|
|
|
|
.menu-link-logout:hover {
|
|
background: var(--red-50);
|
|
color: var(--color-error);
|
|
}
|
|
|
|
/* Dark mode support */
|
|
[data-theme="dark"] .menu-link-logout {
|
|
color: var(--red-400);
|
|
}
|
|
|
|
[data-theme="dark"] .menu-link-logout .menu-icon {
|
|
color: var(--red-400);
|
|
}
|
|
|
|
[data-theme="dark"] .menu-link-logout:hover {
|
|
background: var(--red-900);
|
|
}
|
|
|
|
@media (prefers-color-scheme: dark) {
|
|
:root:not([data-theme]) .menu-link-logout {
|
|
color: var(--red-400);
|
|
}
|
|
|
|
:root:not([data-theme]) .menu-link-logout .menu-icon {
|
|
color: var(--red-400);
|
|
}
|
|
|
|
:root:not([data-theme]) .menu-link-logout:hover {
|
|
background: var(--red-900);
|
|
}
|
|
}
|
|
</style>
|