Files
roa2web-service-auto/src/modules/reports/components/layout/HamburgerMenu.vue
Claude Agent 15327687f4 feat(dashboard-solduri): Complete dashboard solduri v2 implementation
## 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>
2026-01-19 08:37:10 +00:00

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>