Commit e0d5ecfb authored by Mahmoud Aglan's avatar Mahmoud Aglan

cool

parent d0024d34
......@@ -613,12 +613,15 @@ class TutorialController extends Controller
$tutorials = [];
foreach ($section['tutorials'] as $slug => $tutorial) {
$viewFile = $section['viewDir'] . '/' . str_replace('-', '_', $slug) . '.php';
$content = '';
$extracted = ['steps' => [], 'images' => []];
if (file_exists($viewFile)) {
$content = file_get_contents($viewFile);
$content = $this->extractTutorialContent($content);
$raw = file_get_contents($viewFile);
$extracted = $this->extractTutorialSteps($raw);
}
$tutorials[$slug] = array_merge($tutorial, ['htmlContent' => $content]);
$tutorials[$slug] = array_merge($tutorial, [
'steps' => $extracted['steps'],
'images' => $extracted['images'],
]);
}
$book['sections'][$key] = [
'title' => $section['title'],
......@@ -659,14 +662,16 @@ class TutorialController extends Controller
return $book;
}
private function extractTutorialContent(string $raw): string
private function extractTutorialSteps(string $raw): array
{
$steps = [];
$start = strpos($raw, '<div class="tut-page">');
if ($start === false) {
$start = strpos($raw, '<div class="tut-header">');
}
if ($start === false) {
return '';
return $steps;
}
$content = substr($raw, $start);
......@@ -676,11 +681,44 @@ class TutorialController extends Controller
$content = substr($content, 0, $navPos);
}
$content = preg_replace('/<div class="tut-breadcrumb">.*?<\/div>/s', '', $content);
$content = str_replace('loading="lazy"', '', $content);
preg_match_all(
'/<div class="tut-step">(.*?)<\/div>\s*<\/div>/s',
$content,
$stepMatches
);
if (empty($stepMatches[1])) {
preg_match_all(
'/<div class="tut-step">(.+?)(?=<div class="tut-step">|<div class="tut-nav">|$)/s',
$content,
$stepMatches
);
}
foreach ($stepMatches[0] as $stepHtml) {
$title = '';
if (preg_match('/<h3 class="tut-step-title">(.*?)<\/h3>/s', $stepHtml, $m)) {
$title = strip_tags($m[1]);
}
$body = '';
if (preg_match('/<div class="tut-step-body">(.*)/s', $stepHtml, $m)) {
$body = $m[1];
$body = preg_replace('/<\/div>\s*$/', '', $body);
$body = preg_replace('/<i\s+data-lucide="[^"]*"[^>]*><\/i>/', '', $body);
$body = str_replace('loading="lazy"', '', $body);
}
$content = preg_replace('/<i\s+data-lucide="[^"]*"[^>]*><\/i>/', '', $content);
if ($title || $body) {
$steps[] = ['title' => $title, 'body' => $body];
}
}
$images = [];
if (preg_match_all('/<img[^>]+src="([^"]+)"[^>]*>/i', $content, $imgMatches)) {
$images = $imgMatches[1];
}
return $content;
return ['steps' => $steps, 'images' => $images];
}
}
......@@ -254,6 +254,37 @@ final class TutorialRegistry
'icon' => 'sliders',
'color' => '#64748B',
],
// ── إضافات جديدة ──────────────────────────────────
'dashboard' => [
'title' => 'لوحة التحكم',
'subtitle' => 'نظرة عامة على مؤشرات الأداء والتنبيهات',
'icon' => 'layout-dashboard',
'color' => '#0F766E',
],
'family' => [
'title' => 'العائلة والتابعين',
'subtitle' => 'إضافة الأزواج والأبناء والأعضاء المؤقتين',
'icon' => 'heart-handshake',
'color' => '#DB2777',
],
'transfers-waivers' => [
'title' => 'التحويلات والتنازلات',
'subtitle' => 'تحويل العضوية والتنازل والطلاق والوفاة',
'icon' => 'arrow-right-left',
'color' => '#7C3AED',
],
'trainer-portal' => [
'title' => 'بوابة المدربين',
'subtitle' => 'لوحة المدرب وجداوله ومجموعاته',
'icon' => 'graduation-cap',
'color' => '#0D9488',
],
'parent-portal' => [
'title' => 'بوابة أولياء الأمور',
'subtitle' => 'متابعة الأبناء والأنشطة والحضور',
'icon' => 'baby',
'color' => '#7C3AED',
],
];
}
......@@ -300,6 +331,11 @@ final class TutorialRegistry
'medical-board' => self::medicalBoardTutorials(),
'access-matrix' => self::accessMatrixTutorials(),
'rules' => self::rulesTutorials(),
'dashboard' => self::dashboardTutorials(),
'family' => self::familyTutorials(),
'transfers-waivers' => self::transfersWaiversTutorials(),
'trainer-portal' => self::trainerPortalTutorials(),
'parent-portal' => self::parentPortalTutorials(),
default => [],
};
}
......@@ -498,6 +534,23 @@ final class TutorialRegistry
'sa-registration.temp-card-workflow' => 'sa-cards.png',
'sa-registration.booking-wizard' => 'sa-booking-wizard.png',
'sa-registration.academy-pricing' => 'sa-pricing.png',
'dashboard.overview' => 'dashboard.png',
'dashboard.kpi-cards' => 'dashboard.png',
'dashboard.activity-log' => 'dashboard.png',
'dashboard.alerts-widget' => 'dashboard.png',
'family.add-spouse' => 'members-list.png',
'family.add-child' => 'members-list.png',
'family.add-temporary' => 'temporary-list.png',
'family.children-aging' => 'members-list.png',
'transfers-waivers.member-transfer' => 'transfers-list.png',
'transfers-waivers.waiver-request' => 'transfers-list.png',
'transfers-waivers.divorce-transfer' => 'transfers-list.png',
'transfers-waivers.death-registration' => 'transfers-list.png',
'trainer-portal.trainer-dashboard' => 'sa-coaches.png',
'trainer-portal.my-groups' => 'sa-groups.png',
'trainer-portal.record-attendance' => 'sa-attendance.png',
'parent-portal.view-children' => 'parents-list.png',
'parent-portal.attendance-report' => 'parents-list.png',
];
return $map[$section . '.' . $slug] ?? self::getScreenshot($section);
......@@ -542,10 +595,15 @@ final class TutorialRegistry
'playgrounds' => 'sa-mirror.png',
'sa-registration' => 'sa-registration.png',
'news' => 'dashboard.png',
'parents' => 'sa-players.png',
'medical-board' => 'sa-players.png',
'access-matrix' => 'roles-list.png',
'rules' => 'pricing-management.png',
'parents' => 'parents-list.png',
'medical-board' => 'medical-board.png',
'access-matrix' => 'access-matrix.png',
'rules' => 'rules-engine.png',
'dashboard' => 'dashboard.png',
'family' => 'members-list.png',
'transfers-waivers' => 'transfers-list.png',
'trainer-portal' => 'sa-coaches.png',
'parent-portal' => 'parents-list.png',
];
return $map[$section] ?? null;
}
......@@ -1622,6 +1680,11 @@ final class TutorialRegistry
'medical-board' => self::medicalBoardCategories(),
'access-matrix' => self::accessMatrixCategories(),
'rules' => self::rulesCategories(),
'dashboard' => self::dashboardCategories(),
'family' => self::familyCategories(),
'transfers-waivers' => self::transfersWaiversCategories(),
'trainer-portal' => self::trainerPortalCategories(),
'parent-portal' => self::parentPortalCategories(),
default => [],
};
}
......@@ -3759,4 +3822,122 @@ final class TutorialRegistry
'rules' => ['label' => 'القواعد العامة', 'icon' => 'sliders', 'color' => '#64748B'],
];
}
// ─────────────────────────────────────────────────────────────────────
// DASHBOARD
// ─────────────────────────────────────────────────────────────────────
private static function dashboardTutorials(): array
{
return [
'overview' => ['title' => 'نظرة عامة على لوحة التحكم', 'subtitle' => 'فهم المؤشرات والرسوم البيانية', 'icon' => 'layout-dashboard', 'color' => '#0F766E', 'category' => 'overview', 'order' => 1],
'kpi-cards' => ['title' => 'بطاقات المؤشرات', 'subtitle' => 'الأعضاء النشطين والإيرادات والمقابلات والأقساط', 'icon' => 'bar-chart-3', 'color' => '#3B82F6', 'category' => 'overview', 'order' => 2],
'activity-log' => ['title' => 'سجل النشاط الأخير', 'subtitle' => 'متابعة آخر العمليات في النظام', 'icon' => 'activity', 'color' => '#F59E0B', 'category' => 'monitoring', 'order' => 3],
'alerts-widget' => ['title' => 'التنبيهات والإنذارات', 'subtitle' => 'فهم ألوان التنبيهات والاستجابة لها', 'icon' => 'bell-ring', 'color' => '#DC2626', 'category' => 'monitoring', 'order' => 4],
];
}
private static function dashboardCategories(): array
{
return [
'overview' => ['label' => 'نظرة عامة', 'icon' => 'layout-dashboard', 'color' => '#0F766E'],
'monitoring' => ['label' => 'المتابعة', 'icon' => 'activity', 'color' => '#F59E0B'],
];
}
// ─────────────────────────────────────────────────────────────────────
// FAMILY (CHILDREN, SPOUSES, TEMPORARY)
// ─────────────────────────────────────────────────────────────────────
private static function familyTutorials(): array
{
return [
'add-spouse' => ['title' => 'إضافة زوج/زوجة', 'subtitle' => 'تسجيل زوج العضو وإصدار كارنيه', 'icon' => 'heart', 'color' => '#DB2777', 'category' => 'registration', 'order' => 1],
'add-child' => ['title' => 'إضافة ابن/ابنة', 'subtitle' => 'تسجيل أبناء العضو مع بيانات السن', 'icon' => 'baby', 'color' => '#8B5CF6', 'category' => 'registration', 'order' => 2],
'add-temporary' => ['title' => 'عضو مؤقت', 'subtitle' => 'إضافة تابع مؤقت بمدة محددة', 'icon' => 'timer', 'color' => '#F59E0B', 'category' => 'registration', 'order' => 3],
'children-aging' => ['title' => 'بلوغ السن القانوني', 'subtitle' => 'متابعة الأبناء الذين بلغوا سن التحويل', 'icon' => 'calendar-clock', 'color' => '#DC2626', 'category' => 'lifecycle', 'order' => 4],
'family-pricing' => ['title' => 'رسوم التابعين', 'subtitle' => 'حساب رسوم الزوج والأبناء', 'icon' => 'calculator', 'color' => '#059669', 'category' => 'financial', 'order' => 5],
'dependent-carnet' => ['title' => 'كارنيه التابع', 'subtitle' => 'إصدار وطباعة كارنيه لكل تابع', 'icon' => 'id-card', 'color' => '#0284C7', 'category' => 'lifecycle', 'order' => 6],
];
}
private static function familyCategories(): array
{
return [
'registration' => ['label' => 'التسجيل', 'icon' => 'user-plus', 'color' => '#DB2777'],
'lifecycle' => ['label' => 'دورة الحياة', 'icon' => 'refresh-cw', 'color' => '#8B5CF6'],
'financial' => ['label' => 'المالية', 'icon' => 'calculator', 'color' => '#059669'],
];
}
// ─────────────────────────────────────────────────────────────────────
// TRANSFERS & WAIVERS (LIFE EVENTS)
// ─────────────────────────────────────────────────────────────────────
private static function transfersWaiversTutorials(): array
{
return [
'member-transfer' => ['title' => 'تحويل العضوية', 'subtitle' => 'نقل عضوية من شخص لآخر مع الرسوم', 'icon' => 'arrow-right-left', 'color' => '#3B82F6', 'category' => 'transfers', 'order' => 1],
'waiver-request' => ['title' => 'طلب تنازل', 'subtitle' => 'التنازل عن العضوية مع سير الموافقات', 'icon' => 'file-minus', 'color' => '#7C3AED', 'category' => 'transfers', 'order' => 2],
'divorce-transfer' => ['title' => 'تحويل طلاق', 'subtitle' => 'فصل العضوية عند الطلاق مع موافقة المجلس', 'icon' => 'split', 'color' => '#DC2626', 'category' => 'life-events', 'order' => 3],
'death-registration' => ['title' => 'تسجيل وفاة', 'subtitle' => 'تحويل العضوية للورثة مع المستندات', 'icon' => 'heart-off', 'color' => '#475569', 'category' => 'life-events', 'order' => 4],
'freeze-membership' => ['title' => 'تجميد العضوية', 'subtitle' => 'تجميد مؤقت مع الحفاظ على الرقم', 'icon' => 'pause-circle', 'color' => '#0EA5E9', 'category' => 'status', 'order' => 5],
'drop-membership' => ['title' => 'إسقاط العضوية', 'subtitle' => 'إسقاط نهائي بسبب عدم السداد', 'icon' => 'user-x', 'color' => '#DC2626', 'category' => 'status', 'order' => 6],
];
}
private static function transfersWaiversCategories(): array
{
return [
'transfers' => ['label' => 'التحويل والتنازل', 'icon' => 'arrow-right-left', 'color' => '#3B82F6'],
'life-events' => ['label' => 'أحداث الحياة', 'icon' => 'heart', 'color' => '#DC2626'],
'status' => ['label' => 'تغيير الحالة', 'icon' => 'toggle-right', 'color' => '#0EA5E9'],
];
}
// ─────────────────────────────────────────────────────────────────────
// TRAINER PORTAL
// ─────────────────────────────────────────────────────────────────────
private static function trainerPortalTutorials(): array
{
return [
'trainer-dashboard' => ['title' => 'لوحة تحكم المدرب', 'subtitle' => 'الحصص اليوم والمجموعات والإحصائيات', 'icon' => 'layout-dashboard', 'color' => '#0D9488', 'category' => 'portal', 'order' => 1],
'my-groups' => ['title' => 'مجموعاتي', 'subtitle' => 'عرض اللاعبين المسجلين في كل مجموعة', 'icon' => 'users', 'color' => '#3B82F6', 'category' => 'portal', 'order' => 2],
'record-attendance' => ['title' => 'تسجيل الحضور', 'subtitle' => 'تسجيل حضور وغياب اللاعبين', 'icon' => 'check-square', 'color' => '#059669', 'category' => 'operations', 'order' => 3],
'session-feedback' => ['title' => 'تغذية راجعة للحصة', 'subtitle' => 'تقييم أداء المجموعة بعد الحصة', 'icon' => 'message-circle', 'color' => '#F59E0B', 'category' => 'operations', 'order' => 4],
'my-schedule' => ['title' => 'جدولي الأسبوعي', 'subtitle' => 'عرض مواعيد التدريب والفترات', 'icon' => 'calendar', 'color' => '#6366F1', 'category' => 'portal', 'order' => 5],
];
}
private static function trainerPortalCategories(): array
{
return [
'portal' => ['label' => 'البوابة', 'icon' => 'monitor', 'color' => '#0D9488'],
'operations' => ['label' => 'العمليات', 'icon' => 'check-square', 'color' => '#059669'],
];
}
// ─────────────────────────────────────────────────────────────────────
// PARENT PORTAL
// ─────────────────────────────────────────────────────────────────────
private static function parentPortalTutorials(): array
{
return [
'parent-login' => ['title' => 'تسجيل دخول ولي الأمر', 'subtitle' => 'الدخول للبوابة ومتابعة الأبناء', 'icon' => 'log-in', 'color' => '#7C3AED', 'category' => 'access', 'order' => 1],
'view-children' => ['title' => 'عرض بيانات الأبناء', 'subtitle' => 'المجموعات والحضور والتقييمات', 'icon' => 'users', 'color' => '#3B82F6', 'category' => 'monitoring', 'order' => 2],
'attendance-report' => ['title' => 'تقرير الحضور', 'subtitle' => 'نسبة حضور كل ابن شهرياً', 'icon' => 'bar-chart', 'color' => '#059669', 'category' => 'monitoring', 'order' => 3],
'payment-history' => ['title' => 'سجل المدفوعات', 'subtitle' => 'عرض الإيصالات والمستحقات', 'icon' => 'receipt', 'color' => '#F59E0B', 'category' => 'financial', 'order' => 4],
];
}
private static function parentPortalCategories(): array
{
return [
'access' => ['label' => 'الوصول', 'icon' => 'log-in', 'color' => '#7C3AED'],
'monitoring' => ['label' => 'المتابعة', 'icon' => 'eye', 'color' => '#3B82F6'],
'financial' => ['label' => 'المالية', 'icon' => 'receipt', 'color' => '#F59E0B'],
];
}
}
......@@ -4,19 +4,13 @@
<meta charset="UTF-8">
<title>Book of the ERP - كتاب النظام</title>
<style>
/* ══════════════════════════════════════════════════════════════
SCREEN-FIRST DESIGN
Normal document flow for browser viewing.
Print enhancements added via @media print only.
══════════════════════════════════════════════════════════════ */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
body {
font-family: 'Noto Sans Arabic', 'Segoe UI', Tahoma, Arial, sans-serif;
font-size: 14px;
line-height: 1.8;
color: #1F2937;
color: #1f2937;
direction: rtl;
background: #f1f5f9;
padding: 24px;
......@@ -24,23 +18,23 @@ body {
print-color-adjust: exact;
}
.container { max-width: 800px; margin: 0 auto; }
/* ── COVER ── */
.book-cover {
max-width: 800px;
margin: 0 auto 32px;
.cover {
padding: 80px 48px;
background: linear-gradient(160deg, #0F0A2A 0%, #1A1145 30%, #2D1B69 60%, #4C1D95 100%);
background: linear-gradient(160deg, #0F0A2A, #1A1145 30%, #2D1B69 60%, #4C1D95);
border-radius: 16px;
color: #fff;
text-align: center;
position: relative;
overflow: hidden;
margin-bottom: 32px;
}
.book-cover::after {
.cover::after {
content: '';
position: absolute;
bottom: 0; left: 0; right: 0;
height: 5px;
bottom: 0; left: 0; right: 0; height: 5px;
background: linear-gradient(90deg, #8B5CF6, #EC4899, #F59E0B, #10B981, #3B82F6);
}
.cover-icon {
......@@ -52,48 +46,37 @@ body {
border: 2px solid rgba(255,255,255,0.12);
}
.cover-icon svg { width: 50px; height: 50px; fill: none; stroke: #fff; stroke-width: 1.5; }
.book-cover h1 { font-size: 48px; font-weight: 900; margin-bottom: 8px; letter-spacing: -1px; }
.book-cover .subtitle { font-size: 22px; font-weight: 600; opacity: 0.85; margin-bottom: 12px; }
.book-cover .desc { font-size: 14px; opacity: 0.6; max-width: 420px; margin: 0 auto 48px; line-height: 2; }
.cover-stats { display: flex; gap: 40px; justify-content: center; margin-bottom: 48px; }
.cover-stat-num { display: block; font-size: 32px; font-weight: 900; }
.cover-stat-label { font-size: 11px; opacity: 0.5; }
.cover-meta { font-size: 11px; opacity: 0.4; border-top: 1px solid rgba(255,255,255,0.1); padding-top: 16px; }
.cover h1 { font-size: 44px; font-weight: 900; margin-bottom: 8px; }
.cover .sub { font-size: 20px; opacity: 0.85; margin-bottom: 12px; }
.cover .desc { font-size: 14px; opacity: 0.6; max-width: 420px; margin: 0 auto 40px; }
.cover-stats { display: flex; gap: 40px; justify-content: center; margin-bottom: 40px; }
.cover-stats span { display: block; }
.cover-stats .num { font-size: 32px; font-weight: 900; }
.cover-stats .lbl { font-size: 11px; opacity: 0.5; }
.cover .meta { font-size: 11px; opacity: 0.4; border-top: 1px solid rgba(255,255,255,0.1); padding-top: 16px; }
/* ── TABLE OF CONTENTS ── */
.book-toc {
max-width: 800px;
margin: 0 auto 32px;
/* ── TOC ── */
.toc {
padding: 40px;
background: #fff;
border-radius: 16px;
border: 1px solid #e2e8f0;
}
.book-toc h2 { font-size: 28px; font-weight: 900; text-align: center; margin-bottom: 8px; color: #1a1a2e; }
.book-toc .toc-sub { font-size: 13px; color: #6b7280; text-align: center; margin-bottom: 32px; }
.toc-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.toc-item {
padding: 14px 16px;
background: #f9fafb;
border-radius: 10px;
border-right: 4px solid var(--c);
}
.toc-item-title { font-size: 13px; font-weight: 700; color: #1a1a2e; display: flex; align-items: center; gap: 8px; }
.toc-item-num {
display: inline-flex; align-items: center; justify-content: center;
width: 22px; height: 22px; border-radius: 6px;
background: var(--c); color: #fff; font-size: 10px; font-weight: 800;
}
.toc-item-badge { margin-right: auto; background: #ede9fe; color: #7c3aed; font-size: 9px; font-weight: 700; padding: 2px 8px; border-radius: 10px; }
.toc-item ul { list-style: none; margin: 8px 0 0; padding: 0; }
.toc-item li { font-size: 11px; color: #6b7280; padding: 2px 0 2px 0; padding-right: 14px; position: relative; }
.toc-item li::before { content: '—'; position: absolute; right: 0; color: #d1d5db; font-size: 9px; }
margin-bottom: 32px;
}
.toc h2 { font-size: 26px; font-weight: 900; text-align: center; margin-bottom: 8px; }
.toc .toc-sub { font-size: 13px; color: #6b7280; text-align: center; margin-bottom: 28px; }
.toc-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.toc-entry { padding: 12px 16px; background: #f9fafb; border-radius: 10px; border-right: 4px solid var(--c); }
.toc-entry-head { display: flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 700; color: #1a1a2e; }
.toc-num { width: 22px; height: 22px; border-radius: 6px; background: var(--c); color: #fff; font-size: 10px; font-weight: 800; display: inline-flex; align-items: center; justify-content: center; }
.toc-badge { margin-right: auto; background: #ede9fe; color: #7c3aed; font-size: 9px; font-weight: 700; padding: 2px 8px; border-radius: 10px; }
.toc-entry ul { list-style: none; margin: 6px 0 0; padding: 0; }
.toc-entry li { font-size: 11px; color: #6b7280; padding: 1px 0; }
/* ── SECTION DIVIDER ── */
.section-divider {
max-width: 800px;
margin: 48px auto 32px;
padding: 60px 40px;
.divider {
margin: 40px 0 28px;
padding: 56px 40px;
background: #fafbff;
border-radius: 16px;
border: 1px solid #e2e8f0;
......@@ -101,172 +84,119 @@ body {
position: relative;
overflow: hidden;
}
.section-divider::before {
content: '';
position: absolute; top: 0; left: 0; right: 0; height: 5px;
background: var(--c);
.divider::before {
content: ''; position: absolute; top: 0; left: 0; right: 0; height: 5px; background: var(--c);
}
.section-divider-icon {
width: 72px; height: 72px;
margin: 0 auto 24px;
background: var(--c);
border-radius: 18px;
.divider-icon {
width: 68px; height: 68px; margin: 0 auto 20px;
background: var(--c); border-radius: 18px;
display: flex; align-items: center; justify-content: center;
}
.section-divider-icon svg { width: 36px; height: 36px; fill: none; stroke: #fff; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.section-divider h2 { font-size: 32px; font-weight: 900; color: #1a1a2e; margin-bottom: 8px; }
.section-divider .section-sub { font-size: 14px; color: #6b7280; margin-bottom: 24px; max-width: 360px; margin-left: auto; margin-right: auto; line-height: 2; }
.section-stats { display: inline-flex; gap: 24px; background: #fff; padding: 14px 28px; border-radius: 12px; border: 1px solid #e5e7eb; }
.section-stat-num { display: block; font-size: 22px; font-weight: 900; color: var(--c); }
.section-stat-label { font-size: 10px; color: #9ca3af; font-weight: 600; }
.divider-icon svg { width: 34px; height: 34px; fill: none; stroke: #fff; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.divider h2 { font-size: 30px; font-weight: 900; color: #1a1a2e; margin-bottom: 8px; }
.divider .divider-sub { font-size: 14px; color: #6b7280; margin-bottom: 20px; }
.divider-stats { display: inline-flex; gap: 20px; background: #fff; padding: 12px 24px; border-radius: 10px; border: 1px solid #e5e7eb; }
.divider-stats .stat-num { display: block; font-size: 20px; font-weight: 900; color: var(--c); }
.divider-stats .stat-lbl { font-size: 10px; color: #9ca3af; font-weight: 600; }
/* ── CATEGORY HEADER ── */
.cat-header {
max-width: 800px;
margin: 28px auto 16px;
/* ── CATEGORY ── */
.cat-head {
margin: 24px 0 14px;
padding: 10px 18px;
background: #f9fafb;
border-radius: 10px;
border-right: 5px solid var(--c);
font-size: 15px;
font-weight: 800;
color: #1a1a2e;
font-size: 15px; font-weight: 800; color: #1a1a2e;
}
/* ── TUTORIAL CARD ── */
.tutorial-card {
max-width: 800px;
margin: 0 auto 20px;
/* ── TUTORIAL ── */
.tut {
background: #fff;
border: 1px solid #e2e8f0;
border-radius: 12px;
overflow: hidden;
margin-bottom: 20px;
overflow: visible;
}
.tutorial-card-head {
padding: 16px 20px;
.tut-head {
padding: 14px 20px;
background: #f9fafb;
border-bottom: 1px solid #e5e7eb;
display: flex;
align-items: center;
gap: 14px;
display: flex; align-items: center; gap: 12px;
}
.tutorial-card-num {
width: 32px; height: 32px;
background: var(--c);
color: #fff;
border-radius: 10px;
display: flex; align-items: center; justify-content: center;
.tut-num {
width: 30px; height: 30px; background: var(--c); color: #fff;
border-radius: 8px; display: flex; align-items: center; justify-content: center;
font-size: 13px; font-weight: 800; flex-shrink: 0;
}
.tutorial-card-head h3 { font-size: 15px; font-weight: 700; color: #1a1a2e; margin: 0; }
.tutorial-card-head .t-sub { font-size: 11px; color: #6b7280; margin: 2px 0 0; }
.tutorial-card-body {
padding: 20px 24px;
}
.tut-head h3 { font-size: 15px; font-weight: 700; color: #1a1a2e; margin: 0; }
.tut-head .tsub { font-size: 11px; color: #6b7280; margin: 2px 0 0; }
.tut-body { padding: 18px 22px; }
/* ── STEP CARDS ── */
.step-card {
position: relative;
padding: 14px 16px 14px 48px;
margin-bottom: 10px;
background: #fff;
border: 1px solid #e5e7eb;
border-radius: 10px;
border-right: 4px solid var(--c);
}
.step-card-num {
position: absolute; left: 12px; top: 14px;
width: 26px; height: 26px;
background: #ede9fe; color: #7c3aed;
/* ── SCREENSHOT ── */
.tut-img {
margin: 0 0 14px;
border-radius: 8px;
display: flex; align-items: center; justify-content: center;
font-size: 11px; font-weight: 800;
border: 1px solid #e5e7eb;
overflow: hidden;
}
.step-card-title { font-size: 13px; font-weight: 700; color: #1a1a2e; margin-bottom: 4px; }
.step-card-body { font-size: 12px; color: #374151; line-height: 1.8; }
.step-card-body ul { margin: 6px 0; padding-right: 16px; }
.step-card-body li { margin-bottom: 4px; }
.tut-img img { width: 100%; height: auto; display: block; }
/* ── EXTRACTED HTML CONTENT STYLES ── */
.tutorial-card-body .tut-page { max-width: 100%; }
.tutorial-card-body .tut-header {
display: flex; align-items: center; gap: 14px;
margin-bottom: 20px; padding: 14px 16px;
background: #f9fafb; border-radius: 10px; border: 1px solid #e5e7eb;
}
.tutorial-card-body .tut-header-icon {
width: 40px; height: 40px;
background: linear-gradient(135deg, #7C3AED, #8B5CF6);
border-radius: 10px; display: flex; align-items: center; justify-content: center; flex-shrink: 0;
}
.tutorial-card-body .tut-header h1 { font-size: 16px; font-weight: 800; color: #1a1a2e; margin: 0; }
.tutorial-card-body .tut-header p { font-size: 11px; color: #6b7280; margin: 0; }
.tutorial-card-body .tut-step {
position: relative;
padding: 14px 16px 14px 48px;
/* ── STEP ── */
.step {
padding: 14px 18px;
margin-bottom: 10px;
background: #fff;
background: #fafbfc;
border: 1px solid #e5e7eb;
border-radius: 10px;
border-right: 4px solid #8B5CF6;
border-right: 4px solid var(--c);
display: flex;
gap: 12px;
align-items: flex-start;
}
.tutorial-card-body .tut-step-num {
position: absolute; left: 12px; top: 14px;
width: 26px; height: 26px;
.step-num {
width: 28px; height: 28px; flex-shrink: 0;
background: #ede9fe; color: #7c3aed;
border-radius: 8px; display: flex; align-items: center; justify-content: center;
font-size: 11px; font-weight: 800;
}
.tutorial-card-body .tut-step-title { font-size: 13px; font-weight: 700; color: #1a1a2e; margin-bottom: 4px; }
.tutorial-card-body .tut-step-body { font-size: 12px; color: #374151; line-height: 1.8; }
.tutorial-card-body .tut-step-body ul { margin: 6px 0; padding-right: 16px; }
.tutorial-card-body .tut-step-body li { margin-bottom: 4px; }
.tutorial-card-body .tut-step-body .field {
font-size: 12px; font-weight: 800;
}
.step-content { flex: 1; min-width: 0; }
.step-title { font-size: 13px; font-weight: 700; color: #1a1a2e; margin-bottom: 4px; }
.step-body { font-size: 12px; color: #374151; line-height: 1.9; }
.step-body ul { margin: 6px 0; padding-right: 16px; }
.step-body li { margin-bottom: 3px; }
.step-body .field {
display: inline-block; background: #f3f4f6; color: #1a1a2e;
padding: 1px 8px; border-radius: 4px; font-size: 11px; font-weight: 600; border: 1px solid #e5e7eb;
padding: 1px 7px; border-radius: 4px; font-size: 11px; font-weight: 600; border: 1px solid #e5e7eb;
}
.tutorial-card-body .tut-step-body .warn {
.step-body .warn {
display: block; background: #fffbeb; border: 1px solid #fde68a; border-right: 4px solid #f59e0b;
border-radius: 8px; padding: 10px 14px; margin: 8px 0; font-size: 11px; color: #92400e; line-height: 1.8;
border-radius: 8px; padding: 10px 14px; margin: 8px 0; font-size: 11px; color: #92400e;
}
.tutorial-card-body .tut-step-body .info {
.step-body .info {
display: block; background: #eff6ff; border: 1px solid #bfdbfe; border-right: 4px solid #3b82f6;
border-radius: 8px; padding: 10px 14px; margin: 8px 0; font-size: 11px; color: #1e40af; line-height: 1.8;
border-radius: 8px; padding: 10px 14px; margin: 8px 0; font-size: 11px; color: #1e40af;
}
.tutorial-card-body .tut-step-body .success {
.step-body .success {
display: block; background: #ecfdf5; border: 1px solid #a7f3d0; border-right: 4px solid #10b981;
border-radius: 8px; padding: 10px 14px; margin: 8px 0; font-size: 11px; color: #065f46; line-height: 1.8;
border-radius: 8px; padding: 10px 14px; margin: 8px 0; font-size: 11px; color: #065f46;
}
.tutorial-card-body .tut-step-body .tip {
.step-body .tip {
display: block; background: #f5f3ff; border: 1px solid #ddd6fe; border-right: 4px solid #8b5cf6;
border-radius: 8px; padding: 10px 14px; margin: 8px 0; font-size: 11px; color: #5b21b6; line-height: 1.8;
border-radius: 8px; padding: 10px 14px; margin: 8px 0; font-size: 11px; color: #5b21b6;
}
.tutorial-card-body .tut-diagram {
.step-body .tut-diagram {
background: #f8fafc; border: 1px solid #e2e8f0; border-radius: 8px;
padding: 14px; margin: 10px 0; font-family: monospace; font-size: 10px;
direction: ltr; text-align: left; line-height: 1.6;
}
.tutorial-card-body img {
max-width: 100%; height: auto; border-radius: 8px;
border: 1px solid #e5e7eb; margin: 12px 0;
box-shadow: 0 2px 8px rgba(0,0,0,0.06);
padding: 12px 14px; margin: 8px 0; font-family: monospace; font-size: 10px;
direction: ltr; text-align: left; line-height: 1.5; white-space: pre-wrap;
}
/* ── SECTION SCREENSHOT ── */
.section-screenshot {
max-width: 800px;
margin: 0 auto 24px;
text-align: center;
}
.section-screenshot img {
max-width: 100%; height: auto; border-radius: 12px;
border: 1px solid #e2e8f0; box-shadow: 0 4px 16px rgba(0,0,0,0.08);
}
.sec-img { margin: 0 0 24px; text-align: center; }
.sec-img img { max-width: 100%; border-radius: 12px; border: 1px solid #e2e8f0; }
/* ── BACK COVER ── */
.book-back {
max-width: 800px;
margin: 48px auto 0;
/* ── BACK ── */
.back {
margin-top: 40px;
padding: 60px;
background: linear-gradient(160deg, #0F0A2A, #1A1145, #2D1B69);
border-radius: 16px;
......@@ -275,87 +205,44 @@ body {
position: relative;
overflow: hidden;
}
.book-back::after {
content: '';
position: absolute; bottom: 0; left: 0; right: 0; height: 5px;
.back::after {
content: ''; position: absolute; bottom: 0; left: 0; right: 0; height: 5px;
background: linear-gradient(90deg, #8B5CF6, #EC4899, #F59E0B, #10B981, #3B82F6);
}
.book-back-icon {
width: 64px; height: 64px;
margin: 0 auto 20px;
background: rgba(255,255,255,0.08);
border-radius: 16px;
.back-icon {
width: 60px; height: 60px; margin: 0 auto 16px;
background: rgba(255,255,255,0.08); border-radius: 16px;
display: flex; align-items: center; justify-content: center;
border: 1px solid rgba(255,255,255,0.1);
}
.book-back-icon svg { width: 32px; height: 32px; fill: none; stroke: #fff; stroke-width: 1.5; }
.book-back h2 { font-size: 22px; font-weight: 800; margin-bottom: 8px; opacity: 0.9; }
.book-back p { font-size: 12px; opacity: 0.5; margin-bottom: 4px; }
.back-icon svg { width: 30px; height: 30px; fill: none; stroke: #fff; stroke-width: 1.5; }
.back h2 { font-size: 20px; font-weight: 800; margin-bottom: 6px; opacity: 0.9; }
.back p { font-size: 12px; opacity: 0.5; }
/* ══════════════════════════════════════════════════════════════
PRINT ONLY: page breaks, full-page elements, sizing
══════════════════════════════════════════════════════════════ */
/* ── PRINT ── */
@media print {
@page { size: A4; margin: 20mm 18mm 24mm 18mm; }
@page { size: A4; margin: 20mm 16mm 22mm 16mm; }
body { background: #fff; padding: 0; font-size: 11px; }
.container { max-width: 100%; }
.no-print { display: none !important; }
.book-cover, .book-toc, .section-divider, .tutorial-card, .cat-header, .section-screenshot, .book-back {
max-width: 100%; margin-left: 0; margin-right: 0; border: none; border-radius: 0; box-shadow: none;
}
.book-cover {
border-radius: 0;
min-height: 100vh;
margin-bottom: 0;
page-break-after: always;
}
.book-toc {
page-break-after: always;
margin-bottom: 0;
}
.section-divider {
page-break-before: always;
page-break-after: always;
min-height: 80vh;
margin-top: 0;
margin-bottom: 0;
}
.tutorial-card {
page-break-inside: avoid;
margin-bottom: 16px;
}
.step-card, .tutorial-card-body .tut-step {
page-break-inside: avoid;
}
.book-back {
page-break-before: always;
min-height: 80vh;
margin-top: 0;
border-radius: 0;
}
.cover { border-radius: 0; min-height: 90vh; margin-bottom: 0; page-break-after: always; }
.toc { page-break-after: always; margin-bottom: 0; border: none; border-radius: 0; }
.divider { page-break-before: always; page-break-after: always; min-height: 70vh; margin: 0; border: none; border-radius: 0; }
.tut { page-break-inside: avoid; border-radius: 0; }
.step { page-break-inside: avoid; }
.back { page-break-before: always; min-height: 70vh; margin: 0; border-radius: 0; }
}
</style>
</head>
<body>
<div class="container">
<?php
$sectionColors = [
'#8B5CF6', '#3B82F6', '#10B981', '#F59E0B', '#EF4444',
'#06B6D4', '#EC4899', '#14B8A6', '#F97316', '#6366F1',
'#84CC16', '#0EA5E9', '#D946EF', '#22C55E', '#E11D48',
'#0891B2', '#7C3AED', '#059669', '#DC2626', '#2563EB',
'#8B5CF6', '#3B82F6', '#10B981', '#F59E0B', '#EF4444',
'#06B6D4', '#EC4899', '#14B8A6', '#F97316', '#6366F1',
];
$colors = ['#8B5CF6','#3B82F6','#10B981','#F59E0B','#EF4444','#06B6D4','#EC4899','#14B8A6','#F97316','#6366F1','#84CC16','#0EA5E9','#D946EF','#22C55E','#E11D48','#0891B2','#7C3AED','#059669','#DC2626','#2563EB','#8B5CF6','#3B82F6','#10B981','#F59E0B','#EF4444','#06B6D4','#EC4899','#14B8A6','#F97316','#6366F1'];
$totalTutorials = 0;
$totalSections = count($data['sections']);
foreach ($data['sections'] as $s) {
$totalTutorials += count($s['tutorials']);
}
$sectionIcons = [
foreach ($data['sections'] as $s) { $totalTutorials += count($s['tutorials']); }
$icons = [
'membership' => '<path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M23 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/>',
'sports-activity' => '<circle cx="12" cy="12" r="10"/><path d="M12 8v4l3 3"/>',
'treasury' => '<rect x="2" y="4" width="20" height="16" rx="2"/><path d="M12 8v8"/><path d="M8 12h8"/>',
......@@ -363,39 +250,39 @@ $sectionIcons = [
];
?>
<!-- ═══ COVER ═══ -->
<div class="book-cover">
<!-- COVER -->
<div class="cover">
<div class="cover-icon">
<svg viewBox="0 0 24 24"><path d="M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z" stroke-linecap="round" stroke-linejoin="round"/><path d="M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z" stroke-linecap="round" stroke-linejoin="round"/></svg>
</div>
<h1>Book of the ERP</h1>
<div class="subtitle">كتاب النظام الشامل — الإصدار الأول</div>
<div class="desc">الدليل التدريبي التفصيلي لجميع عمليات وأقسام نظام إدارة النادي — مرجع شامل للموظفين</div>
<div class="sub">كتاب النظام الشامل — الإصدار الأول</div>
<div class="desc">الدليل التدريبي التفصيلي لجميع عمليات وأقسام نظام إدارة النادي</div>
<div class="cover-stats">
<div><span class="cover-stat-num"><?= $totalSections ?></span><span class="cover-stat-label">قسم</span></div>
<div><span class="cover-stat-num"><?= $totalTutorials ?></span><span class="cover-stat-label">شرح</span></div>
<div><span class="num"><?= $totalSections ?></span><span class="lbl">قسم</span></div>
<div><span class="num"><?= $totalTutorials ?></span><span class="lbl">شرح</span></div>
</div>
<div class="cover-meta">تم التوليد تلقائياً بواسطة نظام إدارة النادي<br><?= $data['generatedAt'] ?></div>
<div class="meta">تم التوليد تلقائياً — <?= $data['generatedAt'] ?></div>
</div>
<!-- ═══ TABLE OF CONTENTS ═══ -->
<div class="book-toc">
<!-- TOC -->
<div class="toc">
<h2>فهرس المحتويات</h2>
<div class="toc-sub"><?= $totalSections ?> قسم — <?= $totalTutorials ?> شرح تفصيلي</div>
<div class="toc-sub"><?= $totalSections ?> قسم — <?= $totalTutorials ?> شرح</div>
<div class="toc-grid">
<?php $sn = 0; foreach ($data['sections'] as $sk => $sec): $sn++; $c = $sectionColors[$sn - 1] ?? '#8B5CF6'; ?>
<div class="toc-item" style="--c:<?= $c ?>;">
<div class="toc-item-title">
<span class="toc-item-num" style="background:<?= $c ?>;"><?= $sn ?></span>
<?php $sn = 0; foreach ($data['sections'] as $sk => $sec): $sn++; $c = $colors[$sn-1] ?? '#8B5CF6'; ?>
<div class="toc-entry" style="--c:<?= $c ?>;">
<div class="toc-entry-head">
<span class="toc-num"><?= $sn ?></span>
<?= htmlspecialchars($sec['title'], ENT_QUOTES, 'UTF-8') ?>
<span class="toc-item-badge"><?= count($sec['tutorials']) ?></span>
<span class="toc-badge"><?= count($sec['tutorials']) ?></span>
</div>
<ul>
<?php $ti = 0; foreach ($sec['tutorials'] as $tSlug => $tut): $ti++; if ($ti > 5): break; endif; ?>
<li><?= htmlspecialchars($tut['title'], ENT_QUOTES, 'UTF-8') ?></li>
<?php $ti = 0; foreach ($sec['tutorials'] as $t): $ti++; if ($ti > 4) break; ?>
<li><?= htmlspecialchars($t['title'], ENT_QUOTES, 'UTF-8') ?></li>
<?php endforeach; ?>
<?php if (count($sec['tutorials']) > 5): ?>
<li style="color:#9ca3af;font-style:italic;">+ <?= count($sec['tutorials']) - 5 ?> شرح آخر...</li>
<?php if (count($sec['tutorials']) > 4): ?>
<li style="color:#9ca3af;font-style:italic;">+ <?= count($sec['tutorials']) - 4 ?> آخر</li>
<?php endif; ?>
</ul>
</div>
......@@ -403,70 +290,71 @@ $sectionIcons = [
</div>
</div>
<!-- ═══ SECTIONS & TUTORIALS ═══ -->
<?php $sectionNum = 0; foreach ($data['sections'] as $sectionKey => $section): $sectionNum++; $color = $sectionColors[$sectionNum - 1] ?? '#8B5CF6'; ?>
<!-- SECTIONS -->
<?php $sectionNum = 0; foreach ($data['sections'] as $sectionKey => $section): $sectionNum++; $color = $colors[$sectionNum-1] ?? '#8B5CF6'; ?>
<div class="section-divider" style="--c:<?= $color ?>;">
<div class="section-divider-icon" style="background:<?= $color ?>;">
<svg viewBox="0 0 24 24"><?= $sectionIcons[$sectionKey] ?? $sectionIcons['default'] ?></svg>
<div class="divider" style="--c:<?= $color ?>;">
<div class="divider-icon">
<svg viewBox="0 0 24 24"><?= $icons[$sectionKey] ?? $icons['default'] ?></svg>
</div>
<h2><?= htmlspecialchars($section['title'], ENT_QUOTES, 'UTF-8') ?></h2>
<?php if (!empty($section['subtitle'])): ?>
<div class="section-sub"><?= htmlspecialchars($section['subtitle'], ENT_QUOTES, 'UTF-8') ?></div>
<div class="divider-sub"><?= htmlspecialchars($section['subtitle'], ENT_QUOTES, 'UTF-8') ?></div>
<?php endif; ?>
<div class="section-stats">
<div><span class="section-stat-num" style="color:<?= $color ?>;"><?= count($section['tutorials']) ?></span><span class="section-stat-label">شرح</span></div>
<div><span class="section-stat-num" style="color:<?= $color ?>;"><?= count($section['categories'] ?? []) ?></span><span class="section-stat-label">تصنيف</span></div>
<div><span class="section-stat-num" style="color:<?= $color ?>;">القسم <?= $sectionNum ?></span><span class="section-stat-label">من <?= $totalSections ?></span></div>
<div class="divider-stats">
<div><span class="stat-num"><?= count($section['tutorials']) ?></span><span class="stat-lbl">شرح</span></div>
<div><span class="stat-num"><?= count($section['categories'] ?? []) ?></span><span class="stat-lbl">تصنيف</span></div>
</div>
</div>
<?php if (!empty($section['screenshot']) && file_exists($section['screenshot'])): ?>
<?php $webPath = str_replace(realpath(__DIR__ . '/../../../../public'), '', $section['screenshot']); ?>
<div class="section-screenshot">
<img src="<?= $webPath ?>" alt="<?= htmlspecialchars($section['title'], ENT_QUOTES, 'UTF-8') ?>">
</div>
<div class="sec-img"><img src="<?= $webPath ?>" alt="<?= htmlspecialchars($section['title'], ENT_QUOTES, 'UTF-8') ?>"></div>
<?php endif; ?>
<?php
$tutorialNum = 0;
$currentCategory = '';
$tutNum = 0;
$curCat = '';
foreach ($section['tutorials'] as $slug => $tutorial):
$tutorialNum++;
$tutNum++;
$cat = $tutorial['category'] ?? '';
if ($cat !== $currentCategory && !empty($section['categories'][$cat])):
$currentCategory = $cat;
if ($cat !== $curCat && !empty($section['categories'][$cat])):
$curCat = $cat;
?>
<div class="cat-header" style="--c:<?= $color ?>;">
<?= htmlspecialchars($section['categories'][$cat]['label'], ENT_QUOTES, 'UTF-8') ?>
</div>
<div class="cat-head" style="--c:<?= $color ?>;"><?= htmlspecialchars($section['categories'][$cat]['label'], ENT_QUOTES, 'UTF-8') ?></div>
<?php endif; ?>
<div class="tutorial-card" style="--c:<?= $color ?>;">
<div class="tutorial-card-head">
<div class="tutorial-card-num" style="background:<?= $color ?>;"><?= $tutorialNum ?></div>
<div class="tut" style="--c:<?= $color ?>;">
<div class="tut-head">
<div class="tut-num"><?= $tutNum ?></div>
<div>
<h3><?= htmlspecialchars($tutorial['title'], ENT_QUOTES, 'UTF-8') ?></h3>
<?php if (!empty($tutorial['subtitle'])): ?>
<div class="t-sub"><?= htmlspecialchars($tutorial['subtitle'], ENT_QUOTES, 'UTF-8') ?></div>
<div class="tsub"><?= htmlspecialchars($tutorial['subtitle'], ENT_QUOTES, 'UTF-8') ?></div>
<?php endif; ?>
</div>
</div>
<div class="tutorial-card-body">
<?php if (!empty($tutorial['htmlContent'])): ?>
<?= $tutorial['htmlContent'] ?>
<?php elseif (!empty($tutorial['steps'])): ?>
<?php foreach ($tutorial['steps'] as $stepIdx => $step): ?>
<div class="step-card" style="--c:<?= $color ?>;">
<div class="step-card-num"><?= $stepIdx + 1 ?></div>
<div class="step-card-title"><?= htmlspecialchars($step['title'] ?? '', ENT_QUOTES, 'UTF-8') ?></div>
<div class="step-card-body"><?= $step['body'] ?? '' ?></div>
<div class="tut-body">
<?php if (!empty($tutorial['images'])): ?>
<?php foreach ($tutorial['images'] as $img): ?>
<div class="tut-img"><img src="<?= htmlspecialchars($img, ENT_QUOTES, 'UTF-8') ?>" alt=""></div>
<?php endforeach; ?>
<?php endif; ?>
<?php if (!empty($tutorial['steps'])): ?>
<?php foreach ($tutorial['steps'] as $si => $step): ?>
<div class="step" style="--c:<?= $color ?>;">
<div class="step-num"><?= $si + 1 ?></div>
<div class="step-content">
<?php if (!empty($step['title'])): ?>
<div class="step-title"><?= htmlspecialchars($step['title'], ENT_QUOTES, 'UTF-8') ?></div>
<?php endif; ?>
<div class="step-body"><?= $step['body'] ?? '' ?></div>
</div>
</div>
<?php endforeach; ?>
<?php else: ?>
<p style="color:#6b7280;padding:8px 0;">
<?= htmlspecialchars($tutorial['subtitle'] ?? $tutorial['title'], ENT_QUOTES, 'UTF-8') ?>
</p>
<p style="color:#6b7280;padding:4px 0;"><?= htmlspecialchars($tutorial['subtitle'] ?? $tutorial['title'], ENT_QUOTES, 'UTF-8') ?></p>
<?php endif; ?>
</div>
</div>
......@@ -474,16 +362,16 @@ foreach ($section['tutorials'] as $slug => $tutorial):
<?php endforeach; ?>
<?php endforeach; ?>
<!-- ═══ BACK COVER ═══ -->
<div class="book-back">
<div class="book-back-icon">
<!-- BACK -->
<div class="back">
<div class="back-icon">
<svg viewBox="0 0 24 24"><path d="M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z" stroke-linecap="round" stroke-linejoin="round"/><path d="M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z" stroke-linecap="round" stroke-linejoin="round"/></svg>
</div>
<h2>Book of the ERP</h2>
<p>كتاب النظام الشامل — الإصدار الأول</p>
<p style="margin-top:16px;opacity:0.3;font-size:10px;">تم التوليد تلقائياً بواسطة نظام إدارة النادي</p>
<p style="opacity:0.3;font-size:10px;"><?= $data['generatedAt'] ?></p>
<p style="margin-top:12px;opacity:0.3;font-size:10px;"><?= $data['generatedAt'] ?></p>
</div>
</div>
</body>
</html>
......@@ -13,13 +13,17 @@ MenuRegistry::register('tutorials', [
'parent' => null,
'order' => 990,
'children' => [
// ── البداية ──────────────────────────────────────────
['label_ar' => 'لوحة التحكم', 'label_en' => 'Dashboard', 'route' => '/tutorials/dashboard', 'permission' => 'tutorials.view', 'order' => 0],
// ── العمليات (Operations) ──────────────────────────
['label_ar' => 'شئون العضوية', 'label_en' => 'Membership', 'route' => '/tutorials/membership', 'permission' => 'tutorials.view', 'order' => 1],
['label_ar' => 'الأنشطة الرياضية', 'label_en' => 'Sports Activity', 'route' => '/tutorials/sports-activity', 'permission' => 'tutorials.view', 'order' => 2],
['label_ar' => 'الحجوزات', 'label_en' => 'Reservations', 'route' => '/tutorials/reservations', 'permission' => 'tutorials.view', 'order' => 3],
['label_ar' => 'البطولات', 'label_en' => 'Tournaments', 'route' => '/tutorials/tournaments', 'permission' => 'tutorials.view', 'order' => 4],
['label_ar' => 'الكارنيهات والدعوات', 'label_en' => 'Carnets & Invitations','route' => '/tutorials/carnets', 'permission' => 'tutorials.view', 'order' => 5],
['label_ar' => 'أولياء الأمور', 'label_en' => 'Parents', 'route' => '/tutorials/parents', 'permission' => 'tutorials.view', 'order' => 6],
['label_ar' => 'العائلة والتابعين', 'label_en' => 'Family & Dependents', 'route' => '/tutorials/family', 'permission' => 'tutorials.view', 'order' => 2],
['label_ar' => 'التحويلات والتنازلات', 'label_en' => 'Transfers & Waivers', 'route' => '/tutorials/transfers-waivers', 'permission' => 'tutorials.view', 'order' => 3],
['label_ar' => 'الأنشطة الرياضية', 'label_en' => 'Sports Activity', 'route' => '/tutorials/sports-activity', 'permission' => 'tutorials.view', 'order' => 4],
['label_ar' => 'الحجوزات', 'label_en' => 'Reservations', 'route' => '/tutorials/reservations', 'permission' => 'tutorials.view', 'order' => 5],
['label_ar' => 'البطولات', 'label_en' => 'Tournaments', 'route' => '/tutorials/tournaments', 'permission' => 'tutorials.view', 'order' => 6],
['label_ar' => 'الكارنيهات والدعوات', 'label_en' => 'Carnets & Invitations','route' => '/tutorials/carnets', 'permission' => 'tutorials.view', 'order' => 7],
['label_ar' => 'أولياء الأمور', 'label_en' => 'Parents', 'route' => '/tutorials/parents', 'permission' => 'tutorials.view', 'order' => 8],
// ── المالية (Finance) ──────────────────────────────
['label_ar' => 'خزنة العضويات', 'label_en' => 'Cashier', 'route' => '/tutorials/cashier', 'permission' => 'tutorials.view', 'order' => 10],
['label_ar' => 'الخزنة الفرعية', 'label_en' => 'Treasury', 'route' => '/tutorials/treasury', 'permission' => 'tutorials.view', 'order' => 11],
......@@ -32,6 +36,9 @@ MenuRegistry::register('tutorials', [
// ── الشئون الإدارية (Administration) ───────────────
['label_ar' => 'الموارد البشرية', 'label_en' => 'HR', 'route' => '/tutorials/hr', 'permission' => 'tutorials.view', 'order' => 30],
['label_ar' => 'اللجنة الطبية', 'label_en' => 'Medical Board', 'route' => '/tutorials/medical-board', 'permission' => 'tutorials.view', 'order' => 31],
// ── البوابات (Portals) ─────────────────────────────
['label_ar' => 'بوابة المدربين', 'label_en' => 'Trainer Portal', 'route' => '/tutorials/trainer-portal', 'permission' => 'tutorials.view', 'order' => 35],
['label_ar' => 'بوابة أولياء الأمور', 'label_en' => 'Parent Portal', 'route' => '/tutorials/parent-portal', 'permission' => 'tutorials.view', 'order' => 36],
// ── التقارير والنظام (Reports & System) ────────────
['label_ar' => 'التقارير', 'label_en' => 'Reports', 'route' => '/tutorials/reports', 'permission' => 'tutorials.view', 'order' => 40],
['label_ar' => 'المستخدمون والصلاحيات', 'label_en' => 'Users & Permissions', 'route' => '/tutorials/roles', 'permission' => 'tutorials.view', 'order' => 41],
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment