bug fix in persons list and some changes in UI

This commit is contained in:
Hesabix 2025-03-29 16:55:01 +00:00
parent 6d63f427ac
commit 721f0a4934
14 changed files with 81 additions and 54 deletions

View file

@ -4,4 +4,5 @@ label.required:before {
} }
.btn-link{ .btn-link{
text-decoration: none; text-decoration: none;
} }

View file

@ -62,14 +62,17 @@ const vuetify = createVuetify({
VTextField: { VTextField: {
hideDetails: "auto", hideDetails: "auto",
variant: "outlined", variant: "outlined",
size: "small" size: "small",
density: "comfortable"
}, },
VTextarea: { VTextarea: {
hideDetails: "auto", hideDetails: "auto",
density: "comfortable"
}, },
VSelect: { VSelect: {
hideDetails: "auto", hideDetails: "auto",
variant: "outlined" variant: "outlined",
density: "comfortable"
}, },
VDialog: { VDialog: {
VCard: { VCard: {

View file

@ -22,6 +22,7 @@
:items="form.rows" :items="form.rows"
class="elevation-1" class="elevation-1"
hide-default-footer hide-default-footer
:header-props="{ class: 'custom-header' }"
> >
<template v-slot:top> <template v-slot:top>
<v-toolbar flat> <v-toolbar flat>

View file

@ -53,6 +53,8 @@
:loading="loading" :loading="loading"
:search="search" :search="search"
class="elevation-1 text-center" class="elevation-1 text-center"
:header-props="{ class: 'custom-header' }"
> >
<template v-slot:item="{ item }"> <template v-slot:item="{ item }">
<tr> <tr>

View file

@ -187,7 +187,7 @@
<v-row dense> <v-row dense>
<v-col cols="12"> <v-col cols="12">
<v-data-table v-model="itemsSelected" :headers="headers" :items="items" :search="searchValue" :loading="loading" <v-data-table v-model="itemsSelected" :headers="headers" :items="items" :search="searchValue" :loading="loading"
show-select dense :items-per-page="25" class="elevation-1"> show-select dense :items-per-page="25" class="elevation-1" :header-props="{ class: 'custom-header' }">
<template v-slot:top> <template v-slot:top>
<v-toolbar flat dense color="grey-lighten-4"> <v-toolbar flat dense color="grey-lighten-4">
<v-toolbar-title class="text-subtitle-1">{{ $t('pages.person_card.transactions') }}</v-toolbar-title> <v-toolbar-title class="text-subtitle-1">{{ $t('pages.person_card.transactions') }}</v-toolbar-title>

View file

@ -3,7 +3,8 @@
<template v-slot:prepend> <template v-slot:prepend>
<v-tooltip :text="$t('dialog.back')" location="bottom"> <v-tooltip :text="$t('dialog.back')" location="bottom">
<template v-slot:activator="{ props }"> <template v-slot:activator="{ props }">
<v-btn v-bind="props" @click="$router.back()" class="d-none d-sm-flex" variant="text" icon="mdi-arrow-right" /> <v-btn v-bind="props" @click="$router.back()" class="d-none d-sm-flex" variant="text"
icon="mdi-arrow-right" />
</template> </template>
</v-tooltip> </v-tooltip>
</template> </template>
@ -103,39 +104,18 @@
</template> </template>
</v-text-field> </v-text-field>
<v-data-table-server <v-data-table-server v-model:items-per-page="serverOptions.rowsPerPage" v-model:page="serverOptions.page"
v-model:items-per-page="serverOptions.rowsPerPage" v-model:sort-by="serverOptions.sortBy" :headers="visibleHeaders" :items="items" :items-length="totalItems"
v-model:page="serverOptions.page" :loading="loading" multi-sort class="elevation-1" :items-per-page-options="[5, 10, 20, 50]" item-value="code"
v-model:sort-by="serverOptions.sortBy" items-per-page-text="تعداد سطر" no-data-text="اطلاعاتی برای نمایش وجود ندارد"
:headers="visibleHeaders" :header-props="{ class: 'custom-header' }">
:items="items"
:items-length="totalItems"
:loading="loading"
multi-sort
class="elevation-1"
:items-per-page-options="[5, 10, 20, 50]"
item-value="code"
items-per-page-text="تعداد سطر"
no-data-text="اطلاعاتی برای نمایش وجود ندارد"
:header-props="{ class: 'custom-header' }"
>
<!-- ستون چکباکس دستی --> <!-- ستون چکباکس دستی -->
<template v-slot:header.checkbox> <template v-slot:header.checkbox>
<v-checkbox <v-checkbox v-model="selectAll" @change="toggleSelectAll" hide-details density="compact"></v-checkbox>
v-model="selectAll"
@change="toggleSelectAll"
hide-details
density="compact"
></v-checkbox>
</template> </template>
<template v-slot:item.checkbox="{ item }"> <template v-slot:item.checkbox="{ item }">
<v-checkbox <v-checkbox v-model="selectedItems" :value="item" hide-details density="compact"
v-model="selectedItems" @change="updateSelected"></v-checkbox>
:value="item"
hide-details
density="compact"
@change="updateSelected"
></v-checkbox>
</template> </template>
<template v-slot:item.operation="{ item }"> <template v-slot:item.operation="{ item }">
@ -202,7 +182,8 @@
<v-card-text> <v-card-text>
<v-row> <v-row>
<v-col v-for="header in optionalHeaders" :key="header.value" cols="12" sm="4"> <v-col v-for="header in optionalHeaders" :key="header.value" cols="12" sm="4">
<v-checkbox v-model="header.visible" :label="header.title" @change="saveColumnSettings" hide-details class="mb-2"></v-checkbox> <v-checkbox v-model="header.visible" :label="header.title" @change="saveColumnSettings" hide-details
class="mb-2"></v-checkbox>
</v-col> </v-col>
</v-row> </v-row>
</v-card-text> </v-card-text>
@ -334,7 +315,18 @@ const fetchData = async () => {
sortBy: sortBy.length > 0 ? sortBy : null, sortBy: sortBy.length > 0 ? sortBy : null,
}); });
items.value = response.data.items || []; items.value = response.data.items || [];
totalItems.value = response.data.total || 0;
// اگر فیلتری اعمال شده باشد، از total (تعداد فیلترشده) استفاده کن
// اگر فیلتری اعمال نشده باشد، از unfilteredTotal (تعداد کل) استفاده کن
const isFiltered =
searchValue.value ||
selectedTypes.length > 0 ||
selectedTransactionFilters.length > 0;
totalItems.value = isFiltered
? (response.data.total || 0) // تعداد کل فیلترشده
: (response.data.unfilteredTotal || 0); // تعداد کل بدون فیلتر
resetSelections(); resetSelections();
} catch (error) { } catch (error) {
console.error('Error fetching data:', error); console.error('Error fetching data:', error);
@ -394,7 +386,7 @@ const resetSelections = () => {
// توابع خروجی // توابع خروجی
const excellOutput = (allItems = true) => { const excellOutput = (allItems = true) => {
if (!allItems) { if (!allItems) {
if (selectedItems.value.length === 0) { if (selectedItems.value.length === 0) {
Swal.fire({ Swal.fire({
@ -404,7 +396,7 @@ const excellOutput = (allItems = true) => {
}); });
return; return;
} }
// ارسال id و code به سرور // ارسال id و code به سرور
const selected = selectedItems.value.map(item => ({ id: item.id, code: item.code })); const selected = selectedItems.value.map(item => ({ id: item.id, code: item.code }));
axios({ axios({
@ -446,7 +438,7 @@ const excellOutput = (allItems = true) => {
}; };
const print = (allItems = true) => { const print = (allItems = true) => {
if (!allItems) { if (!allItems) {
if (selectedItems.value.length === 0) { if (selectedItems.value.length === 0) {
Swal.fire({ Swal.fire({
@ -456,7 +448,7 @@ const print = (allItems = true) => {
}); });
return; return;
} }
// ارسال id و code به سرور // ارسال id و code به سرور
const selected = selectedItems.value.map(item => ({ id: item.id, code: item.code })); const selected = selectedItems.value.map(item => ({ id: item.id, code: item.code }));
axios.post('/api/person/list/print', { items: selected }).then((response) => { axios.post('/api/person/list/print', { items: selected }).then((response) => {
@ -503,6 +495,4 @@ onMounted(() => {
}); });
</script> </script>
<style> <style></style>
</style>

View file

@ -115,6 +115,7 @@
:loading="loading" :loading="loading"
item-value="code" item-value="code"
class="elevation-1" class="elevation-1"
:header-props="{ class: 'custom-header' }"
:items-per-page-options="[5, 10, 20, 50]" :items-per-page-options="[5, 10, 20, 50]"
items-per-page-text="تعداد سطر در هر صفحه" items-per-page-text="تعداد سطر در هر صفحه"
@update:options="loadData" @update:options="loadData"

View file

@ -62,6 +62,15 @@ export default defineComponent({
{ title: 'تعداد', key: 'count' }, { title: 'تعداد', key: 'count' },
{ title: 'مبلغ کل', key: 'sumTotal' }, { title: 'مبلغ کل', key: 'sumTotal' },
], ],
desktopHeaders: [
{ title: 'کالا', key: 'commodity.name' },
{ title: 'تعداد', key: 'count' },
{ title: 'قیمت واحد', key: 'price' },
{ title: 'تخفیف', key: 'discount' },
{ title: 'مالیات', key: 'tax' },
{ title: 'مبلغ کل', key: 'sumTotal' },
{ title: 'شرح', key: 'des' },
],
}), }),
computed: { computed: {
formattedAmount() { formattedAmount() {
@ -170,7 +179,7 @@ export default defineComponent({
<print-options :invoice-id="$route.params.id" /> <print-options :invoice-id="$route.params.id" />
</v-toolbar> </v-toolbar>
<v-tabs v-model="activeTab" color="primary" grow class="mt-0"> <v-tabs v-model="activeTab" color="primary" grow class="mt-0 bg-gray">
<v-tab value="person-info">اطلاعات شخص</v-tab> <v-tab value="person-info">اطلاعات شخص</v-tab>
<v-tab value="invoice-info">اقلام فاکتور</v-tab> <v-tab value="invoice-info">اقلام فاکتور</v-tab>
<v-tab value="payments">دریافتها</v-tab> <v-tab value="payments">دریافتها</v-tab>
@ -216,13 +225,29 @@ export default defineComponent({
</v-row> </v-row>
<v-list-subheader>اقلام</v-list-subheader> <v-list-subheader>اقلام</v-list-subheader>
<v-data-table :headers="mobileHeaders" :items="commoditys" :loading="loading" show-expand class="elevation-1"> <v-data-table
:headers="$vuetify.display.smAndDown ? mobileHeaders : desktopHeaders"
:items="commoditys"
:loading="loading"
:show-expand="$vuetify.display.smAndDown"
class="elevation-1"
:header-props="{ class: 'custom-header' }"
>
<template v-slot:item.sumTotal="{ item }"> <template v-slot:item.sumTotal="{ item }">
{{ $filters.formatNumber(item.sumTotal) }} {{ $filters.formatNumber(item.sumTotal) }}
</template> </template>
<template v-slot:item.count="{ item }"> <template v-slot:item.count="{ item }">
{{ item.count }} {{ item.commodity.unit }} {{ item.count }} {{ item.commodity.unit }}
</template> </template>
<template v-slot:item.price="{ item }">
{{ $filters.formatNumber(item.price) }}
</template>
<template v-slot:item.discount="{ item }">
{{ $filters.formatNumber(item.discount) }}
</template>
<template v-slot:item.tax="{ item }">
{{ $filters.formatNumber(item.tax) }}
</template>
<template v-slot:expanded-row="{ item }"> <template v-slot:expanded-row="{ item }">
<v-list dense> <v-list dense>
<v-list-item> <v-list-item>
@ -274,7 +299,7 @@ export default defineComponent({
<!-- تب دریافتها --> <!-- تب دریافتها -->
<v-window-item value="payments"> <v-window-item value="payments">
<v-card-text> <v-card-text>
<v-data-table v-if="item.relatedDocs.length" :headers="[ <v-data-table v-if="item.relatedDocs.length" :header-props="{ class: 'custom-header' }" :headers="[
{ title: 'مشاهده', key: 'view' }, { title: 'مشاهده', key: 'view' },
{ title: 'شماره', key: 'code' }, { title: 'شماره', key: 'code' },
{ title: 'تاریخ', key: 'date' }, { title: 'تاریخ', key: 'date' },
@ -318,5 +343,5 @@ export default defineComponent({
</template> </template>
<style scoped> <style scoped>
/* استایل‌ها */
</style> </style>

View file

@ -114,6 +114,7 @@
:items="paysitems" :items="paysitems"
:search="payssearchValue" :search="payssearchValue"
:loading="loading" :loading="loading"
:header-props="{ class: 'custom-header' }"
loading-text="در حال بارگذاری..." loading-text="در حال بارگذاری..."
no-data-text="اطلاعاتی برای نمایش وجود ندارد" no-data-text="اطلاعاتی برای نمایش وجود ندارد"
> >
@ -137,6 +138,7 @@
<v-data-table <v-data-table
:headers="headers" :headers="headers"
:items="items" :items="items"
:header-props="{ class: 'custom-header' }"
:search="searchValue" :search="searchValue"
:loading="loading" :loading="loading"
loading-text="در حال بارگذاری..." loading-text="در حال بارگذاری..."

View file

@ -16,6 +16,7 @@
<v-data-table <v-data-table
v-if="canShowForm && !initialLoading" v-if="canShowForm && !initialLoading"
:headers="headers" :headers="headers"
:header-props="{ class: 'custom-header' }"
:items="packages" :items="packages"
:items-per-page="10" :items-per-page="10"
:loading="isLoading" :loading="isLoading"

View file

@ -34,7 +34,7 @@
<v-window v-model="activeTab"> <v-window v-model="activeTab">
<v-window-item value="pending"> <v-window-item value="pending">
<v-data-table-server v-model:items-per-page="itemsPerPagePending" v-model:page="pagePending" <v-data-table-server v-model:items-per-page="itemsPerPagePending" v-model:page="pagePending"
:headers="headers" :items="pendingItems" :items-length="totalPending" :loading="loading" :header-props="{ class: 'custom-header' }" :headers="headers" :items="pendingItems" :items-length="totalPending" :loading="loading"
:no-data-text="$t('table.no_data')" class="elevation-1" show-select v-model="selectedTickets" :no-data-text="$t('table.no_data')" class="elevation-1" show-select v-model="selectedTickets"
@update:options="loadPendingData"> @update:options="loadPendingData">
<template #item.operation="{ item }"> <template #item.operation="{ item }">
@ -50,7 +50,7 @@
<v-window-item value="responded"> <v-window-item value="responded">
<v-data-table-server v-model:items-per-page="itemsPerPageResponded" v-model:page="pageResponded" <v-data-table-server v-model:items-per-page="itemsPerPageResponded" v-model:page="pageResponded"
:headers="headers" :items="respondedItems" :items-length="totalResponded" :loading="loading" :header-props="{ class: 'custom-header' }" :headers="headers" :items="respondedItems" :items-length="totalResponded" :loading="loading"
:no-data-text="$t('table.no_data')" class="elevation-1" show-select v-model="selectedTickets" :no-data-text="$t('table.no_data')" class="elevation-1" show-select v-model="selectedTickets"
@update:options="loadRespondedData"> @update:options="loadRespondedData">
<template #item.operation="{ item }"> <template #item.operation="{ item }">
@ -66,7 +66,7 @@
<v-window-item value="closed"> <v-window-item value="closed">
<v-data-table-server v-model:items-per-page="itemsPerPageClosed" v-model:page="pageClosed" :headers="headers" <v-data-table-server v-model:items-per-page="itemsPerPageClosed" v-model:page="pageClosed" :headers="headers"
:items="closedItems" :items-length="totalClosed" :loading="loading" :no-data-text="$t('table.no_data')" :header-props="{ class: 'custom-header' }":items="closedItems" :items-length="totalClosed" :loading="loading" :no-data-text="$t('table.no_data')"
class="elevation-1" show-select v-model="selectedTickets" @update:options="loadClosedData"> class="elevation-1" show-select v-model="selectedTickets" @update:options="loadClosedData">
<template #item.operation="{ item }"> <template #item.operation="{ item }">
<v-tooltip :text="$t('dialog.view')" location="bottom"> <v-tooltip :text="$t('dialog.view')" location="bottom">

View file

@ -134,6 +134,7 @@ loadFromServer();
class="elevation-1" class="elevation-1"
item-value="id" item-value="id"
return-object return-object
:header-props="{ class: 'custom-header' }"
> >
<template #item.operation="{ item }"> <template #item.operation="{ item }">
<v-menu> <v-menu>

View file

@ -83,7 +83,7 @@
<v-col cols="12"> <v-col cols="12">
<v-card> <v-card>
<v-card-title>{{ $t('marketing.recent_users') }}</v-card-title> <v-card-title>{{ $t('marketing.recent_users') }}</v-card-title>
<v-data-table :headers="computedHeaders" :items="recentUsers" :loading="loading" hide-default-footer <v-data-table :header-props="{ class: 'custom-header' }" :headers="computedHeaders" :items="recentUsers" :loading="loading" hide-default-footer
class="elevation-1"> class="elevation-1">
<!-- اسلات سفارشی برای ستون وضعیت --> <!-- اسلات سفارشی برای ستون وضعیت -->
<template v-slot:item.active="{ item }"> <template v-slot:item.active="{ item }">

View file

@ -24,7 +24,7 @@
<v-window v-model="activeTab"> <v-window v-model="activeTab">
<v-window-item value="pending"> <v-window-item value="pending">
<v-data-table :headers="headers" :items="pendingItems" :loading="loading" :no-data-text="$t('table.no_data')" <v-data-table :header-props="{ class: 'custom-header' }" :headers="headers" :items="pendingItems" :loading="loading" :no-data-text="$t('table.no_data')"
class="elevation-1"> class="elevation-1">
<template #item.operation="{ item }"> <template #item.operation="{ item }">
<v-tooltip :text="$t('dialog.view')" location="bottom"> <v-tooltip :text="$t('dialog.view')" location="bottom">
@ -38,7 +38,7 @@
</v-window-item> </v-window-item>
<v-window-item value="responded"> <v-window-item value="responded">
<v-data-table :headers="headers" :items="respondedItems" :loading="loading" <v-data-table :header-props="{ class: 'custom-header' }" :headers="headers" :items="respondedItems" :loading="loading"
:no-data-text="$t('table.no_data')" class="elevation-1"> :no-data-text="$t('table.no_data')" class="elevation-1">
<template #item.operation="{ item }"> <template #item.operation="{ item }">
<v-tooltip :text="$t('dialog.view')" location="bottom"> <v-tooltip :text="$t('dialog.view')" location="bottom">
@ -52,7 +52,7 @@
</v-window-item> </v-window-item>
<v-window-item value="closed"> <v-window-item value="closed">
<v-data-table :headers="headers" :items="closedItems" :loading="loading" :no-data-text="$t('table.no_data')" <v-data-table :header-props="{ class: 'custom-header' }" :headers="headers" :items="closedItems" :loading="loading" :no-data-text="$t('table.no_data')"
class="elevation-1"> class="elevation-1">
<template #item.operation="{ item }"> <template #item.operation="{ item }">
<v-tooltip :text="$t('dialog.view')" location="bottom"> <v-tooltip :text="$t('dialog.view')" location="bottom">