Keep title and nav mounted in TreasuryLayout with stable header height, and finish Ant form chrome (MoneyInput, Jalali) on finance pages. Co-authored-by: Cursor <cursoragent@cursor.com>
69 lines
2.0 KiB
Vue
69 lines
2.0 KiB
Vue
<script setup lang="ts">
|
|
import { computed } from 'vue';
|
|
import { useRoute, useRouter } from 'vue-router';
|
|
import { Segmented as ASegmented } from 'ant-design-vue';
|
|
import { useAuthStore } from '@/stores/auth';
|
|
|
|
const route = useRoute();
|
|
const router = useRouter();
|
|
const auth = useAuthStore();
|
|
|
|
const canPayroll = computed(
|
|
() =>
|
|
auth.user?.role === 'owner' ||
|
|
auth.user?.role === 'admin' ||
|
|
Boolean(auth.user?.permissions?.includes('treasury_payroll')),
|
|
);
|
|
|
|
const links = computed(() => [
|
|
{ value: '/finance', label: 'داشبورد', exact: true },
|
|
{ value: '/finance/incomes', label: 'دریافتها و درآمدها' },
|
|
{ value: '/finance/expenses', label: 'پرداختها و هزینهها' },
|
|
{ value: '/finance/receivables', label: 'اقساط و مطالبات' },
|
|
{ value: '/finance/accounts', label: 'صندوق و حسابها' },
|
|
...(canPayroll.value ? [{ value: '/finance/payroll', label: 'حقوق' }] : []),
|
|
{ value: '/finance/recurring', label: 'تکرارشونده' },
|
|
{ value: '/finance/reports', label: 'گزارش' },
|
|
{ value: '/finance/audit', label: 'سوابق' },
|
|
{ value: '/finance/categories', label: 'دستهبندیها' },
|
|
]);
|
|
|
|
const options = computed(() => links.value.map((l) => ({ value: l.value, label: l.label })));
|
|
|
|
const active = computed(() => {
|
|
const path = route.path;
|
|
for (const link of links.value) {
|
|
if (link.exact) {
|
|
if (path === link.value) return link.value;
|
|
} else if (path === link.value || path.startsWith(`${link.value}/`)) {
|
|
return link.value;
|
|
}
|
|
}
|
|
return '/finance';
|
|
});
|
|
|
|
function onChange(value: string | number) {
|
|
const next = String(value);
|
|
if (next && next !== route.path) void router.push(next);
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<div
|
|
:style="{
|
|
width: '100%',
|
|
overflowX: 'auto',
|
|
flexShrink: 0,
|
|
minHeight: '36px',
|
|
}"
|
|
>
|
|
<a-segmented
|
|
:value="active"
|
|
:options="options"
|
|
dir="rtl"
|
|
:style="{ minWidth: 'max-content' }"
|
|
@change="onChange"
|
|
/>
|
|
</div>
|
|
</template>
|