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
de5cfc33
Commit
de5cfc33
authored
Apr 10, 2026
by
Mahmoud Aglan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
goooooooooo
parent
048af80b
Changes
16
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
2691 additions
and
437 deletions
+2691
-437
settings.local.json
.claude/settings.local.json
+7
-0
alerts.php
app/Shared/Components/alerts.php
+17
-33
breadcrumbs.php
app/Shared/Components/breadcrumbs.php
+10
-3
data-table.php
app/Shared/Components/data-table.php
+11
-3
empty-state.php
app/Shared/Components/empty-state.php
+17
-4
form-fields.php
app/Shared/Components/form-fields.php
+8
-3
header.php
app/Shared/Components/header.php
+17
-5
modal.php
app/Shared/Components/modal.php
+6
-2
pagination.php
app/Shared/Components/pagination.php
+13
-3
sidebar.php
app/Shared/Components/sidebar.php
+66
-62
stats-card.php
app/Shared/Components/stats-card.php
+26
-9
auth.php
app/Shared/Layout/auth.php
+274
-20
main.php
app/Shared/Layout/main.php
+89
-11
print.php
app/Shared/Layout/print.php
+40
-7
main.css
public/assets/css/main.css
+1898
-249
app.js
public/assets/js/app.js
+192
-23
No files found.
.claude/settings.local.json
0 → 100644
View file @
de5cfc33
{
"permissions"
:
{
"allow"
:
[
"Bash(wc -l /Users/mahmoudaglan/clubphp/app/Core/*.php)"
]
}
}
app/Shared/Components/alerts.php
View file @
de5cfc33
<?php
/**
* Flash alert messages component.
* Flash alert messages component
— with Lucide icons and animations
.
*/
$session
=
\App\Core\App
::
getInstance
()
->
session
();
$alerts
=
$session
->
getAlerts
();
...
...
@@ -8,42 +8,26 @@ $alerts = $session->getAlerts();
if
(
empty
(
$alerts
))
{
return
;
}
$iconSvg
=
[
'success'
=>
'<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/><polyline points="22 4 12 14.01 9 11.01"/></svg>'
,
'error'
=>
'<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="15" y1="9" x2="9" y2="15"/><line x1="9" y1="9" x2="15" y2="15"/></svg>'
,
'warning'
=>
'<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg>'
,
'info'
=>
'<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M12 16v-4"/><path d="M12 8h.01"/></svg>'
,
];
$closeSvg
=
'<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>'
;
?>
<?php
foreach
(
$alerts
as
$alert
)
:
?>
<?php
$type
=
$alert
[
'type'
]
??
'info'
;
$message
=
$alert
[
'message'
]
??
''
;
$bgColor
=
match
(
$type
)
{
'success'
=>
'#F0FDF4'
,
'error'
=>
'#FEF2F2'
,
'warning'
=>
'#FFF7ED'
,
'info'
=>
'#EFF6FF'
,
default
=>
'#F9FAFB'
,
};
$textColor
=
match
(
$type
)
{
'success'
=>
'#059669'
,
'error'
=>
'#DC2626'
,
'warning'
=>
'#D97706'
,
'info'
=>
'#0284C7'
,
default
=>
'#6B7280'
,
};
$borderColor
=
match
(
$type
)
{
'success'
=>
'#BBF7D0'
,
'error'
=>
'#FECACA'
,
'warning'
=>
'#FED7AA'
,
'info'
=>
'#BFDBFE'
,
default
=>
'#E5E7EB'
,
};
$icon
=
match
(
$type
)
{
'success'
=>
'✓'
,
'error'
=>
'✗'
,
'warning'
=>
'⚠'
,
'info'
=>
'ℹ'
,
default
=>
''
,
};
?>
<div
class=
"alert alert-
<?=
$type
?>
"
style=
"background:
<?=
$bgColor
?>
;color:
<?=
$textColor
?>
;border:1px solid
<?=
$borderColor
?>
;padding:12px 20px;border-radius:8px;margin:0 25px 15px;font-size:14px;display:flex;justify-content:space-between;align-items:center;"
>
<span>
<?=
$icon
?>
<?=
e
(
$message
)
?>
</span>
<button
onclick=
"this.parentElement.remove()"
style=
"background:none;border:none;cursor:pointer;font-size:18px;color:
<?=
$textColor
?>
;opacity:0.6;padding:0 5px;"
>
×
</button>
<div
class=
"alert alert-
<?=
$type
?>
"
data-auto-dismiss=
"5000"
>
<div
class=
"alert-content"
>
<span
class=
"alert-icon"
>
<?=
$iconSvg
[
$type
]
??
$iconSvg
[
'info'
]
?>
</span>
<span>
<?=
e
(
$message
)
?>
</span>
</div>
<button
class=
"alert-close"
onclick=
"var el=this.parentElement;el.classList.add('dismissing');el.addEventListener('animationend',function(){el.remove();})"
>
<?=
$closeSvg
?>
</button>
</div>
<?php
endforeach
;
?>
\ No newline at end of file
<?php
endforeach
;
?>
app/Shared/Components/breadcrumbs.php
View file @
de5cfc33
<?php
/**
* Breadcrumbs component — with Lucide home icon and clean separators.
*
* @var array $items [['label'=>..., 'url'=>...]]
*/
$items
=
$items
??
[];
?>
<?php
if
(
!
empty
(
$items
))
:
?>
<nav
class=
"breadcrumbs"
>
<a
href=
"/"
class=
"breadcrumb-item"
>
🏠 الرئيسية
</a>
<a
href=
"/"
class=
"breadcrumb-item"
>
<i
data-lucide=
"home"
style=
"width:15px;height:15px;"
></i>
الرئيسية
</a>
<?php
foreach
(
$items
as
$i
=>
$item
)
:
?>
<span
class=
"breadcrumb-separator"
>
‹
</span>
<span
class=
"breadcrumb-separator"
>
<svg
xmlns=
"http://www.w3.org/2000/svg"
width=
"14"
height=
"14"
viewBox=
"0 0 24 24"
fill=
"none"
stroke=
"currentColor"
stroke-width=
"2"
stroke-linecap=
"round"
stroke-linejoin=
"round"
><polyline
points=
"15 18 9 12 15 6"
/></svg>
</span>
<?php
if
(
$i
<
count
(
$items
)
-
1
&&
!
empty
(
$item
[
'url'
]))
:
?>
<a
href=
"
<?=
e
(
$item
[
'url'
])
?>
"
class=
"breadcrumb-item"
>
<?=
e
(
$item
[
'label'
])
?>
</a>
<?php
else
:
?>
...
...
@@ -16,4 +23,4 @@ $items = $items ?? [];
<?php
endif
;
?>
<?php
endforeach
;
?>
</nav>
<?php
endif
;
?>
\ No newline at end of file
<?php
endif
;
?>
app/Shared/Components/data-table.php
View file @
de5cfc33
<?php
/**
* Data table component — with row animations and action buttons.
*
* @var array $columns [['key'=>..., 'label_ar'=>..., 'sortable'=>bool, 'class'=>'']]
* @var array $rows
* @var array $pagination (optional)
...
...
@@ -11,7 +13,7 @@ $pagination = $pagination ?? null;
$actions
=
$actions
??
[];
?>
<?php
if
(
empty
(
$rows
))
:
?>
<?php
$__template
->
include
(
'Shared.Components.empty-state'
,
[
'message'
=>
$emptyMessage
??
'لا توجد بيانات'
]);
?>
<?php
$__template
->
include
(
'Shared.Components.empty-state'
,
[
'message'
=>
$emptyMessage
??
'لا توجد بيانات'
,
'icon'
=>
$emptyIcon
??
'inbox'
]);
?>
<?php
else
:
?>
<div
class=
"table-responsive"
>
<table
class=
"data-table"
>
...
...
@@ -52,8 +54,14 @@ $actions = $actions ?? [];
if
(
is_callable
(
$href
))
$href
=
$href
(
$row
);
$label
=
$action
[
'label'
]
??
''
;
$class
=
$action
[
'class'
]
??
'btn btn-sm btn-outline'
;
$iconName
=
$action
[
'icon'
]
??
null
;
?>
<a
href=
"
<?=
e
(
$href
)
?>
"
class=
"
<?=
e
(
$class
)
?>
"
>
<?=
e
(
$label
)
?>
</a>
<a
href=
"
<?=
e
(
$href
)
?>
"
class=
"
<?=
e
(
$class
)
?>
"
>
<?php
if
(
$iconName
)
:
?>
<i
data-lucide=
"
<?=
e
(
$iconName
)
?>
"
style=
"width:14px;height:14px;"
></i>
<?php
endif
;
?>
<?=
e
(
$label
)
?>
</a>
<?php
endforeach
;
?>
</div>
</td>
...
...
@@ -66,4 +74,4 @@ $actions = $actions ?? [];
<?php
if
(
$pagination
)
:
?>
<?php
$__template
->
include
(
'Shared.Components.pagination'
,
[
'pagination'
=>
$pagination
]);
?>
<?php
endif
;
?>
<?php
endif
;
?>
\ No newline at end of file
<?php
endif
;
?>
app/Shared/Components/empty-state.php
View file @
de5cfc33
<?php
/**
* Empty state component — with Lucide icon and subtle animation.
*
* @var string $message
* @var string $icon Lucide icon name (e.g. 'inbox', 'search', 'file-x')
* @var string $actionUrl (optional)
* @var string $actionLabel (optional)
*/
$message
=
$message
??
'لا توجد بيانات لعرضها'
;
$icon
=
$icon
??
'📭
'
;
$icon
Name
=
$icon
??
'inbox
'
;
$actionUrl
=
$actionUrl
??
null
;
$actionLabel
=
$actionLabel
??
null
;
?>
<div
class=
"empty-state"
>
<div
class=
"empty-state-icon"
>
<?=
$icon
?>
</div>
<div
class=
"empty-state-icon"
>
<i
data-lucide=
"
<?=
e
(
$iconName
)
?>
"
></i>
</div>
<p
class=
"empty-state-message"
>
<?=
e
(
$message
)
?>
</p>
<?php
if
(
$actionUrl
&&
$actionLabel
)
:
?>
<a
href=
"
<?=
e
(
$actionUrl
)
?>
"
class=
"btn btn-primary"
>
<?=
e
(
$actionLabel
)
?>
</a>
<a
href=
"
<?=
e
(
$actionUrl
)
?>
"
class=
"btn btn-primary"
>
<i
data-lucide=
"plus"
style=
"width:16px;height:16px;"
></i>
<?=
e
(
$actionLabel
)
?>
</a>
<?php
endif
;
?>
</div>
\ No newline at end of file
</div>
app/Shared/Components/form-fields.php
View file @
de5cfc33
<?php
/**
* Renders a form field.
* Renders a form field — with enhanced styling and Lucide icon support.
*
* @var string $type
* @var string $name
* @var string $label_ar
...
...
@@ -11,6 +12,7 @@
* @var array $options (for select/radio)
* @var string $placeholder
* @var string $help_text
* @var string $icon (optional) Lucide icon name
*/
$type
=
$type
??
'text'
;
$name
=
$name
??
''
;
...
...
@@ -104,10 +106,13 @@ $id = 'field_' . str_replace(['[', ']', '.'], '_', $name);
<?php
endif
;
?>
<?php
if
(
$error
)
:
?>
<div
class=
"form-error"
>
<?=
e
(
$error
)
?>
</div>
<div
class=
"form-error"
>
<svg
xmlns=
"http://www.w3.org/2000/svg"
width=
"14"
height=
"14"
viewBox=
"0 0 24 24"
fill=
"none"
stroke=
"currentColor"
stroke-width=
"2"
stroke-linecap=
"round"
stroke-linejoin=
"round"
><circle
cx=
"12"
cy=
"12"
r=
"10"
/><line
x1=
"15"
y1=
"9"
x2=
"9"
y2=
"15"
/><line
x1=
"9"
y1=
"9"
x2=
"15"
y2=
"15"
/></svg>
<?=
e
(
$error
)
?>
</div>
<?php
endif
;
?>
<?php
if
(
$help_text
)
:
?>
<small
class=
"form-help"
>
<?=
e
(
$help_text
)
?>
</small>
<?php
endif
;
?>
</div>
\ No newline at end of file
</div>
app/Shared/Components/header.php
View file @
de5cfc33
<?php
/**
* Top bar component — with search, notifications, and user profile.
*/
use
App\Core\App
;
$employee
=
App
::
getInstance
()
->
currentEmployee
();
$branch
=
App
::
getInstance
()
->
currentBranch
();
?>
<div
class=
"topbar-right"
>
<button
class=
"topbar-btn sidebar-mobile-toggle"
onclick=
"toggleSidebar()"
>
☰
</button>
<button
class=
"topbar-btn sidebar-mobile-toggle"
onclick=
"toggleSidebar()"
>
<i
data-lucide=
"menu"
style=
"width:20px;height:20px;"
></i>
</button>
<div
class=
"topbar-search"
>
<input
type=
"text"
id=
"global-search"
placeholder=
"بحث سريع..."
class=
"topbar-search-input"
autocomplete=
"off"
>
</div>
...
...
@@ -12,17 +17,24 @@ $branch = App::getInstance()->currentBranch();
<div
class=
"topbar-left"
>
<span
class=
"topbar-date"
>
<?=
arabic_date
(
today
())
?>
</span>
<?php
if
(
$branch
)
:
?>
<span
class=
"topbar-branch"
>
<?=
e
(
$branch
[
'name_ar'
]
??
''
)
?>
</span>
<span
class=
"topbar-branch"
>
<i
data-lucide=
"building-2"
style=
"width:12px;height:12px;display:inline;vertical-align:middle;margin-left:4px;"
></i>
<?=
e
(
$branch
[
'name_ar'
]
??
''
)
?>
</span>
<?php
endif
;
?>
<div
class=
"topbar-notifications"
>
<button
class=
"topbar-btn"
id=
"notif-bell"
title=
"الإشعارات"
>
🔔
<span
class=
"notif-badge"
id=
"notif-badge"
style=
"display:none;"
>
0
</span>
<i
data-lucide=
"bell"
style=
"width:20px;height:20px;"
></i>
<span
class=
"notif-badge"
id=
"notif-badge"
style=
"display:none;"
>
0
</span>
</button>
</div>
<?php
if
(
$employee
)
:
?>
<div
class=
"topbar-user"
>
<span
class=
"topbar-username"
>
<?=
e
(
$employee
->
full_name_ar
??
(
$employee
[
'full_name_ar'
]
??
'مستخدم'
))
?>
</span>
<a
href=
"/logout"
class=
"topbar-btn topbar-logout"
title=
"تسجيل الخروج"
>
خروج
</a>
<a
href=
"/logout"
class=
"topbar-btn topbar-logout"
title=
"تسجيل الخروج"
>
<i
data-lucide=
"log-out"
style=
"width:16px;height:16px;display:inline;vertical-align:middle;margin-left:4px;"
></i>
خروج
</a>
</div>
<?php
endif
;
?>
</div>
\ No newline at end of file
</div>
app/Shared/Components/modal.php
View file @
de5cfc33
<?php
/**
* Modal component — with backdrop blur, scale animation, and Lucide close icon.
*
* @var string $id
* @var string $title
* @var string $size (small|medium|large|fullscreen)
...
...
@@ -12,7 +14,9 @@ $size = $size ?? 'medium';
<div
class=
"modal modal-
<?=
e
(
$size
)
?>
"
>
<div
class=
"modal-header"
>
<h3
class=
"modal-title"
>
<?=
e
(
$title
)
?>
</h3>
<button
class=
"modal-close"
onclick=
"closeModal('
<?=
e
(
$id
)
?>
')"
>
✕
</button>
<button
class=
"modal-close"
onclick=
"closeModal('
<?=
e
(
$id
)
?>
')"
>
<svg
xmlns=
"http://www.w3.org/2000/svg"
width=
"20"
height=
"20"
viewBox=
"0 0 24 24"
fill=
"none"
stroke=
"currentColor"
stroke-width=
"2"
stroke-linecap=
"round"
stroke-linejoin=
"round"
><line
x1=
"18"
y1=
"6"
x2=
"6"
y2=
"18"
/><line
x1=
"6"
y1=
"6"
x2=
"18"
y2=
"18"
/></svg>
</button>
</div>
<div
class=
"modal-body"
>
<?=
$__template
->
yield
(
'modal_body_'
.
$id
,
''
)
?>
...
...
@@ -21,4 +25,4 @@ $size = $size ?? 'medium';
<?=
$__template
->
yield
(
'modal_footer_'
.
$id
,
''
)
?>
</div>
</div>
</div>
\ No newline at end of file
</div>
app/Shared/Components/pagination.php
View file @
de5cfc33
<?php
/**
* Pagination component — with styled links and Lucide arrow icons.
*
* @var array $pagination
* @var string $baseUrl (optional)
*/
...
...
@@ -14,7 +16,11 @@ $separator = str_contains($baseUrl, '?') ? '&' : '?';
</div>
<ul
class=
"pagination"
>
<?php
if
(
$pagination
[
'has_prev'
])
:
?>
<li><a
href=
"
<?=
$baseUrl
.
$separator
?>
page=
<?=
$pagination
[
'prev_page'
]
?>
"
class=
"page-link"
>
السابق
</a></li>
<li>
<a
href=
"
<?=
$baseUrl
.
$separator
?>
page=
<?=
$pagination
[
'prev_page'
]
?>
"
class=
"page-link"
title=
"السابق"
>
<svg
xmlns=
"http://www.w3.org/2000/svg"
width=
"16"
height=
"16"
viewBox=
"0 0 24 24"
fill=
"none"
stroke=
"currentColor"
stroke-width=
"2"
stroke-linecap=
"round"
stroke-linejoin=
"round"
><polyline
points=
"9 18 15 12 9 6"
/></svg>
</a>
</li>
<?php
endif
;
?>
<?php
foreach
(
$pagination
[
'pages'
]
as
$page
)
:
?>
...
...
@@ -31,7 +37,11 @@ $separator = str_contains($baseUrl, '?') ? '&' : '?';
<?php
endforeach
;
?>
<?php
if
(
$pagination
[
'has_next'
])
:
?>
<li><a
href=
"
<?=
$baseUrl
.
$separator
?>
page=
<?=
$pagination
[
'next_page'
]
?>
"
class=
"page-link"
>
التالي
</a></li>
<li>
<a
href=
"
<?=
$baseUrl
.
$separator
?>
page=
<?=
$pagination
[
'next_page'
]
?>
"
class=
"page-link"
title=
"التالي"
>
<svg
xmlns=
"http://www.w3.org/2000/svg"
width=
"16"
height=
"16"
viewBox=
"0 0 24 24"
fill=
"none"
stroke=
"currentColor"
stroke-width=
"2"
stroke-linecap=
"round"
stroke-linejoin=
"round"
><polyline
points=
"15 18 9 12 15 6"
/></svg>
</a>
</li>
<?php
endif
;
?>
</ul>
</nav>
\ No newline at end of file
</nav>
app/Shared/Components/sidebar.php
View file @
de5cfc33
This diff is collapsed.
Click to expand it.
app/Shared/Components/stats-card.php
View file @
de5cfc33
<?php
/**
* Stats card component — with Lucide icon support, animated counters, and hover effects.
*
* @var string $title
* @var string $value
* @var string $icon
* @var string $color (primary|success|danger|warning)
* @var string $link (optional)
* @var string $change (optional, e.g. "+5%")
* @var string $icon
Lucide icon name (e.g. 'users', 'banknote', 'trending-up')
* @var string $color
(primary|success|danger|warning)
* @var string $link
(optional)
* @var string $change
(optional, e.g. "+5%")
*/
$color
=
$color
??
'primary'
;
$iconName
=
$icon
??
'bar-chart-3'
;
$numericValue
=
(
string
)(
$value
??
'0'
);
$isNumeric
=
is_numeric
(
str_replace
([
','
,
' '
],
''
,
$numericValue
));
?>
<div
class=
"stats-card stats-card-
<?=
e
(
$color
)
?>
"
>
<div
class=
"stats-card-icon"
>
<?=
$icon
??
'📊'
?>
</div>
<div
class=
"stats-card-icon"
>
<i
data-lucide=
"
<?=
e
(
$iconName
)
?>
"
></i>
</div>
<div
class=
"stats-card-content"
>
<div
class=
"stats-card-title"
>
<?=
e
(
$title
??
''
)
?>
</div>
<div
class=
"stats-card-value"
>
<?=
e
((
string
)(
$value
??
'0'
)
)
?>
</div>
<div
class=
"stats-card-value"
<?=
$isNumeric
?
'data-count="'
.
e
(
str_replace
([
','
,
' '
],
''
,
$numericValue
))
.
'"'
:
''
?>
>
<?=
e
(
$numericValue
)
?>
</div>
<?php
if
(
!
empty
(
$change
))
:
?>
<div
class=
"stats-card-change"
>
<?=
e
(
$change
)
?>
</div>
<div
class=
"stats-card-change
<?=
str_starts_with
(
$change
,
'+'
)
?
'positive'
:
(
str_starts_with
(
$change
,
'-'
)
?
'negative'
:
''
)
?>
"
>
<?php
if
(
str_starts_with
(
$change
,
'+'
))
:
?>
<i
data-lucide=
"trending-up"
style=
"width:14px;height:14px;"
></i>
<?php
elseif
(
str_starts_with
(
$change
,
'-'
))
:
?>
<i
data-lucide=
"trending-down"
style=
"width:14px;height:14px;"
></i>
<?php
endif
;
?>
<?=
e
(
$change
)
?>
</div>
<?php
endif
;
?>
</div>
<?php
if
(
!
empty
(
$link
))
:
?>
<a
href=
"
<?=
e
(
$link
)
?>
"
class=
"stats-card-link"
>
عرض الكل ←
</a>
<a
href=
"
<?=
e
(
$link
)
?>
"
class=
"stats-card-link"
>
عرض الكل
<i
data-lucide=
"arrow-left"
style=
"width:14px;height:14px;display:inline;vertical-align:middle;"
></i>
</a>
<?php
endif
;
?>
</div>
\ No newline at end of file
</div>
app/Shared/Layout/auth.php
View file @
de5cfc33
This diff is collapsed.
Click to expand it.
app/Shared/Layout/main.php
View file @
de5cfc33
...
...
@@ -10,6 +10,7 @@ use App\Core\CSRF;
$app
=
App
::
getInstance
();
$employee
=
$app
->
currentEmployee
();
$employeeName
=
$employee
?
(
$employee
->
full_name_ar
??
'مستخدم'
)
:
'زائر'
;
$employeeInitial
=
mb_substr
(
$employeeName
,
0
,
1
);
$currentPath
=
parse_url
(
$_SERVER
[
'REQUEST_URI'
]
??
'/'
,
PHP_URL_PATH
);
?>
<!DOCTYPE html>
...
...
@@ -18,12 +19,34 @@ $currentPath = parse_url($_SERVER['REQUEST_URI'] ?? '/', PHP_URL_PATH);
<meta
charset=
"UTF-8"
>
<meta
name=
"viewport"
content=
"width=device-width, initial-scale=1.0"
>
<meta
name=
"csrf-token"
content=
"
<?=
e
(
CSRF
::
token
())
?>
"
>
<title>
<?=
$__template
->
yield
(
'title'
,
'لوحة التحكم'
)
?>
— نادي النادي شيراتون
</title>
<title>
<?=
$__template
->
yield
(
'title'
,
'لوحة التحكم'
)
?>
— THE CLUB
</title>
<!-- Fonts -->
<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=Cairo:wght@400;500;600;700;800;900&display=swap"
rel=
"stylesheet"
>
<!-- Lucide Icons -->
<script
src=
"https://unpkg.com/lucide@latest/dist/umd/lucide.min.js"
></script>
<!-- Main Stylesheet -->
<link
rel=
"stylesheet"
href=
"
<?=
url
(
'assets/css/main.css'
)
?>
"
>
<?=
$__template
->
yield
(
'styles'
,
''
)
?>
</head>
<body>
<!-- Page Loading Overlay -->
<div
class=
"page-loading"
id=
"page-loading"
>
<div
class=
"loader"
>
<div
class=
"loader-dot"
></div>
<div
class=
"loader-dot"
></div>
<div
class=
"loader-dot"
></div>
</div>
</div>
<!-- Sidebar Mobile Overlay -->
<div
class=
"sidebar-overlay"
id=
"sidebar-overlay"
onclick=
"closeSidebar()"
></div>
<!-- Sidebar -->
<aside
class=
"sidebar"
id=
"sidebar"
>
<?php
$__template
->
include
(
'Shared.Components.sidebar'
);
?>
...
...
@@ -33,9 +56,11 @@ $currentPath = parse_url($_SERVER['REQUEST_URI'] ?? '/', PHP_URL_PATH);
<div
class=
"main-wrapper"
id=
"main-wrapper"
>
<!-- Top Header -->
<header
class=
"top-header"
>
<header
class=
"top-header"
id=
"top-header"
>
<div
class=
"header-right"
>
<button
class=
"sidebar-toggle-btn"
onclick=
"toggleSidebar()"
>
☰
</button>
<button
class=
"sidebar-toggle-btn"
onclick=
"toggleSidebar()"
aria-label=
"toggle sidebar"
>
<i
data-lucide=
"menu"
style=
"width:20px;height:20px;"
></i>
</button>
<div
class=
"header-title"
>
<h1>
<?=
$__template
->
yield
(
'title'
,
'لوحة التحكم'
)
?>
</h1>
</div>
...
...
@@ -44,7 +69,10 @@ $currentPath = parse_url($_SERVER['REQUEST_URI'] ?? '/', PHP_URL_PATH);
<?=
$__template
->
yield
(
'page_actions'
,
''
)
?>
<div
class=
"header-user"
>
<span
class=
"header-user-name"
>
<?=
e
(
$employeeName
)
?>
</span>
<a
href=
"/logout"
class=
"header-logout"
title=
"تسجيل الخروج"
>
🚪
</a>
<div
class=
"header-user-avatar"
>
<?=
e
(
$employeeInitial
)
?>
</div>
<a
href=
"/logout"
class=
"header-logout"
title=
"تسجيل الخروج"
>
<i
data-lucide=
"log-out"
style=
"width:18px;height:18px;"
></i>
</a>
</div>
</div>
</header>
...
...
@@ -52,6 +80,9 @@ $currentPath = parse_url($_SERVER['REQUEST_URI'] ?? '/', PHP_URL_PATH);
<!-- Alerts -->
<?php
$__template
->
include
(
'Shared.Components.alerts'
);
?>
<!-- Toast Container -->
<div
id=
"toast-container"
></div>
<!-- Page Content -->
<main
class=
"page-content"
>
<?=
$__template
->
yield
(
'content'
,
''
)
?>
...
...
@@ -59,30 +90,77 @@ $currentPath = parse_url($_SERVER['REQUEST_URI'] ?? '/', PHP_URL_PATH);
<!-- Footer -->
<footer
class=
"page-footer"
>
<span>
نادي النادي شيراتون
©
<?=
date
(
'Y'
)
?>
</span>
<span>
الإصدار
1.0.0
</span>
<span>
THE CLUB Sheraton
©
<?=
date
(
'Y'
)
?>
</span>
<span>
v
1.0.0
</span>
<span>
<?=
arabic_date
(
date
(
'Y-m-d'
))
?>
</span>
</footer>
</div>
<script
src=
"
<?=
url
(
'assets/js/app.js'
)
?>
"
></script>
<script>
// Initialize Lucide icons
lucide
.
createIcons
();
// Sidebar functions
function
toggleSidebar
()
{
var
sb
=
document
.
getElementById
(
'sidebar'
);
var
mw
=
document
.
getElementById
(
'main-wrapper'
);
sb
.
classList
.
toggle
(
'collapsed'
);
mw
.
classList
.
toggle
(
'sidebar-collapsed'
);
var
overlay
=
document
.
getElementById
(
'sidebar-overlay'
);
var
isMobile
=
window
.
innerWidth
<=
1024
;
if
(
isMobile
)
{
sb
.
classList
.
toggle
(
'show'
);
overlay
.
classList
.
toggle
(
'active'
);
}
else
{
sb
.
classList
.
toggle
(
'collapsed'
);
mw
.
classList
.
toggle
(
'sidebar-collapsed'
);
}
}
function
closeSidebar
()
{
var
sb
=
document
.
getElementById
(
'sidebar'
);
var
overlay
=
document
.
getElementById
(
'sidebar-overlay'
);
sb
.
classList
.
remove
(
'show'
);
overlay
.
classList
.
remove
(
'active'
);
}
function
toggleSubmenu
(
el
)
{
var
parent
=
el
.
parentElement
;
var
submenu
=
parent
.
querySelector
(
'.sidebar-submenu'
);
if
(
submenu
)
{
var
isOpen
=
submenu
.
style
.
display
===
'block'
;
submenu
.
style
.
display
=
isOpen
?
'none'
:
'block'
;
var
isOpen
=
parent
.
classList
.
contains
(
'open'
);
parent
.
classList
.
toggle
(
'open'
,
!
isOpen
);
if
(
!
isOpen
)
{
submenu
.
style
.
maxHeight
=
submenu
.
scrollHeight
+
'px'
;
submenu
.
style
.
display
=
'block'
;
}
else
{
submenu
.
style
.
maxHeight
=
'0'
;
setTimeout
(
function
()
{
if
(
!
parent
.
classList
.
contains
(
'open'
))
{
submenu
.
style
.
display
=
'none'
;
}
},
300
);
}
}
}
// Header scroll shadow
var
header
=
document
.
getElementById
(
'top-header'
);
if
(
header
)
{
window
.
addEventListener
(
'scroll'
,
function
()
{
header
.
classList
.
toggle
(
'scrolled'
,
window
.
scrollY
>
10
);
},
{
passive
:
true
});
}
// Hide page loading
window
.
addEventListener
(
'load'
,
function
()
{
var
loader
=
document
.
getElementById
(
'page-loading'
);
if
(
loader
)
{
loader
.
classList
.
add
(
'hidden'
);
setTimeout
(
function
()
{
loader
.
remove
();
},
300
);
}
});
</script>
<?=
$__template
->
yield
(
'scripts'
,
''
)
?>
</body>
</html>
\ No newline at end of file
</html>
app/Shared/Layout/print.php
View file @
de5cfc33
...
...
@@ -3,20 +3,53 @@
<head>
<meta
charset=
"UTF-8"
>
<title>
<?=
$__template
->
yield
(
'title'
,
'طباعة'
)
?>
</title>
<link
rel=
"stylesheet"
href=
"
<?=
url
(
'assets/css/main.css'
)
?>
"
>
<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=Cairo:wght@400;600;700&display=swap"
rel=
"stylesheet"
>
<style>
body
{
padding
:
20px
;
background
:
#fff
;
}
@media
print
{
body
{
padding
:
0
;
}
}
*
{
box-sizing
:
border-box
;
margin
:
0
;
padding
:
0
;
}
body
{
padding
:
30px
;
background
:
#fff
;
font-family
:
'Cairo'
,
'Segoe UI'
,
sans-serif
;
font-size
:
13px
;
color
:
#1a1a2e
;
direction
:
rtl
;
line-height
:
1.7
;
}
.print-header
{
text-align
:
center
;
margin-bottom
:
24px
;
padding-bottom
:
16px
;
border-bottom
:
2px
solid
#0D7377
;
}
.print-header
h2
{
color
:
#0D7377
;
font-size
:
20px
;
font-weight
:
800
;
margin
:
0
0
4px
;
}
.print-header
p
{
color
:
#6B7280
;
font-size
:
12px
;
margin
:
0
;
}
table
{
width
:
100%
;
border-collapse
:
collapse
;
}
th
,
td
{
border
:
1px
solid
#e2e8f0
;
padding
:
8px
12px
;
text-align
:
right
;
font-size
:
12px
;
}
th
{
background
:
#f8fafc
;
font-weight
:
600
;
color
:
#475569
;
}
@media
print
{
body
{
padding
:
0
;
}
}
</style>
</head>
<body>
<div
class=
"print-header"
style=
"text-align:center;margin-bottom:20px;border-bottom:2px solid #0D7377;padding-bottom:10px;"
>
<h2
style=
"color:#0D7377;margin:0;"
>
نادي النادي شيراتون
</h2>
<p
style=
"color:#6B7280;margin:5px 0;"
>
<?=
arabic_date
(
today
())
?>
</p>
<div
class=
"print-header"
>
<h2>
نادي النادي شيراتون
</h2>
<p>
<?=
arabic_date
(
today
())
?>
</p>
</div>
<?=
$__template
->
yield
(
'content'
,
''
)
?>
<script>
window
.
onload
=
function
()
{
window
.
print
();
}
</script>
</body>
</html>
\ No newline at end of file
</html>
public/assets/css/main.css
View file @
de5cfc33
This diff is collapsed.
Click to expand it.
public/assets/js/app.js
View file @
de5cfc33
This diff is collapsed.
Click to expand it.
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