297 lines
16 KiB
PHP
297 lines
16 KiB
PHP
<?php ob_start(); ?>
|
|
<?php
|
|
require_once __DIR__ . '/includes/app.php';
|
|
|
|
$page = $_GET['page'] ?? 'dashboard';
|
|
$action = $_GET['action'] ?? '';
|
|
|
|
// Handle Profile Update
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST' && $page === 'profile') {
|
|
$name = $_POST['name'] ?? '';
|
|
$description = $_POST['description'] ?? '';
|
|
|
|
$logo_path = get_platform_profile()['logo_path'] ?? '';
|
|
$favicon_path = get_platform_profile()['favicon_path'] ?? '';
|
|
|
|
$upload_dir = __DIR__ . '/assets/images/uploads/';
|
|
if (!is_dir($upload_dir)) {
|
|
mkdir($upload_dir, 0777, true);
|
|
}
|
|
|
|
if (!empty($_FILES['logo']['tmp_name'])) {
|
|
$filename = 'logo_' . time() . '_' . basename($_FILES['logo']['name']);
|
|
$target = $upload_dir . $filename;
|
|
if (move_uploaded_file($_FILES['logo']['tmp_name'], $target)) {
|
|
$logo_path = 'assets/images/uploads/' . $filename;
|
|
}
|
|
}
|
|
|
|
if (!empty($_FILES['favicon']['tmp_name'])) {
|
|
$filename = 'favicon_' . time() . '_' . basename($_FILES['favicon']['name']);
|
|
$target = $upload_dir . $filename;
|
|
if (move_uploaded_file($_FILES['favicon']['tmp_name'], $target)) {
|
|
$favicon_path = 'assets/images/uploads/' . $filename;
|
|
}
|
|
}
|
|
|
|
$stmt = db()->prepare("UPDATE platform_profile SET name = :name, description = :description, logo_path = :logo, favicon_path = :favicon WHERE id = 1");
|
|
$stmt->execute([
|
|
'name' => $name,
|
|
'description' => $description,
|
|
'logo' => $logo_path,
|
|
'favicon' => $favicon_path
|
|
]);
|
|
|
|
header('Location: ' . app_url('admin.php', ['page' => 'profile', 'saved' => 1]));
|
|
exit;
|
|
}
|
|
|
|
$metrics = subscription_metrics();
|
|
$recent = fetch_recent_subscriptions();
|
|
render_head(
|
|
t('Admin', 'الإدارة') . ' - ' . ucfirst($page),
|
|
t('Manage your learning platform.', 'إدارة منصة التعلم الخاصة بك.')
|
|
);
|
|
?>
|
|
<nav class="navbar navbar-expand-lg bg-white border-bottom sticky-top admin-navbar" style="z-index: 1040;">
|
|
<div class="container-fluid px-3 px-md-4">
|
|
<a class="navbar-brand fw-semibold d-flex align-items-center" href="<?= h(app_url('index.php')) ?>" target="_blank">
|
|
<?php $prof = get_platform_profile(); if (!empty($prof['logo_path'])): ?>
|
|
<img src="<?= h(asset_url($prof['logo_path'])) ?>" alt="Logo" style="height: 32px; margin-right: 8px; border-radius: 4px;">
|
|
<?php endif; ?>
|
|
<span style="color: var(--accent);"><?= h(app_name()) ?></span>
|
|
</a>
|
|
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#adminNavbar" aria-controls="adminNavbar" aria-expanded="false" aria-label="Toggle navigation">
|
|
<span class="navbar-toggler-icon"></span>
|
|
</button>
|
|
|
|
<div class="collapse navbar-collapse justify-content-end" id="adminNavbar">
|
|
<ul class="navbar-nav mb-2 mb-lg-0 align-items-center gap-3">
|
|
<li class="nav-item">
|
|
<div class="btn-group btn-group-sm" role="group">
|
|
<a class="btn btn-outline-dark <?= current_lang() === 'en' ? 'active' : '' ?>" href="<?= h(page_lang_link('en')) ?>">EN</a>
|
|
<a class="btn btn-outline-dark <?= current_lang() === 'ar' ? 'active' : '' ?>" href="<?= h(page_lang_link('ar')) ?>">AR</a>
|
|
</div>
|
|
</li>
|
|
<li class="nav-item dropdown">
|
|
<a class="nav-link dropdown-toggle d-flex align-items-center gap-2" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
|
<div class="bg-light rounded-circle d-flex align-items-center justify-content-center" style="width: 32px; height: 32px; border: 1px solid var(--border);">
|
|
<svg width="16" height="16" fill="currentColor" viewBox="0 0 16 16">
|
|
<path d="M11 6a3 3 0 1 1-6 0 3 3 0 0 1 6 0"/>
|
|
<path fill-rule="evenodd" d="M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8m8-7a7 7 0 0 0-5.468 11.37C3.242 11.226 4.805 10 8 10s4.757 1.225 5.468 2.37A7 7 0 0 0 8 1"/>
|
|
</svg>
|
|
</div>
|
|
<span class="fw-medium"><?= h(t('Admin', 'المدير')) ?></span>
|
|
</a>
|
|
<ul class="dropdown-menu dropdown-menu-end shadow-sm">
|
|
<li><a class="dropdown-item" href="<?= h(app_url('admin.php', ['page' => 'profile'])) ?>"><?= h(t('Platform Profile', 'ملف المنصة')) ?></a></li>
|
|
<li><hr class="dropdown-divider"></li>
|
|
<li><a class="dropdown-item" href="<?= h(app_url('index.php')) ?>"><?= h(t('Exit Admin', 'خروج من الإدارة')) ?></a></li>
|
|
</ul>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</nav>
|
|
|
|
<div class="d-flex flex-column flex-md-row" style="min-height: calc(100vh - 61px); overflow: hidden;">
|
|
<!-- Sidebar -->
|
|
<aside class="d-flex flex-column flex-shrink-0 p-3 bg-white border-end shadow-sm admin-sidebar">
|
|
<div class="fs-5 fw-bold mb-3 mt-2 px-2 text-secondary d-none d-md-block"><?= h(t('Admin Menu', 'قائمة الإدارة')) ?></div>
|
|
<ul class="nav nav-pills flex-row flex-md-column mb-auto gap-2 flex-wrap">
|
|
<li class="nav-item">
|
|
<a href="<?= h(app_url('admin.php', ['page' => 'dashboard'])) ?>" class="nav-link <?= $page === 'dashboard' ? 'active' : 'link-dark' ?>" <?= $page === 'dashboard' ? 'style="background-color: var(--accent); color: white;"' : '' ?>>
|
|
<?= h(t('Dashboard', 'لوحة القيادة')) ?>
|
|
</a>
|
|
</li>
|
|
<li class="nav-item">
|
|
<a href="<?= h(app_url('admin.php', ['page' => 'profile'])) ?>" class="nav-link <?= $page === 'profile' ? 'active' : 'link-dark' ?>" <?= $page === 'profile' ? 'style="background-color: var(--accent); color: white;"' : '' ?>>
|
|
<?= h(t('Platform Profile', 'ملف المنصة')) ?>
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a href="<?= h(app_url('admin.php', ['page' => 'classes'])) ?>" class="nav-link <?= $page === 'classes' ? 'active' : 'link-dark' ?>" <?= $page === 'classes' ? 'style="background-color: var(--accent); color: white;"' : '' ?>>
|
|
<?= h(t('Classes', 'الصفوف')) ?>
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a href="<?= h(app_url('admin.php', ['page' => 'subjects'])) ?>" class="nav-link <?= $page === 'subjects' ? 'active' : 'link-dark' ?>" <?= $page === 'subjects' ? 'style="background-color: var(--accent); color: white;"' : '' ?>>
|
|
<?= h(t('Subjects', 'المواد')) ?>
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a href="<?= h(app_url('admin.php', ['page' => 'plans'])) ?>" class="nav-link <?= $page === 'plans' ? 'active' : 'link-dark' ?>" <?= $page === 'plans' ? 'style="background-color: var(--accent); color: white;"' : '' ?>>
|
|
<?= h(t('Plans', 'الخطط')) ?>
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a href="<?= h(app_url('admin.php', ['page' => 'students'])) ?>" class="nav-link <?= $page === 'students' ? 'active' : 'link-dark' ?>" <?= $page === 'students' ? 'style="background-color: var(--accent); color: white;"' : '' ?>>
|
|
<?= h(t('Students', 'الطلاب')) ?>
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a href="<?= h(app_url('admin.php', ['page' => 'teachers'])) ?>" class="nav-link <?= $page === 'teachers' ? 'active' : 'link-dark' ?>" <?= $page === 'teachers' ? 'style="background-color: var(--accent); color: white;"' : '' ?>>
|
|
<?= h(t('Teachers', 'المعلمون')) ?>
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
|
|
</aside>
|
|
|
|
<!-- Content Area -->
|
|
<main class="flex-grow-1 d-flex flex-column" style="height: calc(100vh - 61px); overflow-y: auto;">
|
|
<div class="p-4 p-md-5 flex-grow-1">
|
|
<?php if ($page === 'dashboard'): ?>
|
|
<div class="section-header mb-4">
|
|
<div>
|
|
<span class="eyebrow"><?= h(t('Admin', 'الإدارة')) ?></span>
|
|
<h1 class="section-title mb-2"><?= h(t('Platform subscription overview', 'نظرة عامة على اشتراكات المنصة')) ?></h1>
|
|
<p class="text-secondary mb-0"><?= h(t('This first admin screen focuses on the subscription funnel that powers student access.', 'تركز شاشة الإدارة الأولى هذه على مسار الاشتراك الذي يغذي وصول الطلاب.')) ?></p>
|
|
</div>
|
|
</div>
|
|
<div class="row g-3 mb-4">
|
|
<div class="col-md-4"><div class="metric-card tall"><strong><?= h((string) $metrics['total']) ?></strong><span><?= h(t('total subscriptions', 'إجمالي الاشتراكات')) ?></span></div></div>
|
|
<div class="col-md-4"><div class="metric-card tall"><strong><?= h((string) $metrics['active']) ?></strong><span><?= h(t('active plans', 'خطط نشطة')) ?></span></div></div>
|
|
<div class="col-md-4"><div class="metric-card tall"><strong><?= h((string) $metrics['arabic']) ?></strong><span><?= h(t('Arabic preference', 'تفضيل العربية')) ?></span></div></div>
|
|
</div>
|
|
<div class="panel-card">
|
|
<div class="d-flex justify-content-between align-items-center mb-3">
|
|
<h2 class="h5 mb-0"><?= h(t('Latest subscriptions', 'أحدث الاشتراكات')) ?></h2>
|
|
</div>
|
|
<?php if (!$recent): ?>
|
|
<div class="empty-state-inline"><?= h(t('No subscriptions recorded yet.', 'لم يتم تسجيل أي اشتراكات بعد.')) ?></div>
|
|
<?php elseif ($page === 'classes'): ?>
|
|
<div class="table-responsive">
|
|
<table class="table align-middle dashboard-table mb-0">
|
|
<thead>
|
|
<tr>
|
|
<th>#</th>
|
|
<th><?= h(t('Student', 'الطالب')) ?></th>
|
|
<th><?= h(t('Plan', 'الخطة')) ?></th>
|
|
<th><?= h(t('Language', 'اللغة')) ?></th>
|
|
<th><?= h(t('Payment', 'الدفع')) ?></th>
|
|
<th><?= h(t('Detail', 'التفاصيل')) ?></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach ($recent as $item): ?>
|
|
<?php $plan = get_plan($item['plan_key']) ?? get_plan('plus'); ?>
|
|
<tr>
|
|
<td><?= h((string) $item['id']) ?></td>
|
|
<td>
|
|
<div class="fw-semibold"><?= h($item['full_name']) ?></div>
|
|
<div class="small text-secondary"><?= h($item['email']) ?></div>
|
|
</td>
|
|
<td><?= h(plan_name($plan)) ?></td>
|
|
<td><?= h($item['preferred_language'] === 'ar' ? 'العربية' : 'English') ?></td>
|
|
<td><span class="<?= h(status_badge((string) $item['payment_status'])) ?>"><?= h((string) $item['payment_status']) ?></span></td>
|
|
<td><a class="btn btn-sm btn-outline-dark" href="<?= h(app_url('subscription.php', ['id' => (int) $item['id']])) ?>"><?= h(t('Open', 'فتح')) ?></a></td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<?php endif; ?>
|
|
</div>
|
|
|
|
<?php elseif ($page === 'profile'): ?>
|
|
<?php $prof = get_platform_profile(); ?>
|
|
<div class="section-header mb-4">
|
|
<div>
|
|
<span class="eyebrow"><?= h(t('Settings', 'الإعدادات')) ?></span>
|
|
<h1 class="section-title mb-2"><?= h(t('Platform Profile', 'ملف المنصة')) ?></h1>
|
|
<p class="text-secondary mb-0"><?= h(t('Update your platforms name, description, logo, and favicon.', 'قم بتحديث اسم منصتك ووصفها وشعارها والأيقونة المفضلة.')) ?></p>
|
|
</div>
|
|
</div>
|
|
<?php if (!empty($_GET['saved'])): ?>
|
|
<div class="alert alert-success"><?= h(t('Profile updated successfully.', 'تم تحديث الملف بنجاح.')) ?></div>
|
|
<?php endif; ?>
|
|
<div class="panel-card" style="max-width: 600px;">
|
|
<form method="post" enctype="multipart/form-data">
|
|
<div class="mb-3">
|
|
<label class="form-label"><?= h(t('Platform Name', 'اسم المنصة')) ?></label>
|
|
<input type="text" name="name" class="form-control" value="<?= h($prof['name'] ?? '') ?>" required>
|
|
</div>
|
|
<div class="mb-3">
|
|
<label class="form-label"><?= h(t('Description', 'الوصف')) ?></label>
|
|
<textarea name="description" class="form-control" rows="3"><?= h($prof['description'] ?? '') ?></textarea>
|
|
</div>
|
|
<div class="mb-3">
|
|
<label class="form-label"><?= h(t('Logo', 'الشعار')) ?></label>
|
|
<?php if (!empty($prof['logo_path'])): ?>
|
|
<div class="mb-2">
|
|
<img src="<?= h(asset_url($prof['logo_path'])) ?>" alt="Logo" style="height: 60px; border: 1px solid var(--border); border-radius: 8px; padding: 4px; background: #fff;">
|
|
</div>
|
|
<?php endif; ?>
|
|
<input type="file" name="logo" class="form-control" accept="image/*">
|
|
</div>
|
|
<div class="mb-4">
|
|
<label class="form-label"><?= h(t('Favicon', 'الأيقونة المفضلة')) ?></label>
|
|
<?php if (!empty($prof['favicon_path'])): ?>
|
|
<div class="mb-2">
|
|
<img src="<?= h(asset_url($prof['favicon_path'])) ?>" alt="Favicon" style="height: 32px; border: 1px solid var(--border); border-radius: 4px; padding: 2px; background: #fff;">
|
|
</div>
|
|
<?php endif; ?>
|
|
<input type="file" name="favicon" class="form-control" accept="image/x-icon,image/png,image/jpeg,image/svg+xml">
|
|
</div>
|
|
<button type="submit" class="btn btn-primary" style="background-color: var(--accent); border-color: var(--accent);">
|
|
<?= h(t('Save Changes', 'حفظ التغييرات')) ?>
|
|
</button>
|
|
</form>
|
|
</div>
|
|
|
|
<?php elseif ($page === 'classes'): ?>
|
|
<?php require_once __DIR__ . '/admin_classes.php'; ?>
|
|
<?php elseif ($page === 'subjects'): ?>
|
|
<?php require_once __DIR__ . '/admin_subjects.php'; ?>
|
|
<?php else: ?>
|
|
<div class="section-header mb-4">
|
|
<div>
|
|
<h1 class="section-title mb-2"><?= h(ucfirst($page)) ?></h1>
|
|
</div>
|
|
</div>
|
|
<div class="panel-card">
|
|
<div class="empty-state-inline">
|
|
<?= h(t('This section is currently under construction. More admin features coming soon!', 'هذا القسم قيد الإنشاء حالياً. المزيد من ميزات الإدارة قريباً!')) ?>
|
|
</div>
|
|
</div>
|
|
<?php endif; ?>
|
|
</div>
|
|
|
|
<footer class="bg-white border-top py-3 mt-auto w-100">
|
|
<div class="container-fluid px-4 px-md-5 d-flex justify-content-between align-items-center small text-secondary">
|
|
<div>
|
|
© <?= date('Y') ?> <?= h(app_name()) ?>. <?= h(t('All rights reserved.', 'جميع الحقوق محفوظة.')) ?>
|
|
</div>
|
|
<div>
|
|
<a href="<?= h(app_url('index.php')) ?>" class="text-decoration-none text-secondary"><?= h(t('View Site', 'عرض الموقع')) ?></a>
|
|
</div>
|
|
</div>
|
|
</footer>
|
|
</main>
|
|
</div>
|
|
|
|
<style>
|
|
.admin-sidebar {
|
|
width: 280px;
|
|
height: calc(100vh - 61px);
|
|
overflow-y: auto;
|
|
}
|
|
.admin-navbar {
|
|
box-shadow: 0 1px 3px rgba(0,0,0,0.05);
|
|
}
|
|
@media (max-width: 767.98px) {
|
|
.admin-sidebar {
|
|
width: 100%;
|
|
height: auto;
|
|
border-right: none !important;
|
|
border-bottom: 1px solid var(--border);
|
|
}
|
|
}
|
|
</style>
|
|
|
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" crossorigin="anonymous"></script>
|
|
<script src="<?= h(asset_url('assets/js/main.js')) ?>"></script>
|
|
</body>
|
|
</html>
|