Files
mbmanager-dashboard/src/components/dashboard/WarehouseActivityWidget.vue
T
2026-08-30 11:25:31 +03:30

143 lines
7.4 KiB
Vue
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script setup>
import { useRouter } from 'vue-router';
import { parseDateToJalali } from '@/utils/jalali';
const props = defineProps({
transactions: {
type: Array,
default: () => []
},
warehouseFlow: {
type: Object,
default: () => ({ inCount: 0, outCount: 0, inQuantity: 0, outQuantity: 0 })
},
loading: {
type: Boolean,
default: false
}
});
const router = useRouter();
function viewAllTransactions() {
router.push('/warehouse-items/transactions');
}
function createTransaction() {
router.push('/warehouse-items/create-transaction');
}
function formatJalaliDate(dateVal) {
if (!dateVal) return '—';
const j = parseDateToJalali(dateVal);
if (!j) return '—';
return `${j.jy}/${String(j.jm).padStart(2, '0')}/${String(j.jd).padStart(2, '0')}`;
}
const formatNumber = (num) => {
if (num === null || num === undefined) return '۰';
return Number(num).toLocaleString('fa-IR');
};
</script>
<template>
<div class="card h-full p-5 border border-surface-200 dark:border-surface-800 rounded-2xl bg-surface-0 dark:bg-surface-900 flex flex-col justify-between">
<div>
<div class="flex justify-between items-center mb-4">
<div>
<h3 class="font-bold text-lg text-surface-900 dark:text-surface-0 mb-1">آخرین گردش‌های انبار</h3>
<p class="text-xs text-muted-color">گزارش لحظه‌ای ثبت ورود و خروج کالا در انبارها</p>
</div>
<Button label="مشاهده همه" icon="pi pi-arrow-left" iconPos="right" size="small" text class="text-xs" @click="viewAllTransactions" />
</div>
<!-- Flow stats summary banner -->
<div class="grid grid-cols-2 gap-3 mb-4">
<div class="p-3 rounded-xl bg-emerald-50/60 dark:bg-emerald-950/20 border border-emerald-200/50 dark:border-emerald-800/30 flex items-center justify-between">
<div class="flex items-center gap-2">
<div class="w-8 h-8 rounded-lg bg-emerald-500/10 text-emerald-600 dark:text-emerald-400 flex items-center justify-center">
<i class="pi pi-arrow-down-left text-sm"></i>
</div>
<div>
<span class="text-[11px] text-muted-color block">مجموع ورودی</span>
<span class="text-xs font-bold text-emerald-700 dark:text-emerald-400"> {{ formatNumber(warehouseFlow.inQuantity) }} واحد </span>
</div>
</div>
<span class="text-xs font-medium text-emerald-600 dark:text-emerald-400"> {{ formatNumber(warehouseFlow.inCount) }} تراکنش </span>
</div>
<div class="p-3 rounded-xl bg-rose-50/60 dark:bg-rose-950/20 border border-rose-200/50 dark:border-rose-800/30 flex items-center justify-between">
<div class="flex items-center gap-2">
<div class="w-8 h-8 rounded-lg bg-rose-500/10 text-rose-600 dark:text-rose-400 flex items-center justify-center">
<i class="pi pi-arrow-up-right text-sm"></i>
</div>
<div>
<span class="text-[11px] text-muted-color block">مجموع خروجی</span>
<span class="text-xs font-bold text-rose-700 dark:text-rose-400"> {{ formatNumber(warehouseFlow.outQuantity) }} واحد </span>
</div>
</div>
<span class="text-xs font-medium text-rose-600 dark:text-rose-400"> {{ formatNumber(warehouseFlow.outCount) }} تراکنش </span>
</div>
</div>
<!-- Loading -->
<div v-if="loading" class="py-10 flex items-center justify-center">
<i class="pi pi-spin pi-spinner text-primary text-2xl"></i>
</div>
<!-- Empty -->
<div v-else-if="!transactions || transactions.length === 0" class="py-10 flex flex-col items-center justify-center text-muted-color">
<i class="pi pi-history text-4xl mb-2 opacity-40"></i>
<span class="text-sm">تراکنش انباری ثبت نشده است</span>
<Button label="ثبت اولین تراکنش" icon="pi pi-plus" size="small" class="mt-3" @click="createTransaction" />
</div>
<!-- Transactions List -->
<ul v-else class="list-none p-0 m-0 divide-y divide-surface-100 dark:divide-surface-800">
<li v-for="tx in transactions" :key="tx._id" class="py-3 flex items-center justify-between gap-3 hover:bg-surface-50 dark:hover:bg-surface-800/50 px-2 rounded-xl transition-colors duration-150">
<div class="flex items-center gap-3 min-w-0">
<div
:class="[
'w-9 h-9 rounded-xl flex items-center justify-center shrink-0 font-bold text-xs',
tx.type === 'IN' ? 'bg-emerald-100 dark:bg-emerald-500/20 text-emerald-600 dark:text-emerald-400' : 'bg-rose-100 dark:bg-rose-500/20 text-rose-600 dark:text-rose-400'
]"
>
<i :class="['pi text-xs', tx.type === 'IN' ? 'pi-arrow-down' : 'pi-arrow-up']"></i>
</div>
<div class="truncate">
<div class="flex items-center gap-2">
<span class="font-semibold text-surface-900 dark:text-surface-100 text-sm truncate">
{{ tx.itemName }}
</span>
<span
:class="[
'px-1.5 py-0.2 rounded text-[10px] font-bold',
tx.type === 'IN' ? 'bg-emerald-100 dark:bg-emerald-900/40 text-emerald-700 dark:text-emerald-300' : 'bg-rose-100 dark:bg-rose-900/40 text-rose-700 dark:text-rose-300'
]"
>
{{ tx.type === 'IN' ? 'ورود' : 'خروج' }}
</span>
</div>
<div class="text-[11px] text-muted-color flex items-center gap-2 mt-0.5">
<span>انبار: {{ tx.warehouseName }}</span>
<span>•</span>
<span>توسط: {{ tx.actorName }}</span>
</div>
</div>
</div>
<div class="text-left shrink-0">
<div :class="['font-bold text-sm font-mono', tx.type === 'IN' ? 'text-emerald-600 dark:text-emerald-400' : 'text-rose-600 dark:text-rose-400']">
{{ tx.type === 'IN' ? '+' : '-' }}{{ formatNumber(tx.quantity) }} {{ tx.unit }}
</div>
<span class="text-[10px] text-muted-color font-mono block">
{{ formatJalaliDate(tx.date) }}
</span>
</div>
</li>
</ul>
</div>
</div>
</template>