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.
498 lines
16 KiB
PHP
498 lines
16 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: #f8fafc !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;
|
||
}
|
||
|
||
/* ─── زیرمنوها: متن سفید پیشفرض، سفیدِ کامل در هاور، کهربایی برای آیتم فعال ─── */
|
||
.fi-sidebar-item a .fi-sidebar-item-label {
|
||
color: #e2e8f0 !important;
|
||
}
|
||
|
||
.fi-sidebar-item a .fi-icon {
|
||
color: #cbd5e1 !important;
|
||
}
|
||
|
||
/* هاور زیرمنو: پسزمینه روشن میشود → متن تیره برای خوانایی */
|
||
.fi-sidebar-item a:hover .fi-sidebar-item-label {
|
||
color: #1e293b !important;
|
||
}
|
||
|
||
.fi-sidebar-item a:hover .fi-icon {
|
||
color: #1e293b !important;
|
||
}
|
||
|
||
/* در دارکمود پسزمینه هاور تیره میماند → متن سفید */
|
||
.dark .fi-sidebar-item a:hover .fi-sidebar-item-label,
|
||
.dark .fi-sidebar-item a:hover .fi-icon {
|
||
color: #ffffff !important;
|
||
}
|
||
|
||
/* آیتم فعال همان کهربایی برند میماند (بعد از قواعد سفید تا اولویت بگیرد) */
|
||
.fi-sidebar-item-active > a .fi-sidebar-item-label {
|
||
color: #f59e0b !important;
|
||
}
|
||
|
||
.fi-sidebar-item-active > a .fi-icon {
|
||
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: #f1f5f9;
|
||
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;
|
||
}
|
||
|
||
/* ─── IFNEX Dashboard redesign — card / badge / trend design tokens ─── */
|
||
|
||
/* Base card: rounded-2xl, soft multi-layer shadow, 1px gray-200 border */
|
||
.ifnex-card-shadow,
|
||
.ifnex-card {
|
||
box-shadow:
|
||
0 1px 3px rgba(0, 0, 0, 0.08),
|
||
0 1px 2px rgba(0, 0, 0, 0.04) !important;
|
||
}
|
||
|
||
/* Stat card base — used by StatsOverviewWidget cards */
|
||
.fi-wi-stats-overview-stat.ifnex-stat-card {
|
||
border-radius: 16px !important;
|
||
border: 1px solid #e5e7eb !important;
|
||
padding: 1.25rem !important;
|
||
background: #FAF9F6 !important;
|
||
}
|
||
|
||
.dark .fi-wi-stats-overview-stat.ifnex-stat-card {
|
||
background: rgb(30 41 59) !important;
|
||
border-color: rgb(51 65 85) !important;
|
||
}
|
||
|
||
.ifnex-stat-card {
|
||
border-radius: 16px !important;
|
||
border: 1px solid #e5e7eb !important;
|
||
padding: 1.25rem !important;
|
||
background: #FAF9F6 !important;
|
||
box-shadow:
|
||
0 1px 3px rgba(0, 0, 0, 0.08),
|
||
0 1px 2px rgba(0, 0, 0, 0.04) !important;
|
||
transition: transform 0.25s ease, box-shadow 0.25s ease !important;
|
||
}
|
||
|
||
.ifnex-stat-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) !important;
|
||
}
|
||
|
||
/* Stat icon — colored soft circle (40×40), centered heroicon */
|
||
.ifnex-stat-icon {
|
||
width: 40px;
|
||
height: 40px;
|
||
border-radius: 12px;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
flex-shrink: 0;
|
||
}
|
||
.ifnex-stat-icon-amber { background: #fef3c7; color: #d97706; }
|
||
.ifnex-stat-icon-green { background: #d1fae5; color: #059669; }
|
||
.ifnex-stat-icon-red { background: #fee2e2; color: #dc2626; }
|
||
.ifnex-stat-icon-blue { background: #dbeafe; color: #2563eb; }
|
||
.ifnex-stat-icon-gray { background: #f1f5f9; color: #475569; }
|
||
|
||
.dark .ifnex-stat-icon-amber { background: rgba(245,158,11,.18); color: #fbbf24; }
|
||
.dark .ifnex-stat-icon-green { background: rgba(16,185,129,.18); color: #34d399; }
|
||
.dark .ifnex-stat-icon-red { background: rgba(239,68,68,.18); color: #f87171; }
|
||
.dark .ifnex-stat-icon-blue { background: rgba(59,130,246,.18); color: #60a5fa; }
|
||
.dark .ifnex-stat-icon-gray { background: rgba(148,163,184,.18); color: #cbd5e1; }
|
||
|
||
/* Big number typography */
|
||
.ifnex-stat-number {
|
||
font-family: 'Vazirmatn', sans-serif !important;
|
||
font-size: 28px;
|
||
line-height: 1.2;
|
||
font-weight: 800;
|
||
color: #111827;
|
||
letter-spacing: -0.5px;
|
||
}
|
||
.dark .ifnex-stat-number { color: #f9fafb; }
|
||
|
||
/* Stat label */
|
||
.ifnex-stat-label {
|
||
font-family: 'Vazirmatn', sans-serif !important;
|
||
font-size: 12px;
|
||
font-weight: 500;
|
||
color: #6b7280;
|
||
}
|
||
.dark .ifnex-stat-label { color: #9ca3af; }
|
||
|
||
/* Trend indicators */
|
||
.ifnex-stat-trend-up {
|
||
color: #10b981;
|
||
font-weight: 600;
|
||
font-size: 12px;
|
||
}
|
||
.ifnex-stat-trend-down {
|
||
color: #ef4444;
|
||
font-weight: 600;
|
||
font-size: 12px;
|
||
}
|
||
.ifnex-stat-trend-flat {
|
||
color: #9ca3af;
|
||
font-weight: 600;
|
||
font-size: 12px;
|
||
}
|
||
|
||
/* ─── Brand status 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 row hover (Layer 3 tables) ─── */
|
||
.ifnex-table-row-hover:hover {
|
||
background-color: #fffbeb !important;
|
||
}
|
||
.dark .ifnex-table-row-hover:hover {
|
||
background-color: rgba(245, 158, 11, 0.08) !important;
|
||
}
|
||
|
||
/* Compact table cells + headers used by ifnex widgets */
|
||
.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;
|
||
}
|
||
|
||
/* Inline link (e.g. "مشاهده همه ←") */
|
||
.ifnex-link-inline {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 2px;
|
||
}
|
||
|
||
/* ─── Stat card icon color tinting for IFNEX KPIs ─── */
|
||
.fi-wi-stats-overview-stat .fi-icon,
|
||
.fi-stat-icon {
|
||
border-radius: 12px !important;
|
||
}
|
||
</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');
|
||
}
|
||
}
|
||
|
||
// ⚠️ کلیک روی عنوان گروه را خود فیلامنت بهصورت بومی هندل میکند
|
||
// (x-on:click روی .fi-sidebar-group-button در vendor) — هندلر اضافه اینجا
|
||
// باعث toggle دوباره و در نتیجه «هیچ اتفاقی نمیافتد» میشد؛ حذف شد.
|
||
|
||
// دکمه «بستن/باز کردن همه» بالای سایدبار
|
||
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> |