ifnex/04_Laravel/app/Filament/Widgets/RecentShipmentsWidget.php
Kazem Alghasi 91984dbde3 feat(ui): redesign admin dashboard with layered grid and custom branding
Implement a comprehensive overhaul of the Filament admin dashboard,
introducing a structured 12-column responsive grid layout and enhanced
visual identity.

Key changes include:
- Redesigned Dashboard layout with a 4-layer progressive disclosure
  architecture (KPIs, Exchange Rates, Data Tables, and Trends).
- Introduced custom IFNEX design tokens via CSS, including branded
  stat cards, status badges, and improved sidebar typography.
- Enhanced FinanceOverviewWidget with real-time trend analysis and
  sparkline-ready data structures.
- Refactored RecentShipments and RecentTransactions widgets to use
  custom Blade templates for a more polished, consistent UI.
- Integrated brand assets including the company logo and custom
  authentication pages.
- Added global number formatting helpers and integrated them into
  financial widgets.
- Updated AdminPanelProvider to support custom login pages and
  brand-specific header/footer hooks.
2026-10-03 11:08:50 +03:30

86 lines
3.1 KiB
PHP

<?php
namespace App\Filament\Widgets;
use App\Models\Shipment;
use Filament\Widgets\Widget;
use Morilog\Jalali\Jalalian;
/**
* Layer 3 (left) — recent shipments table, spanning 6/12 of the body grid.
*/
class RecentShipmentsWidget extends Widget
{
protected static ?int $sort = 6;
protected static bool $isLazy = false;
protected int|string|array $columnSpan = 6;
protected static string $view = 'filament.widgets.recent-shipments';
protected function getViewData(): array
{
$recentShipments = Shipment::query()
->with(['fromCountry', 'toCountry'])
->orderBy('created_at', 'desc')
->limit(5)
->get()
->map(function ($s) {
return [
'awb' => $s->awb_no,
'route' => ($s->fromCountry?->name ?? '?') . ' ← ' . ($s->toCountry?->name ?? '?'),
'status' => $s->status?->value ?? '—',
'status_label' => $this->statusLabel($s->status?->value),
'status_color' => $this->statusBadgeClass($s->status?->value),
'date' => Jalalian::fromCarbon($s->created_at)->format('Y/m/d'),
'amount' => $s->total_fee ? ifnex_format_number($s->total_fee) : '—',
'url' => route('filament.admin.resources.shipments.view', $s),
];
});
return [
'recentShipments' => $recentShipments,
'viewAllUrl' => route('filament.admin.resources.shipments.index'),
];
}
private function statusLabel(?string $status): string
{
return match ($status) {
'pending_approval' => 'در انتظار تأیید',
'approved' => 'تأیید شده',
'pending_payment' => 'در انتظار پرداخت',
'cancelled' => 'لغو شده',
'processed' => 'در حال پردازش',
'picked_up' => 'تحویل به حمل‌کننده',
'in_transit' => 'در حال حمل',
'out_for_delivery' => 'آماده تحویل',
'failed' => 'تحویل ناموفق',
'delivered' => 'تحویل شده',
'returned' => 'برگشتی',
'archived' => 'آرشیو',
default => '—',
};
}
/**
* Return the badge CSS class name — uses the new ifnex-badge-* styles
* defined in head.blade.php (success / warning / danger / info / gray).
*/
private function statusBadgeClass(?string $status): string
{
return match ($status) {
'pending_approval', 'pending_payment' => 'ifnex-badge-warning',
'approved' => 'ifnex-badge-info',
'picked_up', 'in_transit' => 'ifnex-badge-info',
'out_for_delivery' => 'ifnex-badge-info',
'delivered' => 'ifnex-badge-success',
'cancelled', 'failed' => 'ifnex-badge-danger',
'returned' => 'ifnex-badge-warning',
'processed' => 'ifnex-badge-info',
'archived' => 'ifnex-badge-gray',
default => 'ifnex-badge-gray',
};
}
}