feat: complete admin panel and backend admin api migration
This commit is contained in:
@@ -0,0 +1,210 @@
|
||||
<template>
|
||||
<!--
|
||||
Shared implementation of legacy ViewOmdeCustomer.vue (376 lines) and
|
||||
ViewSingleCustomer.vue (425 lines) — the customer detail screens.
|
||||
|
||||
Both show the same four panels (profile, orders, financial documents, wallet)
|
||||
against the same customer record; legacy duplicated the whole page per
|
||||
customer kind. The differing bits are parameterised:
|
||||
- the wholesale screen adds an activity-log panel (legacy log/ago/{id})
|
||||
- the retail screen adds a wallet panel (legacy single/wallet/{id})
|
||||
-->
|
||||
<a-spin :spinning="loading">
|
||||
<a-card :title="title">
|
||||
<a-descriptions bordered size="small" :column="3">
|
||||
<a-descriptions-item label="نام">{{ customer?.name ?? '-' }}</a-descriptions-item>
|
||||
<a-descriptions-item label="موبایل">{{ customer?.mobile ?? '-' }}</a-descriptions-item>
|
||||
<a-descriptions-item label="کد ملی">
|
||||
{{ customer?.national_code ?? '-' }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="شهر">{{ customer?.city?.title ?? '-' }}</a-descriptions-item>
|
||||
<a-descriptions-item label="کارشناس فروش">
|
||||
{{ customer?.reagent?.name ?? '-' }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="وضعیت">
|
||||
<a-tag :color="customer?.active === 1 ? 'green' : 'red'">
|
||||
{{ customer?.active === 1 ? 'فعال' : 'غیر فعال' }}
|
||||
</a-tag>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="سطح اعتبار">
|
||||
{{ customer?.gram_level ?? '-' }} گرم
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="بدهی گرمی">{{ customer?.remain ?? '-' }}</a-descriptions-item>
|
||||
<a-descriptions-item label="بدهی ریالی">
|
||||
{{ customer?.rial_remain ?? '-' }}
|
||||
</a-descriptions-item>
|
||||
</a-descriptions>
|
||||
|
||||
<div v-if="dashboard" class="stats mt-4">
|
||||
<a-tag color="blue">کل سفارشها: {{ dashboard.total_order }}</a-tag>
|
||||
<a-tag color="orange">سفارش باز: {{ dashboard.open_order }}</a-tag>
|
||||
<a-tag color="green">اسناد: {{ dashboard.ledger_entries }}</a-tag>
|
||||
</div>
|
||||
</a-card>
|
||||
|
||||
<a-tabs class="mt-4" :default-active-key="defaultTab">
|
||||
<a-tab-pane key="orders" tab="سفارش ها">
|
||||
<a-table
|
||||
size="small"
|
||||
:data-source="orders"
|
||||
:columns="orderColumns"
|
||||
:pagination="{ pageSize: 10 }"
|
||||
row-key="id"
|
||||
>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.dataIndex === 'caj'">{{ jdate(record.caj) }}</template>
|
||||
</template>
|
||||
</a-table>
|
||||
</a-tab-pane>
|
||||
|
||||
<a-tab-pane key="documents" tab="سند های مالی">
|
||||
<a-table
|
||||
size="small"
|
||||
:data-source="documents"
|
||||
:columns="documentColumns"
|
||||
:pagination="{ pageSize: 10 }"
|
||||
row-key="id"
|
||||
>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.dataIndex === 'confirmed'">
|
||||
<a-tag :color="record.confirmed === 1 ? 'green' : ''">
|
||||
{{ record.confirmed === 1 ? 'تایید شده' : 'تایید نشده' }}
|
||||
</a-tag>
|
||||
</template>
|
||||
<template v-else-if="column.dataIndex === 'caj'">{{ jdate(record.caj) }}</template>
|
||||
</template>
|
||||
</a-table>
|
||||
</a-tab-pane>
|
||||
|
||||
<a-tab-pane v-if="showWallet" key="wallet" tab="کیف پول">
|
||||
<a-table
|
||||
size="small"
|
||||
:data-source="wallet"
|
||||
:columns="walletColumns"
|
||||
:pagination="false"
|
||||
row-key="id"
|
||||
>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.dataIndex === 'caj'">{{ jdate(record.caj) }}</template>
|
||||
<template v-else-if="column.dataIndex === 'expires_at'">
|
||||
{{ jdate(record.expires_at) }}
|
||||
</template>
|
||||
</template>
|
||||
</a-table>
|
||||
</a-tab-pane>
|
||||
|
||||
<a-tab-pane v-if="showActivity" key="activity" tab="فعالیت ها">
|
||||
<a-table
|
||||
size="small"
|
||||
:data-source="activity"
|
||||
:columns="activityColumns"
|
||||
:pagination="{ pageSize: 15 }"
|
||||
row-key="id"
|
||||
>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.dataIndex === 'caj'">{{ jdateTime(record.caj) }}</template>
|
||||
</template>
|
||||
</a-table>
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
</a-spin>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted, ref } from 'vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
import { jdate, jdateTime } from '../../utils/filters';
|
||||
import api from '../../api/client';
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
title?: string;
|
||||
/** The retail screen shows the wallet panel. */
|
||||
showWallet?: boolean;
|
||||
/** The wholesale screen shows the activity log. */
|
||||
showActivity?: boolean;
|
||||
defaultTab?: string;
|
||||
}>(),
|
||||
{ title: 'مشاهده اطلاعات مشتری', showWallet: false, showActivity: false, defaultTab: 'orders' },
|
||||
);
|
||||
|
||||
const route = useRoute();
|
||||
const id = route.params.id as string;
|
||||
|
||||
const loading = ref(false);
|
||||
const customer = ref<Record<string, any> | undefined>(undefined);
|
||||
const dashboard = ref<Record<string, any> | undefined>(undefined);
|
||||
const orders = ref<Record<string, any>[]>([]);
|
||||
const documents = ref<Record<string, any>[]>([]);
|
||||
const wallet = ref<Record<string, any>[]>([]);
|
||||
const activity = ref<Record<string, any>[]>([]);
|
||||
|
||||
const orderColumns = [
|
||||
{ title: 'شماره سفارش', dataIndex: 'name' },
|
||||
{ title: 'وزن', dataIndex: 'w' },
|
||||
{ title: 'تعداد آیتم', dataIndex: 'items_count' },
|
||||
{ title: 'شعبه', dataIndex: 'branch' },
|
||||
{ title: 'تاریخ', dataIndex: 'caj' },
|
||||
];
|
||||
|
||||
const documentColumns = [
|
||||
{ title: 'نوع', dataIndex: 'type' },
|
||||
{ title: 'مقدار', dataIndex: 'value' },
|
||||
{ title: 'وضعیت', dataIndex: 'confirmed' },
|
||||
{ title: 'توضیحات', dataIndex: 'note' },
|
||||
{ title: 'تاریخ', dataIndex: 'caj' },
|
||||
];
|
||||
|
||||
const walletColumns = [
|
||||
{ title: 'مقدار (گرم)', dataIndex: 'value' },
|
||||
{ title: 'تاریخ اعطا', dataIndex: 'caj' },
|
||||
{ title: 'انقضا', dataIndex: 'expires_at' },
|
||||
];
|
||||
|
||||
const activityColumns = [
|
||||
{ title: 'عملیات', dataIndex: 'action' },
|
||||
{ title: 'جزئیات', dataIndex: 'detail' },
|
||||
{ title: 'تاریخ', dataIndex: 'caj' },
|
||||
];
|
||||
|
||||
onMounted(async () => {
|
||||
try {
|
||||
loading.value = true;
|
||||
const [c, d, o, docs] = await Promise.all([
|
||||
api.get(`customer/${id}`),
|
||||
api.get(`major/dashboard/${id}`).catch(() => ({ data: undefined })),
|
||||
api.get(`admin/customers-omde/${id}/orders`).catch(() => ({ data: [] })),
|
||||
api.get(`admin/customers-omde/${id}/documents`).catch(() => ({ data: [] })),
|
||||
]);
|
||||
customer.value = c.data;
|
||||
dashboard.value = d.data;
|
||||
orders.value = o.data;
|
||||
documents.value = docs.data;
|
||||
|
||||
if (props.showWallet) {
|
||||
const w = await api
|
||||
.get(`admin/customers-omde/${id}/wallet`)
|
||||
.catch(() => ({ data: [] }));
|
||||
wallet.value = w.data;
|
||||
}
|
||||
if (props.showActivity) {
|
||||
const a = await api.get(`log/ago/${id}`).catch(() => ({ data: [] }));
|
||||
activity.value = a.data;
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.stats {
|
||||
display: flex;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
.mt-4 {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user