fix(finance): shared treasury layout so tab switches stop jumping
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>
This commit is contained in:
@@ -22,12 +22,12 @@ import {
|
||||
Space as ASpace,
|
||||
Textarea as ATextarea,
|
||||
Typography,
|
||||
message,
|
||||
theme,
|
||||
} from 'ant-design-vue';
|
||||
import type { FormInstance } from 'ant-design-vue';
|
||||
import {
|
||||
ArrowDownOutlined,
|
||||
ArrowLeftOutlined,
|
||||
BankOutlined,
|
||||
CheckOutlined,
|
||||
ClockCircleOutlined,
|
||||
@@ -48,10 +48,11 @@ import type {
|
||||
TreasuryDashboardDto,
|
||||
} from '@mento/shared';
|
||||
import JalaliDateInput from '@/components/JalaliDateInput.vue';
|
||||
import TreasuryNav from '@/components/treasury/TreasuryNav.vue';
|
||||
import MoneyInput from '@/components/MoneyInput.vue';
|
||||
import { toman } from './treasury-format';
|
||||
import { parseMoneyNumber } from '@/lib/money';
|
||||
|
||||
const { Title: ATypographyTitle, Text: ATypographyText } = Typography;
|
||||
const { Text: ATypographyText } = Typography;
|
||||
const AListItem = AList.Item;
|
||||
const AListItemMeta = AList.Item.Meta;
|
||||
const ASelectOption = ASelect.Option;
|
||||
@@ -91,7 +92,6 @@ function emptyForm() {
|
||||
|
||||
const form = ref(emptyForm());
|
||||
|
||||
const pageTitle = 'دریافتها و درآمدها';
|
||||
const settleLabel = 'مبلغ دریافتشده';
|
||||
const statusLabel: Record<string, string> = {
|
||||
open: 'دریافتنشده',
|
||||
@@ -122,11 +122,15 @@ const formTabOptions = [
|
||||
];
|
||||
|
||||
const remainingAmount = computed(() => {
|
||||
const total = Number(form.value.amount) || 0;
|
||||
const settled = Number(form.value.settleAmount) || 0;
|
||||
const total = parseMoneyNumber(String(form.value.amount ?? ''), 0) ?? 0;
|
||||
const settled = parseMoneyNumber(String(form.value.settleAmount ?? ''), 0) ?? 0;
|
||||
return Math.max(0, total - settled);
|
||||
});
|
||||
|
||||
function onFinishFailed() {
|
||||
message.warning('لطفاً فیلدهای الزامی را کامل کنید.');
|
||||
}
|
||||
|
||||
function apiMessage(e: unknown) {
|
||||
if (!axios.isAxiosError(e)) return 'ذخیره ناموفق بود.';
|
||||
const msg = (e.response?.data as { message?: string | string[] })?.message;
|
||||
@@ -158,14 +162,20 @@ async function createDoc() {
|
||||
error.value = '';
|
||||
ok.value = '';
|
||||
try {
|
||||
const amount = parseMoneyNumber(String(form.value.amount ?? ''), 0);
|
||||
if (amount == null || amount <= 0) {
|
||||
error.value = 'مبلغ کل معتبر نیست.';
|
||||
return;
|
||||
}
|
||||
const settleAmount = parseMoneyNumber(String(form.value.settleAmount ?? ''), 0) ?? 0;
|
||||
await api.post('/treasury/documents', {
|
||||
kind,
|
||||
title: form.value.title,
|
||||
amount: form.value.amount,
|
||||
amount,
|
||||
categoryId: form.value.categoryId || null,
|
||||
partyName: form.value.partyName || null,
|
||||
accountId: form.value.accountId || null,
|
||||
settleAmount: form.value.settleAmount || 0,
|
||||
settleAmount,
|
||||
method: form.value.method,
|
||||
reference: form.value.reference || null,
|
||||
notes: form.value.notes || null,
|
||||
@@ -243,18 +253,6 @@ onMounted(() => {
|
||||
<!-- ─── Mobile app experience ─── -->
|
||||
<template v-if="isMobile">
|
||||
<a-flex vertical :gap="token.margin">
|
||||
<div>
|
||||
<a-flex align="center" :gap="token.marginXS">
|
||||
<a-typography-title :level="3" :style="{ margin: 0, flex: 1 }">
|
||||
ثبت دریافت جدید
|
||||
</a-typography-title>
|
||||
<ArrowLeftOutlined :style="{ color: token.colorTextSecondary, fontSize: '18px' }" />
|
||||
</a-flex>
|
||||
<a-typography-text type="secondary">اطلاعات دریافت را وارد کنید</a-typography-text>
|
||||
</div>
|
||||
|
||||
<TreasuryNav />
|
||||
|
||||
<a-row :gutter="[12, 12]">
|
||||
<a-col :span="12">
|
||||
<a-card
|
||||
@@ -418,14 +416,7 @@ onMounted(() => {
|
||||
name="amount"
|
||||
:rules="[{ required: true, message: 'مبلغ کل را وارد کنید' }]"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="form.amount"
|
||||
inputmode="decimal"
|
||||
placeholder="۰"
|
||||
dir="ltr"
|
||||
>
|
||||
<template #prefix><NumberOutlined /></template>
|
||||
</a-input>
|
||||
<MoneyInput v-model="form.amount" :decimals="0" placeholder="۰" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
@@ -434,14 +425,7 @@ onMounted(() => {
|
||||
name="settleAmount"
|
||||
:rules="[{ required: true, message: 'مبلغ دریافتشده را وارد کنید' }]"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="form.settleAmount"
|
||||
inputmode="decimal"
|
||||
placeholder="۰"
|
||||
dir="ltr"
|
||||
>
|
||||
<template #prefix><NumberOutlined /></template>
|
||||
</a-input>
|
||||
<MoneyInput v-model="form.settleAmount" :decimals="0" placeholder="۰" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
@@ -596,35 +580,39 @@ onMounted(() => {
|
||||
<!-- ─── Desktop (unchanged interaction model) ─── -->
|
||||
<template v-else>
|
||||
<a-flex vertical :gap="16">
|
||||
<div>
|
||||
<a-typography-title :level="3" :style="{ margin: 0 }">{{ pageTitle }}</a-typography-title>
|
||||
<a-typography-text type="secondary">
|
||||
ثبت سند، موجودی را عوض نمیکند مگر مبلغ دریافت یا پرداخت واقعی وارد شود.
|
||||
</a-typography-text>
|
||||
</div>
|
||||
|
||||
<TreasuryNav />
|
||||
|
||||
<a-alert v-if="error" type="error" show-icon :message="error" />
|
||||
<a-alert v-if="ok" type="success" show-icon :message="ok" />
|
||||
|
||||
<a-card :bordered="false">
|
||||
<a-divider orientation="right">سند جدید</a-divider>
|
||||
<a-form layout="vertical" @finish="createDoc">
|
||||
<a-form
|
||||
layout="vertical"
|
||||
:model="form"
|
||||
@finish="createDoc"
|
||||
@finishFailed="onFinishFailed"
|
||||
>
|
||||
<a-row :gutter="[16, 0]">
|
||||
<a-col :xs="24" :md="12">
|
||||
<a-form-item label="عنوان" name="title">
|
||||
<a-form-item
|
||||
label="عنوان"
|
||||
name="title"
|
||||
:rules="[{ required: true, message: 'عنوان الزامی است' }]"
|
||||
>
|
||||
<a-input v-model:value="form.title" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :xs="24" :md="8">
|
||||
<a-form-item label="مبلغ کل" name="amount">
|
||||
<a-input v-model:value="form.amount" />
|
||||
<a-form-item
|
||||
label="مبلغ کل"
|
||||
name="amount"
|
||||
:rules="[{ required: true, message: 'مبلغ الزامی است' }]"
|
||||
>
|
||||
<MoneyInput v-model="form.amount" :decimals="0" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :xs="24" :md="8">
|
||||
<a-form-item :label="settleLabel" name="settleAmount">
|
||||
<a-input v-model:value="form.settleAmount" />
|
||||
<MoneyInput v-model="form.settleAmount" :decimals="0" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :xs="24" :md="8">
|
||||
|
||||
Reference in New Issue
Block a user