304 lines
19 KiB
PHP
304 lines
19 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;
|
|
$application = $applicationId > 0 ? get_application($applicationId) : null;
|
|
$isApprovedSchool = $application && (string) $application['status'] === 'approved';
|
|
$values = student_defaults();
|
|
$errors = [];
|
|
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST' && $application) {
|
|
[$values, $errors] = validate_student_input($_POST);
|
|
|
|
if (!$isApprovedSchool) {
|
|
$errors['form'] = 'لا يمكن فتح تسجيل الطلاب قبل اعتماد المركز.';
|
|
}
|
|
|
|
if ($errors === []) {
|
|
try {
|
|
create_student((int) $application['id'], $values);
|
|
set_flash('success', 'تم تسجيل الطالب بنجاح وإضافته إلى كشف المدرسة.');
|
|
header('Location: students.php?id=' . urlencode((string) $application['id']));
|
|
exit;
|
|
} catch (PDOException $exception) {
|
|
$duplicateCode = isset($exception->errorInfo[1]) && (int) $exception->errorInfo[1] === 1062;
|
|
if ($duplicateCode) {
|
|
$errors['student_code'] = 'هذا الكود مستخدم مسبقاً داخل نفس المدرسة.';
|
|
} else {
|
|
$errors['form'] = 'تعذر حفظ بيانات الطالب حالياً. يرجى المحاولة مرة أخرى.';
|
|
}
|
|
} catch (Throwable $exception) {
|
|
$errors['form'] = 'تعذر حفظ بيانات الطالب حالياً. يرجى المحاولة مرة أخرى.';
|
|
}
|
|
}
|
|
}
|
|
|
|
$students = $isApprovedSchool ? list_school_students((int) $application['id']) : [];
|
|
$metrics = $isApprovedSchool ? school_student_metrics((int) $application['id']) : [
|
|
'total' => 0,
|
|
'boys' => 0,
|
|
'girls' => 0,
|
|
'active' => 0,
|
|
'waiting' => 0,
|
|
'withdrawn' => 0,
|
|
];
|
|
|
|
$expectedCapacity = $application ? (int) ($application['expected_students'] ?? 0) : 0;
|
|
$remainingSeats = max(0, $expectedCapacity - $metrics['total']);
|
|
$pageTitle = $application ? 'تسجيل الطلاب: ' . (string) $application['center_name'] : 'تسجيل الطلاب';
|
|
$pageDescription = 'صفحة مستقلة لتسجيل الطلاب وإدارة كشف المدرسة بعد الاعتماد، مع فصل واضح بين النموذج والكشف والجاهزية التشغيلية.';
|
|
|
|
if (!$application) {
|
|
http_response_code(404);
|
|
}
|
|
|
|
render_page_start($pageTitle, 'approved', $pageDescription);
|
|
render_flash($flash);
|
|
?>
|
|
<section class="py-4 py-lg-5">
|
|
<div class="container-xxl">
|
|
<?php if (!$application): ?>
|
|
<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-dark" href="applications.php?status=approved">المراكز المعتمدة</a>
|
|
</div>
|
|
<?php elseif (!$isApprovedSchool): ?>
|
|
<div class="page-banner mb-4 mb-lg-5">
|
|
<div class="row g-4 align-items-center">
|
|
<div class="col-lg-8">
|
|
<span class="eyebrow mb-3">التسجيل يبدأ بعد الاعتماد</span>
|
|
<h1 class="page-title mb-3"><?= e((string) $application['center_name']) ?></h1>
|
|
<p class="page-copy mb-3">هذه الصفحة جاهزة، لكن فتح سجل الطلاب مرتبط بتحويل حالة المركز إلى <strong>معتمد</strong> أولاً حتى يبقى التسلسل الإداري منظمًا.</p>
|
|
<div class="hero-meta">
|
|
<span>الحالة الحالية: <?= e(status_meta((string) $application['status'])['label']) ?></span>
|
|
<span>المدينة: <?= e((string) $application['city']) ?></span>
|
|
</div>
|
|
<div class="cta-stack mt-4">
|
|
<a class="btn btn-dark" href="application_detail.php?id=<?= e((string) $application['id']) ?>">العودة لملف الاعتماد</a>
|
|
<a class="btn btn-outline-secondary" href="approved_school.php?id=<?= e((string) $application['id']) ?>">صفحة المركز</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<?php else: ?>
|
|
<div class="page-banner approved-hero mb-4 mb-lg-5">
|
|
<div class="row g-4 align-items-start">
|
|
<div class="col-lg-8">
|
|
<span class="approved-kicker mb-3">صفحة مستقلة لتسجيل الطلاب</span>
|
|
<h1 class="page-title mb-3">سجل الطلاب — <?= e((string) $application['center_name']) ?></h1>
|
|
<p class="page-copy mb-3">هذا هو أول موديول تشغيلي بعد اعتماد المدرسة. هنا يتم إدخال بيانات الطلاب في صفحة منفصلة وواضحة، مع كشف جاهز للمراجعة دون خلطه مع بقية وظائف المدرسة.</p>
|
|
<div class="hero-meta">
|
|
<span><?= e((string) $application['city']) ?></span>
|
|
<span>السعة المعتمدة <?= e((string) $expectedCapacity) ?> طالب</span>
|
|
<span>المقاعد المتبقية <?= e((string) $remainingSeats) ?></span>
|
|
</div>
|
|
<div class="cta-stack mt-4">
|
|
<a class="btn btn-dark" href="approved_school.php?id=<?= e((string) $application['id']) ?>">العودة لصفحة المركز</a>
|
|
<a class="btn btn-outline-secondary" href="teachers.php?id=<?= e((string) $application['id']) ?>">فريق المعلمين</a>
|
|
<a class="btn btn-outline-secondary" href="application_detail.php?id=<?= e((string) $application['id']) ?>">ملف الاعتماد</a>
|
|
</div>
|
|
</div>
|
|
<div class="col-lg-4">
|
|
<div class="app-card approved-note h-100">
|
|
<div class="section-title mb-3">ملخص التسجيل</div>
|
|
<div class="launch-metrics">
|
|
<div class="launch-metric"><strong><?= e((string) $metrics['total']) ?></strong><span>إجمالي الطلاب</span></div>
|
|
<div class="launch-metric"><strong><?= e((string) $metrics['active']) ?></strong><span>طلاب مؤكدون</span></div>
|
|
<div class="launch-metric"><strong><?= e((string) $metrics['waiting']) ?></strong><span>قائمة الانتظار</span></div>
|
|
</div>
|
|
<div class="score-bar mt-3 mb-2"><span style="width: <?= e((string) ($expectedCapacity > 0 ? min(100, (int) round(($metrics['total'] / max(1, $expectedCapacity)) * 100)) : 0)) ?>%"></span></div>
|
|
<p class="capacity-note mb-0">تم شغل <?= e((string) $metrics['total']) ?> من أصل <?= e((string) $expectedCapacity) ?> مقعد متوقع حتى الآن.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row g-4 align-items-start">
|
|
<div class="col-lg-4">
|
|
<div class="app-card sidebar-card mb-4">
|
|
<div class="section-head mb-3">
|
|
<div>
|
|
<div class="section-title">إضافة طالب جديد</div>
|
|
<div class="section-copy">نموذج مخصص للتسجيل فقط، مفصول عن صفحة المدرسة وعن بقية الوحدات.</div>
|
|
</div>
|
|
</div>
|
|
|
|
<?php if (!empty($errors['form'])): ?>
|
|
<div class="alert alert-danger mb-3"><?= e($errors['form']) ?></div>
|
|
<?php endif; ?>
|
|
|
|
<form method="post" novalidate>
|
|
<div class="form-section-block mb-3">
|
|
<div class="form-section-heading">
|
|
<div>
|
|
<h2 class="form-section-title">الهوية التعليمية</h2>
|
|
<p class="form-section-copy">البيانات الأساسية التي تدخل مباشرة إلى كشف المدرسة.</p>
|
|
</div>
|
|
</div>
|
|
<div class="row g-3">
|
|
<div class="col-12">
|
|
<label class="form-label" for="student_code">الرقم / الكود</label>
|
|
<input class="form-control <?= isset($errors['student_code']) ? 'is-invalid' : '' ?>" id="student_code" name="student_code" value="<?= e($values['student_code']) ?>" placeholder="مثال: ST-401">
|
|
<?php if (isset($errors['student_code'])): ?><div class="invalid-feedback"><?= e($errors['student_code']) ?></div><?php endif; ?>
|
|
</div>
|
|
<div class="col-12">
|
|
<label class="form-label" for="full_name">اسم الطالب / الطالبة</label>
|
|
<input class="form-control <?= isset($errors['full_name']) ? 'is-invalid' : '' ?>" id="full_name" name="full_name" value="<?= e($values['full_name']) ?>" placeholder="الاسم الثلاثي">
|
|
<?php if (isset($errors['full_name'])): ?><div class="invalid-feedback"><?= e($errors['full_name']) ?></div><?php endif; ?>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<label class="form-label" for="gender">النوع</label>
|
|
<select class="form-select <?= isset($errors['gender']) ? 'is-invalid' : '' ?>" id="gender" name="gender">
|
|
<option value="">اختر</option>
|
|
<?php foreach (student_gender_options() as $option): ?>
|
|
<option value="<?= e($option) ?>" <?= $values['gender'] === $option ? 'selected' : '' ?>><?= e($option) ?></option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
<?php if (isset($errors['gender'])): ?><div class="invalid-feedback"><?= e($errors['gender']) ?></div><?php endif; ?>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<label class="form-label" for="grade_level">الصف الدراسي</label>
|
|
<select class="form-select <?= isset($errors['grade_level']) ? 'is-invalid' : '' ?>" id="grade_level" name="grade_level">
|
|
<option value="">اختر</option>
|
|
<?php foreach (student_grade_options() as $option): ?>
|
|
<option value="<?= e($option) ?>" <?= $values['grade_level'] === $option ? 'selected' : '' ?>><?= e($option) ?></option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
<?php if (isset($errors['grade_level'])): ?><div class="invalid-feedback"><?= e($errors['grade_level']) ?></div><?php endif; ?>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-section-block mb-3">
|
|
<div class="form-section-heading">
|
|
<div>
|
|
<h2 class="form-section-title">ولي الأمر وحالة القيد</h2>
|
|
<p class="form-section-copy">تفاصيل التواصل والمتابعة قبل بداية الدوام.</p>
|
|
</div>
|
|
</div>
|
|
<div class="row g-3">
|
|
<div class="col-12">
|
|
<label class="form-label" for="guardian_name">اسم ولي الأمر</label>
|
|
<input class="form-control <?= isset($errors['guardian_name']) ? 'is-invalid' : '' ?>" id="guardian_name" name="guardian_name" value="<?= e($values['guardian_name']) ?>" placeholder="الاسم الكامل">
|
|
<?php if (isset($errors['guardian_name'])): ?><div class="invalid-feedback"><?= e($errors['guardian_name']) ?></div><?php endif; ?>
|
|
</div>
|
|
<div class="col-12">
|
|
<label class="form-label" for="guardian_phone">هاتف ولي الأمر</label>
|
|
<input class="form-control <?= isset($errors['guardian_phone']) ? 'is-invalid' : '' ?>" id="guardian_phone" name="guardian_phone" value="<?= e($values['guardian_phone']) ?>" placeholder="0500000000">
|
|
<?php if (isset($errors['guardian_phone'])): ?><div class="invalid-feedback"><?= e($errors['guardian_phone']) ?></div><?php endif; ?>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<label class="form-label" for="birth_date">تاريخ الميلاد</label>
|
|
<input type="date" class="form-control <?= isset($errors['birth_date']) ? 'is-invalid' : '' ?>" id="birth_date" name="birth_date" value="<?= e($values['birth_date']) ?>">
|
|
<?php if (isset($errors['birth_date'])): ?><div class="invalid-feedback"><?= e($errors['birth_date']) ?></div><?php endif; ?>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<label class="form-label" for="enrollment_status">حالة التسجيل</label>
|
|
<select class="form-select <?= isset($errors['enrollment_status']) ? 'is-invalid' : '' ?>" id="enrollment_status" name="enrollment_status">
|
|
<?php foreach (student_enrollment_status_map() as $key => $meta): ?>
|
|
<option value="<?= e($key) ?>" <?= $values['enrollment_status'] === $key ? 'selected' : '' ?>><?= e($meta['label']) ?></option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
<?php if (isset($errors['enrollment_status'])): ?><div class="invalid-feedback"><?= e($errors['enrollment_status']) ?></div><?php endif; ?>
|
|
</div>
|
|
<div class="col-12">
|
|
<label class="form-label" for="notes">ملاحظات</label>
|
|
<textarea class="form-control" id="notes" name="notes" rows="4" placeholder="مثال: احتياج تعليمي، ملاحظة صحية، أو حالة انتظار."><?= e($values['notes']) ?></textarea>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="d-grid">
|
|
<button class="btn btn-dark" type="submit">حفظ الطالب</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
|
|
<div class="app-card sidebar-card">
|
|
<div class="section-title mb-3">جاهزية بقية الوحدات</div>
|
|
<ul class="module-roadmap-list mb-0">
|
|
<li><strong>المعلمين</strong><span class="section-subtle">الصفحة أصبحت جاهزة الآن لإدارة الفريق التعليمي لهذا المركز.</span><div class="mt-2"><a class="btn btn-sm btn-outline-secondary" href="teachers.php?id=<?= e((string) $application['id']) ?>">فتح صفحة المعلمين</a></div></li>
|
|
<li><strong>التقييمات والأوزان</strong><span class="section-subtle">الأساس جاهز لتخزين نوع التقييم، المقياس، والوزن.</span></li>
|
|
<li><strong>غياب الطلاب</strong><span class="section-subtle">سجل الغياب موجود في القاعدة وسيتم بناء صفحته المنفصلة لاحقاً.</span></li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-lg-8">
|
|
<div class="app-card mb-4">
|
|
<div class="section-head mb-3">
|
|
<div>
|
|
<div class="section-title">كشف المدرسة</div>
|
|
<div class="section-copy">الطلاب المسجلون حالياً في هذه المدرسة فقط.</div>
|
|
</div>
|
|
<span class="header-chip"><?= e((string) $metrics['boys']) ?> طلاب / <?= e((string) $metrics['girls']) ?> طالبات</span>
|
|
</div>
|
|
|
|
<div class="row g-3 mb-3">
|
|
<div class="col-md-4"><div class="school-data-item"><strong>إجمالي القيد</strong><span><?= e((string) $metrics['total']) ?> طالب</span></div></div>
|
|
<div class="col-md-4"><div class="school-data-item"><strong>حالات نشطة</strong><span><?= e((string) $metrics['active']) ?> طالب مؤكد</span></div></div>
|
|
<div class="col-md-4"><div class="school-data-item"><strong>مقاعد متاحة</strong><span><?= e((string) $remainingSeats) ?> مقعد متبقٍ</span></div></div>
|
|
</div>
|
|
|
|
<?php if ($students === []): ?>
|
|
<div class="empty-state text-center p-4">
|
|
<div class="empty-title mb-2">لا يوجد طلاب مسجلون بعد</div>
|
|
<p class="text-muted mb-0">ابدأ من نموذج التسجيل في الجانب الأيمن لإضافة أول طالب إلى كشف المدرسة.</p>
|
|
</div>
|
|
<?php else: ?>
|
|
<div class="table-responsive">
|
|
<table class="table app-table align-middle">
|
|
<thead>
|
|
<tr>
|
|
<th>الكود</th>
|
|
<th>الطالب</th>
|
|
<th>الصف</th>
|
|
<th>ولي الأمر</th>
|
|
<th>الهاتف</th>
|
|
<th>الحالة</th>
|
|
<th>التسجيل</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach ($students as $student): ?>
|
|
<tr>
|
|
<td><strong><?= e((string) $student['student_code']) ?></strong></td>
|
|
<td>
|
|
<strong><?= e((string) $student['full_name']) ?></strong>
|
|
<small><?= e((string) $student['gender']) ?></small>
|
|
</td>
|
|
<td><?= e((string) $student['grade_level']) ?></td>
|
|
<td>
|
|
<strong><?= e((string) $student['guardian_name']) ?></strong>
|
|
<?php if (!empty($student['notes'])): ?><small><?= e((string) $student['notes']) ?></small><?php endif; ?>
|
|
</td>
|
|
<td><?= e((string) $student['guardian_phone']) ?></td>
|
|
<td><?= student_enrollment_status_badge((string) $student['enrollment_status']) ?></td>
|
|
<td><?= e(substr((string) $student['created_at'], 0, 10)) ?></td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<?php endif; ?>
|
|
</div>
|
|
|
|
<div class="app-card">
|
|
<div class="section-title mb-3">سياق المدرسة</div>
|
|
<div class="row g-3">
|
|
<div class="col-md-6"><div class="school-data-item"><strong>مدير المركز</strong><span><?= e((string) $application['director_name']) ?></span></div></div>
|
|
<div class="col-md-6"><div class="school-data-item"><strong>فترة التشغيل</strong><span><?= e((string) $application['start_date']) ?> — <?= e((string) $application['end_date']) ?></span></div></div>
|
|
<div class="col-md-6"><div class="school-data-item"><strong>الفئة المستهدفة</strong><span><?= e((string) $application['gender_scope']) ?></span></div></div>
|
|
<div class="col-md-6"><div class="school-data-item"><strong>البريد الرسمي</strong><span><?= e((string) $application['email']) ?></span></div></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<?php endif; ?>
|
|
</div>
|
|
</section>
|
|
<?php render_page_end(); ?>
|