feat(admin): add customer financial overview page

Implement a new Filament page to provide a comprehensive overview of
customer financial data, including new page class and blade template.
This commit is contained in:
Kazem Alghasi 2026-10-03 21:27:21 +03:30
parent e6c67e217a
commit ab972fe3e8
2 changed files with 622 additions and 0 deletions

View File

@ -0,0 +1,230 @@
<?php
namespace App\Filament\Pages;
use App\Enums\ShipmentStatus;
use App\Models\CustomerCredit;
use App\Models\Shipment;
use App\Models\User;
use App\Models\WalletTransaction;
use App\Services\CustomerCreditService;
use Filament\Forms\Components\Select;
use Filament\Forms\Form;
use Filament\Pages\Page;
use Filament\Tables\Columns\TextColumn;
use Illuminate\Support\Facades\DB;
/**
* صفحهٔ «وضعیت مالی مشتری» — نمای یکپارچه مالی per-customer در پنل ادمین.
*
* مدیر/کارمند مشتری را انتخاب می‌کند و در یک نگاه می‌بیند:
* - موجودی کیف پول
* - کل بدهی (سفارشات تأییدشده پرداخت‌نشده)
* - کل پرداختی (تاریخچه)
* - تعداد کل سفارشات
* - اعتبارات چندارزی فعال
* - سفارشات اخیر
* - تراکنش‌های اخیر
*/
class CustomerFinancialOverview extends Page
{
protected static ?string $navigationIcon = 'heroicon-o-banknotes';
protected static ?string $navigationLabel = 'وضعیت مالی مشتری';
protected static ?string $navigationGroup = 'مالی';
protected static ?int $navigationSort = 5;
protected static ?string $slug = 'customer-financial';
protected static string $view = 'filament.pages.customer-financial-overview';
/** @var array فرم انتخاب مشتری */
public ?array $data = [];
/** @var array|null داده‌های مالی پس از انتخاب مشتری */
public ?array $financialData = null;
public function mount(): void
{
$this->form->fill();
}
public function form(Form $form): Form
{
return $form
->schema([
Select::make('customer_id')
->label('انتخاب مشتری')
->placeholder('نام، ایمیل یا شماره موبایل را جستجو کنید…')
->options(fn () => $this->getCustomerOptions())
->searchable()
->reactive()
->preload()
->required(),
])
->statePath('data');
}
/**
* لیست مشتریان برای Select — کاربرانی که مشتری هستند (role = customer یا بدون نقش).
*/
protected function getCustomerOptions(): array
{
return User::query()
->where('role', 'customer')
->orWhereNull('role')
->where('is_active', true)
->orderBy('name')
->limit(500)
->get()
->mapWithKeys(fn ($user) => [
$user->id => "{$user->name}" . ($user->phone ? " — {$user->phone}" : ''),
])
->toArray();
}
/**
* Livewire lifecycle hook — هنگام تغییر فرم صدا زده می‌شود.
*/
public function updated($property, $value): void
{
if ($property === 'data.customer_id') {
if (!empty($value)) {
$this->loadFinancialData((int) $value);
} else {
$this->financialData = null;
}
}
}
/**
* بارگذاری داده‌های مالی مشتری انتخاب‌شده.
*/
public function loadFinancialData(int $customerId): void
{
$customer = User::with(['wallet'])->find($customerId);
if (!$customer) {
$this->financialData = null;
return;
}
$creditService = app(CustomerCreditService::class);
// ─── KPI محاسبات ───
$walletBalance = (float) ($customer->wallet?->balance ?? 0);
$totalPendingIrr = (float) Shipment::where('user_id', $customer->id)
->where('status', ShipmentStatus::Approved)
->sum('total_fee');
$pendingCount = Shipment::where('user_id', $customer->id)
->where('status', ShipmentStatus::Approved)
->count();
$totalOrders = Shipment::where('user_id', $customer->id)->count();
$totalPaid = (float) WalletTransaction::whereHas('wallet', fn ($q) => $q->where('user_id', $customer->id))
->where('type', 'order_payment')
->where('status', 'completed')
->where('amount', '>', 0)
->sum('amount');
$totalDeposits = (float) WalletTransaction::whereHas('wallet', fn ($q) => $q->where('user_id', $customer->id))
->where('type', 'deposit')
->where('status', 'completed')
->where('amount', '>', 0)
->sum('amount');
// بدهی‌های چندارزی (EU/AED/USD)
$foreignCredits = $creditService->getCustomerDebtsByCurrency($customer);
// اعتبارات فعال (ریکوردهای قابل ویرایش)
$activeCredits = CustomerCredit::where('user_id', $customer->id)
->whereIn('status', ['open', 'partially_settled'])
->orderBy('created_at', 'desc')
->get();
// سفارشات اخیر (۵ ردیف)
$recentOrders = Shipment::where('user_id', $customer->id)
->with(['fromCountry', 'toCountry'])
->orderBy('created_at', 'desc')
->limit(5)
->get();
// تراکنش‌های اخیر (۵ ردیف)
$recentTransactions = WalletTransaction::whereHas('wallet', fn ($q) => $q->where('user_id', $customer->id))
->with('wallet')
->orderBy('created_at', 'desc')
->limit(5)
->get();
// مانده حساب = کیف پول منهای تعهدات ریالی
$accountBalance = $walletBalance - $totalPendingIrr;
$this->financialData = [
'customer' => [
'id' => $customer->id,
'name' => $customer->name,
'email' => $customer->email,
'phone' => $customer->phone,
'created_at' => $customer->created_at?->format('Y/m/d'),
],
'kpis' => [
[
'label' => 'موجودی کیف پول',
'value' => ifnex_format_number($walletBalance),
'desc' => $walletBalance > 0 ? 'موجودی مثبت' : 'صفر یا منفی',
'icon' => 'heroicon-o-wallet',
'color' => 'blue',
],
[
'label' => 'بدهی فعلی (سفارشات پرداخت‌نشده)',
'value' => ifnex_format_number($totalPendingIrr),
'desc' => ifnex_persian_digits(number_format($pendingCount)) . ' سفارش تأییدشده',
'icon' => 'heroicon-o-clock',
'color' => $totalPendingIrr > 0 ? 'red' : 'gray',
],
[
'label' => 'کل پرداختی (تاریخچه)',
'value' => ifnex_format_number($totalPaid),
'desc' => 'مجموع پرداخت‌های موفق',
'icon' => 'heroicon-o-arrow-trending-up',
'color' => 'green',
],
[
'label' => 'مانده حساب',
'value' => ifnex_format_number($accountBalance),
'desc' => $accountBalance >= 0 ? 'موجودی‌ساز' : 'بدهکار — منفی',
'icon' => 'heroicon-o-banknotes',
'color' => $accountBalance >= 0 ? 'green' : 'red',
],
],
'walletBalance' => $walletBalance,
'totalPendingIrr' => $totalPendingIrr,
'totalOrders' => $totalOrders,
'totalDeposits' => $totalDeposits,
'accountBalance' => $accountBalance,
'foreignCredits' => $foreignCredits,
'activeCredits' => $activeCredits,
'recentOrders' => $recentOrders,
'recentTransactions' => $recentTransactions,
];
}
/**
* فقط مدیر و کارمند می‌توانند این صفحه را ببینند.
*/
public static function canAccess(): bool
{
$user = auth()->user();
if (!$user) return false;
// مدیر یا کارمند
return $user->hasRole('super_admin')
|| $user->hasRole('admin')
|| $user->hasRole('tracking_operator')
|| $user->hasRole('data_entry')
|| $user->role === 'super_admin'
|| $user->role === 'admin'
|| $user->role === 'tracking_operator'
|| $user->role === 'data_entry';
}
}

View File

@ -0,0 +1,392 @@
{{--
IFNEX — Customer Financial Overview page.
Director/staff selects a customer, sees complete financial status:
KPIs + multi-currency credits + recent orders + recent transactions.
--}}
<x-filament-panels::page>
<div class="space-y-6">
<style>
/* ════════ KPI Grid & Cards (matching dashboard design) ════════ */
.ifnex-kpi-grid {
display: grid !important;
grid-template-columns: repeat(4, 1fr) !important;
gap: 1rem !important;
width: 100% !important;
}
@media (max-width: 1024px) {
.ifnex-kpi-grid {
grid-template-columns: repeat(2, 1fr) !important;
}
}
@media (max-width: 640px) {
.ifnex-kpi-grid {
grid-template-columns: 1fr !important;
}
}
.ifnex-kpi-card {
display: flex;
align-items: flex-start;
gap: 0.875rem;
padding: 1.25rem;
background: #ffffff;
border: 1px solid #e5e7eb;
border-radius: 16px;
box-shadow: 0 1px 3px rgba(0,0,0,0.08), 0 1px 2px rgba(0,0,0,0.04);
text-decoration: none;
color: inherit;
transition: transform 0.25s ease, box-shadow 0.25s ease;
}
.dark .ifnex-kpi-card {
background: rgb(30 41 59);
border-color: rgb(51 65 85);
}
.ifnex-kpi-card:hover {
transform: translateY(-2px);
box-shadow: 0 10px 25px rgba(0,0,0,0.10), 0 4px 6px rgba(0,0,0,0.05);
}
.ifnex-kpi-icon-wrap {
width: 44px;
height: 44px;
border-radius: 12px;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
}
.ifnex-kpi-icon-amber { background: #fef3c7; color: #d97706; }
.ifnex-kpi-icon-green { background: #d1fae5; color: #059669; }
.ifnex-kpi-icon-red { background: #fee2e2; color: #dc2626; }
.ifnex-kpi-icon-blue { background: #dbeafe; color: #2563eb; }
.ifnex-kpi-icon-gray { background: #f1f5f9; color: #475569; }
.dark .ifnex-kpi-icon-amber { background: rgba(245,158,11,.18); color: #fbbf24; }
.dark .ifnex-kpi-icon-green { background: rgba(16,185,129,.18); color: #34d399; }
.dark .ifnex-kpi-icon-red { background: rgba(239,68,68,.18); color: #f87171; }
.dark .ifnex-kpi-icon-blue { background: rgba(59,130,246,.18); color: #60a5fa; }
.dark .ifnex-kpi-icon-gray { background: rgba(148,163,184,.18); color: #cbd5e1; }
.ifnex-kpi-body { flex: 1; min-width: 0; }
.ifnex-kpi-label {
font-size: 12px;
font-weight: 500;
color: #6b7280;
margin-bottom: 0.25rem;
}
.dark .ifnex-kpi-label { color: #9ca3af; }
.ifnex-kpi-value {
font-size: 26px;
font-weight: 800;
color: #111827;
line-height: 1.2;
letter-spacing: -0.5px;
margin-bottom: 0.25rem;
}
.dark .ifnex-kpi-value { color: #f9fafb; }
.ifnex-kpi-desc {
font-size: 11px;
color: #9ca3af;
line-height: 1.4;
}
.dark .ifnex-kpi-desc { color: #6b7280; }
/* ════════ Badges ════════ */
.ifnex-badge {
display: inline-flex;
align-items: center;
gap: 4px;
padding: 0.125rem 0.625rem;
border-radius: 9999px;
font-size: 11.5px;
font-weight: 600;
line-height: 1.4;
white-space: nowrap;
}
.ifnex-badge-success { background: #d1fae5; color: #047857; }
.ifnex-badge-warning { background: #fef3c7; color: #b45309; }
.ifnex-badge-danger { background: #fee2e2; color: #b91c1c; }
.ifnex-badge-info { background: #dbeafe; color: #1d4ed8; }
.ifnex-badge-gray { background: #f1f5f9; color: #475569; }
.dark .ifnex-badge-success { background: rgba(16,185,129,.18); color: #6ee7b7; }
.dark .ifnex-badge-warning { background: rgba(245,158,11,.18); color: #fcd34d; }
.dark .ifnex-badge-danger { background: rgba(239,68,68,.18); color: #fca5a5; }
.dark .ifnex-badge-info { background: rgba(59,130,246,.18); color: #93c5fd; }
.dark .ifnex-badge-gray { background: rgba(148,163,184,.18); color: #cbd5e1; }
/* ════════ Table styling ════════ */
.ifnex-th { padding: 0.625rem 0.75rem; font-size: 11.5px; font-weight: 600; text-transform: none; }
.ifnex-td { padding: 0.625rem 0.75rem; vertical-align: middle; }
.ifnex-table-row-hover:hover { background-color: #fffbeb !important; }
.dark .ifnex-table-row-hover:hover { background-color: rgba(245, 158, 11, 0.08) !important; }
.ifnex-link-inline { display: inline-flex; align-items: center; gap: 2px; }
/* ════════ Buttons ════════ */
.ifnex-btn {
display: inline-flex;
align-items: center;
gap: 0.375rem;
padding: 0.5rem 1rem;
border-radius: 8px;
font-size: 13px;
font-weight: 600;
text-decoration: none;
transition: all 0.2s;
cursor: pointer;
border: none;
}
.ifnex-btn-sm { padding: 0.375rem 0.75rem; font-size: 12px; }
.ifnex-btn-primary { background: linear-gradient(135deg, #f59e0b 0%, #FDB913 100%); color: #ffffff !important; }
.ifnex-btn-primary:hover { transform: translateY(-1px); box-shadow: 0 4px 12px rgba(245,158,11,0.35); color: #fff !important; }
.ifnex-btn-info { background: #dbeafe; color: #1d4ed8 !important; }
.ifnex-btn-info:hover { background: #bfdbfe; color: #1e40af !important; }
.ifnex-btn-success { background: #d1fae5; color: #047857 !important; }
.ifnex-btn-success:hover { background: #a7f3d0; color: #065f46 !important; }
.dark .ifnex-btn-info { background: rgba(59,130,246,.18); color: #93c5fd !important; }
.dark .ifnex-btn-primary { color: #fff !important; }
</style>
{{-- ════════ Customer Selector ════════ --}}
<div class="bg-white dark:bg-gray-800 rounded-2xl border border-gray-200 dark:border-gray-700 p-5">
<h3 class="text-base font-bold text-gray-900 dark:text-white mb-4 flex items-center gap-2">
<x-heroicon-o-magnifying-glass class="w-5 h-5 text-amber-500" />
جستجوی مشتری
</h3>
{{ $this->form }}
</div>
{{-- ════════ Financial Overview (only when customer selected) ════════ --}}
@if(!empty($financialData))
{{-- Customer Info + KPIs --}}
<div class="space-y-4">
{{-- Customer header --}}
<div class="bg-gradient-to-l from-amber-50 to-white dark:from-gray-800 dark:to-gray-900 rounded-2xl border border-amber-200 dark:border-gray-700 p-5">
<div class="flex items-center justify-between flex-wrap gap-3">
<div>
<h2 class="text-xl font-bold text-gray-900 dark:text-white">
{{ $financialData['customer']['name'] }}
</h2>
<div class="text-sm text-gray-500 dark:text-gray-400 mt-1">
@if($financialData['customer']['phone'])
<span class="ltr:inline-block">{{ $financialData['customer']['phone'] }}</span>
@endif
@if($financialData['customer']['email'])
— {{ $financialData['customer']['email'] }}
@endif
— عضو از {{ $financialData['customer']['created_at'] }}
</div>
</div>
<div class="flex gap-2">
<a href="{{ route('filament.admin.resources.customer-credits.create') }}?user_id={{ $financialData['customer']['id'] }}"
class="ifnex-btn ifnex-btn-sm ifnex-btn-primary">
<x-heroicon-o-plus class="w-4 h-4 inline" /> اعتبار جدید
</a>
<a href="{{ route('filament.admin.resources.shipments.index') }}?tableFilters[user_id][value]={{ $financialData['customer']['id'] }}"
class="ifnex-btn ifnex-btn-sm ifnex-btn-info">
<x-heroicon-o-truck class="w-4 h-4 inline" /> سفارشات
</a>
</div>
</div>
</div>
{{-- KPI Grid --}}
<div class="ifnex-kpi-grid">
@foreach($financialData['kpis'] as $kpi)
<div class="ifnex-kpi-card ifnex-kpi-{{ $kpi['color'] }}">
<div class="ifnex-kpi-icon-wrap ifnex-kpi-icon-{{ $kpi['color'] }}">
<x-dynamic-component :component="$kpi['icon']" class="w-6 h-6" />
</div>
<div class="ifnex-kpi-body">
<div class="ifnex-kpi-label">{{ $kpi['label'] }}</div>
<div class="ifnex-kpi-value">{{ $kpi['value'] }}</div>
<div class="ifnex-kpi-desc">{{ $kpi['desc'] }}</div>
</div>
</div>
@endforeach
</div>
</div>
{{-- Multi-Currency Credits --}}
<div class="bg-white dark:bg-gray-800 rounded-2xl border border-gray-200 dark:border-gray-700 overflow-hidden">
<div class="px-5 py-4 border-b border-gray-100 dark:border-gray-700 flex items-center gap-2.5">
<span class="inline-flex items-center justify-center w-9 h-9 rounded-xl bg-amber-100 dark:bg-amber-900/40 text-amber-600 dark:text-amber-400">
<x-heroicon-o-globe-alt class="w-5 h-5" />
</span>
<h3 class="text-base font-bold text-gray-900 dark:text-white">بدهی‌های چندارزی</h3>
</div>
@if(empty($financialData['foreignCredits']))
<div class="p-8 text-center">
<p class="text-sm text-gray-500 dark:text-gray-400">بدهی چندارزی فعال ندارد ✅</p>
</div>
@else
<div class="overflow-x-auto">
<table class="w-full text-sm">
<thead>
<tr class="bg-gray-50 dark:bg-gray-900/40 text-gray-500 dark:text-gray-400 border-b border-gray-100 dark:border-gray-700">
<th class="ifnex-th text-right">ارز</th>
<th class="ifnex-th text-right">مبلغ کل</th>
<th class="ifnex-th text-right">تسویه‌شده</th>
<th class="ifnex-th text-right">مانده</th>
<th class="ifnex-th text-right">تعداد رکورد</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-50 dark:divide-gray-700/60">
@foreach($financialData['foreignCredits'] as $credit)
<tr class="ifnex-table-row-hover transition-colors duration-150">
<td class="ifnex-td">
<span class="ifnex-badge ifnex-badge-info">{{ $credit['currency_code'] }}</span>
</td>
<td class="ifnex-td font-semibold">{{ number_format($credit['total_amount'], 2) }}</td>
<td class="ifnex-td text-green-600">{{ number_format($credit['total_settled'], 2) }}</td>
<td class="ifnex-td font-bold text-red-600">{{ number_format($credit['balance'], 2) }}</td>
<td class="ifnex-td text-gray-500">{{ ifnex_persian_digits(number_format($credit['count'])) }}</td>
</tr>
@endforeach
</tbody>
</table>
</div>
@endif
</div>
{{-- Recent Orders + Transactions (side by side) --}}
<div class="grid grid-cols-1 lg:grid-cols-2 gap-4">
{{-- Recent Orders --}}
<div class="bg-white dark:bg-gray-800 rounded-2xl border border-gray-200 dark:border-gray-700 overflow-hidden">
<div class="px-5 py-4 border-b border-gray-100 dark:border-gray-700 flex items-center justify-between">
<div class="flex items-center gap-2.5">
<span class="inline-flex items-center justify-center w-9 h-9 rounded-xl bg-amber-100 dark:bg-amber-900/40 text-amber-600 dark:text-amber-400">
<x-heroicon-o-truck class="w-5 h-5" />
</span>
<h3 class="text-base font-bold text-gray-900 dark:text-white">سفارشات اخیر</h3>
</div>
<span class="text-xs text-gray-500">{{ ifnex_persian_digits(number_format($financialData['totalOrders'])) }} سفارش کل</span>
</div>
@if($financialData['recentOrders']->isEmpty())
<div class="p-6 text-center text-sm text-gray-500">سفارشی ثبت نشده است</div>
@else
<div class="overflow-x-auto">
<table class="w-full text-sm">
<thead>
<tr class="bg-gray-50 dark:bg-gray-900/40 text-gray-500 border-b border-gray-100 dark:border-gray-700">
<th class="ifnex-th text-right">AWB</th>
<th class="ifnex-th text-right">مسیر</th>
<th class="ifnex-th text-right">وضعیت</th>
<th class="ifnex-th text-right">مبلغ</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-50 dark:divide-gray-700/60">
@foreach($financialData['recentOrders'] as $order)
<tr class="ifnex-table-row-hover transition-colors duration-150">
<td class="ifnex-td">
<a href="{{ route('filament.admin.resources.shipments.view', $order) }}"
class="font-mono text-xs font-bold text-gray-900 dark:text-white hover:text-amber-600 transition-colors">
{{ $order->awb_no }}
</a>
</td>
<td class="ifnex-td text-xs text-gray-700 dark:text-gray-300">
{{ $order->fromCountry?->name }} ← {{ $order->toCountry?->name }}
</td>
<td class="ifnex-td">
@php
$stColor = match($order->status?->value) {
'approved' => 'ifnex-badge-info',
'delivered' => 'ifnex-badge-success',
'cancelled', 'failed' => 'ifnex-badge-danger',
'pending_approval', 'pending_payment' => 'ifnex-badge-warning',
default => 'ifnex-badge-gray',
};
@endphp
<span class="ifnex-badge {{ $stColor }}">
{{ $order->status?->label() ?? '—' }}
</span>
</td>
<td class="ifnex-td text-xs font-semibold">
{{ $order->total_fee ? ifnex_format_number($order->total_fee) : '—' }}
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
@endif
</div>
{{-- Recent Transactions --}}
<div class="bg-white dark:bg-gray-800 rounded-2xl border border-gray-200 dark:border-gray-700 overflow-hidden">
<div class="px-5 py-4 border-b border-gray-100 dark:border-gray-700 flex items-center justify-between">
<div class="flex items-center gap-2.5">
<span class="inline-flex items-center justify-center w-9 h-9 rounded-xl bg-blue-100 dark:bg-blue-900/40 text-blue-600 dark:text-blue-400">
<x-heroicon-o-arrow-path class="w-5 h-5" />
</span>
<h3 class="text-base font-bold text-gray-900 dark:text-white">تراکنش‌های اخیر</h3>
</div>
<a href="{{ route('filament.admin.resources.wallet-transactions.index') }}"
class="ifnex-link-inline text-xs font-semibold text-amber-600 hover:text-amber-700">
مشاهده همه ←
</a>
</div>
@if($financialData['recentTransactions']->isEmpty())
<div class="p-6 text-center text-sm text-gray-500">تراکنشی ثبت نشده است</div>
@else
<div class="overflow-x-auto">
<table class="w-full text-sm">
<thead>
<tr class="bg-gray-50 dark:bg-gray-900/40 text-gray-500 border-b border-gray-100 dark:border-gray-700">
<th class="ifnex-th text-right">نوع</th>
<th class="ifnex-th text-right">مبلغ</th>
<th class="ifnex-th text-right">توضیحات</th>
<th class="ifnex-th text-right">تاریخ</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-50 dark:divide-gray-700/60">
@foreach($financialData['recentTransactions'] as $tx)
<tr class="ifnex-table-row-hover transition-colors duration-150">
<td class="ifnex-td">
@php
$txColor = match($tx->type?->value) {
'deposit' => 'ifnex-badge-success',
'withdrawal' => 'ifnex-badge-danger',
'order_payment' => 'ifnex-badge-warning',
'refund' => 'ifnex-badge-info',
default => 'ifnex-badge-gray',
};
@endphp
<span class="ifnex-badge {{ $txColor }}">
{{ $tx->type?->label() ?? '—' }}
</span>
</td>
<td class="ifnex-td text-xs font-semibold {{ $tx->amount >= 0 ? 'text-green-600' : 'text-red-600' }}">
{{ $tx->amount >= 0 ? '+' : '' }}{{ ifnex_format_number(abs($tx->amount)) }}
</td>
<td class="ifnex-td text-xs text-gray-700 dark:text-gray-300">
{{ \Illuminate\Support\Str::limit($tx->description ?? '—', 30) }}
</td>
<td class="ifnex-td text-xs text-gray-500">
{{ \Morilog\Jalali\Jalalian::fromCarbon($tx->created_at)->format('Y/m/d H:i') }}
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
@endif
</div>
</div>
@else
{{-- Empty state --}}
<div class="bg-white dark:bg-gray-800 rounded-2xl border border-dashed border-gray-300 dark:border-gray-600 p-12 text-center">
<div class="inline-flex items-center justify-center w-16 h-16 rounded-2xl bg-amber-100 dark:bg-amber-900/30 text-amber-500 mb-4">
<x-heroicon-o-banknotes class="w-8 h-8" />
</div>
<h3 class="text-base font-bold text-gray-900 dark:text-white mb-1">
مشتری را انتخاب کنید
</h3>
<p class="text-sm text-gray-500 dark:text-gray-400">
برای مشاهده وضعیت مالی کامل، از فرم بالا یک مشتری جستجو و انتخاب کنید.
</p>
</div>
@endif
</div>
</x-filament-panels::page>