refactor(admin): optimize dashboard layout and enhance sidebar UX
Refactor the Filament admin dashboard by decoupling the recent shipments logic into a dedicated widget and improving the sidebar navigation experience. Additionally, implement several improvements to the WordPress theme for better client-side usability. Laravel/Filament: - Extract `RecentShipmentsWidget` from `DashboardInfoWidget` to improve modularization and dashboard performance. - Update widget sorting and layout to accommodate the new structure. - Inject custom CSS and Alpine.js logic into the admin head to provide sidebar group toggling and a "collapse all" utility. - Improve sidebar group label visibility and hover states. WordPress: - Implement `ifnex_login_url()` to support Polylang-aware, language-specific login pages. - Hide the WordPress admin bar for non-administrator users to provide a cleaner client interface. - Add conditional rendering for the registration link in the login template based on WordPress user registration settings.
This commit is contained in:
parent
40cb104a86
commit
c54530d8da
@ -30,6 +30,15 @@ function ifnex_theme_setup() {
|
||||
}
|
||||
add_action('after_setup_theme', 'ifnex_theme_setup');
|
||||
|
||||
// ─── مخفیکردن نوار مدیریت وردپرس برای غیرمدیرها ──────
|
||||
// مشتریان نباید نوار پیشفرض ادمین را در پنل خود ببینند
|
||||
add_filter('show_admin_bar', function ($show) {
|
||||
if (current_user_can('administrator')) {
|
||||
return $show;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
// ─── بارگذاری فایلهای کمکی ──────────────────────────
|
||||
$ifnex_includes = ['/inc/customizer.php'];
|
||||
foreach ($ifnex_includes as $file) {
|
||||
@ -68,6 +77,22 @@ function ifnex_text_direction() {
|
||||
return ifnex_is_english() ? 'ltr' : 'rtl';
|
||||
}
|
||||
|
||||
// ─── آدرس صفحه لاگین سازگار با زبان جاری (Polylang) ───
|
||||
// صفحه EN با slug یگانه login-en ساخته شده تا با صفحه FA تداخل canonical رخ ندهد
|
||||
function ifnex_login_url() {
|
||||
$page = get_page_by_path('login');
|
||||
if (!$page) {
|
||||
return home_url('/login/');
|
||||
}
|
||||
if (function_exists('pll_get_post')) {
|
||||
$translated = pll_get_post($page->ID, ifnex_get_current_lang());
|
||||
if ($translated) {
|
||||
return get_permalink($translated);
|
||||
}
|
||||
}
|
||||
return get_permalink($page->ID);
|
||||
}
|
||||
|
||||
// ─── سوئیچر زبان (سازگار با Polylang) ───────────────
|
||||
function ifnex_language_switcher() {
|
||||
if (function_exists('pll_the_languages')) {
|
||||
|
||||
@ -16,7 +16,7 @@ if (is_user_logged_in()) {
|
||||
$login_btn_text = ifnex_t('پنل کاربری', 'Dashboard');
|
||||
$login_btn_class = 'btn btn-primary';
|
||||
} else {
|
||||
$login_btn_url = esc_url(home_url('/login/'));
|
||||
$login_btn_url = esc_url(ifnex_login_url());
|
||||
$login_btn_text = ifnex_t('ورود مشتریان', 'Client Login');
|
||||
$login_btn_class = 'btn btn-secondary';
|
||||
}
|
||||
|
||||
@ -142,10 +142,13 @@ get_header();
|
||||
</form>
|
||||
|
||||
<div class="ifnx-login-footer">
|
||||
<?php // لینک ثبتنام فقط وقتی «عضویت» در تنظیمات وردپرس فعال است نمایش داده میشود؛ در غیر این صورت wp_registration_url به صفحه پیشفرض lostpassword میرود ?>
|
||||
<?php if (get_option('users_can_register')): ?>
|
||||
<p><?php echo $is_en ? "Don't have an account?" : 'حساب کاربری ندارید؟'; ?>
|
||||
<a href="<?php echo esc_url(wp_registration_url()); ?>">
|
||||
<?php echo $is_en ? 'Register now' : 'ثبتنام کنید'; ?>
|
||||
</a></p>
|
||||
<?php endif; ?>
|
||||
<a href="<?php echo esc_url(home_url('/')); ?>" class="ifnx-login-back">
|
||||
← <?php echo $is_en ? 'Back to home' : 'بازگشت به سایت'; ?>
|
||||
</a>
|
||||
|
||||
@ -2,84 +2,32 @@
|
||||
|
||||
namespace App\Filament\Widgets;
|
||||
|
||||
use App\Models\Shipment;
|
||||
use Filament\Widgets\Widget;
|
||||
use Morilog\Jalali\Jalalian;
|
||||
|
||||
/**
|
||||
* کارت کوچک تاریخ/ساعت/خوشآمد — گوشه داشبورد.
|
||||
* جدول «آخرین سفارشات» به RecentShipmentsWidget جدا منتقل شده است.
|
||||
*/
|
||||
class DashboardInfoWidget extends Widget
|
||||
{
|
||||
protected static ?int $sort = 1; // اولین ویجت
|
||||
protected static ?int $sort = 1;
|
||||
|
||||
protected static bool $isLazy = false;
|
||||
|
||||
protected int | string | array $columnSpan = 'full';
|
||||
|
||||
|
||||
protected int | string | array $columnSpan = 1;
|
||||
|
||||
protected static string $view = 'filament.widgets.dashboard-info';
|
||||
|
||||
protected function getViewData(): array
|
||||
{
|
||||
$now = now();
|
||||
|
||||
// تاریخ میلادی
|
||||
$gregorianDate = $now->format('l, j F Y');
|
||||
|
||||
// تاریخ شمسی با Morilog\Jalali (سادهتر)
|
||||
$jalaliDate = Jalalian::fromCarbon($now)->format('l، d F Y');
|
||||
|
||||
// ساعت
|
||||
$time = $now->format('H:i');
|
||||
|
||||
// آخرین ۵ سفارش
|
||||
$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->statusColor($s->status?->value),
|
||||
'date' => Jalalian::fromCarbon($s->created_at)->format('Y/m/d'),
|
||||
'amount' => $s->total_fee ? number_format($s->total_fee) . ' ریال' : '—',
|
||||
];
|
||||
});
|
||||
|
||||
return [
|
||||
'gregorianDate' => $gregorianDate,
|
||||
'jalaliDate' => $jalaliDate,
|
||||
'time' => $time,
|
||||
'recentShipments' => $recentShipments,
|
||||
'userName' => auth()->user()?->name ?? 'کاربر',
|
||||
'gregorianDate' => $now->format('l, j F Y'),
|
||||
'jalaliDate' => Jalalian::fromCarbon($now)->format('l، d F Y'),
|
||||
'time' => $now->format('H:i'),
|
||||
'userName' => auth()->user()?->name ?? 'کاربر',
|
||||
];
|
||||
}
|
||||
|
||||
private function statusLabel(?string $status): string
|
||||
{
|
||||
return match($status) {
|
||||
'processed' => 'پردازش شده',
|
||||
'picked_up' => 'تحویل گرفته شده',
|
||||
'in_transit' => 'در حال حمل',
|
||||
'out_for_delivery' => 'در مسیر تحویل',
|
||||
'delivered' => 'تحویل داده شده',
|
||||
'failed' => 'ناموفق',
|
||||
'returned' => 'برگشتی',
|
||||
default => '—',
|
||||
};
|
||||
}
|
||||
|
||||
private function statusColor(?string $status): string
|
||||
{
|
||||
return match($status) {
|
||||
'processed' => 'bg-gray-100 text-gray-700 dark:bg-gray-800 dark:text-gray-300',
|
||||
'picked_up' => 'bg-blue-100 text-blue-700 dark:bg-blue-900 dark:text-blue-300',
|
||||
'in_transit' => 'bg-amber-100 text-amber-700 dark:bg-amber-900 dark:text-amber-300',
|
||||
'out_for_delivery' => 'bg-purple-100 text-purple-700 dark:bg-purple-900 dark:text-purple-300',
|
||||
'delivered' => 'bg-green-100 text-green-700 dark:bg-green-900 dark:text-green-300',
|
||||
'failed' => 'bg-red-100 text-red-700 dark:bg-red-900 dark:text-red-300',
|
||||
'returned' => 'bg-orange-100 text-orange-700 dark:bg-orange-900 dark:text-orange-300',
|
||||
default => 'bg-gray-100 text-gray-700',
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,7 +9,7 @@ use App\Models\ExchangeRateHistory;
|
||||
|
||||
class ExchangeRateWidget extends BaseWidget
|
||||
{
|
||||
protected static ?int $sort = 2;
|
||||
protected static ?int $sort = 3;
|
||||
protected static bool $isLazy = false;
|
||||
|
||||
protected int | string | array $columnSpan = 'full';
|
||||
|
||||
73
04_Laravel/app/Filament/Widgets/RecentShipmentsWidget.php
Normal file
73
04_Laravel/app/Filament/Widgets/RecentShipmentsWidget.php
Normal file
@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Widgets;
|
||||
|
||||
use App\Models\Shipment;
|
||||
use Filament\Widgets\Widget;
|
||||
use Morilog\Jalali\Jalalian;
|
||||
|
||||
/**
|
||||
* جدول آخرین ۵ سفارش — تمامعرض، زیر کارت تاریخ/ساعت.
|
||||
*/
|
||||
class RecentShipmentsWidget extends Widget
|
||||
{
|
||||
protected static ?int $sort = 2;
|
||||
|
||||
protected static bool $isLazy = false;
|
||||
|
||||
protected int | string | array $columnSpan = 'full';
|
||||
|
||||
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->statusColor($s->status?->value),
|
||||
'date' => Jalalian::fromCarbon($s->created_at)->format('Y/m/d'),
|
||||
'amount' => $s->total_fee ? number_format($s->total_fee) . ' ریال' : '—',
|
||||
];
|
||||
});
|
||||
|
||||
return [
|
||||
'recentShipments' => $recentShipments,
|
||||
];
|
||||
}
|
||||
|
||||
private function statusLabel(?string $status): string
|
||||
{
|
||||
return match($status) {
|
||||
'processed' => 'پردازش شده',
|
||||
'picked_up' => 'تحویل گرفته شده',
|
||||
'in_transit' => 'در حال حمل',
|
||||
'out_for_delivery' => 'در مسیر تحویل',
|
||||
'delivered' => 'تحویل داده شده',
|
||||
'failed' => 'ناموفق',
|
||||
'returned' => 'برگشتی',
|
||||
default => '—',
|
||||
};
|
||||
}
|
||||
|
||||
private function statusColor(?string $status): string
|
||||
{
|
||||
return match($status) {
|
||||
'processed' => 'bg-gray-100 text-gray-700 dark:bg-gray-800 dark:text-gray-300',
|
||||
'picked_up' => 'bg-blue-100 text-blue-700 dark:bg-blue-900 dark:text-blue-300',
|
||||
'in_transit' => 'bg-amber-100 text-amber-700 dark:bg-amber-900 dark:text-amber-300',
|
||||
'out_for_delivery' => 'bg-purple-100 text-purple-700 dark:bg-purple-900 dark:text-purple-300',
|
||||
'delivered' => 'bg-green-100 text-green-700 dark:bg-green-900 dark:text-green-300',
|
||||
'failed' => 'bg-red-100 text-red-700 dark:bg-red-900 dark:text-red-300',
|
||||
'returned' => 'bg-orange-100 text-orange-700 dark:bg-orange-900 dark:text-orange-300',
|
||||
default => 'bg-gray-100 text-gray-700',
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -10,7 +10,7 @@ use Illuminate\Support\Facades\DB;
|
||||
|
||||
class WalletStats extends BaseWidget
|
||||
{
|
||||
protected static ?int $sort = 3; // سومین ویجت
|
||||
protected static ?int $sort = 4; // چهارمین ویجت
|
||||
protected static bool $isLazy = false;
|
||||
|
||||
protected int | string | array $columnSpan = 'full';
|
||||
|
||||
@ -73,6 +73,7 @@ class AdminPanelProvider extends PanelProvider
|
||||
->widgets([
|
||||
// ویجتهای سفارشی IFNEX (به ترتیب sort)
|
||||
\App\Filament\Widgets\DashboardInfoWidget::class,
|
||||
\App\Filament\Widgets\RecentShipmentsWidget::class,
|
||||
\App\Filament\Widgets\ExchangeRateWidget::class,
|
||||
\App\Filament\Widgets\WalletStats::class,
|
||||
])
|
||||
|
||||
@ -187,4 +187,132 @@
|
||||
.fi-ta-text-wrap {
|
||||
gap: 0.125rem !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
/* ─── عناوین گروههای سایدبار: سفید روی پسزمینه تیره ─── */
|
||||
.fi-sidebar-group-label {
|
||||
color: #e2e8f0 !important;
|
||||
font-weight: 600 !important;
|
||||
}
|
||||
|
||||
.fi-sidebar-group-icon {
|
||||
color: #cbd5e1 !important;
|
||||
}
|
||||
|
||||
.fi-sidebar-group-collapse-button {
|
||||
color: #cbd5e1 !important;
|
||||
}
|
||||
|
||||
.fi-sidebar-group-button:hover .fi-sidebar-group-label,
|
||||
.fi-sidebar-group-button:hover .fi-sidebar-group-icon,
|
||||
.fi-sidebar-group-button:hover .fi-sidebar-group-collapse-button {
|
||||
color: #f59e0b !important;
|
||||
}
|
||||
|
||||
/* ─── دکمه بستن/باز کردن همه منوها ─── */
|
||||
.ifnex-sidebar-collapse-all {
|
||||
display: block;
|
||||
width: calc(100% - 16px);
|
||||
margin: 4px 8px 8px;
|
||||
padding: 7px 10px;
|
||||
font-size: 11.5px;
|
||||
font-family: inherit;
|
||||
color: #cbd5e1;
|
||||
background: rgba(255, 255, 255, .06);
|
||||
border: 1px solid rgba(255, 255, 255, .14);
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
transition: all .2s;
|
||||
}
|
||||
|
||||
.ifnex-sidebar-collapse-all:hover {
|
||||
background: rgba(245, 158, 11, .15);
|
||||
border-color: rgba(245, 158, 11, .35);
|
||||
color: #f59e0b;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
/* ─── گروههای سایدبار: پیشفرض بسته + کلیک روی عنوان + دکمه بستن/باز کردن همه ───
|
||||
از استور بومی Alpine فیلامنت (sidebar.collapsedGroups) استفاده میکند؛
|
||||
بنابراین وضعیت هر گروه در localStorage فیلامنت حفظ میشود. */
|
||||
(function () {
|
||||
function groupLabels() {
|
||||
return Array.from(document.querySelectorAll('.fi-sidebar-group-label'))
|
||||
.map(function (el) { return el.textContent.trim(); })
|
||||
.filter(Boolean);
|
||||
}
|
||||
|
||||
function collapseAll(store) {
|
||||
groupLabels().forEach(function (label) { store.collapseGroup(label); });
|
||||
}
|
||||
|
||||
function expandAll(store) {
|
||||
groupLabels().forEach(function (label) {
|
||||
if (store.groupIsCollapsed(label)) store.toggleCollapsedGroup(label);
|
||||
});
|
||||
}
|
||||
|
||||
// بار اول برای هر مرورگر: همه منوها بسته باشند؛ بعد از آن انتخاب کاربر محترم است
|
||||
function initDefaultCollapsed() {
|
||||
if (!window.Alpine) return;
|
||||
var store = window.Alpine.store('sidebar');
|
||||
if (!store || typeof store.collapseGroup !== 'function') return;
|
||||
if (!localStorage.getItem('ifnex-sidebar-default-collapsed')) {
|
||||
collapseAll(store);
|
||||
localStorage.setItem('ifnex-sidebar-default-collapsed', '1');
|
||||
}
|
||||
}
|
||||
|
||||
// کلیک روی ردیف عنوان گروه = باز/بسته کردن گروه (علاوه بر دکمه فلش)
|
||||
document.addEventListener('click', function (e) {
|
||||
var btn = e.target.closest('.fi-sidebar-group-button');
|
||||
if (!btn || e.target.closest('.fi-sidebar-group-collapse-button')) return;
|
||||
if (!window.Alpine) return;
|
||||
var store = window.Alpine.store('sidebar');
|
||||
if (!store) return;
|
||||
var labelEl = btn.querySelector('.fi-sidebar-group-label');
|
||||
// در حالت جمعشدهٔ کناری (فقط آیکون)، عنوان مخفی است — نادیده بگیر
|
||||
if (!labelEl || labelEl.offsetParent === null) return;
|
||||
var label = labelEl.textContent.trim();
|
||||
if (label) store.toggleCollapsedGroup(label);
|
||||
});
|
||||
|
||||
// دکمه «بستن/باز کردن همه» بالای سایدبار
|
||||
function injectToggle() {
|
||||
if (!document.querySelector('.fi-main-sidebar') || document.querySelector('.ifnex-sidebar-collapse-all')) return;
|
||||
var nav = document.querySelector('.fi-main-sidebar .fi-sidebar-nav');
|
||||
if (!nav) return;
|
||||
var b = document.createElement('button');
|
||||
b.type = 'button';
|
||||
b.className = 'ifnex-sidebar-collapse-all';
|
||||
b.textContent = 'بستن همه منوها ⌃';
|
||||
b.dataset.mode = 'collapse';
|
||||
b.addEventListener('click', function () {
|
||||
if (!window.Alpine) return;
|
||||
var store = window.Alpine.store('sidebar');
|
||||
if (!store) return;
|
||||
if (b.dataset.mode === 'collapse') {
|
||||
collapseAll(store);
|
||||
b.textContent = 'باز کردن همه منوها ⌄';
|
||||
b.dataset.mode = 'expand';
|
||||
} else {
|
||||
expandAll(store);
|
||||
b.textContent = 'بستن همه منوها ⌃';
|
||||
b.dataset.mode = 'collapse';
|
||||
}
|
||||
});
|
||||
nav.insertBefore(b, nav.firstChild);
|
||||
}
|
||||
|
||||
function boot() { initDefaultCollapsed(); injectToggle(); }
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', boot);
|
||||
} else {
|
||||
boot();
|
||||
}
|
||||
// SPA: بعد از هر ناوبری لایووایر، اگر سایدبار تازه رندر شده دکمه را تزریق کن
|
||||
document.addEventListener('livewire:navigated', injectToggle);
|
||||
})();
|
||||
</script>
|
||||
@ -1,92 +1,29 @@
|
||||
<x-filament-widgets::widget>
|
||||
<div class="grid grid-cols-1 lg:grid-cols-3 gap-4">
|
||||
|
||||
{{-- کارت تاریخ و ساعت --}}
|
||||
<div class="lg:col-span-1 bg-gradient-to-br from-amber-50 to-orange-50 rounded-xl p-6 border border-amber-200 dark:from-gray-800 dark:to-gray-900 dark:border-gray-700">
|
||||
<div class="flex items-center gap-3 mb-4">
|
||||
<div class="w-12 h-12 bg-amber-500 rounded-xl flex items-center justify-center text-white">
|
||||
<x-heroicon-o-calendar-days class="w-6 h-6" />
|
||||
</div>
|
||||
<div>
|
||||
<div class="text-xs text-gray-500 dark:text-gray-400">امروز</div>
|
||||
<div class="text-sm font-bold text-gray-800 dark:text-white">{{ $time }}</div>
|
||||
</div>
|
||||
<div class="bg-gradient-to-br from-amber-50 to-orange-50 rounded-xl p-6 border border-amber-200 dark:from-gray-800 dark:to-gray-900 dark:border-gray-700">
|
||||
<div class="flex items-center gap-3 mb-4">
|
||||
<div class="w-12 h-12 bg-amber-500 rounded-xl flex items-center justify-center text-white">
|
||||
<x-heroicon-o-calendar-days class="w-6 h-6" />
|
||||
</div>
|
||||
|
||||
<div class="space-y-2">
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="text-xs text-gray-500 dark:text-gray-400 w-16">📅 شمسی:</span>
|
||||
<span class="font-bold text-amber-700 dark:text-amber-400">{{ $jalaliDate }}</span>
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="text-xs text-gray-500 dark:text-gray-400 w-16">🌍 میلادی:</span>
|
||||
<span class="text-sm text-gray-700 dark:text-gray-300 capitalize">{{ $gregorianDate }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-4 pt-4 border-t border-amber-200 dark:border-gray-700">
|
||||
<div class="text-xs text-gray-500 dark:text-gray-400">خوش آمدید</div>
|
||||
<div class="font-bold text-gray-800 dark:text-white">{{ $userName }}</div>
|
||||
<div>
|
||||
<div class="text-xs text-gray-500 dark:text-gray-400">امروز</div>
|
||||
<div class="text-sm font-bold text-gray-800 dark:text-white">{{ $time }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- کارت آخرین سفارشات --}}
|
||||
<div class="lg:col-span-2 bg-white dark:bg-gray-800 rounded-xl border border-gray-200 dark:border-gray-700 overflow-hidden">
|
||||
<div class="px-6 py-4 border-b border-gray-200 dark:border-gray-700 flex items-center justify-between">
|
||||
<div class="flex items-center gap-2">
|
||||
<x-heroicon-o-truck class="w-5 h-5 text-amber-500" />
|
||||
<h3 class="font-bold text-gray-800 dark:text-white">آخرین سفارشات</h3>
|
||||
</div>
|
||||
<a href="{{ route('filament.admin.resources.shipments.index') }}"
|
||||
class="text-xs text-amber-600 hover:text-amber-700 font-semibold">
|
||||
مشاهده همه ←
|
||||
</a>
|
||||
<div class="space-y-2">
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="text-xs text-gray-500 dark:text-gray-400 w-16">📅 شمسی:</span>
|
||||
<span class="font-bold text-amber-700 dark:text-amber-400">{{ $jalaliDate }}</span>
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="text-xs text-gray-500 dark:text-gray-400 w-16">🌍 میلادی:</span>
|
||||
<span class="text-sm text-gray-700 dark:text-gray-300 capitalize">{{ $gregorianDate }}</span>
|
||||
</div>
|
||||
|
||||
@if($recentShipments->isEmpty())
|
||||
<div class="p-8 text-center text-gray-500 dark:text-gray-400">
|
||||
<x-heroicon-o-inbox class="w-12 h-12 mx-auto mb-2 text-gray-300" />
|
||||
<p>هنوز سفارشی ثبت نشده است</p>
|
||||
</div>
|
||||
@else
|
||||
<div class="overflow-x-auto">
|
||||
<table class="w-full text-sm">
|
||||
<thead class="bg-gray-50 dark:bg-gray-900 text-gray-600 dark:text-gray-400">
|
||||
<tr>
|
||||
<th class="text-right px-4 py-2 font-medium">AWB</th>
|
||||
<th class="text-right px-4 py-2 font-medium">مسیر</th>
|
||||
<th class="text-right px-4 py-2 font-medium">وضعیت</th>
|
||||
<th class="text-right px-4 py-2 font-medium">تاریخ</th>
|
||||
<th class="text-right px-4 py-2 font-medium">مبلغ</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-gray-100 dark:divide-gray-700">
|
||||
@foreach($recentShipments as $shipment)
|
||||
<tr class="hover:bg-gray-50 dark:hover:bg-gray-900/50">
|
||||
<td class="px-4 py-3 font-mono text-xs font-semibold text-gray-800 dark:text-white">
|
||||
{{ $shipment['awb'] }}
|
||||
</td>
|
||||
<td class="px-4 py-3 text-gray-700 dark:text-gray-300">
|
||||
{{ $shipment['route'] }}
|
||||
</td>
|
||||
<td class="px-4 py-3">
|
||||
<span class="inline-block px-2 py-1 rounded-full text-xs font-semibold {{ $shipment['status_color'] }}">
|
||||
{{ $shipment['status_label'] }}
|
||||
</span>
|
||||
</td>
|
||||
<td class="px-4 py-3 text-xs text-gray-500 dark:text-gray-400">
|
||||
{{ $shipment['date'] }}
|
||||
</td>
|
||||
<td class="px-4 py-3 text-xs font-semibold text-gray-700 dark:text-gray-300">
|
||||
{{ $shipment['amount'] }}
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
|
||||
<div class="mt-4 pt-4 border-t border-amber-200 dark:border-gray-700">
|
||||
<div class="text-xs text-gray-500 dark:text-gray-400">خوش آمدید</div>
|
||||
<div class="font-bold text-gray-800 dark:text-white">{{ $userName }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</x-filament-widgets::widget>
|
||||
</x-filament-widgets::widget>
|
||||
|
||||
@ -0,0 +1,58 @@
|
||||
<x-filament-widgets::widget>
|
||||
<div class="bg-white dark:bg-gray-800 rounded-xl border border-gray-200 dark:border-gray-700 overflow-hidden">
|
||||
<div class="px-6 py-4 border-b border-gray-200 dark:border-gray-700 flex items-center justify-between">
|
||||
<div class="flex items-center gap-2">
|
||||
<x-heroicon-o-truck class="w-5 h-5 text-amber-500" />
|
||||
<h3 class="font-bold text-gray-800 dark:text-white">آخرین سفارشات</h3>
|
||||
</div>
|
||||
<a href="{{ route('filament.admin.resources.shipments.index') }}"
|
||||
class="text-xs text-amber-600 hover:text-amber-700 font-semibold">
|
||||
مشاهده همه ←
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@if($recentShipments->isEmpty())
|
||||
<div class="p-8 text-center text-gray-500 dark:text-gray-400">
|
||||
<x-heroicon-o-inbox class="w-12 h-12 mx-auto mb-2 text-gray-300" />
|
||||
<p>هنوز سفارشی ثبت نشده است</p>
|
||||
</div>
|
||||
@else
|
||||
<div class="overflow-x-auto">
|
||||
<table class="w-full text-sm">
|
||||
<thead class="bg-gray-50 dark:bg-gray-900 text-gray-600 dark:text-gray-400">
|
||||
<tr>
|
||||
<th class="text-right px-4 py-2 font-medium">AWB</th>
|
||||
<th class="text-right px-4 py-2 font-medium">مسیر</th>
|
||||
<th class="text-right px-4 py-2 font-medium">وضعیت</th>
|
||||
<th class="text-right px-4 py-2 font-medium">تاریخ</th>
|
||||
<th class="text-right px-4 py-2 font-medium">مبلغ</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-gray-100 dark:divide-gray-700">
|
||||
@foreach($recentShipments as $shipment)
|
||||
<tr class="hover:bg-gray-50 dark:hover:bg-gray-900/50">
|
||||
<td class="px-4 py-3 font-mono text-xs font-semibold text-gray-800 dark:text-white">
|
||||
{{ $shipment['awb'] }}
|
||||
</td>
|
||||
<td class="px-4 py-3 text-gray-700 dark:text-gray-300">
|
||||
{{ $shipment['route'] }}
|
||||
</td>
|
||||
<td class="px-4 py-3">
|
||||
<span class="inline-block px-2 py-1 rounded-full text-xs font-semibold {{ $shipment['status_color'] }}">
|
||||
{{ $shipment['status_label'] }}
|
||||
</span>
|
||||
</td>
|
||||
<td class="px-4 py-3 text-xs text-gray-500 dark:text-gray-400">
|
||||
{{ $shipment['date'] }}
|
||||
</td>
|
||||
<td class="px-4 py-3 text-xs font-semibold text-gray-700 dark:text-gray-300">
|
||||
{{ $shipment['amount'] }}
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</x-filament-widgets::widget>
|
||||
Loading…
Reference in New Issue
Block a user