39669-vm/approved_school.php
2026-04-17 03:38:41 +00:00

350 lines
24 KiB
PHP

<?php
declare(strict_types=1);
require_once __DIR__ . '/includes/app.php';
$flash = consume_flash();
$applicationId = filter_input(INPUT_GET, 'id', FILTER_VALIDATE_INT) ?: 0;
$requestedCycleId = filter_input(INPUT_GET, 'cycle', FILTER_VALIDATE_INT) ?: 0;
$application = $applicationId > 0 ? get_application($applicationId) : null;
$cycleValues = school_cycle_defaults($application ?: null);
$cycleErrors = [];
$cycleRollover = school_cycle_rollover_defaults();
if (!$application) {
http_response_code(404);
render_page_start('صفحة المركز غير موجودة', 'approved', 'تعذر العثور على المركز المطلوب لعرض صفحة الهبوط بعد الاعتماد.');
render_flash($flash);
?>
<section class="py-5">
<div class="container-xxl">
<div class="admin-layout row g-4 align-items-start">
<div class="col-lg-3 layout-sidebar-column">
<?php require __DIR__ . '/includes/sidebar.php'; ?>
</div>
<div class="col-lg-9 layout-content-column">
<div class="app-card text-center py-5">
<div class="empty-title mb-2">المركز غير موجود</div>
<p class="text-muted mb-3">تحقق من رقم الطلب أو ارجع إلى قائمة المراكز المعتمدة.</p>
<a class="btn btn-primary" href="applications.php?status=approved">عرض المراكز المعتمدة</a>
</div>
</div>
</section>
<?php
render_page_end();
exit;
}
$isApproved = (string) $application['status'] === 'approved';
$cycleContext = ['cycles' => [], 'selected' => null, 'active' => null, 'read_only' => false];
$selectedCycle = null;
$selectedCycleId = 0;
$isCycleReadOnly = false;
$cycleLabel = 'لا توجد دورة بعد';
if ($isApproved) {
$cycleContext = resolve_school_cycle_context((int) $application['id'], $application, $requestedCycleId);
$selectedCycle = $cycleContext['selected'];
$selectedCycleId = $selectedCycle ? (int) ($selectedCycle['id'] ?? 0) : 0;
$isCycleReadOnly = (bool) $cycleContext['read_only'];
$cycleLabel = $selectedCycle ? (string) $selectedCycle['cycle_name'] : $cycleLabel;
$cycleRollover = school_cycle_rollover_defaults($selectedCycle);
}
if ($_SERVER['REQUEST_METHOD'] === 'POST' && $isApproved) {
$cycleAction = clean_text((string) ($_POST['cycle_action'] ?? ''), 30);
if ($cycleAction === 'create_cycle') {
[$cycleValues, $cycleErrors] = validate_school_cycle_input($_POST, $application);
$cycleRollover = school_cycle_rollover_input((int) $application['id'], $_POST, $selectedCycle);
$wantsRollover = !empty($cycleRollover['copy_teachers']) || !empty($cycleRollover['copy_assessments']) || !empty($cycleRollover['copy_students']);
if ($wantsRollover && (int) $cycleRollover['source_cycle_id'] <= 0) {
$cycleErrors['form'] = 'اختر دورة مصدر إذا كنت تريد نسخ الفريق أو التقييمات أو الطلاب إلى الدورة الجديدة.';
}
if ($cycleErrors === []) {
try {
$cycleCreation = create_school_cycle((int) $application['id'], $cycleValues, $cycleRollover);
$newCycleId = (int) ($cycleCreation['cycle_id'] ?? 0);
$rolloverSummary = (array) ($cycleCreation['rollover'] ?? []);
$flashMessage = 'تم إنشاء الدورة الموسمية الجديدة بنجاح. يمكنك الآن العمل داخل ' . e((string)($cycleValues['cycle_name'] ?? 'الدورة الجديدة')) . '.';
$rolloverParts = [];
if (!empty($rolloverSummary['teachers'])) {
$rolloverParts[] = 'ترحيل ' . (int) $rolloverSummary['teachers'] . ' من أعضاء الفريق';
}
if (!empty($rolloverSummary['assessments'])) {
$rolloverParts[] = 'نسخ ' . (int) $rolloverSummary['assessments'] . ' من بنود التقييم';
}
if (!empty($rolloverSummary['students'])) {
$rolloverParts[] = 'نقل ' . (int) $rolloverSummary['students'] . ' من الطلاب المستمرين';
}
if ($rolloverParts !== []) {
$sourceCycleName = (string) ($cycleCreation['source_cycle_name'] ?? 'الدورة السابقة');
$flashMessage .= ' تم أيضاً ' . implode('، ', $rolloverParts) . ' من ' . $sourceCycleName . '.';
}
set_flash('success', $flashMessage);
header('Location: ' . school_page_url('approved_school.php', (int) $application['id'], $newCycleId));
exit;
} catch (PDOException $exception) {
$duplicateCode = isset($exception->errorInfo[1]) && (int) $exception->errorInfo[1] === 1062;
if ($duplicateCode) {
$cycleErrors['year'] = 'هذه الدورة موجودة مسبقاً لهذا المركز. اختر موسماً أو سنة مختلفة.';
} else {
$cycleErrors['form'] = 'تعذر إنشاء الدورة حالياً. يرجى المحاولة مرة أخرى.';
}
} catch (InvalidArgumentException $exception) {
$cycleErrors['form'] = 'تعذر ترحيل البيانات من الدورة المحددة. اختر دورة صحيحة ثم حاول مرة أخرى.';
} catch (Throwable $exception) {
$cycleErrors['form'] = 'تعذر إنشاء الدورة حالياً. يرجى المحاولة مرة أخرى.';
}
}
} elseif ($cycleAction === 'archive_cycle') {
$postedCycleId = (int) ($_POST['cycle_id'] ?? 0);
$cycleToArchive = $postedCycleId > 0 ? get_school_cycle((int) $application['id'], $postedCycleId) : null;
if (!$cycleToArchive) {
$cycleErrors['form'] = 'تعذر العثور على الدورة المطلوب أرشفتها.';
} elseif ((string) $cycleToArchive['status'] === 'archived') {
$cycleErrors['form'] = 'هذه الدورة مؤرشفة بالفعل.';
} else {
archive_school_cycle((int) $application['id'], $postedCycleId);
set_flash('success', 'تمت أرشفة الدورة ' . (string) $cycleToArchive['cycle_name'] . ' بنجاح. يمكنك فتح دورة جديدة متى شئت.');
header('Location: ' . school_page_url('approved_school.php', (int) $application['id']));
exit;
}
}
$cycleContext = resolve_school_cycle_context((int) $application['id'], $application, $requestedCycleId);
$selectedCycle = $cycleContext['selected'];
$selectedCycleId = $selectedCycle ? (int) ($selectedCycle['id'] ?? 0) : 0;
$isCycleReadOnly = (bool) $cycleContext['read_only'];
$cycleLabel = $selectedCycle ? (string) $selectedCycle['cycle_name'] : $cycleLabel;
if ($cycleAction !== 'create_cycle') {
$cycleRollover = school_cycle_rollover_defaults($selectedCycle);
}
}
$scoreValue = $application['evaluation_score'] !== null ? max(0, min(100, (int) $application['evaluation_score'])) : null;
$durationDays = 0;
$startTs = strtotime((string) $application['start_date']);
$endTs = strtotime((string) $application['end_date']);
if ($startTs !== false && $endTs !== false && $endTs >= $startTs) {
$durationDays = (int) floor(($endTs - $startTs) / 86400) + 1;
}
$studentsUrl = school_page_url('students.php', (int) $application['id'], $selectedCycleId);
$teachersUrl = school_page_url('teachers.php', (int) $application['id'], $selectedCycleId);
$assessmentsUrl = school_page_url('assessments.php', (int) $application['id'], $selectedCycleId);
$attendanceUrl = school_page_url('attendance.php', (int) $application['id'], $selectedCycleId);
$assessmentScoresUrl = school_page_url('assessment_scores.php', (int) $application['id'], $selectedCycleId);
$approvedSchoolUrl = school_page_url('approved_school.php', (int) $application['id'], $selectedCycleId);
$centerSubjectsUrl = school_page_url('center_subjects.php', (int) $application['id'], $selectedCycleId);
$studentCycleMetrics = $isApproved && $selectedCycleId > 0 ? school_student_metrics_by_cycle((int) $application['id'], $selectedCycleId) : ['total' => 0, 'active' => 0];
$teacherCycleMetrics = $isApproved && $selectedCycleId > 0 ? school_teacher_metrics_by_cycle((int) $application['id'], $selectedCycleId) : ['total' => 0, 'active' => 0];
$assessmentCycleMetrics = $isApproved && $selectedCycleId > 0 ? school_assessment_metrics_by_cycle((int) $application['id'], $selectedCycleId) : ['total' => 0, 'active' => 0, 'active_weight' => 0];
$attendanceCycleMetrics = $isApproved && $selectedCycleId > 0 ? school_attendance_metrics_by_cycle((int) $application['id'], $selectedCycleId) : ['total' => 0, 'today_count' => 0, 'latest_date' => ''];
$pageTitle = $isApproved ? 'صفحة المركز المعتمد: ' . (string) $application['center_name'] . ($selectedCycle ? ' — ' . $cycleLabel : '') : 'صفحة المركز بعد الاعتماد';
$pageDescription = $isApproved
? 'صفحة تشغيلية للمركز المعتمد تعرض الجاهزية، الدورات الموسمية، والخطوات التالية بعد الموافقة.'
: 'هذه الصفحة تصبح متاحة بعد اعتماد طلب المركز من المشرف العام.';
render_page_start($pageTitle, 'approved', $pageDescription, (string) ($application['favicon'] ?? ''));
render_flash($flash);
?>
<section class="py-4 py-lg-5">
<div class="container-xxl">
<div class="admin-layout row g-4 align-items-start">
<div class="col-lg-3 layout-sidebar-column">
<?php if ($application) { require __DIR__ . '/includes/center_sidebar.php'; } else { require __DIR__ . '/includes/sidebar.php'; } ?>
</div>
<div class="col-lg-9 layout-content-column">
<?php if (!$isApproved): ?>
<div class="d-flex flex-column flex-md-row justify-content-between align-items-md-center mb-4">
<div>
<span class="badge bg-warning text-primary mb-2">هذه الصفحة تُفتح بعد الاعتماد فقط</span>
<h1 class="h3 mb-2"><?= e((string) $application['center_name']) ?></h1>
<div class="text-muted small">
الحالة الحالية: <?= e(status_meta((string) $application['status'])['label']) ?> • مرجع الطلب #<?= e((string) $application['id']) ?>
</div>
</div>
<div class="mt-3 mt-md-0 d-flex gap-2">
<a class="btn btn-sm btn-outline-secondary" href="application_detail.php?id=<?= e((string) $application['id']) ?>">العودة لملف المراجعة</a>
<a class="btn btn-sm btn-primary" href="admin.php">لوحة الإدارة</a>
</div>
</div>
<div class="app-card text-center py-5">
<div class="empty-title mb-2">في انتظار الاعتماد</div>
<p class="text-muted mb-3">تم تجهيز صفحة الهبوط لهذا المركز، لكنها ستصبح الصفحة التشغيلية الرسمية فقط بعد تغيير الحالة إلى <strong>معتمد</strong>.</p>
</div>
<?php else: ?>
<div class="d-flex flex-column flex-md-row justify-content-between align-items-md-center mb-4">
<div>
<span class="badge bg-success mb-2">مركز معتمد وجاهز للانطلاق</span>
<h1 class="h3 mb-2"><?= e((string) $application['center_name']) ?></h1>
<div class="text-muted small">
<?= e((string) $application['city']) ?> • <?= e((string) $application['center_type']) ?> • <?= e((string) $application['gender_scope']) ?> • من <?= e((string) $application['start_date']) ?> إلى <?= e((string) $application['end_date']) ?>
</div>
</div>
<div class="mt-3 mt-md-0 d-flex gap-2">
<a class="btn btn-sm btn-outline-secondary" href="<?= e($assessmentScoresUrl) ?>">إدخال الدرجات</a>
<a class="btn btn-sm btn-outline-secondary" href="center_profile.php?id=<?= e((string) $application['id']) ?>">إعدادات المركز</a>
<a class="btn btn-sm btn-outline-secondary" href="application_detail.php?id=<?= e((string) $application['id']) ?>">ملف الاعتماد</a>
<a class="btn btn-sm btn-primary" href="admin.php">لوحة الإدارة</a>
</div>
</div>
<div class="row g-4 mb-4">
<div class="col-md-6 col-xl-3"><div class="app-card stat-tile p-3"><div class="mini-stat-label mb-1 text-muted small">المقاعد المتوقعة</div><div class="mini-stat-value fs-4 fw-bold"><?= e((string) $application['expected_students']) ?></div></div></div>
<div class="col-md-6 col-xl-3"><div class="app-card stat-tile p-3"><div class="mini-stat-label mb-1 text-muted small">مدة البرنامج</div><div class="mini-stat-value fs-4 fw-bold"><?= e((string) ($durationDays > 0 ? $durationDays : '—')) ?> يوم</div></div></div>
<div class="col-md-6 col-xl-3"><div class="app-card stat-tile p-3"><div class="mini-stat-label mb-1 text-muted small">مرجع التشغيل</div><div class="mini-stat-value fs-4 fw-bold">#<?= e((string) $application['id']) ?></div></div></div>
<div class="col-md-6 col-xl-3"><div class="app-card stat-tile p-3"><div class="mini-stat-label mb-1 text-muted small">درجة التقييم</div><div class="mini-stat-value fs-4 fw-bold"><?= $scoreValue !== null ? e((string) $scoreValue) . '%' : '—' ?></div></div></div>
</div>
<?php if ($selectedCycle): ?>
<div class="row g-4 mb-4" id="cycles">
<div class="<?= is_super_admin() ? 'col-lg-8' : 'col-lg-12' ?>">
<div class="app-card h-100 p-4">
<div class="d-flex justify-content-between align-items-center mb-4">
<h5 class="mb-0">الدورة الموسمية الحالية</h5>
<?= school_cycle_status_badge((string) $selectedCycle['status']) ?>
</div>
<div class="row g-4 mb-4">
<div class="col-md-4"><div class="school-data-item"><div class="text-muted small mb-1">الدورة المحددة</div><div class="fw-semibold"><?= e($cycleLabel) ?></div></div></div>
<div class="col-md-4"><div class="school-data-item"><div class="text-muted small mb-1">الفترة</div><div class="fw-semibold" dir="ltr"><?= e((string) $selectedCycle['start_date']) ?> <br> <?= e((string) $selectedCycle['end_date']) ?></div></div></div>
<div class="col-md-4"><div class="school-data-item"><div class="text-muted small mb-1">حالة الدورة</div><div class="fw-semibold"><?= e((string) school_cycle_status_map()[$selectedCycle['status']]['label']) ?></div></div></div>
<div class="col-md-3"><div class="school-data-item"><div class="text-muted small mb-1">الطلاب</div><div class="fw-semibold"><?= e((string) $studentCycleMetrics['total']) ?></div></div></div>
<div class="col-md-3"><div class="school-data-item"><div class="text-muted small mb-1">الفريق</div><div class="fw-semibold"><?= e((string) $teacherCycleMetrics['total']) ?></div></div></div>
<div class="col-md-3"><div class="school-data-item"><div class="text-muted small mb-1">التقييمات</div><div class="fw-semibold"><?= e((string) $assessmentCycleMetrics['active']) ?></div></div></div>
<div class="col-md-3"><div class="school-data-item"><div class="text-muted small mb-1">سجلات الغياب</div><div class="fw-semibold"><?= e((string) $attendanceCycleMetrics['total']) ?></div></div></div>
</div>
<?php if (!$isCycleReadOnly && is_super_admin()): ?>
<div class="text-end border-top pt-3 mt-2">
<form method="post" class="d-inline">
<input type="hidden" name="cycle_action" value="archive_cycle">
<input type="hidden" name="cycle_id" value="<?= e((string) $selectedCycleId) ?>">
<button class="btn btn-sm btn-outline-danger" type="submit">أرشفة هذه الدورة</button>
</form>
</div>
<?php endif; ?>
<?php if ($isCycleReadOnly): ?>
<div class="alert alert-warning mt-3 mb-0">هذه الدورة مؤرشفة حالياً، لذلك كل الصفحات المرتبطة بها أصبحت للقراءة فقط. يمكنك فتح دورة جديدة من النموذج المجاور.</div>
<?php endif; ?>
</div>
</div>
<?php if (is_super_admin()): ?>
<div class="col-lg-4">
<div class="app-card sidebar-card mb-4 p-4">
<h6 class="mb-3">كل دورات المركز</h6>
<div class="vstack gap-2">
<?php foreach ($cycleContext['cycles'] as $cycle): ?>
<a class="text-decoration-none bg-light rounded px-3 py-2 text-primary" href="<?= e(school_page_url('approved_school.php', (int) $application['id'], (int) $cycle['id'])) ?>#cycles">
<div class="d-flex justify-content-between align-items-center mb-1">
<strong class="small"><?= e((string) $cycle['cycle_name']) ?></strong>
<span class="badge bg-white text-primary border" style="font-size: 0.7rem;"><?= e((string) school_cycle_status_map()[$cycle['status']]['label']) ?></span>
</div>
<div class="text-muted" style="font-size: 0.75rem;" dir="ltr"><?= e((string) $cycle['start_date']) ?> &rarr; <?= e((string) $cycle['end_date']) ?></div>
</a>
<?php endforeach; ?>
</div>
</div>
<div class="app-card sidebar-card p-4">
<h6 class="mb-3">فتح دورة جديدة</h6>
<?php if (isset($cycleErrors['form'])): ?><div class="alert alert-danger py-2 small mb-3"><?= e($cycleErrors['form']) ?></div><?php endif; ?>
<form method="post" class="vstack gap-3" novalidate>
<input type="hidden" name="cycle_action" value="create_cycle">
<div>
<label class="form-label small text-muted mb-1" for="global_cycle_id">اختر الدورة</label>
<select class="form-select form-select-sm <?= isset($cycleErrors['global_cycle_id']) ? 'is-invalid' : '' ?>" id="global_cycle_id" name="global_cycle_id">
<option value="">اختر دورة مسجلة مسبقاً</option>
<?php foreach (get_active_global_cycles() as $cycle): ?>
<option value="<?= e((string)$cycle['id']) ?>"><?= e((string)$cycle['cycle_name']) ?> (<?= e((string)$cycle['start_date']) ?> - <?= e((string)$cycle['end_date']) ?>)</option>
<?php endforeach; ?>
</select>
<?php if (isset($cycleErrors['global_cycle_id'])): ?><div class="invalid-feedback"><?= e($cycleErrors['global_cycle_id']) ?></div><?php endif; ?>
</div>
<div>
<label class="form-label small text-muted mb-1" for="status">حالة البداية</label>
<select class="form-select form-select-sm <?= isset($cycleErrors['status']) ? 'is-invalid' : '' ?>" id="status" name="status">
<option value="active" <?= $cycleValues['status'] === 'active' ? 'selected' : '' ?>>نشطة مباشرة</option>
<option value="upcoming" <?= $cycleValues['status'] === 'upcoming' ? 'selected' : '' ?>>قادمة</option>
</select>
<?php if (isset($cycleErrors['status'])): ?><div class="invalid-feedback"><?= e($cycleErrors['status']) ?></div><?php endif; ?>
</div>
<?php if (!empty($cycleContext['cycles'])): ?>
<div class="border rounded-3 p-3 bg-light-subtle">
<div class="fw-semibold mb-2" style="font-size: 0.8rem;">ترحيل البيانات من دورة سابقة</div>
<div class="mb-3">
<select class="form-select form-select-sm" id="source_cycle_id" name="source_cycle_id">
<option value="0">بدون نسخ مسبق</option>
<?php foreach ($cycleContext['cycles'] as $cycle): ?>
<option value="<?= e((string) $cycle['id']) ?>" <?= (int) $cycleRollover['source_cycle_id'] === (int) $cycle['id'] ? 'selected' : '' ?>><?= e((string) $cycle['cycle_name']) ?> — <?= e((string) school_cycle_status_map()[$cycle['status']]['label']) ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="vstack gap-2" style="font-size: 0.8rem;">
<label class="form-check mb-0">
<input class="form-check-input" type="checkbox" name="copy_teachers" value="1" <?= !empty($cycleRollover['copy_teachers']) ? 'checked' : '' ?>>
<span class="form-check-label">الفريق التعليمي والوظائف</span>
</label>
<label class="form-check mb-0">
<input class="form-check-input" type="checkbox" name="copy_assessments" value="1" <?= !empty($cycleRollover['copy_assessments']) ? 'checked' : '' ?>>
<span class="form-check-label">خطة التقييم والأوزان</span>
</label>
<label class="form-check mb-0">
<input class="form-check-input" type="checkbox" name="copy_students" value="1" <?= !empty($cycleRollover['copy_students']) ? 'checked' : '' ?>>
<span class="form-check-label">الطلاب المستمرين فقط</span>
</label>
</div>
</div>
<?php endif; ?>
<button class="btn btn-sm btn-primary w-100" type="submit">إنشاء الدورة الجديدة</button>
</form>
</div>
</div>
<?php endif; ?>
</div>
<?php endif; ?>
<div class="row g-4 align-items-start">
<div class="col-lg-8">
<div class="app-card mb-4 p-4">
<h6 class="mb-3">نبذة المدرسة / المركز</h6>
<p class="mb-0 text-muted small lh-lg"><?= nl2br(e((string) ($application['notes'] ?: 'مركز صيفي معتمد لتقديم برنامج منظم يجمع بين الأنشطة التعليمية والتربوية والمهارية تحت إشراف الولاية.'))) ?></p>
</div>
</div>
<div class="col-lg-4">
<div class="app-card sidebar-card mb-4 p-4">
<h6 class="mb-3">بيانات التواصل</h6>
<div class="vstack gap-2 small">
<div class="d-flex justify-content-between border-bottom pb-2">
<strong class="text-primary">المدير:</strong>
<span class="text-muted"><?= e((string) $application['director_name']) ?></span>
</div>
<div class="d-flex justify-content-between border-bottom pb-2">
<strong class="text-primary">الهاتف:</strong>
<span class="text-muted" dir="ltr"><?= e((string) $application['phone']) ?></span>
</div>
<div class="d-flex justify-content-between border-bottom pb-2">
<strong class="text-primary">الإيميل:</strong>
<span class="text-muted"><?= e((string) $application['email']) ?></span>
</div>
<div class="d-flex justify-content-between">
<strong class="text-primary">المدينة:</strong>
<span class="text-muted"><?= e((string) $application['city']) ?></span>
</div>
</div>
</div>
</div>
</div>
<?php endif; ?>
</div>
</div>
</div>
</div>
</section>
<?php render_page_end();