hesabixCore/webUI/src/components/PersonInfo.vue
2025-07-18 16:29:35 +00:00

322 lines
10 KiB
Vue

<template>
<div class="person-info">
<v-card v-if="person" class="person-card" elevation="2">
<v-card-title class="d-flex align-center">
<v-avatar color="primary" size="40" class="mr-3">
<v-icon color="white">mdi-account</v-icon>
</v-avatar>
<div>
<div class="text-h6">{{ person.nikename }}</div>
<div class="text-caption text-medium-emphasis">{{ person.code }}</div>
</div>
<v-spacer></v-spacer>
<v-chip
:color="getBalanceColor(person.balance.balance_status)"
size="small"
variant="flat"
>
{{ person.balance.balance_status }}
</v-chip>
</v-card-title>
<v-card-text>
<!-- اطلاعات اصلی -->
<div class="info-section mb-4">
<h4 class="text-subtitle-1 font-weight-medium mb-2">اطلاعات اصلی</h4>
<v-row>
<v-col cols="12" md="6">
<div class="info-item">
<span class="info-label">نام کامل:</span>
<span class="info-value">{{ person.name || 'نامشخص' }}</span>
</div>
<div class="info-item" v-if="person.company">
<span class="info-label">شرکت:</span>
<span class="info-value">{{ person.company }}</span>
</div>
<div class="info-item" v-if="person.mobile">
<span class="info-label">موبایل:</span>
<span class="info-value">{{ person.mobile }}</span>
</div>
<div class="info-item" v-if="person.tel">
<span class="info-label">تلفن:</span>
<span class="info-value">{{ person.tel }}</span>
</div>
</v-col>
<v-col cols="12" md="6">
<div class="info-item" v-if="person.email">
<span class="info-label">ایمیل:</span>
<span class="info-value">{{ person.email }}</span>
</div>
<div class="info-item" v-if="person.address">
<span class="info-label">آدرس:</span>
<span class="info-value">{{ person.address }}</span>
</div>
<div class="info-item" v-if="person.shahr">
<span class="info-label">شهر:</span>
<span class="info-value">{{ person.shahr }}</span>
</div>
<div class="info-item" v-if="person.ostan">
<span class="info-label">استان:</span>
<span class="info-value">{{ person.ostan }}</span>
</div>
</v-col>
</v-row>
</div>
<!-- موجودی مالی -->
<div class="info-section mb-4">
<h4 class="text-subtitle-1 font-weight-medium mb-2">موجودی مالی</h4>
<v-row>
<v-col cols="12" md="4">
<v-card variant="outlined" class="balance-card">
<v-card-text class="text-center">
<div class="text-caption text-medium-emphasis">بستانکار</div>
<div class="text-h6 text-success">{{ formatNumber(person.balance.total_bs) }} ریال</div>
</v-card-text>
</v-card>
</v-col>
<v-col cols="12" md="4">
<v-card variant="outlined" class="balance-card">
<v-card-text class="text-center">
<div class="text-caption text-medium-emphasis">بدهکار</div>
<div class="text-h6 text-error">{{ formatNumber(person.balance.total_bd) }} ریال</div>
</v-card-text>
</v-card>
</v-col>
<v-col cols="12" md="4">
<v-card variant="outlined" class="balance-card">
<v-card-text class="text-center">
<div class="text-caption text-medium-emphasis">موجودی</div>
<div class="text-h6" :class="getBalanceTextColor(person.balance.balance_status)">
{{ formatNumber(person.balance.balance) }} ریال
</div>
</v-card-text>
</v-card>
</v-col>
</v-row>
<div class="text-caption text-medium-emphasis mt-2">
تعداد تراکنش‌ها: {{ person.balance.transaction_count }}
</div>
</div>
<!-- نوع اشخاص -->
<div class="info-section mb-4" v-if="person.types && person.types.length > 0">
<h4 class="text-subtitle-1 font-weight-medium mb-2">نوع اشخاص</h4>
<div class="d-flex flex-wrap gap-1">
<v-chip
v-for="type in person.types"
:key="type.id"
size="small"
variant="tonal"
color="primary"
>
{{ type.name }}
</v-chip>
</div>
</div>
<!-- کارت‌های بانکی -->
<div class="info-section mb-4" v-if="person.cards && person.cards.length > 0">
<h4 class="text-subtitle-1 font-weight-medium mb-2">کارت‌های بانکی</h4>
<v-row>
<v-col cols="12" md="6" v-for="card in person.cards" :key="card.bank">
<v-card variant="outlined" class="card-item">
<v-card-text>
<div class="d-flex align-center mb-2">
<v-icon color="primary" class="mr-2">mdi-credit-card</v-icon>
<span class="font-weight-medium">{{ card.bank }}</span>
</div>
<div class="text-caption" v-if="card.card_number">
شماره کارت: {{ maskCardNumber(card.card_number) }}
</div>
<div class="text-caption" v-if="card.account_number">
شماره حساب: {{ card.account_number }}
</div>
<div class="text-caption" v-if="card.shaba_number">
شماره شبا: {{ card.shaba_number }}
</div>
</v-card-text>
</v-card>
</v-col>
</v-row>
</div>
<!-- تراکنش‌های اخیر -->
<div class="info-section" v-if="transactions.length > 0">
<h4 class="text-subtitle-1 font-weight-medium mb-2">تراکنش‌های اخیر</h4>
<v-table density="compact">
<thead>
<tr>
<th>تاریخ</th>
<th>نوع</th>
<th>بستانکار</th>
<th>بدهکار</th>
<th>توضیحات</th>
</tr>
</thead>
<tbody>
<tr v-for="transaction in transactions" :key="transaction.id">
<td>{{ formatDate(transaction.doc_date) }}</td>
<td>
<v-chip size="x-small" variant="tonal" color="primary">
{{ transaction.doc_type }}
</v-chip>
</td>
<td class="text-success" v-if="transaction.bs > 0">
{{ formatNumber(transaction.bs) }}
</td>
<td v-else>-</td>
<td class="text-error" v-if="transaction.bd > 0">
{{ formatNumber(transaction.bd) }}
</td>
<td v-else>-</td>
<td>{{ transaction.description || transaction.doc_description }}</td>
</tr>
</tbody>
</v-table>
</div>
</v-card-text>
</v-card>
<v-card v-else class="no-data-card" elevation="1">
<v-card-text class="text-center">
<v-icon size="48" color="grey" class="mb-3">mdi-account-off</v-icon>
<div class="text-h6 text-grey">اطلاعات شخص یافت نشد</div>
<div class="text-caption text-grey">لطفاً نام یا کد شخص را بررسی کنید</div>
</v-card-text>
</v-card>
</div>
</template>
<script>
export default {
name: 'PersonInfo',
props: {
person: {
type: Object,
default: null
},
transactions: {
type: Array,
default: () => []
}
},
methods: {
formatNumber(number) {
return new Intl.NumberFormat('fa-IR').format(number);
},
formatDate(dateString) {
if (!dateString) return '-';
// تبدیل تاریخ شمسی به میلادی و نمایش
return dateString;
},
maskCardNumber(cardNumber) {
if (!cardNumber) return '-';
return cardNumber.replace(/(\d{4})(\d{4})(\d{4})(\d{4})/, '$1-$2-$3-$4');
},
getBalanceColor(status) {
switch (status) {
case 'بستانکار':
return 'success';
case 'بدهکار':
return 'error';
default:
return 'grey';
}
},
getBalanceTextColor(status) {
switch (status) {
case 'بستانکار':
return 'text-success';
case 'بدهکار':
return 'text-error';
default:
return 'text-grey';
}
}
}
};
</script>
<style scoped>
.person-info {
max-width: 100%;
}
.person-card {
border-radius: 12px;
}
.info-section {
border-bottom: 1px solid rgba(0, 0, 0, 0.08);
padding-bottom: 16px;
}
.info-section:last-child {
border-bottom: none;
padding-bottom: 0;
}
.info-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 8px 0;
border-bottom: 1px solid rgba(0, 0, 0, 0.04);
}
.info-item:last-child {
border-bottom: none;
}
.info-label {
font-weight: 500;
color: rgba(0, 0, 0, 0.7);
min-width: 80px;
}
.info-value {
color: rgba(0, 0, 0, 0.9);
text-align: left;
}
.balance-card {
border-radius: 8px;
transition: all 0.3s ease;
}
.balance-card:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
.card-item {
border-radius: 8px;
transition: all 0.3s ease;
}
.card-item:hover {
transform: translateY(-1px);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.no-data-card {
border-radius: 12px;
min-height: 200px;
display: flex;
align-items: center;
justify-content: center;
}
.gap-1 {
gap: 4px;
}
.gap-2 {
gap: 8px;
}
</style>