223 lines
11 KiB
PHP
223 lines
11 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
require_once __DIR__ . '/includes/app.php';
|
|
|
|
if (!is_super_admin()) {
|
|
http_response_code(403);
|
|
render_page_start('صلاحيات غير كافية', 'admin', 'هذه الصفحة مخصصة للمشرف العام لإدارة بنود قوالب تقييم المراكز.');
|
|
?>
|
|
<section class="py-5 text-center">
|
|
<div class="container-xxl">
|
|
<h1 class="mb-3">عذراً</h1>
|
|
<p>هذه الصفحة مخصصة للمشرف العام فقط.</p>
|
|
<a href="admin.php" class="btn btn-primary mt-3">العودة إلى لوحة الإدارة</a>
|
|
</div>
|
|
</section>
|
|
<?php
|
|
render_page_end();
|
|
exit;
|
|
}
|
|
|
|
$assessmentId = filter_input(INPUT_GET, 'assessment_id', FILTER_VALIDATE_INT) ?: 0;
|
|
if ($assessmentId <= 0) {
|
|
set_flash('error', 'اختر أولاً قالب تقييم من صفحة القوالب العامة.');
|
|
header('Location: global_center_assessments.php');
|
|
exit;
|
|
}
|
|
|
|
$assessment = get_global_center_assessment_type($assessmentId);
|
|
if (!$assessment) {
|
|
set_flash('error', 'قالب التقييم المطلوب غير موجود أو تم حذفه.');
|
|
header('Location: global_center_assessments.php');
|
|
exit;
|
|
}
|
|
|
|
$flash = consume_flash();
|
|
$criteria = list_global_center_assessment_criteria_by_assessment($assessmentId);
|
|
$criteriaMetrics = global_center_assessment_criteria_metrics($assessmentId);
|
|
$errors = [];
|
|
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
[$submittedData, $errors] = validate_global_center_assessment_criteria_input($assessmentId, $_POST);
|
|
if ($errors === []) {
|
|
try {
|
|
save_global_center_assessment_criteria($assessmentId, $submittedData);
|
|
set_flash('success', 'تم حفظ بنود قالب تقييم المراكز بنجاح.');
|
|
header('Location: global_center_assessment_criteria.php?assessment_id=' . $assessmentId);
|
|
exit;
|
|
} catch (Throwable $exception) {
|
|
$errors['form'] = 'تعذر حفظ البنود حالياً. يرجى المحاولة مرة أخرى.';
|
|
$criteria = $submittedData['criteria'];
|
|
}
|
|
} else {
|
|
$criteria = $submittedData['criteria'];
|
|
}
|
|
}
|
|
|
|
$blankRows = 3;
|
|
for ($i = 0; $i < $blankRows; $i++) {
|
|
$criteria[] = [
|
|
'id' => 0,
|
|
'title' => '',
|
|
'max_score' => '',
|
|
'notes' => '',
|
|
'is_active' => '1',
|
|
];
|
|
}
|
|
|
|
render_page_start(
|
|
'بنود قالب تقييم المراكز',
|
|
'admin',
|
|
'إدارة البنود والمعايير التفصيلية للقالب العام الذي سيُستخدم لاحقاً عند تقييم المراكز.'
|
|
);
|
|
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 require __DIR__ . '/includes/sidebar.php'; ?>
|
|
</div>
|
|
<div class="col-lg-9 layout-content-column">
|
|
|
|
<div class="page-banner mb-4">
|
|
<div class="row g-4 align-items-start">
|
|
<div class="col-lg-8">
|
|
<span class="eyebrow mb-3">بناء المعايير</span>
|
|
<h1 class="page-title mb-3">بنود القالب: <?= e((string) ($assessment['title'] ?? '')) ?></h1>
|
|
<p class="page-copy mb-3">أضف هنا البنود التي سيعتمد عليها المشرف العام أو المقيم المسؤول عند تقييم المراكز. مجموع البنود النشطة يحدّث الدرجة القصوى تلقائياً.</p>
|
|
<div class="hero-meta">
|
|
<span>الفئة <?= e((string) ($assessment['category'] ?? '')) ?></span>
|
|
<span>المقياس <?= e(assessment_scale_type_label((string) ($assessment['scale_type'] ?? 'percentage'))) ?></span>
|
|
<span>الوزن <?= e(rtrim(rtrim(number_format((float) ($assessment['weight_percentage'] ?? 0), 2, '.', ''), '0'), '.')) ?>٪</span>
|
|
</div>
|
|
<div class="cta-stack mt-4">
|
|
<a class="btn btn-outline-secondary" href="global_center_assessments.php">العودة إلى القوالب</a>
|
|
<a class="btn btn-primary" href="center_assessments.php">فتح صفحة تقييم المراكز</a>
|
|
</div>
|
|
</div>
|
|
<div class="col-lg-4">
|
|
<div class="page-banner-panel h-100">
|
|
<div class="mini-stat-label">الدرجة القصوى الحالية</div>
|
|
<div class="mini-stat-value"><?= e(rtrim(rtrim(number_format((float) ($assessment['max_score'] ?? 0), 2, '.', ''), '0'), '.')) ?></div>
|
|
<div class="mini-stat-copy mb-3">يتم تحديثها تلقائياً وفق مجموع درجات البنود النشطة فقط.</div>
|
|
<div><?= assessment_active_badge((int) ($assessment['is_active'] ?? 0)) ?></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row g-3 mb-4">
|
|
<div class="col-md-4"><div class="app-card stat-tile"><div class="mini-stat-label">إجمالي البنود</div><div class="mini-stat-value"><?= e((string) $criteriaMetrics['total']) ?></div><div class="mini-stat-copy">كل البنود المحفوظة لهذا القالب.</div></div></div>
|
|
<div class="col-md-4"><div class="app-card stat-tile"><div class="mini-stat-label">البنود النشطة</div><div class="mini-stat-value"><?= e((string) $criteriaMetrics['active']) ?></div><div class="mini-stat-copy">هي التي يعتمد عليها التقييم الفعلي.</div></div></div>
|
|
<div class="col-md-4"><div class="app-card stat-tile"><div class="mini-stat-label">مجموع الدرجات النشطة</div><div class="mini-stat-value"><?= e(rtrim(rtrim(number_format((float) $criteriaMetrics['active_max_score'], 2, '.', ''), '0'), '.')) ?></div><div class="mini-stat-copy">يعيد ضبط الدرجة القصوى للقالب تلقائياً.</div></div></div>
|
|
</div>
|
|
|
|
<div class="app-card">
|
|
<div class="section-head mb-3">
|
|
<div>
|
|
<div class="section-title">إدارة البنود</div>
|
|
<div class="section-copy">يمكنك تعديل البنود الحالية أو إضافة بنود جديدة. الصفوف الفارغة لن تُحفظ.</div>
|
|
</div>
|
|
<button type="button" class="btn btn-outline-secondary btn-sm" id="addCriteriaRow">إضافة صف جديد</button>
|
|
</div>
|
|
|
|
<?php if (isset($errors['form'])): ?>
|
|
<div class="alert alert-danger"><?= e($errors['form']) ?></div>
|
|
<?php endif; ?>
|
|
|
|
<?php foreach ($errors as $errorKey => $message): ?>
|
|
<?php if (str_starts_with($errorKey, 'criteria_')): ?>
|
|
<div class="alert alert-warning py-2 mb-2"><?= e($message) ?></div>
|
|
<?php endif; ?>
|
|
<?php endforeach; ?>
|
|
|
|
<form method="post">
|
|
<div id="criteriaRows" class="d-grid gap-3">
|
|
<?php foreach ($criteria as $index => $criterion): ?>
|
|
<div class="border rounded-4 p-3 bg-white">
|
|
<input type="hidden" name="criteria[<?= e((string) $index) ?>][id]" value="<?= e((string) ($criterion['id'] ?? 0)) ?>">
|
|
<div class="row g-3 align-items-start">
|
|
<div class="col-lg-4">
|
|
<label class="form-label">اسم البند</label>
|
|
<input class="form-control" name="criteria[<?= e((string) $index) ?>][title]" value="<?= e((string) ($criterion['title'] ?? '')) ?>" placeholder="مثال: الالتزام بالخطة التشغيلية">
|
|
</div>
|
|
<div class="col-lg-2">
|
|
<label class="form-label">الدرجة</label>
|
|
<input class="form-control" type="number" min="0.01" max="1000" step="0.01" name="criteria[<?= e((string) $index) ?>][max_score]" value="<?= e((string) ($criterion['max_score'] ?? '')) ?>" placeholder="10">
|
|
</div>
|
|
<div class="col-lg-2">
|
|
<label class="form-label">الحالة</label>
|
|
<select class="form-select" name="criteria[<?= e((string) $index) ?>][is_active]">
|
|
<option value="1" <?= ((string) ($criterion['is_active'] ?? '1')) === '1' ? 'selected' : '' ?>>مفعّل</option>
|
|
<option value="0" <?= ((string) ($criterion['is_active'] ?? '1')) === '0' ? 'selected' : '' ?>>مؤرشف</option>
|
|
</select>
|
|
</div>
|
|
<div class="col-lg-4">
|
|
<label class="form-label">ملاحظات</label>
|
|
<input class="form-control" name="criteria[<?= e((string) $index) ?>][notes]" value="<?= e((string) ($criterion['notes'] ?? '')) ?>" placeholder="شرح مختصر لما يجب مراجعته في هذا البند">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<?php endforeach; ?>
|
|
</div>
|
|
|
|
<div class="d-flex flex-wrap gap-2 mt-4">
|
|
<button class="btn btn-primary" type="submit">حفظ البنود</button>
|
|
<a class="btn btn-outline-secondary" href="global_center_assessments.php?edit=<?= e((string) $assessmentId) ?>#assessmentFormCard">تحرير القالب</a>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<template id="criteriaRowTemplate">
|
|
<div class="border rounded-4 p-3 bg-white">
|
|
<input type="hidden" data-name="id" value="0">
|
|
<div class="row g-3 align-items-start">
|
|
<div class="col-lg-4">
|
|
<label class="form-label">اسم البند</label>
|
|
<input class="form-control" data-name="title" placeholder="مثال: الجاهزية الإدارية">
|
|
</div>
|
|
<div class="col-lg-2">
|
|
<label class="form-label">الدرجة</label>
|
|
<input class="form-control" type="number" min="0.01" max="1000" step="0.01" data-name="max_score" placeholder="10">
|
|
</div>
|
|
<div class="col-lg-2">
|
|
<label class="form-label">الحالة</label>
|
|
<select class="form-select" data-name="is_active">
|
|
<option value="1" selected>مفعّل</option>
|
|
<option value="0">مؤرشف</option>
|
|
</select>
|
|
</div>
|
|
<div class="col-lg-4">
|
|
<label class="form-label">ملاحظات</label>
|
|
<input class="form-control" data-name="notes" placeholder="شرح مختصر لما يجب فحصه">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
(function () {
|
|
const rowsContainer = document.getElementById('criteriaRows');
|
|
const addButton = document.getElementById('addCriteriaRow');
|
|
const template = document.getElementById('criteriaRowTemplate');
|
|
if (!rowsContainer || !addButton || !template) return;
|
|
|
|
let rowIndex = rowsContainer.children.length;
|
|
addButton.addEventListener('click', function () {
|
|
const fragment = template.content.cloneNode(true);
|
|
fragment.querySelectorAll('[data-name]').forEach(function (field) {
|
|
field.setAttribute('name', 'criteria[' + rowIndex + '][' + field.getAttribute('data-name') + ']');
|
|
});
|
|
rowsContainer.appendChild(fragment);
|
|
rowIndex += 1;
|
|
});
|
|
})();
|
|
</script>
|
|
<?php render_page_end(); ?>
|