+
+
+
+
+
= e($errors['app_slogan']) ?>
+
diff --git a/approved_school.php b/approved_school.php
index 863d830..3be3fe4 100644
--- a/approved_school.php
+++ b/approved_school.php
@@ -133,6 +133,7 @@ $studentsUrl = school_page_url('students.php', (int) $application['id'], $select
$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];
@@ -185,6 +186,7 @@ render_flash($flash);
+
إدخال الدرجات
إعدادات المركز
ملف الاعتماد
لوحة الإدارة
diff --git a/assessment_scores.php b/assessment_scores.php
new file mode 100644
index 0000000..62f64b7
--- /dev/null
+++ b/assessment_scores.php
@@ -0,0 +1,439 @@
+ 0 ? get_application($applicationId) : null;
+$isApprovedSchool = $application && (string) $application['status'] === 'approved';
+$errors = [];
+$search = clean_text($_GET['search'] ?? '', 255);
+$cycleContext = ['cycles' => [], 'selected' => null, 'active' => null, 'read_only' => false];
+$selectedCycle = null;
+$selectedCycleId = 0;
+$isCycleReadOnly = false;
+$cycleLabel = 'لا توجد دورة بعد';
+$values = [
+ 'assessment_type_id' => '',
+ 'teacher_id' => '',
+ 'assessed_on' => date('Y-m-d'),
+ 'assessment_max_score' => 0.0,
+ 'entries' => [],
+];
+
+if ($application && $isApprovedSchool) {
+ $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;
+}
+
+$assessmentOptions = $isApprovedSchool && $selectedCycleId > 0 ? school_assessment_type_options_by_cycle((int) $application['id'], $selectedCycleId, true) : [];
+$teacherOptions = $isApprovedSchool && $selectedCycleId > 0 ? school_teacher_options_by_cycle((int) $application['id'], $selectedCycleId, true) : [];
+$studentFilters = ['enrollment_status' => 'active'];
+$students = $isApprovedSchool && $selectedCycleId > 0 ? list_school_students_by_cycle((int) $application['id'], $selectedCycleId, $search, 0, 0, $studentFilters) : [];
+
+$selectedAssessmentId = $requestedAssessmentId;
+if ($selectedAssessmentId <= 0 && $assessmentOptions !== []) {
+ $keys = array_keys($assessmentOptions);
+ $selectedAssessmentId = (int) ($keys[0] ?? 0);
+}
+if ($selectedAssessmentId > 0) {
+ $values['assessment_type_id'] = (string) $selectedAssessmentId;
+}
+
+if ($_SERVER['REQUEST_METHOD'] === 'POST' && $application) {
+ if (!$isApprovedSchool) {
+ $errors['form'] = 'لا يمكن إدخال الدرجات قبل اعتماد المركز.';
+ } elseif ($selectedCycleId <= 0) {
+ $errors['form'] = 'يرجى إنشاء دورة موسمية أولاً من صفحة المركز.';
+ } elseif ($isCycleReadOnly) {
+ $errors['form'] = 'هذه الدورة مؤرشفة للقراءة فقط. افتح دورة جديدة أو اختر دورة نشطة لإدخال درجات جديدة.';
+ } else {
+ [$values, $errors, $selectedAssessmentMeta] = validate_assessment_scores_batch_input((int) $application['id'], $selectedCycleId, $_POST);
+ $selectedAssessmentId = (int) ($values['assessment_type_id'] ?? 0);
+ if ($errors === []) {
+ try {
+ $savedRows = save_assessment_scores_in_cycle((int) $application['id'], $selectedCycleId, $values);
+ set_flash('success', 'تم حفظ درجات ' . $savedRows . ' طالب/طالبة في هذا التقييم.');
+ header('Location: ' . school_page_url('assessment_scores.php', (int) $application['id'], $selectedCycleId) . '&assessment_id=' . urlencode((string) $selectedAssessmentId) . ($search !== '' ? '&search=' . urlencode($search) : ''));
+ exit;
+ } catch (Throwable $exception) {
+ $errors['form'] = 'تعذر حفظ الدرجات حالياً. يرجى المحاولة مرة أخرى.';
+ }
+ }
+ }
+}
+
+$selectedAssessment = $selectedAssessmentId > 0 ? ($assessmentOptions[$selectedAssessmentId] ?? null) : null;
+$scoreMap = $isApprovedSchool && $selectedCycleId > 0 && $selectedAssessmentId > 0
+ ? school_assessment_score_map_by_assessment((int) $application['id'], $selectedCycleId, $selectedAssessmentId)
+ : [];
+
+if ($_SERVER['REQUEST_METHOD'] !== 'POST' && $scoreMap !== []) {
+ $firstRecord = reset($scoreMap);
+ if (is_array($firstRecord)) {
+ if (!empty($firstRecord['teacher_id'])) {
+ $values['teacher_id'] = (string) ((int) $firstRecord['teacher_id']);
+ }
+ if (!empty($firstRecord['assessed_on'])) {
+ $values['assessed_on'] = (string) $firstRecord['assessed_on'];
+ }
+ }
+}
+
+$assessmentMetrics = $isApprovedSchool && $selectedCycleId > 0 ? school_assessment_metrics_by_cycle((int) $application['id'], $selectedCycleId) : [
+ 'total' => 0, 'active' => 0, 'inactive' => 0, 'total_weight' => 0.0, 'active_weight' => 0.0,
+ 'average_max_score' => 0.0, 'percentage' => 0, 'points' => 0, 'rubric' => 0,
+];
+$studentMetrics = $isApprovedSchool && $selectedCycleId > 0 ? school_student_metrics_by_cycle((int) $application['id'], $selectedCycleId) : [
+ 'total' => 0, 'boys' => 0, 'girls' => 0, 'active' => 0, 'waiting' => 0, 'withdrawn' => 0,
+];
+$teacherMetrics = $isApprovedSchool && $selectedCycleId > 0 ? school_teacher_metrics_by_cycle((int) $application['id'], $selectedCycleId) : [
+ 'total' => 0, 'active' => 0, 'pending' => 0, 'inactive' => 0, 'teachers' => 0, 'supervisors' => 0,
+];
+$scoreMetrics = $isApprovedSchool && $selectedCycleId > 0 ? school_assessment_score_metrics_by_cycle((int) $application['id'], $selectedCycleId, $selectedAssessmentId) : [
+ 'total' => 0, 'present' => 0, 'absent' => 0, 'excused' => 0, 'average_score' => 0.0, 'latest_date' => '',
+];
+
+$pageTitle = $application ? 'إدخال درجات الطلاب: ' . (string) $application['center_name'] . ($selectedCycle ? ' — ' . $cycleLabel : '') : 'إدخال درجات الطلاب';
+$pageDescription = 'صفحة مستقلة تسمح للمعلم أو الإدارة الأكاديمية بإدخال درجات الطلاب لكل تقييم داخل دورة موسمية محددة.';
+$approvedSchoolUrl = $application ? school_page_url('approved_school.php', (int) $application['id'], $selectedCycleId) : 'approved_school.php';
+$studentsUrl = $application ? school_page_url('students.php', (int) $application['id'], $selectedCycleId) : 'students.php';
+$teachersUrl = $application ? school_page_url('teachers.php', (int) $application['id'], $selectedCycleId) : 'teachers.php';
+$assessmentsUrl = $application ? school_page_url('assessments.php', (int) $application['id'], $selectedCycleId) : 'assessments.php';
+$attendanceUrl = $application ? school_page_url('attendance.php', (int) $application['id'], $selectedCycleId) : 'attendance.php';
+$assessmentSwitchBaseUrl = $application ? school_page_url('assessment_scores.php', (int) $application['id'], $selectedCycleId) : 'assessment_scores.php';
+$latestScoreDate = $scoreMetrics['latest_date'] !== '' ? $scoreMetrics['latest_date'] : 'لا يوجد';
+$averageScoreDisplay = $selectedAssessment && $scoreMetrics['present'] > 0
+ ? number_format((float) $scoreMetrics['average_score'], 2, '.', '') . ' / ' . rtrim(rtrim(number_format((float) $selectedAssessment['max_score'], 2, '.', ''), '0'), '.')
+ : 'لا يوجد';
+
+if (!$application) {
+ http_response_code(404);
+}
+
+render_page_start($pageTitle, 'approved', $pageDescription, (string) ($application['favicon'] ?? ''));
+render_flash($flash);
+?>
+
+
+
+
+
+
+
+
+
+
+
المدرسة غير موجودة
+
تحقق من رابط المدرسة أو ارجع إلى قائمة المراكز المعتمدة.
+
المراكز المعتمدة
+
+
+
+
+
+
الدرجات تُفتح بعد الاعتماد
+
= e((string) $application['center_name']) ?>
+
تم تجهيز صفحة إدخال الدرجات، لكنها لا تعمل إلا بعد اعتماد المركز وفتح الدورة الأكاديمية الخاصة به.
+
+
+
+
+
+
+
+
+
خطوة التنفيذ بعد تصميم ورقة التقييم
+
إدخال درجات الطلاب — = e((string) $application['center_name']) ?>
+
اختر التقييم، حدّد المعلّم إن رغبت، ثم أدخل درجات الطلاب مباشرة داخل نفس الدورة = e($cycleLabel) ?>. كل درجة تُحفَظ على مستوى الطالب والتقييم والموسم الحالي.
+
+ = e((string) $studentMetrics['active']) ?> طلاب نشطون
+ = e((string) $assessmentMetrics['active']) ?> تقييمات مفعلة
+ = e((string) $teacherMetrics['active']) ?> معلمين نشطين
+
+
+
+
+
+
ملخص الدرجة الحالية
+
+
السجلات المحفوظة= e((string) $scoreMetrics['total']) ?> سجل
+
درجات فعلية= e((string) $scoreMetrics['present']) ?> طالب
+
آخر تحديث= e($latestScoreDate) ?>
+
+
المتوسط الحالي: = e($averageScoreDisplay) ?> ضمن التقييم = e($selectedAssessment['label']) ?>.
+
+
+
+
+
+
+
+
+
+
+
+
+
الدورة الموسمية الحالية
+
كل الدرجات في هذه الصفحة مرتبطة بالدورة = e($cycleLabel) ?>. أرشفة الدورة تجعل الصفحة للقراءة فقط بدون خلط النتائج مع الموسم التالي.
+
+ = school_cycle_status_badge((string) $selectedCycle['status']) ?>
+
+
+
اسم الدورة= e($cycleLabel) ?>
+
الفترة= e((string) $selectedCycle['start_date']) ?> → = e((string) $selectedCycle['end_date']) ?>
+
عدد الدورات= e((string) count($cycleContext['cycles'])) ?> دورة للمركز
+
+
+
هذه الدورة مؤرشفة، لذلك تبقى صفحة إدخال الدرجات للقراءة فقط حالياً.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
كشف إدخال الدرجات
+
كل صف يمثل طالباً واحداً ضمن التقييم المختار. عند حفظ النموذج يتم تحديث الصفوف التي تحتوي على درجة أو حالة خاصة أو ملاحظة.
+
+
+
+
+
+
+
لا توجد تقييمات مفعلة بعد
+
أنشئ أول تقييم من صفحة التقييمات، ثم عد هنا لبدء رصد النتائج.
+
+
+
+
لا يوجد طلاب مطابقون لهذا العرض
+
جرّب إزالة البحث الحالي أو أضف طلاباً نشطين من صفحة الطلاب.
+
+
+
+
+
+
+
+
سياق المدرسة
+
+
الطلاب النشطون= e((string) $studentMetrics['active']) ?> طالب/طالبة
+
المعلمون النشطون= e((string) $teacherMetrics['active']) ?> عضو
+
التقييمات المفعلة= e((string) $assessmentMetrics['active']) ?> نوع
+
آخر رصد محفوظ= e($latestScoreDate) ?>
+
+
+
+
+
+
+
+
+
+
+
+إدارة أنواع التقييم وتوزيع الدرجات ضمن الخطة الأكاديمية للدورة
= e($cycleLabel) ?>.