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.
318 lines
10 KiB
PHP
318 lines
10 KiB
PHP
<!-- فونت وزیرمتن برای فارسی -->
|
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
<link href="https://fonts.googleapis.com/css2?family=Vazirmatn:wght@300;400;500;600;700;800;900&display=swap" rel="stylesheet">
|
|
|
|
<style>
|
|
/* ─── تنظیمات پایه RTL ─── */
|
|
html {
|
|
direction: rtl;
|
|
font-family: 'Vazirmatn', 'IranYekan', Tahoma, sans-serif !important;
|
|
}
|
|
|
|
body {
|
|
font-family: 'Vazirmatn', 'IranYekan', Tahoma, sans-serif !important;
|
|
}
|
|
|
|
/* ─── Sidebar استایل سفارشی ─── */
|
|
.fi-sidebar {
|
|
background: linear-gradient(180deg, #1a1a2e 0%, #16213e 100%) !important;
|
|
}
|
|
|
|
.fi-sidebar-item a {
|
|
transition: all 0.25s cubic-bezier(.4,0,.2,1);
|
|
}
|
|
|
|
.fi-sidebar-item-active > a {
|
|
background: rgba(245, 158, 11, 0.15) !important;
|
|
border-right: 3px solid #f59e0b !important;
|
|
}
|
|
|
|
.fi-sidebar-item-active > a .fi-sidebar-item-label {
|
|
color: #f59e0b !important;
|
|
font-weight: 700;
|
|
}
|
|
|
|
.fi-sidebar-item-active > a .fi-icon {
|
|
color: #f59e0b !important;
|
|
}
|
|
|
|
/* ─── دکمهها ─── */
|
|
.fi-btn.fi-btn-color-primary {
|
|
box-shadow: 0 8px 20px rgba(245, 158, 11, 0.35);
|
|
}
|
|
|
|
/* ─── کارتهای Stat ─── */
|
|
.fi-wi-stats-overview-stat {
|
|
border-radius: 16px !important;
|
|
border: 1px solid #e5e7eb;
|
|
}
|
|
|
|
/* ─── Logo استایل ─── */
|
|
.fi-brand {
|
|
font-family: 'Vazirmatn', sans-serif;
|
|
font-weight: 900;
|
|
letter-spacing: -0.5px;
|
|
}
|
|
|
|
.fi-brand-name {
|
|
font-family: 'Vazirmatn', sans-serif !important;
|
|
font-weight: 900 !important;
|
|
}
|
|
|
|
/* ─── اعداد فارسی ─── */
|
|
.fi-wi-stats-overview-stat-value,
|
|
.fi-tables-column-type-numeric {
|
|
font-family: 'Vazirmatn', sans-serif !important;
|
|
}
|
|
|
|
/* ─── Dark Mode بهبودها ─── */
|
|
.dark .fi-sidebar {
|
|
background: linear-gradient(180deg, #0f172a 0%, #1a1a2e 100%) !important;
|
|
}
|
|
|
|
.dark .fi-sidebar-item-active > a {
|
|
background: rgba(245, 158, 11, 0.2) !important;
|
|
}
|
|
|
|
/* ─── Notifications badge ─── */
|
|
.fi-badge {
|
|
font-family: 'Vazirmatn', sans-serif !important;
|
|
}
|
|
|
|
/* ─── Tables RTL fix ─── */
|
|
.fi-ta-ctn {
|
|
direction: rtl;
|
|
}
|
|
|
|
.fi-ta-header-heading {
|
|
font-family: 'Vazirmatn', sans-serif;
|
|
font-weight: 700;
|
|
}
|
|
|
|
/* ─── Forms RTL ─── */
|
|
.fi-input-wrp {
|
|
direction: rtl;
|
|
}
|
|
|
|
.fi-input-wrp-input {
|
|
text-align: right;
|
|
}
|
|
|
|
/* ─── Login Page بهبود ─── */
|
|
.fi-auth-layout {
|
|
background: linear-gradient(135deg, #1a0a00 0%, #3d1a00 30%, #7c3100 60%, #d97706 85%, #f59e0b 100%);
|
|
}
|
|
|
|
.fi-auth-card {
|
|
backdrop-filter: blur(20px);
|
|
background: rgba(255, 255, 255, 0.97) !important;
|
|
border-radius: 20px !important;
|
|
box-shadow: 0 25px 80px rgba(0, 0, 0, 0.25) !important;
|
|
}
|
|
|
|
.fi-login-heading {
|
|
font-family: 'Vazirmatn', sans-serif;
|
|
font-weight: 800;
|
|
color: #111827;
|
|
}
|
|
|
|
/* ─── Scrollbar سفارشی ─── */
|
|
::-webkit-scrollbar {
|
|
width: 8px;
|
|
height: 8px;
|
|
}
|
|
|
|
::-webkit-scrollbar-track {
|
|
background: #f1f5f9;
|
|
}
|
|
|
|
::-webkit-scrollbar-thumb {
|
|
background: #f59e0b;
|
|
border-radius: 4px;
|
|
}
|
|
|
|
::-webkit-scrollbar-thumb:hover {
|
|
background: #d97706;
|
|
}
|
|
|
|
/* ─── Page transitions ─── */
|
|
.fi-section {
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
/* ─── Fix برای اعداد فارسی ─── */
|
|
.fi-wi-stats-overview-stat-description,
|
|
.fi-wi-stats-overview-stat-label {
|
|
font-family: 'Vazirmatn', sans-serif;
|
|
}
|
|
|
|
/* ─── Stats card hover ─── */
|
|
.fi-wi-stats-overview-stat:hover {
|
|
transform: translateY(-4px);
|
|
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
/* ─── Badge colors ─── */
|
|
.fi-badge.fi-badge-color-success {
|
|
background: #d1fae5 !important;
|
|
color: #065f46 !important;
|
|
}
|
|
|
|
.fi-badge.fi-badge-color-danger {
|
|
background: #fee2e2 !important;
|
|
color: #991b1b !important;
|
|
}
|
|
|
|
.fi-badge.fi-badge-color-warning {
|
|
background: #fef3c7 !important;
|
|
color: #92400e !important;
|
|
}
|
|
|
|
/* ─── فشردهسازی جداول فیلمنت (فونت کوچکتر + padding کمتر) ─── */
|
|
.fi-ta-text,
|
|
.fi-ta-text-content {
|
|
font-size: 0.8125rem !important; /* 13px بهجای 14px پیشفرض */
|
|
line-height: 1.4 !important;
|
|
}
|
|
.fi-ta-header-heading {
|
|
font-size: 0.75rem !important; /* سرست 12px */
|
|
font-weight: 600 !important;
|
|
}
|
|
.fi-ta-cell,
|
|
.fi-ta-header-cell {
|
|
padding: 0.5rem 0.625rem !important; /* فشردهتر */
|
|
}
|
|
.fi-ta-text-wrap {
|
|
gap: 0.125rem !important;
|
|
}
|
|
|
|
/* ─── عناوین گروههای سایدبار: سفید روی پسزمینه تیره ─── */
|
|
.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> |