Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
Clubphp
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Administrator
Clubphp
Commits
59e1896c
Commit
59e1896c
authored
Apr 08, 2026
by
Administrator
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Update 4 files via Son of Anton
parent
54a87b2e
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
567 additions
and
635 deletions
+567
-635
sidebar.php
app/Shared/Components/sidebar.php
+58
-168
auth.php
app/Shared/Layout/auth.php
+28
-60
main.php
app/Shared/Layout/main.php
+98
-67
main.css
public/assets/css/main.css
+383
-340
No files found.
app/Shared/Components/sidebar.php
View file @
59e1896c
<?php
<?php
/**
* Sidebar component — reads menu items from MenuRegistry.
*/
use
App\Core\App
;
use
App\Core\Registries\MenuRegistry
;
$currentPath
=
parse_url
(
$_SERVER
[
'REQUEST_URI'
]
??
'/'
,
PHP_URL_PATH
);
$currentPath
=
parse_url
(
$_SERVER
[
'REQUEST_URI'
]
??
'/'
,
PHP_URL_PATH
);
$employee
=
App
::
getInstance
()
->
currentEmployee
();
$currentPath
=
rtrim
(
$currentPath
,
'/'
)
?:
'/'
;
// Icon name → emoji mapping
$iconMap
=
[
'dashboard'
=>
'📊'
,
'tachometer-alt'
=>
'📊'
,
'home'
=>
'🏠'
,
'users'
=>
'👥'
,
'user'
=>
'👤'
,
'user-plus'
=>
'👤'
,
'user-clock'
=>
'⏰'
,
'user-tie'
=>
'👔'
,
'user-shield'
=>
'🛡️'
,
'user-friends'
=>
'👥'
,
'clipboard'
=>
'📋'
,
'clipboard-list'
=>
'📋'
,
'file-alt'
=>
'📄'
,
'calendar'
=>
'📅'
,
'calendar-alt'
=>
'📅'
,
'calendar-check'
=>
'✅'
,
'money-bill'
=>
'💰'
,
'wallet'
=>
'💳'
,
'cash-register'
=>
'💰'
,
'credit-card'
=>
'💳'
,
'receipt'
=>
'🧾'
,
'coins'
=>
'🪙'
,
'file-invoice-dollar'
=>
'💲'
,
'hand-holding-usd'
=>
'💰'
,
'exchange-alt'
=>
'🔀'
,
'random'
=>
'🔀'
,
'transfer'
=>
'🔀'
,
'gavel'
=>
'⚖️'
,
'balance-scale'
=>
'⚖️'
,
'exclamation-triangle'
=>
'⚠️'
,
'alert'
=>
'⚠️'
,
'warning'
=>
'⚠️'
,
'ban'
=>
'🚫'
,
'trophy'
=>
'🏆'
,
'medal'
=>
'🏅'
,
'award'
=>
'🎖️'
,
'star'
=>
'⭐'
,
'globe'
=>
'🌍'
,
'globe-americas'
=>
'🌎'
,
'flag'
=>
'🏳️'
,
'id-card'
=>
'🪪'
,
'address-card'
=>
'🪪'
,
'qrcode'
=>
'📱'
,
'file'
=>
'📁'
,
'folder'
=>
'📁'
,
'folder-open'
=>
'📂'
,
'sms'
=>
'📱'
,
'envelope'
=>
'✉️'
,
'bell'
=>
'🔔'
,
'comment'
=>
'💬'
,
'chart-bar'
=>
'📈'
,
'chart-line'
=>
'📈'
,
'chart-pie'
=>
'📊'
,
'cog'
=>
'⚙️'
,
'cogs'
=>
'⚙️'
,
'wrench'
=>
'🔧'
,
'tools'
=>
'🛠️'
,
'sliders-h'
=>
'⚙️'
,
'settings'
=>
'⚙️'
,
'shield-alt'
=>
'🔐'
,
'lock'
=>
'🔒'
,
'key'
=>
'🔑'
,
'building'
=>
'🏢'
,
'city'
=>
'🏙️'
,
'store'
=>
'🏪'
,
'book'
=>
'📖'
,
'history'
=>
'📜'
,
'archive'
=>
'🗄️'
,
'sitemap'
=>
'🔄'
,
'project-diagram'
=>
'🔄'
,
'workflow'
=>
'🔄'
,
'heart'
=>
'❤️'
,
'heartbeat'
=>
'💓'
,
'cross'
=>
'✝️'
,
'ring'
=>
'💍'
,
'baby'
=>
'👶'
,
'child'
=>
'👦'
,
'children'
=>
'👨👩👧👦'
,
'repeat'
=>
'🔄'
,
'sync'
=>
'🔄'
,
'redo'
=>
'🔄'
,
'print'
=>
'🖨️'
,
'search'
=>
'🔍'
,
'plus'
=>
'➕'
,
'edit'
=>
'✏️'
,
'trash'
=>
'🗑️'
,
'times'
=>
'❌'
,
'check'
=>
'✅'
,
'dollar-sign'
=>
'💲'
,
'percentage'
=>
'💹'
,
'swimming-pool'
=>
'🏊'
,
'running'
=>
'🏃'
,
'futbol'
=>
'⚽'
,
'sun'
=>
'☀️'
,
'umbrella-beach'
=>
'🏖️'
,
];
$getIcon
=
function
(
?
string
$icon
)
use
(
$iconMap
)
:
string
{
if
(
$icon
===
null
||
$icon
===
''
)
return
'📌'
;
// Already an emoji
if
(
mb_strlen
(
$icon
)
<=
2
&&
!
ctype_alpha
(
$icon
))
return
$icon
;
// Check map
return
$iconMap
[
$icon
]
??
$iconMap
[
strtolower
(
$icon
)]
??
'📌'
;
};
// Get all permissions for current employee
$employeePermissions
=
[];
if
(
$employee
&&
method_exists
(
$employee
,
'getAllPermissions'
))
{
$employeePermissions
=
$employee
->
getAllPermissions
();
}
elseif
(
$employee
)
{
try
{
$db
=
App
::
getInstance
()
->
db
();
$empId
=
$employee
->
id
??
0
;
$perms
=
$db
->
select
(
"SELECT DISTINCT rp.permission_key
FROM employee_roles er
JOIN role_permissions rp ON rp.role_id = er.role_id
WHERE er.employee_id = ? AND er.is_active = 1"
,
[(
int
)
$empId
]
);
$employeePermissions
=
array_column
(
$perms
,
'permission_key'
);
$isSuperAdmin
=
$db
->
selectOne
(
function
sidebarActive
(
string
$path
,
string
$current
)
:
string
{
"SELECT 1 FROM employee_roles er
if
(
$path
===
'/'
&&
$current
===
'/'
)
return
'active'
;
JOIN roles r ON r.id = er.role_id
if
(
$path
!==
'/'
&&
str_starts_with
(
$current
,
$path
))
return
'active'
;
WHERE er.employee_id = ? AND r.role_code = 'super_admin' AND er.is_active = 1
return
''
;
LIMIT 1"
,
[(
int
)
$empId
]
);
if
(
$isSuperAdmin
)
{
$employeePermissions
=
[
'*'
];
}
}
catch
(
\Throwable
$e
)
{
$employeePermissions
=
[];
}
}
$hasPerm
=
function
(
string
$perm
)
use
(
$employeePermissions
)
:
bool
{
if
(
empty
(
$perm
))
return
true
;
if
(
in_array
(
'*'
,
$employeePermissions
))
return
true
;
return
in_array
(
$perm
,
$employeePermissions
);
};
$isActive
=
function
(
string
$route
)
use
(
$currentPath
)
:
bool
{
if
(
$route
===
'/'
)
return
$currentPath
===
'/'
;
return
str_starts_with
(
$currentPath
,
$route
);
};
// Get menu items from registry
$menuItems
=
MenuRegistry
::
getAll
();
usort
(
$menuItems
,
fn
(
$a
,
$b
)
=>
(
$a
[
'order'
]
??
999
)
<=>
(
$b
[
'order'
]
??
999
));
// Fallback if registry empty
if
(
empty
(
$menuItems
))
{
$menuItems
=
[
[
'key'
=>
'dashboard'
,
'label_ar'
=>
'لوحة التحكم'
,
'icon'
=>
'📊'
,
'route'
=>
'/dashboard'
,
'permission'
=>
''
,
'order'
=>
10
,
'children'
=>
[]],
[
'key'
=>
'members'
,
'label_ar'
=>
'إدارة الأعضاء'
,
'icon'
=>
'👥'
,
'route'
=>
'/members'
,
'permission'
=>
'member.view'
,
'order'
=>
100
,
'children'
=>
[
[
'label_ar'
=>
'كل الأعضاء'
,
'route'
=>
'/members'
,
'permission'
=>
'member.view'
],
[
'label_ar'
=>
'عضو جديد'
,
'route'
=>
'/members/create'
,
'permission'
=>
'member.create'
],
]],
[
'key'
=>
'users'
,
'label_ar'
=>
'الموظفون'
,
'icon'
=>
'👤'
,
'route'
=>
'/users'
,
'permission'
=>
'user.view'
,
'order'
=>
910
,
'children'
=>
[]],
[
'key'
=>
'roles'
,
'label_ar'
=>
'الأدوار'
,
'icon'
=>
'🔐'
,
'route'
=>
'/roles'
,
'permission'
=>
'role.view'
,
'order'
=>
920
,
'children'
=>
[]],
[
'key'
=>
'branches'
,
'label_ar'
=>
'الفروع'
,
'icon'
=>
'🏢'
,
'route'
=>
'/branches'
,
'permission'
=>
'branch.view'
,
'order'
=>
930
,
'children'
=>
[]],
[
'key'
=>
'settings'
,
'label_ar'
=>
'الإعدادات'
,
'icon'
=>
'⚙️'
,
'route'
=>
'/settings'
,
'permission'
=>
'settings.view'
,
'order'
=>
960
,
'children'
=>
[]],
];
}
}
?>
?>
<aside
class=
"sidebar"
id=
"mainSidebar"
>
<div
class=
"sidebar-header"
>
<div
class=
"sidebar-logo"
>
<div
class=
"sidebar-brand"
>
THE CLUB
</div>
<h1>
🏛️ THE CLUB
</h1>
</div>
<div
class=
"subtitle"
>
نادي النادي شيراتون — Sports City
</div>
</div>
<nav
class=
"sidebar-nav"
>
<ul
class=
"sidebar-menu"
>
<nav
class=
"sidebar-nav"
>
<?php
foreach
(
$menuItems
as
$item
)
:
?>
<div
class=
"sidebar-section"
>
الرئيسية
</div>
<?php
<a
href=
"/dashboard"
class=
"sidebar-link
<?=
sidebarActive
(
'/dashboard'
,
$currentPath
)
?>
"
><span
class=
"icon"
>
📊
</span>
لوحة التحكم
</a>
if
(
!
empty
(
$item
[
'permission'
])
&&
!
$hasPerm
(
$item
[
'permission'
]))
continue
;
<div
class=
"sidebar-section"
>
الأعضاء
</div>
if
(
!
empty
(
$item
[
'is_separator'
]))
{
<a
href=
"/members"
class=
"sidebar-link
<?=
sidebarActive
(
'/members'
,
$currentPath
)
?>
"
><span
class=
"icon"
>
👥
</span>
إدارة الأعضاء
</a>
echo
'<li style="padding:15px 20px 5px;font-size:11px;color:#6B7280;text-transform:uppercase;letter-spacing:1px;">'
.
e
(
$item
[
'label_ar'
])
.
'</li>'
;
<a
href=
"/members/search"
class=
"sidebar-link
<?=
sidebarActive
(
'/members/search'
,
$currentPath
)
?>
"
><span
class=
"icon"
>
🔍
</span>
بحث الأعضاء
</a>
continue
;
<a
href=
"/interviews"
class=
"sidebar-link
<?=
sidebarActive
(
'/interviews'
,
$currentPath
)
?>
"
><span
class=
"icon"
>
🗓️
</span>
المقابلات
</a>
}
<a
href=
"/carnets"
class=
"sidebar-link
<?=
sidebarActive
(
'/carnets'
,
$currentPath
)
?>
"
><span
class=
"icon"
>
🪪
</span>
الكارنيهات
</a>
$children
=
$item
[
'children'
]
??
[];
<div
class=
"sidebar-section"
>
مالية
</div>
$visibleChildren
=
[];
<a
href=
"/payments"
class=
"sidebar-link
<?=
sidebarActive
(
'/payments'
,
$currentPath
)
?>
"
><span
class=
"icon"
>
💰
</span>
المدفوعات
</a>
foreach
(
$children
as
$child
)
{
<a
href=
"/receipts"
class=
"sidebar-link
<?=
sidebarActive
(
'/receipts'
,
$currentPath
)
?>
"
><span
class=
"icon"
>
🧾
</span>
الإيصالات
</a>
if
(
empty
(
$child
[
'permission'
])
||
$hasPerm
(
$child
[
'permission'
]))
{
<a
href=
"/installments"
class=
"sidebar-link
<?=
sidebarActive
(
'/installments'
,
$currentPath
)
?>
"
><span
class=
"icon"
>
📅
</span>
الأقساط
</a>
$visibleChildren
[]
=
$child
;
<a
href=
"/subscriptions"
class=
"sidebar-link
<?=
sidebarActive
(
'/subscriptions'
,
$currentPath
)
?>
"
><span
class=
"icon"
>
📋
</span>
الاشتراكات
</a>
}
}
<div
class=
"sidebar-section"
>
المخالفات
</div>
<a
href=
"/violations"
class=
"sidebar-link
<?=
sidebarActive
(
'/violations'
,
$currentPath
)
?>
"
><span
class=
"icon"
>
⚠️
</span>
المخالفات
</a>
$hasChildren
=
!
empty
(
$visibleChildren
);
<a
href=
"/fines"
class=
"sidebar-link
<?=
sidebarActive
(
'/fines'
,
$currentPath
)
?>
"
><span
class=
"icon"
>
💸
</span>
الغرامات
</a>
$itemRoute
=
$item
[
'route'
]
??
'#'
;
$itemActive
=
$isActive
(
$itemRoute
);
<div
class=
"sidebar-section"
>
عمليات
</div>
<a
href=
"/transfers"
class=
"sidebar-link
<?=
sidebarActive
(
'/transfers'
,
$currentPath
)
?>
"
><span
class=
"icon"
>
🔄
</span>
التحويلات
</a>
$childActive
=
false
;
<a
href=
"/divorce"
class=
"sidebar-link
<?=
sidebarActive
(
'/divorce'
,
$currentPath
)
?>
"
><span
class=
"icon"
>
💔
</span>
الطلاق
</a>
foreach
(
$visibleChildren
as
$child
)
{
<a
href=
"/death"
class=
"sidebar-link
<?=
sidebarActive
(
'/death'
,
$currentPath
)
?>
"
><span
class=
"icon"
>
🕊️
</span>
الوفاة
</a>
if
(
$isActive
(
$child
[
'route'
]
??
''
))
{
$childActive
=
true
;
break
;
}
<a
href=
"/waiver"
class=
"sidebar-link
<?=
sidebarActive
(
'/waiver'
,
$currentPath
)
?>
"
><span
class=
"icon"
>
📝
</span>
التنازل
</a>
}
<div
class=
"sidebar-section"
>
أنواع العضوية
</div>
$isOpen
=
$itemActive
||
$childActive
;
<a
href=
"/temporary"
class=
"sidebar-link
<?=
sidebarActive
(
'/temporary'
,
$currentPath
)
?>
"
><span
class=
"icon"
>
⏱️
</span>
المؤقتون
</a>
$icon
=
$getIcon
(
$item
[
'icon'
]
??
''
);
<a
href=
"/seasonal"
class=
"sidebar-link
<?=
sidebarActive
(
'/seasonal'
,
$currentPath
)
?>
"
><span
class=
"icon"
>
🌊
</span>
الموسمية
</a>
?>
<a
href=
"/sports"
class=
"sidebar-link
<?=
sidebarActive
(
'/sports'
,
$currentPath
)
?>
"
><span
class=
"icon"
>
🏅
</span>
الرياضية
</a>
<li
class=
"sidebar-item
<?=
$isOpen
&&
$hasChildren
?
' open'
:
''
?>
"
>
<a
href=
"/honorary"
class=
"sidebar-link
<?=
sidebarActive
(
'/honorary'
,
$currentPath
)
?>
"
><span
class=
"icon"
>
🎖️
</span>
الشرفية
</a>
<?php
if
(
$hasChildren
)
:
?>
<a
href=
"/foreign"
class=
"sidebar-link
<?=
sidebarActive
(
'/foreign'
,
$currentPath
)
?>
"
><span
class=
"icon"
>
🌍
</span>
الأجانب
</a>
<a
href=
"javascript:void(0)"
class=
"sidebar-link
<?=
$itemActive
?
' active'
:
''
?>
"
onclick=
"toggleSubmenu(this)"
>
<span
class=
"sidebar-icon"
>
<?=
$icon
?>
</span>
<div
class=
"sidebar-section"
>
نماذج و مستندات
</div>
<span
class=
"sidebar-text"
>
<?=
e
(
$item
[
'label_ar'
])
?>
</span>
<a
href=
"/forms/submissions"
class=
"sidebar-link
<?=
sidebarActive
(
'/forms'
,
$currentPath
)
?>
"
><span
class=
"icon"
>
📄
</span>
النماذج
</a>
<span
class=
"sidebar-arrow"
>
◀
</span>
<a
href=
"/documents"
class=
"sidebar-link
<?=
sidebarActive
(
'/documents'
,
$currentPath
)
?>
"
><span
class=
"icon"
>
📁
</span>
المستندات
</a>
</a>
<ul
class=
"sidebar-submenu"
style=
"display:
<?=
$isOpen
?
'block'
:
'none'
?>
;"
>
<div
class=
"sidebar-section"
>
تقارير و إشعارات
</div>
<?php
foreach
(
$visibleChildren
as
$child
)
:
?>
<a
href=
"/reports"
class=
"sidebar-link
<?=
sidebarActive
(
'/reports'
,
$currentPath
)
?>
"
><span
class=
"icon"
>
📈
</span>
التقارير
</a>
<?php
$childRoute
=
$child
[
'route'
]
??
'#'
;
?>
<a
href=
"/notifications/templates"
class=
"sidebar-link
<?=
sidebarActive
(
'/notifications'
,
$currentPath
)
?>
"
><span
class=
"icon"
>
📱
</span>
الإشعارات
</a>
<li>
<a
href=
"
<?=
e
(
$childRoute
)
?>
"
class=
"sidebar-sublink
<?=
$isActive
(
$childRoute
)
?
' active'
:
''
?>
"
>
<div
class=
"sidebar-section"
>
النظام
</div>
<?=
e
(
$child
[
'label_ar'
])
?>
<a
href=
"/users"
class=
"sidebar-link
<?=
sidebarActive
(
'/users'
,
$currentPath
)
?>
"
><span
class=
"icon"
>
👤
</span>
المستخدمون
</a>
</a>
<a
href=
"/roles"
class=
"sidebar-link
<?=
sidebarActive
(
'/roles'
,
$currentPath
)
?>
"
><span
class=
"icon"
>
🔐
</span>
الصلاحيات
</a>
</li>
<a
href=
"/branches"
class=
"sidebar-link
<?=
sidebarActive
(
'/branches'
,
$currentPath
)
?>
"
><span
class=
"icon"
>
🏢
</span>
الفروع
</a>
<?php
endforeach
;
?>
<a
href=
"/rules"
class=
"sidebar-link
<?=
sidebarActive
(
'/rules'
,
$currentPath
)
?>
"
><span
class=
"icon"
>
⚙️
</span>
القواعد
</a>
</ul>
<a
href=
"/pricing"
class=
"sidebar-link
<?=
sidebarActive
(
'/pricing'
,
$currentPath
)
?>
"
><span
class=
"icon"
>
💲
</span>
التسعير
</a>
<?php
else
:
?>
<a
href=
"/settings"
class=
"sidebar-link
<?=
sidebarActive
(
'/settings'
,
$currentPath
)
?>
"
><span
class=
"icon"
>
🛠️
</span>
الإعدادات
</a>
<a
href=
"
<?=
e
(
$itemRoute
)
?>
"
class=
"sidebar-link
<?=
$itemActive
?
' active'
:
''
?>
"
>
<a
href=
"/workflow"
class=
"sidebar-link
<?=
sidebarActive
(
'/workflow'
,
$currentPath
)
?>
"
><span
class=
"icon"
>
🔀
</span>
سير العمل
</a>
<span
class=
"sidebar-icon"
>
<?=
$icon
?>
</span>
<a
href=
"/audit"
class=
"sidebar-link
<?=
sidebarActive
(
'/audit'
,
$currentPath
)
?>
"
><span
class=
"icon"
>
📜
</span>
سجل المراجعة
</a>
<span
class=
"sidebar-text"
>
<?=
e
(
$item
[
'label_ar'
])
?>
</span>
<a
href=
"/archive"
class=
"sidebar-link
<?=
sidebarActive
(
'/archive'
,
$currentPath
)
?>
"
><span
class=
"icon"
>
🗄️
</span>
الأرشيف
</a>
</a>
</nav>
<?php
endif
;
?>
</aside>
</li>
\ No newline at end of file
<?php
endforeach
;
?>
</ul>
</nav>
\ No newline at end of file
app/Shared/Layout/auth.php
View file @
59e1896c
<?php
use
App\Core\CSRF
;
?>
<!DOCTYPE html>
<!DOCTYPE html>
<html
lang=
"ar"
dir=
"rtl"
>
<html
lang=
"ar"
dir=
"rtl"
>
<head>
<head>
<meta
charset=
"UTF-8"
>
<meta
charset=
"UTF-8"
>
<meta
name=
"viewport"
content=
"width=device-width, initial-scale=1.0"
>
<meta
name=
"viewport"
content=
"width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"
>
<meta
name=
"csrf-token"
content=
"
<?=
e
(
CSRF
::
token
())
?>
"
>
<title>
<?php
$__template
->
yield
(
'title'
,
'تسجيل الدخول'
);
?>
— نادي النادي
</title>
<title>
<?=
$__template
->
yield
(
'title'
,
'تسجيل الدخول'
)
?>
— نادي النادي شيراتون
</title>
<link
rel=
"preconnect"
href=
"https://fonts.googleapis.com"
>
<link
href=
"https://fonts.googleapis.com/css2?family=Cairo:wght@400;500;600;700;800&display=swap"
rel=
"stylesheet"
>
<link
rel=
"stylesheet"
href=
"
<?=
url
(
'assets/css/main.css'
)
?>
"
>
<link
rel=
"stylesheet"
href=
"
<?=
url
(
'assets/css/main.css'
)
?>
"
>
<style>
<style>
body
{
body
{
display
:
flex
;
align-items
:
center
;
justify-content
:
center
;
min-height
:
100vh
;
background
:
linear-gradient
(
135deg
,
#0D7377
0%
,
#1A1A2E
100%
);
padding
:
20px
;
}
display
:
flex
;
.auth-card
{
background
:
#fff
;
border-radius
:
12px
;
padding
:
40px
;
width
:
100%
;
max-width
:
420px
;
box-shadow
:
0
20px
60px
rgba
(
0
,
0
,
0
,
0.3
);
}
justify-content
:
center
;
.auth-logo
{
text-align
:
center
;
margin-bottom
:
30px
;
}
align-items
:
center
;
.auth-logo
h1
{
font-size
:
24px
;
color
:
#0D7377
;
margin
:
0
;
}
min-height
:
100vh
;
.auth-logo
p
{
color
:
#6B7280
;
font-size
:
13px
;
margin-top
:
5px
;
}
margin
:
0
;
@media
(
max-width
:
480px
)
{
background
:
linear-gradient
(
135deg
,
#1A1A2E
0%
,
#0D7377
100%
);
.auth-card
{
padding
:
25px
20px
;
}
font-family
:
'Cairo'
,
'Segoe UI'
,
Tahoma
,
Arial
,
sans-serif
;
.auth-logo
h1
{
font-size
:
20px
;
}
direction
:
rtl
;
}
.auth-card
{
background
:
#fff
;
border-radius
:
12px
;
box-shadow
:
0
20px
60px
rgba
(
0
,
0
,
0
,
0.3
);
padding
:
40px
;
width
:
100%
;
max-width
:
420px
;
}
.auth-header
{
text-align
:
center
;
margin-bottom
:
30px
;
}
.auth-header
h1
{
color
:
#0D7377
;
font-size
:
24px
;
margin
:
0
0
5px
;
}
.auth-header
p
{
color
:
#6B7280
;
font-size
:
14px
;
margin
:
0
;
}
}
</style>
</style>
</head>
</head>
<body>
<body>
<div
class=
"auth-card"
>
<div
class=
"auth-card"
>
<div
class=
"auth-header
"
>
<div
class=
"auth-logo
"
>
<h1>
نادي النادي شيراتون
</h1>
<h1>
🏛️ THE CLUB
</h1>
<p>
THE CLUB Sheraton
</p>
<p>
نادي النادي شيراتون — Sports City
</p>
</div>
</div>
<?php
<?php
$session
=
\App\Core\App
::
getInstance
()
->
session
();
$__session
=
\App\Core\App
::
getInstance
()
->
session
();
$alerts
=
$session
->
getAlerts
();
$__alerts
=
$__session
->
flash
(
'_alerts'
)
??
[];
if
(
!
empty
(
$alerts
))
:
foreach
(
$alerts
as
$alert
)
:
?>
<div
style=
"padding:10px 15px;border-radius:6px;margin-bottom:15px;font-size:13px;
background:
<?=
(
$alert
[
'type'
]
??
''
)
===
'error'
?
'#FEF2F2'
:
'#F0FDF4'
?>
;
color:
<?=
(
$alert
[
'type'
]
??
''
)
===
'error'
?
'#DC2626'
:
'#059669'
?>
;
border:1px solid
<?=
(
$alert
[
'type'
]
??
''
)
===
'error'
?
'#FECACA'
:
'#BBF7D0'
?>
;"
>
<?=
e
(
$alert
[
'message'
]
??
''
)
?>
</div>
<?php
endforeach
;
endif
;
?>
?>
<?php
if
(
!
empty
(
$__alerts
))
:
?>
<?php
foreach
(
$__alerts
as
$__alert
)
:
?>
<div
class=
"alert alert-
<?=
e
(
$__alert
[
'type'
]
??
'info'
)
?>
"
style=
"margin-bottom:15px;"
>
<?=
e
(
$__alert
[
'message'
]
??
''
)
?>
</div>
<?php
endforeach
;
?>
<?php
endif
;
?>
<?=
$__template
->
yield
(
'content'
,
''
)
?>
<?php
$__template
->
yield
(
'content'
);
?>
</div>
</div>
</body>
</body>
</html>
</html>
\ No newline at end of file
app/Shared/Layout/main.php
View file @
59e1896c
<?php
/**
* Main application layout — RTL Arabic-first.
* All authenticated pages use this layout.
*/
use
App\Core\App
;
use
App\Core\CSRF
;
$app
=
App
::
getInstance
();
$employee
=
$app
->
currentEmployee
();
$employeeName
=
$employee
?
(
$employee
->
full_name_ar
??
'مستخدم'
)
:
'زائر'
;
$currentPath
=
parse_url
(
$_SERVER
[
'REQUEST_URI'
]
??
'/'
,
PHP_URL_PATH
);
?>
<!DOCTYPE html>
<!DOCTYPE html>
<html
lang=
"ar"
dir=
"rtl"
>
<html
lang=
"ar"
dir=
"rtl"
>
<head>
<head>
<meta
charset=
"UTF-8"
>
<meta
charset=
"UTF-8"
>
<meta
name=
"viewport"
content=
"width=device-width, initial-scale=1.0"
>
<meta
name=
"viewport"
content=
"width=device-width, initial-scale=1.0
, maximum-scale=1.0, user-scalable=no
"
>
<
meta
name=
"csrf-token"
content=
"
<?=
e
(
CSRF
::
token
())
?>
"
>
<
title>
<?php
$__template
->
yield
(
'title'
,
'النظام'
);
?>
— نادي النادي
</title
>
<
title>
<?=
$__template
->
yield
(
'title'
,
'لوحة التحكم'
)
?>
— نادي النادي شيراتون
</title
>
<
link
rel=
"preconnect"
href=
"https://fonts.googleapis.com"
>
<link
rel=
"stylesheet"
href=
"
<?=
url
(
'assets/css/main.css'
)
?>
"
>
<link
href=
"https://fonts.googleapis.com/css2?family=Cairo:wght@400;500;600;700;800&display=swap"
rel=
"stylesheet
"
>
<
?=
$__template
->
yield
(
'styles'
,
''
)
?
>
<
link
rel=
"stylesheet"
href=
"
<?=
url
(
'assets/css/main.css'
)
?>
?v=
<?=
filemtime
(
App\Core\App
::
getInstance
()
->
basePath
()
.
'/public/assets/css/main.css'
)
?>
"
>
</head>
</head>
<body>
<body>
<!-- Sidebar -->
<div
class=
"app-layout"
>
<aside
class=
"sidebar"
id=
"sidebar"
>
<!-- Sidebar Overlay (mobile) -->
<?php
$__template
->
include
(
'Shared.Components.sidebar'
);
?>
<div
class=
"sidebar-overlay"
id=
"sidebarOverlay"
></div>
</aside>
<!-- Main Wrappe
r -->
<!-- Sideba
r -->
<div
class=
"main-wrapper"
id=
"main-wrapper"
>
<?php
$__template
->
include
(
'Shared.Components.sidebar'
);
?
>
<!--
Top Head
er -->
<!--
Main Wrapp
er -->
<
header
class=
"top-head
er"
>
<
div
class=
"main-wrapp
er"
>
<
div
class=
"header-right"
>
<
!-- Header --
>
<button
class=
"sidebar-toggle-btn"
onclick=
"toggleSidebar()"
>
☰
</button
>
<header
class=
"main-header"
>
<div
class=
"header-title
"
>
<div
style=
"display:flex;align-items:center;gap:12px;
"
>
<
h1>
<?=
$__template
->
yield
(
'title'
,
'لوحة التحكم'
)
?>
</h1
>
<
button
class=
"hamburger-btn"
id=
"hamburgerBtn"
aria-label=
"القائمة"
>
☰
</button
>
</div
>
<h1
class=
"page-title"
>
<?php
$__template
->
yield
(
'title'
,
'لوحة التحكم'
);
?>
</h1
>
</div>
</div>
<div
class=
"header-left"
>
<div
class=
"page-actions"
>
<?=
$__template
->
yield
(
'page_actions'
,
''
)
?>
<?php
$__template
->
yield
(
'page_actions'
,
''
);
?>
<div
class=
"header-user"
>
<div
class=
"user-info"
>
<span
class=
"header-user-name"
>
<?=
e
(
$employeeName
)
?>
</span>
<?php
<a
href=
"/logout"
class=
"header-logout"
title=
"تسجيل الخروج"
>
🚪
</a>
$__employee
=
\App\Core\App
::
getInstance
()
->
currentEmployee
();
if
(
$__employee
)
:
?>
<span
class=
"user-name-text"
>
<?=
e
(
$__employee
->
full_name_ar
??
''
)
?>
</span>
<a
href=
"/logout"
class=
"btn btn-sm btn-outline"
style=
"color:var(--red);border-color:var(--red);"
>
خروج
</a>
<?php
endif
;
?>
</div>
</div>
</div>
</div>
</header>
</header>
<!-- Alerts -->
<!-- Alerts -->
<?php
$__template
->
include
(
'Shared.Components.alerts'
);
?>
<?php
$__session
=
\App\Core\App
::
getInstance
()
->
session
();
$__alerts
=
$__session
->
flash
(
'_alerts'
)
??
[];
?>
<?php
if
(
!
empty
(
$__alerts
))
:
?>
<div
style=
"padding:15px 25px 0;"
>
<?php
foreach
(
$__alerts
as
$__alert
)
:
?>
<div
class=
"alert alert-
<?=
e
(
$__alert
[
'type'
]
??
'info'
)
?>
"
>
<?=
e
(
$__alert
[
'message'
]
??
''
)
?>
</div>
<?php
endforeach
;
?>
</div>
<?php
endif
;
?>
<!-- Page
Content -->
<!-- Main
Content -->
<main
class=
"page
-content"
>
<main
class=
"main
-content"
>
<?=
$__template
->
yield
(
'content'
,
''
)
?>
<?php
$__template
->
yield
(
'content'
);
?>
</main>
</main>
</div>
<!-- Footer -->
<footer
class=
"page-footer"
>
<span>
نادي النادي شيراتون
©
<?=
date
(
'Y'
)
?>
</span>
<span>
الإصدار 1.0.0
</span>
<span>
<?=
arabic_date
(
date
(
'Y-m-d'
))
?>
</span>
</footer>
</div>
</div>
<script
src=
"
<?=
url
(
'assets/js/app.js'
)
?>
"
></script>
<script
src=
"
<?=
url
(
'assets/js/app.js'
)
?>
"
></script>
<script>
<script>
function
toggleSidebar
()
{
(
function
()
{
var
sb
=
document
.
getElementById
(
'sidebar'
);
var
sidebar
=
document
.
querySelector
(
'.sidebar'
);
var
mw
=
document
.
getElementById
(
'main-wrapper'
);
var
overlay
=
document
.
getElementById
(
'sidebarOverlay'
);
sb
.
classList
.
toggle
(
'collapsed'
);
var
hamburger
=
document
.
getElementById
(
'hamburgerBtn'
);
mw
.
classList
.
toggle
(
'sidebar-collapsed'
);
}
function
openSidebar
()
{
function
toggleSubmenu
(
el
)
{
sidebar
.
classList
.
add
(
'open'
);
var
parent
=
el
.
parentElement
;
overlay
.
classList
.
add
(
'active'
);
var
submenu
=
parent
.
querySelector
(
'.sidebar-submenu'
);
document
.
body
.
style
.
overflow
=
'hidden'
;
if
(
submenu
)
{
}
var
isOpen
=
submenu
.
style
.
display
===
'block'
;
function
closeSidebar
()
{
submenu
.
style
.
display
=
isOpen
?
'none'
:
'block'
;
sidebar
.
classList
.
remove
(
'open'
);
parent
.
classList
.
toggle
(
'open'
,
!
isOpen
);
overlay
.
classList
.
remove
(
'active'
);
document
.
body
.
style
.
overflow
=
''
;
}
if
(
hamburger
)
{
hamburger
.
addEventListener
(
'click'
,
function
(
e
)
{
e
.
stopPropagation
();
if
(
sidebar
.
classList
.
contains
(
'open'
))
{
closeSidebar
();
}
else
{
openSidebar
();
}
});
}
if
(
overlay
)
{
overlay
.
addEventListener
(
'click'
,
closeSidebar
);
}
// Close sidebar on link click (mobile)
var
sidebarLinks
=
sidebar
?
sidebar
.
querySelectorAll
(
'.sidebar-link'
)
:
[];
sidebarLinks
.
forEach
(
function
(
link
)
{
link
.
addEventListener
(
'click'
,
function
()
{
if
(
window
.
innerWidth
<=
768
)
{
closeSidebar
();
}
});
});
// Close on Escape
document
.
addEventListener
(
'keydown'
,
function
(
e
)
{
if
(
e
.
key
===
'Escape'
)
closeSidebar
();
});
// Close sidebar if window resizes above mobile
window
.
addEventListener
(
'resize'
,
function
()
{
if
(
window
.
innerWidth
>
768
)
{
closeSidebar
();
}
}
}
});
})();
</script>
</script>
<?
=
$__template
->
yield
(
'scripts'
,
''
)
?>
<?
php
$__template
->
yield
(
'scripts'
,
''
);
?>
</body>
</body>
</html>
</html>
\ No newline at end of file
public/assets/css/main.css
View file @
59e1896c
/* ═══════════════════════════════════════════
/* ═══════════════════════════════════════════════════
ADD THESE TO THE END OF YOUR main.css
THE CLUB ERP — MAIN STYLESHEET
IF SIDEBAR STYLES ARE MISSING
RTL-first · Mobile-responsive · Production-ready
═══════════════════════════════════════════ */
═══════════════════════════════════════════════════ */
/* ── Reset & Base ── */
*,
*
::before
,
*
::after
{
box-sizing
:
border-box
;
margin
:
0
;
padding
:
0
;
}
:root
{
--primary
:
#0D7377
;
--primary-dark
:
#0A5C5F
;
--primary-light
:
#E6F4F4
;
--dark
:
#1A1A2E
;
--gray-50
:
#F9FAFB
;
--gray-100
:
#F3F4F6
;
--gray-200
:
#E5E7EB
;
--gray-300
:
#D1D5DB
;
--gray-400
:
#9CA3AF
;
--gray-500
:
#6B7280
;
--gray-600
:
#4B5563
;
--gray-700
:
#374151
;
--red
:
#DC2626
;
--green
:
#059669
;
--amber
:
#D97706
;
--blue
:
#0284C7
;
--purple
:
#7C3AED
;
--sidebar-width
:
260px
;
--header-height
:
60px
;
}
html
{
font-size
:
14px
;
}
body
{
font-family
:
'Cairo'
,
'Segoe UI'
,
Tahoma
,
Arial
,
sans-serif
;
background
:
var
(
--gray-50
);
color
:
var
(
--dark
);
direction
:
rtl
;
line-height
:
1.6
;
min-height
:
100vh
;
-webkit-font-smoothing
:
antialiased
;
}
a
{
color
:
var
(
--primary
);
text-decoration
:
none
;
}
a
:hover
{
text-decoration
:
underline
;
}
/* ── Layout Shell ── */
.app-layout
{
display
:
flex
;
min-height
:
100vh
;
}
/* ── Sidebar ── */
.sidebar
{
.sidebar
{
width
:
var
(
--sidebar-width
);
background
:
var
(
--dark
);
color
:
#fff
;
position
:
fixed
;
position
:
fixed
;
top
:
0
;
top
:
0
;
right
:
0
;
right
:
0
;
width
:
260px
;
bottom
:
0
;
height
:
100vh
;
z-index
:
1000
;
background
:
#1A1A2E
;
color
:
#E5E7EB
;
overflow-y
:
auto
;
overflow-y
:
auto
;
overflow-x
:
hidden
;
overflow-x
:
hidden
;
z-index
:
1000
;
transition
:
transform
0.3s
ease
;
transition
:
width
0.3s
ease
,
transform
0.3s
ease
;
display
:
flex
;
flex-direction
:
column
;
}
}
.sidebar.collapsed
{
.sidebar-logo
{
width
:
0
;
padding
:
20px
;
transform
:
translateX
(
260px
);
text-align
:
center
;
}
.sidebar-header
{
padding
:
20px
15px
;
border-bottom
:
1px
solid
rgba
(
255
,
255
,
255
,
0.1
);
border-bottom
:
1px
solid
rgba
(
255
,
255
,
255
,
0.1
);
display
:
flex
;
justify-content
:
space-between
;
align-items
:
center
;
flex-shrink
:
0
;
}
}
.sidebar-logo
h1
{
.sidebar-brand
{
font-size
:
18px
;
font-size
:
18px
;
font-weight
:
700
;
font-weight
:
700
;
color
:
#14b8a6
;
letter-spacing
:
1px
;
}
.sidebar-toggle
{
background
:
none
;
border
:
none
;
color
:
#9CA3AF
;
font-size
:
18px
;
cursor
:
pointer
;
padding
:
5px
;
}
.sidebar-toggle
:hover
{
color
:
#fff
;
color
:
#fff
;
margin
:
0
;
}
}
.sidebar-logo
.subtitle
{
.sidebar-nav
{
font-size
:
11px
;
flex
:
1
;
color
:
var
(
--gray-400
);
overflow-y
:
auto
;
margin-top
:
2px
;
padding
:
10px
0
;
}
}
.sidebar-menu
{
.sidebar-nav
{
padding
:
10px
0
;
}
list-style
:
none
;
padding
:
0
;
margin
:
0
;
}
.sidebar-item
{
.sidebar-section
{
margin
:
2px
0
;
padding
:
8px
20px
4px
;
font-size
:
10px
;
text-transform
:
uppercase
;
letter-spacing
:
1px
;
color
:
var
(
--gray-400
);
font-weight
:
700
;
}
}
.sidebar-link
{
.sidebar-link
{
...
@@ -75,212 +96,90 @@
...
@@ -75,212 +96,90 @@
align-items
:
center
;
align-items
:
center
;
gap
:
10px
;
gap
:
10px
;
padding
:
10px
20px
;
padding
:
10px
20px
;
color
:
#D1D5DB
;
color
:
var
(
--gray-300
);
text-decoration
:
none
;
font-size
:
13px
;
font-size
:
14px
;
font-weight
:
500
;
font-weight
:
500
;
transition
:
all
0.
2s
ease
;
transition
:
all
0.
15s
;
border-r
adius
:
0
;
border-r
ight
:
3px
solid
transparent
;
position
:
relativ
e
;
text-decoration
:
non
e
;
}
}
.sidebar-link
:hover
{
.sidebar-link
:hover
{
background
:
rgba
(
255
,
255
,
255
,
0.08
);
background
:
rgba
(
255
,
255
,
255
,
0.08
);
color
:
#fff
;
color
:
#fff
;
}
.sidebar-link.active
{
background
:
rgba
(
13
,
115
,
119
,
0.3
);
color
:
#14b8a6
;
border-left
:
3px
solid
#14b8a6
;
}
.sidebar-icon
{
font-size
:
16px
;
width
:
24px
;
text-align
:
center
;
flex-shrink
:
0
;
}
.sidebar-text
{
flex
:
1
;
white-space
:
nowrap
;
overflow
:
hidden
;
text-overflow
:
ellipsis
;
}
.sidebar-arrow
{
font-size
:
10px
;
transition
:
transform
0.2s
ease
;
color
:
#6B7280
;
}
.sidebar-item.open
>
.sidebar-link
.sidebar-arrow
{
transform
:
rotate
(
-90deg
);
}
.sidebar-submenu
{
list-style
:
none
;
padding
:
0
;
margin
:
0
;
background
:
rgba
(
0
,
0
,
0
,
0.15
);
}
.sidebar-sublink
{
display
:
block
;
padding
:
8px
20px
8px
45px
;
color
:
#9CA3AF
;
text-decoration
:
none
;
text-decoration
:
none
;
font-size
:
13px
;
transition
:
all
0.2s
ease
;
}
}
.sidebar-link.active
{
.sidebar-sublink
:hover
{
background
:
rgba
(
13
,
115
,
119
,
0.3
);
color
:
#fff
;
color
:
#fff
;
background
:
rgba
(
255
,
255
,
255
,
0.05
);
border-right-color
:
var
(
--primary
);
}
font-weight
:
700
;
.sidebar-sublink.active
{
color
:
#14b8a6
;
font-weight
:
600
;
}
}
.sidebar-link
.icon
{
font-size
:
16px
;
width
:
22px
;
text-align
:
center
;
flex-shrink
:
0
;
}
/* ── Main Wrapper ── */
.main-wrapper
{
.main-wrapper
{
margin-right
:
260px
;
flex
:
1
;
margin-right
:
var
(
--sidebar-width
);
min-height
:
100vh
;
min-height
:
100vh
;
display
:
flex
;
display
:
flex
;
flex-direction
:
column
;
flex-direction
:
column
;
transition
:
margin-right
0.3s
ease
;
background
:
#F3F4F6
;
}
.main-wrapper.sidebar-collapsed
{
margin-right
:
0
;
}
}
/* ── Top Header ── */
/* ── Header ── */
.top-header
{
.main-header
{
height
:
var
(
--header-height
);
background
:
#fff
;
background
:
#fff
;
border-bottom
:
1px
solid
#E5E7EB
;
border-bottom
:
1px
solid
var
(
--gray-200
);
padding
:
12px
25px
;
display
:
flex
;
display
:
flex
;
justify-content
:
space-between
;
align-items
:
center
;
align-items
:
center
;
justify-content
:
space-between
;
padding
:
0
25px
;
position
:
sticky
;
position
:
sticky
;
top
:
0
;
top
:
0
;
z-index
:
100
;
z-index
:
900
;
box-shadow
:
0
1px
3px
rgba
(
0
,
0
,
0
,
0.05
);
}
}
.main-header
.page-title
{
.header-right
{
display
:
flex
;
align-items
:
center
;
gap
:
15px
;
}
.header-left
{
display
:
flex
;
align-items
:
center
;
gap
:
15px
;
}
.header-title
h1
{
margin
:
0
;
font-size
:
18px
;
font-size
:
18px
;
font-weight
:
700
;
font-weight
:
700
;
color
:
#1A1A2E
;
color
:
var
(
--dark
)
;
}
}
.main-header
.page-actions
{
.header-user
{
display
:
flex
;
display
:
flex
;
align-items
:
center
;
align-items
:
center
;
gap
:
10px
;
gap
:
10px
;
font-size
:
14px
;
color
:
#4B5563
;
}
}
.main-header
.user-info
{
.header-user-name
{
display
:
flex
;
font-weight
:
600
;
align-items
:
center
;
}
gap
:
8px
;
font-size
:
13px
;
.header-logout
{
color
:
var
(
--gray-500
);
text-decoration
:
none
;
font-size
:
18px
;
padding
:
4px
;
}
}
.hamburger-btn
{
.sidebar-toggle-btn
{
display
:
none
;
background
:
none
;
background
:
none
;
border
:
1px
solid
#E5E7EB
;
border
:
none
;
border-radius
:
6px
;
font-size
:
24px
;
padding
:
6px
10px
;
cursor
:
pointer
;
cursor
:
pointer
;
font-size
:
16
px
;
padding
:
5
px
;
color
:
#4B5563
;
color
:
var
(
--dark
)
;
display
:
none
;
line-height
:
1
;
}
}
/* ──
Page
Content ── */
/* ──
Main
Content ── */
.
page
-content
{
.
main
-content
{
flex
:
1
;
flex
:
1
;
padding
:
25px
;
padding
:
25px
;
}
}
/* ── Footer ── */
.page-footer
{
padding
:
15px
25px
;
background
:
#fff
;
border-top
:
1px
solid
#E5E7EB
;
display
:
flex
;
justify-content
:
space-between
;
font-size
:
12px
;
color
:
#9CA3AF
;
}
/* ── Cards ── */
/* ── Cards ── */
.card
{
.card
{
background
:
#fff
;
background
:
#fff
;
border-radius
:
8px
;
border-radius
:
8px
;
border
:
1px
solid
#E5E7EB
;
box-shadow
:
0
1px
3px
rgba
(
0
,
0
,
0
,
0.06
);
box-shadow
:
0
1px
3px
rgba
(
0
,
0
,
0
,
0.04
);
border
:
1px
solid
var
(
--gray-200
);
margin-bottom
:
0
;
overflow
:
hidden
;
overflow
:
hidden
;
}
}
/* ── Tables ── */
.table-responsive
{
overflow-x
:
auto
;
}
.data-table
{
width
:
100%
;
border-collapse
:
collapse
;
font-size
:
14px
;
}
.data-table
thead
{
background
:
#0D7377
;
color
:
#fff
;
}
.data-table
th
{
padding
:
12px
15px
;
text-align
:
right
;
font-weight
:
600
;
white-space
:
nowrap
;
}
.data-table
td
{
padding
:
10px
15px
;
border-bottom
:
1px
solid
#F3F4F6
;
text-align
:
right
;
}
.data-table
tbody
tr
:hover
{
background
:
#F9FAFB
;
}
/* ── Buttons ── */
/* ── Buttons ── */
.btn
{
.btn
{
display
:
inline-flex
;
display
:
inline-flex
;
...
@@ -288,193 +187,337 @@
...
@@ -288,193 +187,337 @@
justify-content
:
center
;
justify-content
:
center
;
gap
:
6px
;
gap
:
6px
;
padding
:
8px
16px
;
padding
:
8px
16px
;
border-radius
:
6px
;
font-size
:
13px
;
font-size
:
14px
;
font-weight
:
600
;
font-weight
:
600
;
text-decoration
:
none
;
border-radius
:
6px
;
cursor
:
pointer
;
border
:
1px
solid
transparent
;
border
:
1px
solid
transparent
;
transition
:
all
0.2s
ease
;
cursor
:
pointer
;
transition
:
all
0.15s
;
text-decoration
:
none
;
white-space
:
nowrap
;
white-space
:
nowrap
;
font-family
:
inherit
;
font-family
:
inherit
;
line-height
:
1.4
;
}
}
.btn
:hover
{
text-decoration
:
none
;
opacity
:
0.9
;
}
.btn
:active
{
transform
:
scale
(
0.98
);
}
.btn-primary
{
.btn-primary
{
background
:
var
(
--primary
);
color
:
#fff
;
border-color
:
var
(
--primary
);
}
background
:
#0D7377
;
.btn-primary
:hover
{
background
:
var
(
--primary-dark
);
}
color
:
#fff
;
border-color
:
#0D7377
;
}
.btn-primary
:hover
{
.btn-outline
{
background
:
#fff
;
color
:
var
(
--dark
);
border-color
:
var
(
--gray-300
);
}
background
:
#0a5c5f
;
.btn-outline
:hover
{
background
:
var
(
--gray-50
);
border-color
:
var
(
--gray-400
);
}
}
.btn-outline
{
background
:
transparent
;
color
:
#0D7377
;
border-color
:
#D1D5DB
;
}
.btn-outline
:hover
{
.btn-sm
{
padding
:
4px
10px
;
font-size
:
12px
;
}
background
:
#F3F4F6
;
.btn-xs
{
padding
:
2px
6px
;
font-size
:
11px
;
}
border-color
:
#0D7377
;
}
.btn-sm
{
padding
:
4px
10px
;
font-size
:
12px
;
}
/* ── Forms ── */
/* ── Forms ── */
.form-group
{
.form-group
{
margin-bottom
:
0
;
}
margin-bottom
:
0
;
}
.form-label
{
.form-label
{
display
:
block
;
display
:
block
;
margin-bottom
:
5px
;
font-size
:
13px
;
font-size
:
13px
;
font-weight
:
600
;
font-weight
:
600
;
color
:
#374151
;
color
:
var
(
--gray-700
);
margin-bottom
:
4px
;
}
}
.form-input
,
.form-input
,
.form-select
,
.form-textarea
{
.form-select
,
.form-textarea
{
width
:
100%
;
width
:
100%
;
padding
:
8px
12px
;
padding
:
8px
12px
;
border
:
1px
solid
#D1D5DB
;
border-radius
:
6px
;
font-size
:
14px
;
font-size
:
14px
;
font-family
:
inherit
;
font-family
:
inherit
;
border
:
1px
solid
var
(
--gray-300
);
border-radius
:
6px
;
background
:
#fff
;
background
:
#fff
;
color
:
#1A1A2E
;
color
:
var
(
--dark
)
;
transition
:
border-color
0.
2
s
;
transition
:
border-color
0.
15
s
;
box-sizing
:
border-box
;
direction
:
rtl
;
}
}
.form-input
:focus
,
.form-select
:focus
,
.form-textarea
:focus
{
.form-input
:focus
,
.form-select
:focus
,
.form-textarea
:focus
{
outline
:
none
;
outline
:
none
;
border-color
:
#0D7377
;
border-color
:
var
(
--primary
)
;
box-shadow
:
0
0
0
3px
rgba
(
13
,
115
,
119
,
0.1
);
box-shadow
:
0
0
0
3px
rgba
(
13
,
115
,
119
,
0.1
);
}
}
.form-textarea
{
resize
:
vertical
;
min-height
:
60px
;
}
.form-select
{
appearance
:
auto
;
}
.form-textarea
{
/* ── Tables ── */
resize
:
vertical
;
.table-responsive
{
min-height
:
80px
;
overflow-x
:
auto
;
-webkit-overflow-scrolling
:
touch
;
}
.data-table
{
width
:
100%
;
border-collapse
:
collapse
;
font-size
:
13px
;
}
.data-table
thead
{
background
:
var
(
--gray-50
);
}
.data-table
th
{
padding
:
10px
14px
;
text-align
:
right
;
font-weight
:
700
;
color
:
var
(
--gray-600
);
border-bottom
:
2px
solid
var
(
--gray-200
);
white-space
:
nowrap
;
font-size
:
12px
;
}
.data-table
td
{
padding
:
10px
14px
;
border-bottom
:
1px
solid
var
(
--gray-100
);
vertical-align
:
middle
;
}
}
.data-table
tbody
tr
:hover
{
background
:
var
(
--gray-50
);
}
/* ── Alerts ── */
/* ── Alerts ── */
.alert
{
.alert
{
padding
:
12px
20
px
;
padding
:
12px
16
px
;
border-radius
:
8
px
;
border-radius
:
6
px
;
margin
:
0
25px
15px
;
margin
-bottom
:
15px
;
font-size
:
14px
;
font-size
:
14px
;
font-weight
:
500
;
font-weight
:
500
;
display
:
flex
;
display
:
flex
;
justify-content
:
space-between
;
align-items
:
center
;
align-items
:
center
;
gap
:
8px
;
}
}
.alert-success
{
background
:
#F0FDF4
;
border
:
1px
solid
#BBF7D0
;
color
:
var
(
--green
);
}
.alert-error
{
background
:
#FEF2F2
;
border
:
1px
solid
#FECACA
;
color
:
var
(
--red
);
}
.alert-warning
{
background
:
#FFF7ED
;
border
:
1px
solid
#FED7AA
;
color
:
var
(
--amber
);
}
.alert-info
{
background
:
#EFF6FF
;
border
:
1px
solid
#BFDBFE
;
color
:
var
(
--blue
);
}
.alert-success
{
/* ── Pagination ── */
background
:
#F0FDF4
;
.pagination-wrapper
{
display
:
flex
;
justify-content
:
center
;
}
color
:
#059669
;
.pagination
{
border
:
1px
solid
#BBF7D0
;
display
:
flex
;
}
gap
:
5px
;
list-style
:
none
;
.alert-error
{
padding
:
0
;
background
:
#FEF2F2
;
margin
:
0
;
color
:
#DC2626
;
flex-wrap
:
wrap
;
border
:
1px
solid
#FECACA
;
justify-content
:
center
;
}
.alert-warning
{
background
:
#FFF7ED
;
color
:
#D97706
;
border
:
1px
solid
#FED7AA
;
}
}
.alert-info
{
/* ── Sidebar Overlay (mobile) ── */
background
:
#EFF6FF
;
.sidebar-overlay
{
color
:
#0284C7
;
display
:
none
;
border
:
1px
solid
#BFDBFE
;
position
:
fixed
;
}
inset
:
0
;
background
:
rgba
(
0
,
0
,
0
,
0.5
);
z-index
:
999
;
}
.sidebar-overlay.active
{
display
:
block
;
}
/* ── Scrollbar ── */
.sidebar
::-webkit-scrollbar
{
width
:
4px
;
}
.sidebar
::-webkit-scrollbar-track
{
background
:
transparent
;
}
.sidebar
::-webkit-scrollbar-thumb
{
background
:
rgba
(
255
,
255
,
255
,
0.2
);
border-radius
:
4px
;
}
/* ── Utility ── */
.text-center
{
text-align
:
center
;
}
.text-left
{
text-align
:
left
;
}
.text-right
{
text-align
:
right
;
}
.font-bold
{
font-weight
:
700
;
}
.hidden
{
display
:
none
!important
;
}
/* ══════════════════════════════════════════
RESPONSIVE — TABLET (≤1024px)
══════════════════════════════════════════ */
@media
(
max-width
:
1024px
)
{
:root
{
--sidebar-width
:
220px
;
}
.alert-close
{
.sidebar-link
{
padding
:
9px
15px
;
font-size
:
12px
;
}
background
:
none
;
.sidebar-section
{
padding
:
8px
15px
4px
;
}
border
:
none
;
.main-content
{
padding
:
20px
;
}
cursor
:
pointer
;
.main-header
{
padding
:
0
20px
;
}
font-size
:
18px
;
color
:
inherit
;
opacity
:
0.6
;
padding
:
0
5px
;
}
}
.alert-close
:hover
{
/* ══════════════════════════════════════════
opacity
:
1
;
RESPONSIVE — MOBILE (≤768px)
}
══════════════════════════════════════════ */
@media
(
max-width
:
768px
)
{
:root
{
--sidebar-width
:
270px
;
--header-height
:
54px
;
}
/* ── Responsive ── */
/* Sidebar: off-canvas */
@media
(
max-width
:
1024px
)
{
.sidebar
{
.sidebar
{
transform
:
translateX
(
260px
);
transform
:
translateX
(
100%
);
width
:
260px
;
}
}
.sidebar.
show
{
.sidebar.
open
{
transform
:
translateX
(
0
);
transform
:
translateX
(
0
);
}
}
/* Main wrapper: full width */
.main-wrapper
{
.main-wrapper
{
margin-right
:
0
;
margin-right
:
0
;
}
}
.sidebar-toggle-btn
{
/* Show hamburger */
.hamburger-btn
{
display
:
block
;
display
:
block
;
}
}
}
/* ── Print ──
*/
/* Header
*/
@media
print
{
.main-header
{
.sidebar
,
.top-header
,
.page-footer
,
.btn
,
.sidebar-toggle-btn
{
padding
:
0
15px
;
display
:
none
!important
;
gap
:
10px
;
}
}
.main-wrapper
{
.main-header
.page-title
{
margin-right
:
0
!important
;
font-size
:
15px
;
overflow
:
hidden
;
text-overflow
:
ellipsis
;
white-space
:
nowrap
;
max-width
:
50vw
;
}
.main-header
.page-actions
{
gap
:
6px
;
flex-wrap
:
wrap
;
}
}
.page-content
{
.main-header
.page-actions
.btn
{
padding
:
0
!important
;
padding
:
5px
10px
;
font-size
:
11px
;
}
.main-header
.user-info
.user-name-text
{
display
:
none
;
}
}
}
/* ── Body Reset ──
*/
/* Content
*/
*
{
.main-content
{
box-sizing
:
border-bo
x
;
padding
:
15p
x
;
}
}
body
{
/* ── Grid overrides: stack everything ── */
margin
:
0
;
[
style
*=
"grid-template-columns: 1fr 1fr"
],
padding
:
0
;
[
style
*=
"grid-template-columns:1fr 1fr"
],
font-family
:
'Cairo'
,
'Segoe UI'
,
Tahoma
,
Arial
,
sans-serif
;
[
style
*=
"grid-template-columns: 2fr 1fr"
],
font-size
:
14px
;
[
style
*=
"grid-template-columns:2fr 1fr"
],
color
:
#1A1A2E
;
[
style
*=
"grid-template-columns: 1fr 300px"
],
background
:
#F3F4F6
;
[
style
*=
"grid-template-columns:1fr 300px"
],
direction
:
rtl
;
[
style
*=
"grid-template-columns: 250px 1fr"
],
line-height
:
1.6
;
[
style
*=
"grid-template-columns:250px 1fr"
]
{
}
grid-template-columns
:
1
fr
!important
;
}
a
{
/* Stats cards row */
color
:
#0D7377
;
[
style
*=
"grid-template-columns: repeat(auto-fit"
],
text-decoration
:
none
;
[
style
*=
"grid-template-columns:repeat(auto-fit"
]
{
grid-template-columns
:
1
fr
1
fr
!important
;
}
/* ── Filter forms: stack vertically ── */
.card
form
[
style
*=
"display:flex"
],
.card
form
[
style
*=
"display: flex"
]
{
flex-direction
:
column
!important
;
align-items
:
stretch
!important
;
}
.card
form
[
style
*=
"display:flex"
]
>
div
,
.card
form
[
style
*=
"display: flex"
]
>
div
{
min-width
:
0
!important
;
width
:
100%
!important
;
}
.card
form
[
style
*=
"display:flex"
]
.form-input
,
.card
form
[
style
*=
"display:flex"
]
.form-select
,
.card
form
[
style
*=
"display: flex"
]
.form-input
,
.card
form
[
style
*=
"display: flex"
]
.form-select
{
min-width
:
0
!important
;
width
:
100%
!important
;
}
.card
form
[
style
*=
"display:flex"
]
.btn
,
.card
form
[
style
*=
"display: flex"
]
.btn
{
width
:
100%
;
}
/* ── Tables: tighter ── */
.data-table
th
,
.data-table
td
{
padding
:
8px
8px
;
font-size
:
12px
;
}
.data-table
th
{
font-size
:
11px
;
}
/* ── Cards: less padding ── */
.card
>
div
[
style
*=
"padding:20px"
],
.card
>
div
[
style
*=
"padding: 20px"
]
{
padding
:
15px
!important
;
}
.card
>
div
[
style
*=
"padding:15px 20px"
],
.card
>
div
[
style
*=
"padding: 15px 20px"
]
{
padding
:
12px
15px
!important
;
}
/* ── Buttons in table cells: stack ── */
td
[
style
*=
"display:flex"
],
td
[
style
*=
"display: flex"
]
{
flex-wrap
:
wrap
!important
;
}
/* ── Member show page: action buttons wrap ── */
.member-actions
{
flex-wrap
:
wrap
!important
;
}
/* ── Inline forms (pay buttons etc) ── */
td
form
[
style
*=
"display:flex"
],
td
form
[
style
*=
"display: flex"
]
{
flex-wrap
:
wrap
!important
;
}
/* ── Full-width grid children on mobile ── */
[
style
*=
"grid-column:1/-1"
],
[
style
*=
"grid-column: 1/-1"
]
{
grid-column
:
1
/
-1
!important
;
}
/* ── Print button row ── */
[
style
*=
"display:flex;gap:10px;"
],
[
style
*=
"display: flex; gap: 10px;"
]
{
flex-wrap
:
wrap
!important
;
}
}
}
a
:hover
{
/* ══════════════════════════════════════════
text-decoration
:
underline
;
RESPONSIVE — SMALL MOBILE (≤480px)
══════════════════════════════════════════ */
@media
(
max-width
:
480px
)
{
html
{
font-size
:
13px
;
}
.main-content
{
padding
:
10px
;
}
.main-header
.page-title
{
font-size
:
14px
;
max-width
:
40vw
;
}
/* Stats cards: single column */
[
style
*=
"grid-template-columns: repeat(auto-fit"
],
[
style
*=
"grid-template-columns:repeat(auto-fit"
]
{
grid-template-columns
:
1
fr
!important
;
}
/* Even tighter table cells */
.data-table
th
,
.data-table
td
{
padding
:
6px
6px
;
font-size
:
11px
;
}
.btn
{
padding
:
6px
12px
;
font-size
:
12px
;
}
.btn-sm
{
padding
:
3px
8px
;
font-size
:
11px
;
}
/* Card section headers */
.card
h3
{
font-size
:
15px
!important
;
}
.card
h4
{
font-size
:
14px
!important
;
}
/* Large money displays */
[
style
*=
"font-size:28px"
]
{
font-size
:
22px
!important
;
}
[
style
*=
"font-size: 28px"
]
{
font-size
:
22px
!important
;
}
[
style
*=
"font-size:20px"
]
{
font-size
:
16px
!important
;
}
[
style
*=
"font-size: 20px"
]
{
font-size
:
16px
!important
;
}
}
}
code
{
/* ══════════════════════════════════════════
background
:
#F3F4F6
;
PRINT
padding
:
2px
6px
;
══════════════════════════════════════════ */
border-radius
:
4px
;
@media
print
{
font-size
:
12px
;
.sidebar
,
.main-header
,
.hamburger-btn
,
.sidebar-overlay
{
display
:
none
!important
;
}
font-family
:
'Courier New'
,
monospace
;
.main-wrapper
{
margin-right
:
0
!important
;
}
.main-content
{
padding
:
0
!important
;
}
.card
{
box-shadow
:
none
;
border
:
1px
solid
#ddd
;
}
.btn
{
display
:
none
!important
;
}
}
}
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment