some edits
This commit is contained in:
@@ -1,27 +1,79 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, ref } from 'vue'
|
||||
import { computed, onMounted, ref } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import AdminIcon from '@/components/icons/AdminIcon.vue'
|
||||
import StatusBadge from '@/components/ui/StatusBadge.vue'
|
||||
import { checks, orders } from '@/data/mockData'
|
||||
import { checksApi, mapAdminOrder, ordersApi, type ApiOrder } from '@/services/api'
|
||||
import { ApiError } from '@/services/http'
|
||||
import { formatCurrency, formatNumber } from '@/utils/format'
|
||||
import { useToast } from '@/composables/useToast'
|
||||
import type { Check } from '@/types'
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const toast = useToast()
|
||||
|
||||
const activeTab = ref<'info' | 'images' | 'history'>('info')
|
||||
const order = ref<ApiOrder | null>(null)
|
||||
const orderChecks = ref<Check[]>([])
|
||||
const busyId = ref<string | null>(null)
|
||||
|
||||
const order = computed(() => orders.find((o) => o.id === route.params.id) ?? orders[0]!)
|
||||
|
||||
const orderChecks = computed(() => checks.filter((c) => c.orderId === order.value.id))
|
||||
const displayOrder = computed(() =>
|
||||
order.value ? mapAdminOrder(order.value) : null,
|
||||
)
|
||||
|
||||
const totalCheckAmount = computed(() =>
|
||||
orderChecks.value.reduce((sum, c) => sum + c.amount, 0),
|
||||
)
|
||||
|
||||
async function loadData() {
|
||||
const orderId = String(route.params.id)
|
||||
try {
|
||||
const [orderData, checksData] = await Promise.all([
|
||||
ordersApi.get(orderId),
|
||||
checksApi.listByOrder(orderId),
|
||||
])
|
||||
order.value = orderData
|
||||
orderChecks.value = checksData
|
||||
} catch (err) {
|
||||
toast.error(err instanceof ApiError ? err.message : 'بارگذاری چکها انجام نشد.')
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
void loadData()
|
||||
})
|
||||
|
||||
function goBack() {
|
||||
router.push('/orders')
|
||||
}
|
||||
|
||||
function checkBadgeStatus(status: Check['status']) {
|
||||
if (status === 'approved') return 'final_approval'
|
||||
if (status === 'rejected') return 'needs_correction'
|
||||
return 'pending_check_review'
|
||||
}
|
||||
|
||||
async function updateCheckStatus(check: Check, status: Check['status']) {
|
||||
busyId.value = check.id
|
||||
try {
|
||||
const updated = await checksApi.updateStatus(check.id, { status })
|
||||
const index = orderChecks.value.findIndex((c) => c.id === check.id)
|
||||
if (index !== -1) orderChecks.value[index] = updated
|
||||
toast.success(status === 'approved' ? 'چک تأیید شد.' : 'چک رد شد.')
|
||||
} catch (err) {
|
||||
toast.error(err instanceof ApiError ? err.message : 'بهروزرسانی وضعیت چک انجام نشد.')
|
||||
} finally {
|
||||
busyId.value = null
|
||||
}
|
||||
}
|
||||
|
||||
async function approveAll() {
|
||||
const pending = orderChecks.value.filter((c) => c.status === 'pending_review')
|
||||
for (const check of pending) {
|
||||
await updateCheckStatus(check, 'approved')
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -31,9 +83,9 @@ function goBack() {
|
||||
<h1 class="admin-page-header__title">مدیریت چکها</h1>
|
||||
<p class="admin-page-header__breadcrumb">سفارشها / مدیریت سفارش</p>
|
||||
</div>
|
||||
<div class="checks-page__order-meta">
|
||||
<strong>{{ order.orderNumber }}</strong>
|
||||
<StatusBadge status="pending_check" />
|
||||
<div v-if="displayOrder" class="checks-page__order-meta">
|
||||
<strong>{{ displayOrder.orderNumber }}</strong>
|
||||
<StatusBadge :status="displayOrder.status" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -74,9 +126,11 @@ function goBack() {
|
||||
<p class="admin-summary-item__label">راس چکها</p>
|
||||
<p class="admin-summary-item__value">
|
||||
<AdminIcon name="check" :size="14" />
|
||||
۲ روز
|
||||
{{ order?.checkRassDays ?? '—' }} روز
|
||||
</p>
|
||||
<p v-if="order?.checkRassDate" class="checks-page__rass-date">
|
||||
تاریخ راس: {{ order.checkRassDate.slice(0, 10) }}
|
||||
</p>
|
||||
<p class="checks-page__rass-date">تاریخ راس: ۱۴۰۳/۰۸/۰۶</p>
|
||||
</div>
|
||||
<div class="admin-summary-item">
|
||||
<p class="admin-summary-item__label">مجموع چکها</p>
|
||||
@@ -85,7 +139,7 @@ function goBack() {
|
||||
<div class="admin-summary-item">
|
||||
<p class="admin-summary-item__label">مبلغ کل سفارش</p>
|
||||
<p class="admin-summary-item__value">
|
||||
{{ order.totalAmount ? formatCurrency(order.totalAmount) : '—' }}
|
||||
{{ displayOrder?.totalAmount ? formatCurrency(displayOrder.totalAmount) : '—' }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -110,18 +164,28 @@ function goBack() {
|
||||
<td>{{ formatNumber(check.amount) }}</td>
|
||||
<td>{{ check.bankName }}</td>
|
||||
<td>{{ check.sayadId }}</td>
|
||||
<td>{{ check.dueDate }}</td>
|
||||
<td><StatusBadge status="pending_check_review" /></td>
|
||||
<td>{{ check.dueDate.slice(0, 10) }}</td>
|
||||
<td><StatusBadge :status="checkBadgeStatus(check.status)" /></td>
|
||||
<td>
|
||||
<div class="admin-action-group">
|
||||
<button type="button" class="admin-btn admin-btn--outline-success admin-btn--xs">
|
||||
<div v-if="check.status === 'pending_review'" class="admin-action-group">
|
||||
<button
|
||||
type="button"
|
||||
class="admin-btn admin-btn--outline-success admin-btn--xs"
|
||||
:disabled="busyId === check.id"
|
||||
@click="updateCheckStatus(check, 'approved')"
|
||||
>
|
||||
تأیید
|
||||
<AdminIcon name="chevron-down" :size="12" />
|
||||
</button>
|
||||
<button type="button" class="admin-btn admin-btn--outline admin-btn--xs">
|
||||
مشاهده
|
||||
<button
|
||||
type="button"
|
||||
class="admin-btn admin-btn--outline-danger admin-btn--xs"
|
||||
:disabled="busyId === check.id"
|
||||
@click="updateCheckStatus(check, 'rejected')"
|
||||
>
|
||||
رد
|
||||
</button>
|
||||
</div>
|
||||
<span v-else>—</span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
@@ -133,19 +197,29 @@ function goBack() {
|
||||
<article v-for="check in orderChecks" :key="check.id" class="admin-card-item">
|
||||
<div class="admin-card-item__header">
|
||||
<p class="admin-card-item__title">چک {{ check.row }} — {{ formatNumber(check.amount) }} تومان</p>
|
||||
<StatusBadge status="pending_check_review" />
|
||||
<StatusBadge :status="checkBadgeStatus(check.status)" />
|
||||
</div>
|
||||
<div class="admin-card-item__meta">
|
||||
<span>بانک {{ check.bankName }}</span>
|
||||
<span>سررسید {{ check.dueDate }}</span>
|
||||
<span>سررسید {{ check.dueDate.slice(0, 10) }}</span>
|
||||
<span dir="ltr">{{ check.sayadId }}</span>
|
||||
</div>
|
||||
<div class="admin-card-item__actions">
|
||||
<button type="button" class="admin-btn admin-btn--outline-success admin-btn--xs">
|
||||
<div v-if="check.status === 'pending_review'" class="admin-card-item__actions">
|
||||
<button
|
||||
type="button"
|
||||
class="admin-btn admin-btn--outline-success admin-btn--xs"
|
||||
:disabled="busyId === check.id"
|
||||
@click="updateCheckStatus(check, 'approved')"
|
||||
>
|
||||
تأیید
|
||||
</button>
|
||||
<button type="button" class="admin-btn admin-btn--outline admin-btn--xs">
|
||||
مشاهده
|
||||
<button
|
||||
type="button"
|
||||
class="admin-btn admin-btn--outline-danger admin-btn--xs"
|
||||
:disabled="busyId === check.id"
|
||||
@click="updateCheckStatus(check, 'rejected')"
|
||||
>
|
||||
رد
|
||||
</button>
|
||||
</div>
|
||||
</article>
|
||||
@@ -156,7 +230,9 @@ function goBack() {
|
||||
راس چکها بر اساس تاریخ ثبت سفارش محاسبه شده است.
|
||||
</p>
|
||||
<div class="admin-action-group">
|
||||
<button type="button" class="admin-btn admin-btn--success">تأیید همه چکها</button>
|
||||
<button type="button" class="admin-btn admin-btn--success" @click="approveAll">
|
||||
تأیید همه چکها
|
||||
</button>
|
||||
<button type="button" class="admin-btn admin-btn--outline">
|
||||
<AdminIcon name="print" :size="16" />
|
||||
چاپ لیستها
|
||||
@@ -199,8 +275,9 @@ function goBack() {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-top: 20px;
|
||||
gap: 16px;
|
||||
margin-top: 16px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.checks-page__note {
|
||||
|
||||
Reference in New Issue
Block a user