Commit d2162963 authored by Mahmoud Aglan's avatar Mahmoud Aglan

fix(sports): redesign assessment wizard — programs as expandable list with...

fix(sports): redesign assessment wizard — programs as expandable list with inline groups & centered modal

- Programs display as vertical list items with chevron toggle
- Clicking a program expands its groups panel directly beneath it
- Group creation opens a centered modal popup instead of inline section
- Fixed GroupQuickCreateApiController to return full group data (fees, coach, discipline)
- Groups render with progress bars and proper fee display after creation
Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
parent e695c32c
...@@ -57,17 +57,35 @@ class GroupQuickCreateApiController extends Controller ...@@ -57,17 +57,35 @@ class GroupQuickCreateApiController extends Controller
'created_by' => $employee ? (int) $employee->id : null, 'created_by' => $employee ? (int) $employee->id : null,
]); ]);
$fullGroup = $db->selectOne(
"SELECT g.id, g.name_ar, g.code, g.current_count, g.max_capacity, g.is_full,
p.id as program_id, p.name_ar as program_name,
p.monthly_fee_member, p.monthly_fee_nonmember,
d.id as discipline_id, d.name_ar as discipline_name,
c.full_name_ar as coach_name
FROM sa_groups g
LEFT JOIN sa_programs p ON p.id = g.program_id
LEFT JOIN sa_disciplines d ON d.id = p.discipline_id
LEFT JOIN sa_coaches c ON c.id = g.coach_id
WHERE g.id = ?",
[$groupId]
);
return $this->json([ return $this->json([
'success' => true, 'success' => true,
'group' => [ 'group' => $fullGroup ?: [
'id' => $groupId, 'id' => $groupId,
'name_ar' => $nameAr, 'name_ar' => $nameAr,
'code' => $code, 'code' => $code,
'program_id' => $programId, 'program_id' => $programId,
'program_name' => $program['name_ar'], 'program_name' => $program['name_ar'],
'discipline_name' => $program['discipline_name'] ?? '', 'discipline_name' => $program['discipline_name'] ?? '',
'max_capacity' => (int) ($program['max_capacity'] ?? 20), 'monthly_fee_member' => $program['monthly_fee_member'] ?? '0',
'current_count' => 0, 'monthly_fee_nonmember'=> $program['monthly_fee_nonmember'] ?? '0',
'coach_name' => null,
'max_capacity' => (int) ($program['max_capacity'] ?? 20),
'current_count' => 0,
'is_full' => 0,
], ],
]); ]);
} }
......
...@@ -27,9 +27,7 @@ ...@@ -27,9 +27,7 @@
<span style="margin-right:8px;direction:ltr;display:inline-block;"><?= e($registration['player_nid']) ?></span> <span style="margin-right:8px;direction:ltr;display:inline-block;"><?= e($registration['player_nid']) ?></span>
<?php endif; ?> <?php endif; ?>
<?php if (!empty($registration['date_of_birth'])): ?> <?php if (!empty($registration['date_of_birth'])): ?>
<?php <?php $age = (int) ((time() - strtotime($registration['date_of_birth'])) / (365.25 * 86400)); ?>
$age = (int) ((time() - strtotime($registration['date_of_birth'])) / (365.25 * 86400));
?>
<span style="margin-right:8px;"><?= $age ?> سنة</span> <span style="margin-right:8px;"><?= $age ?> سنة</span>
<?php endif; ?> <?php endif; ?>
</div> </div>
...@@ -66,7 +64,6 @@ ...@@ -66,7 +64,6 @@
<h3 style="margin:0;color:#0D7377;font-size:15px;">تصنيف المستوى</h3> <h3 style="margin:0;color:#0D7377;font-size:15px;">تصنيف المستوى</h3>
</div> </div>
<div style="padding:20px;"> <div style="padding:20px;">
<!-- Skill Level -->
<div class="form-group" style="margin-bottom:20px;"> <div class="form-group" style="margin-bottom:20px;">
<label class="form-label">المستوى <span style="color:#DC2626;">*</span></label> <label class="form-label">المستوى <span style="color:#DC2626;">*</span></label>
<div style="display:grid;grid-template-columns:1fr 1fr 1fr;gap:10px;"> <div style="display:grid;grid-template-columns:1fr 1fr 1fr;gap:10px;">
...@@ -85,8 +82,7 @@ ...@@ -85,8 +82,7 @@
</div> </div>
</div> </div>
<!-- Assessment Notes --> <div class="form-group">
<div class="form-group" style="margin-bottom:20px;">
<label class="form-label">ملاحظات المدرب</label> <label class="form-label">ملاحظات المدرب</label>
<textarea name="assessment_notes" class="form-input" rows="3" placeholder="ملاحظات عن مستوى اللاعب..."></textarea> <textarea name="assessment_notes" class="form-input" rows="3" placeholder="ملاحظات عن مستوى اللاعب..."></textarea>
</div> </div>
...@@ -119,7 +115,6 @@ ...@@ -119,7 +115,6 @@
</div> </div>
<div style="padding:16px;"> <div style="padding:16px;">
<!-- Step 1: Discipline Tabs -->
<?php if (count($programsByDisc) > 1): ?> <?php if (count($programsByDisc) > 1): ?>
<div style="display:flex;gap:8px;flex-wrap:wrap;margin-bottom:14px;"> <div style="display:flex;gap:8px;flex-wrap:wrap;margin-bottom:14px;">
<?php foreach ($programsByDisc as $dId => $dData): ?> <?php foreach ($programsByDisc as $dId => $dData): ?>
...@@ -130,63 +125,45 @@ ...@@ -130,63 +125,45 @@
</div> </div>
<?php endif; ?> <?php endif; ?>
<!-- Step 2: Program Cards --> <!-- Programs List (vertical, expandable) -->
<div id="programsList" style="display:grid;gap:10px;margin-bottom:16px;"> <div id="programsList">
<?php foreach ($programs as $p): <?php foreach ($programs as $p):
$pId = (int) $p['id']; $pId = (int) $p['id'];
$pGroups = $groupsByProgram[$pId] ?? [];
$fee = $playerType === 'member' ? (float) $p['monthly_fee_member'] : (float) $p['monthly_fee_nonmember']; $fee = $playerType === 'member' ? (float) $p['monthly_fee_member'] : (float) $p['monthly_fee_nonmember'];
?> ?>
<div class="program-card" data-disc-id="<?= (int) $p['discipline_id'] ?>" data-program-id="<?= $pId ?>" <div class="program-item" data-disc-id="<?= (int) $p['discipline_id'] ?>" data-program-id="<?= $pId ?>" style="margin-bottom:6px;">
style="border:2px solid #E5E7EB;border-radius:12px;padding:14px 16px;cursor:pointer;transition:all 0.2s;" <!-- Program Row -->
onclick="selectProgram(this, <?= $pId ?>)"> <div class="program-row" onclick="toggleProgram(this, <?= $pId ?>)"
<div style="display:flex;align-items:center;justify-content:space-between;"> style="display:flex;align-items:center;justify-content:space-between;padding:12px 16px;border:2px solid #E5E7EB;border-radius:10px;cursor:pointer;transition:all 0.2s;background:#fff;">
<div> <div style="display:flex;align-items:center;gap:10px;">
<div style="font-weight:700;font-size:14px;color:#1A1A2E;"><?= e($p['name_ar']) ?></div> <i data-lucide="chevron-down" class="program-chevron" style="width:16px;height:16px;color:#9CA3AF;transition:transform 0.2s;transform:rotate(-90deg);"></i>
<div style="font-size:12px;color:#6B7280;margin-top:3px;"> <div>
<?= (int) $p['session_duration_minutes'] ?> دقيقة | <?= (int) $p['sessions_per_week'] ?> مرات/أسبوع <div style="font-weight:700;font-size:14px;color:#1A1A2E;"><?= e($p['name_ar']) ?></div>
| سعة: <?= (int) $p['max_capacity'] ?> <div style="font-size:11px;color:#6B7280;margin-top:2px;">
<?= (int) $p['session_duration_minutes'] ?> دقيقة | <?= (int) $p['sessions_per_week'] ?> مرات/أسبوع | سعة: <?= (int) $p['max_capacity'] ?>
</div>
</div> </div>
</div> </div>
<div style="text-align:left;"> <div style="text-align:left;flex-shrink:0;">
<div style="font-size:15px;font-weight:700;color:#059669;"><?= number_format($fee, 0) ?> ج.م</div> <div style="font-size:15px;font-weight:700;color:#059669;"><?= number_format($fee, 0) ?> ج.م</div>
<div style="font-size:10px;color:#6B7280;"><?= $playerType === 'member' ? 'عضو' : 'غير عضو' ?></div> <div style="font-size:10px;color:#6B7280;"><?= $playerType === 'member' ? 'عضو' : 'غير عضو' ?></div>
</div> </div>
</div> </div>
</div>
<?php endforeach; ?>
</div>
<!-- Step 3: Groups under selected program --> <!-- Groups Panel (hidden by default, expands under program) -->
<div id="groupsSection" style="display:none;"> <div class="program-groups-panel" data-program-id="<?= $pId ?>" style="display:none;margin:4px 0 0 28px;padding:12px;border:1px solid #E8ECF0;border-radius:8px;background:#F9FAFB;">
<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:10px;"> <div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:10px;">
<h4 style="margin:0;font-size:14px;color:#374151;"><i data-lucide="users" style="width:16px;height:16px;vertical-align:middle;margin-left:4px;color:#0D7377;"></i> المجموعات المتاحة</h4> <span style="font-size:13px;font-weight:600;color:#374151;">المجموعات</span>
<button type="button" id="btnAddGroup" class="btn btn-outline" style="font-size:12px;padding:6px 12px;border-radius:8px;color:#0D7377;border-color:#0D7377;" onclick="showAddGroupModal()"> <button type="button" class="btn btn-outline" style="font-size:11px;padding:4px 10px;border-radius:6px;color:#0D7377;border-color:#0D7377;" onclick="event.stopPropagation();openCreateGroupModal(<?= $pId ?>, '<?= e(addslashes($p['name_ar'])) ?>')">
<i data-lucide="plus" style="width:14px;height:14px;vertical-align:middle;margin-left:4px;"></i> أضف مجموعة <i data-lucide="plus" style="width:12px;height:12px;vertical-align:middle;margin-left:3px;"></i> أضف مجموعة
</button> </button>
</div> </div>
<div id="groupCards" style="display:grid;gap:10px;max-height:350px;overflow-y:auto;"> <div class="groups-container" data-program-id="<?= $pId ?>">
<!-- Populated by JS --> <!-- Filled by JS -->
</div> </div>
<div id="noGroupsMsg" style="display:none;text-align:center;padding:24px;color:#6B7280;font-size:13px;"> </div>
<i data-lucide="inbox" style="width:32px;height:32px;color:#D1D5DB;display:block;margin:0 auto 8px;"></i>
لا توجد مجموعات لهذا البرنامج — أضف مجموعة جديدة
</div> </div>
</div> <?php endforeach; ?>
</div>
</div>
<!-- Add Group Modal -->
<div id="addGroupModal" style="display:none;position:fixed;inset:0;background:rgba(0,0,0,0.4);z-index:9998;align-items:center;justify-content:center;">
<div style="background:#fff;border-radius:14px;padding:24px;width:90%;max-width:380px;box-shadow:0 20px 60px rgba(0,0,0,0.2);">
<h3 style="margin:0 0 16px;font-size:16px;font-weight:700;color:#1A1A2E;">إضافة مجموعة جديدة</h3>
<div class="form-group" style="margin-bottom:14px;">
<label class="form-label" style="font-size:13px;">اسم المجموعة (اختياري)</label>
<input type="text" id="newGroupName" class="form-input" placeholder="سيتم إنشاء اسم تلقائي إن تُرك فارغاً">
</div>
<div style="display:grid;grid-template-columns:1fr 1fr;gap:10px;">
<button type="button" class="btn btn-outline" onclick="hideAddGroupModal()">إلغاء</button>
<button type="button" class="btn btn-primary" id="btnConfirmAddGroup" onclick="createGroup()">إنشاء</button>
</div> </div>
</div> </div>
</div> </div>
...@@ -229,118 +206,184 @@ ...@@ -229,118 +206,184 @@
</div> </div>
</form> </form>
<!-- Create Group Modal (centered popup) -->
<div id="createGroupModal" style="display:none;position:fixed;inset:0;background:rgba(0,0,0,0.5);z-index:9998;align-items:center;justify-content:center;">
<div style="background:#fff;border-radius:16px;padding:28px;width:90%;max-width:400px;box-shadow:0 24px 60px rgba(0,0,0,0.25);">
<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:20px;">
<h3 style="margin:0;font-size:16px;font-weight:700;color:#1A1A2E;">
<i data-lucide="plus-circle" style="width:18px;height:18px;vertical-align:middle;margin-left:6px;color:#0D7377;"></i>
إنشاء مجموعة جديدة
</h3>
<button type="button" onclick="closeCreateGroupModal()" style="background:none;border:none;cursor:pointer;padding:4px;">
<i data-lucide="x" style="width:20px;height:20px;color:#6B7280;"></i>
</button>
</div>
<div style="margin-bottom:16px;padding:10px 14px;background:#F0FDFA;border-radius:8px;border:1px solid #CCFBF1;">
<div style="font-size:12px;color:#6B7280;">البرنامج:</div>
<div id="modalProgramName" style="font-size:14px;font-weight:600;color:#0D7377;margin-top:2px;"></div>
</div>
<div class="form-group" style="margin-bottom:20px;">
<label class="form-label" style="font-size:13px;">اسم المجموعة <span style="color:#9CA3AF;">(اختياري)</span></label>
<input type="text" id="newGroupName" class="form-input" placeholder="سيتم إنشاء اسم تلقائي إن تُرك فارغاً" style="font-size:14px;">
</div>
<div style="display:grid;grid-template-columns:1fr 1fr;gap:10px;">
<button type="button" class="btn btn-outline" onclick="closeCreateGroupModal()" style="padding:12px;font-size:14px;border-radius:10px;">إلغاء</button>
<button type="button" class="btn btn-primary" id="btnCreateGroup" onclick="createGroup()" style="padding:12px;font-size:14px;border-radius:10px;">
<i data-lucide="plus" style="width:14px;height:14px;vertical-align:middle;margin-left:4px;"></i> إنشاء
</button>
</div>
</div>
</div>
<script> <script>
var groupsData = JSON.parse(document.getElementById('groupsData').textContent); var groupsData = JSON.parse(document.getElementById('groupsData').textContent);
var playerType = JSON.parse(document.getElementById('playerType').textContent); var playerType = JSON.parse(document.getElementById('playerType').textContent);
var selectedProgramId = null; var selectedProgramId = null;
var modalProgramId = null;
var csrfToken = document.querySelector('input[name="_csrf_token"]').value; var csrfToken = document.querySelector('input[name="_csrf_token"]').value;
function selectProgram(el, programId) { function toggleProgram(rowEl, programId) {
selectedProgramId = programId; var item = rowEl.closest('.program-item');
document.querySelectorAll('.program-card').forEach(function(c) { var panel = item.querySelector('.program-groups-panel');
c.style.borderColor = '#E5E7EB'; var chevron = rowEl.querySelector('.program-chevron');
c.style.background = ''; var wasOpen = panel.style.display !== 'none';
// Close all other panels
document.querySelectorAll('.program-item').forEach(function(el) {
var p = el.querySelector('.program-groups-panel');
var r = el.querySelector('.program-row');
var c = r.querySelector('.program-chevron');
p.style.display = 'none';
r.style.borderColor = '#E5E7EB';
r.style.background = '#fff';
c.style.transform = 'rotate(-90deg)';
}); });
el.style.borderColor = '#0D7377';
el.style.background = '#F0FDFA';
renderGroups(programId); if (!wasOpen) {
document.getElementById('groupsSection').style.display = ''; panel.style.display = '';
rowEl.style.borderColor = '#0D7377';
rowEl.style.background = '#F0FDFA';
chevron.style.transform = 'rotate(0deg)';
selectedProgramId = programId;
renderGroupsInPanel(programId);
} else {
selectedProgramId = null;
}
if (typeof lucide !== 'undefined') lucide.createIcons(); if (typeof lucide !== 'undefined') lucide.createIcons();
} }
function renderGroups(programId) { function renderGroupsInPanel(programId) {
var groups = groupsData[programId] || []; var container = document.querySelector('.groups-container[data-program-id="' + programId + '"]');
var container = document.getElementById('groupCards'); if (!container) return;
var noMsg = document.getElementById('noGroupsMsg');
var groups = groupsData[programId] || [];
if (groups.length === 0) { if (groups.length === 0) {
container.innerHTML = ''; container.innerHTML = '<div style="text-align:center;padding:16px;color:#9CA3AF;font-size:13px;">' +
noMsg.style.display = ''; '<i data-lucide="inbox" style="width:24px;height:24px;display:block;margin:0 auto 6px;color:#D1D5DB;"></i>' +
} else { 'لا توجد مجموعات — أنشئ واحدة جديدة</div>';
noMsg.style.display = 'none'; if (typeof lucide !== 'undefined') lucide.createIcons();
var html = ''; return;
groups.forEach(function(g) {
var fee = playerType === 'member' ? parseFloat(g.monthly_fee_member) : parseFloat(g.monthly_fee_nonmember);
var pct = g.max_capacity > 0 ? Math.round((g.current_count / g.max_capacity) * 100) : 0;
var barColor = pct >= 90 ? '#DC2626' : pct >= 70 ? '#F59E0B' : '#059669';
var checked = '';
html += '<label class="group-radio-option" style="display:block;border:2px solid #E5E7EB;border-radius:12px;padding:14px 16px;cursor:pointer;transition:all 0.2s;">';
html += '<div style="display:flex;align-items:center;gap:12px;">';
html += '<input type="radio" name="group_id" value="' + g.id + '" required style="accent-color:#2563EB;width:20px;height:20px;flex-shrink:0;" onchange="highlightGroup(this)">';
html += '<div style="flex:1;min-width:0;">';
html += '<div style="font-weight:600;font-size:14px;">' + esc(g.name_ar) + '</div>';
html += '<div style="font-size:12px;color:#6B7280;margin-top:2px;">';
if (g.coach_name) html += 'مدرب: ' + esc(g.coach_name) + ' | ';
html += esc(g.discipline_name || '') + ' — ' + esc(g.program_name || '');
html += '</div>';
html += '</div>';
html += '<div style="text-align:left;flex-shrink:0;">';
html += '<div style="font-size:15px;font-weight:700;color:#059669;">' + fee.toLocaleString() + ' ج.م</div>';
html += '<div style="font-size:11px;color:#6B7280;">' + g.current_count + '/' + g.max_capacity + '</div>';
html += '</div>';
html += '</div>';
// Progress bar
html += '<div style="margin-top:10px;background:#F3F4F6;border-radius:6px;height:6px;overflow:hidden;">';
html += '<div style="height:100%;width:' + pct + '%;background:' + barColor + ';border-radius:6px;transition:width 0.3s;"></div>';
html += '</div>';
html += '<div style="display:flex;justify-content:space-between;margin-top:4px;font-size:10px;color:#9CA3AF;">';
html += '<span>' + pct + '% ممتلئة</span>';
html += '<span>متبقي ' + (g.max_capacity - g.current_count) + ' مكان</span>';
html += '</div>';
html += '</label>';
});
container.innerHTML = html;
} }
var html = '';
groups.forEach(function(g) {
var fee = playerType === 'member' ? parseFloat(g.monthly_fee_member || 0) : parseFloat(g.monthly_fee_nonmember || 0);
var pct = g.max_capacity > 0 ? Math.round((g.current_count / g.max_capacity) * 100) : 0;
var barColor = pct >= 90 ? '#DC2626' : pct >= 70 ? '#F59E0B' : '#059669';
html += '<label class="group-radio-card" style="display:block;border:2px solid #E5E7EB;border-radius:10px;padding:12px 14px;cursor:pointer;transition:all 0.15s;margin-bottom:6px;background:#fff;">';
html += '<div style="display:flex;align-items:center;gap:10px;">';
html += '<input type="radio" name="group_id" value="' + g.id + '" required style="accent-color:#0D7377;width:18px;height:18px;flex-shrink:0;" onchange="onGroupSelect(this)">';
html += '<div style="flex:1;min-width:0;">';
html += '<div style="font-weight:600;font-size:13px;color:#1A1A2E;">' + esc(g.name_ar) + '</div>';
html += '<div style="font-size:11px;color:#6B7280;margin-top:2px;">';
if (g.coach_name) html += 'المدرب: ' + esc(g.coach_name);
html += '</div>';
html += '</div>';
html += '<div style="text-align:left;flex-shrink:0;">';
html += '<div style="font-size:14px;font-weight:700;color:#059669;">' + fee.toLocaleString() + ' ج.م</div>';
html += '</div>';
html += '</div>';
// Progress bar
html += '<div style="margin-top:8px;display:flex;align-items:center;gap:8px;">';
html += '<div style="flex:1;background:#F3F4F6;border-radius:4px;height:5px;overflow:hidden;">';
html += '<div style="height:100%;width:' + pct + '%;background:' + barColor + ';border-radius:4px;"></div>';
html += '</div>';
html += '<span style="font-size:10px;color:#6B7280;flex-shrink:0;">' + g.current_count + '/' + g.max_capacity + '</span>';
html += '</div>';
html += '</label>';
});
container.innerHTML = html;
if (typeof lucide !== 'undefined') lucide.createIcons(); if (typeof lucide !== 'undefined') lucide.createIcons();
} }
function highlightGroup(radio) { function onGroupSelect(radio) {
document.querySelectorAll('#groupCards .group-radio-option').forEach(function(el) { document.querySelectorAll('.group-radio-card').forEach(function(el) {
el.style.borderColor = '#E5E7EB'; el.style.borderColor = '#E5E7EB';
el.style.background = ''; el.style.background = '#fff';
}); });
radio.closest('.group-radio-option').style.borderColor = '#2563EB'; radio.closest('.group-radio-card').style.borderColor = '#0D7377';
radio.closest('.group-radio-option').style.background = '#F0F7FF'; radio.closest('.group-radio-card').style.background = '#F0FDFA';
} }
function showAddGroupModal() { function openCreateGroupModal(programId, programName) {
document.getElementById('addGroupModal').style.display = 'flex'; modalProgramId = programId;
document.getElementById('modalProgramName').textContent = programName;
document.getElementById('newGroupName').value = ''; document.getElementById('newGroupName').value = '';
document.getElementById('createGroupModal').style.display = 'flex';
document.getElementById('newGroupName').focus();
if (typeof lucide !== 'undefined') lucide.createIcons();
} }
function hideAddGroupModal() { function closeCreateGroupModal() {
document.getElementById('addGroupModal').style.display = 'none'; document.getElementById('createGroupModal').style.display = 'none';
modalProgramId = null;
} }
function createGroup() { function createGroup() {
if (!selectedProgramId) return; if (!modalProgramId) return;
var name = document.getElementById('newGroupName').value.trim(); var name = document.getElementById('newGroupName').value.trim();
var btn = document.getElementById('btnConfirmAddGroup'); var btn = document.getElementById('btnCreateGroup');
btn.disabled = true; btn.disabled = true;
btn.textContent = 'جاري الإنشاء...'; btn.innerHTML = '<i data-lucide="loader" style="width:14px;height:14px;vertical-align:middle;margin-left:4px;animation:spin 1s linear infinite;"></i> جاري الإنشاء...';
fetch('/api/sa/groups/quick-create', { fetch('/api/sa/groups/quick-create', {
method: 'POST', method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded', 'X-Requested-With': 'XMLHttpRequest'}, headers: {
body: '_csrf_token=' + encodeURIComponent(csrfToken) + '&program_id=' + selectedProgramId + '&name_ar=' + encodeURIComponent(name) 'Content-Type': 'application/x-www-form-urlencoded',
'X-Requested-With': 'XMLHttpRequest',
'X-CSRF-TOKEN': csrfToken
},
body: '_csrf_token=' + encodeURIComponent(csrfToken) + '&program_id=' + modalProgramId + '&name_ar=' + encodeURIComponent(name)
})
.then(function(r) {
if (!r.ok) {
return r.text().then(function(t) {
try { return JSON.parse(t); } catch(e) { throw new Error('خطأ ' + r.status); }
});
}
return r.json();
}) })
.then(function(r) { return r.json(); })
.then(function(data) { .then(function(data) {
btn.disabled = false; btn.disabled = false;
btn.textContent = 'إنشاء'; btn.innerHTML = '<i data-lucide="plus" style="width:14px;height:14px;vertical-align:middle;margin-left:4px;"></i> إنشاء';
if (!data.success) { alert(data.error || 'فشل'); return; } if (typeof lucide !== 'undefined') lucide.createIcons();
// Add to local data
if (!groupsData[selectedProgramId]) groupsData[selectedProgramId] = []; if (!data.success) {
groupsData[selectedProgramId].push(data.group); alert(data.error || data.message || 'فشل في إنشاء المجموعة');
renderGroups(selectedProgramId); return;
hideAddGroupModal(); }
if (!groupsData[modalProgramId]) groupsData[modalProgramId] = [];
groupsData[modalProgramId].push(data.group);
renderGroupsInPanel(modalProgramId);
closeCreateGroupModal();
}) })
.catch(function() { .catch(function(err) {
btn.disabled = false; btn.disabled = false;
btn.textContent = 'إنشاء'; btn.innerHTML = '<i data-lucide="plus" style="width:14px;height:14px;vertical-align:middle;margin-left:4px;"></i> إنشاء';
alert('خطأ في الاتصال'); if (typeof lucide !== 'undefined') lucide.createIcons();
alert(err.message || 'خطأ في الاتصال');
}); });
} }
...@@ -356,11 +399,16 @@ document.addEventListener('DOMContentLoaded', function() { ...@@ -356,11 +399,16 @@ document.addEventListener('DOMContentLoaded', function() {
this.style.background = '#0D7377'; this.style.background = '#0D7377';
this.style.color = '#fff'; this.style.color = '#fff';
var discId = this.dataset.discId; var discId = this.dataset.discId;
document.querySelectorAll('.program-card').forEach(function(c) { document.querySelectorAll('.program-item').forEach(function(c) {
c.style.display = c.dataset.discId === discId ? '' : 'none'; c.style.display = c.dataset.discId === discId ? '' : 'none';
}); });
// Hide groups until new program selected // Close expanded panels
document.getElementById('groupsSection').style.display = 'none'; document.querySelectorAll('.program-groups-panel').forEach(function(p) { p.style.display = 'none'; });
document.querySelectorAll('.program-row').forEach(function(r) {
r.style.borderColor = '#E5E7EB';
r.style.background = '#fff';
r.querySelector('.program-chevron').style.transform = 'rotate(-90deg)';
});
selectedProgramId = null; selectedProgramId = null;
}); });
}); });
...@@ -391,19 +439,24 @@ document.addEventListener('DOMContentLoaded', function() { ...@@ -391,19 +439,24 @@ document.addEventListener('DOMContentLoaded', function() {
if (!selectedGroup) { alert('اختر مجموعة أولاً'); return; } if (!selectedGroup) { alert('اختر مجموعة أولاً'); return; }
if (!selectedLevel) { alert('اختر المستوى أولاً'); return; } if (!selectedLevel) { alert('اختر المستوى أولاً'); return; }
var progCard = document.querySelector('.program-card[data-program-id="' + selectedProgramId + '"]'); var progItem = document.querySelector('.program-item[data-program-id="' + selectedProgramId + '"]');
var progName = progCard ? progCard.querySelector('div[style*="font-weight:700"]').textContent.trim() : ''; var progRow = progItem ? progItem.querySelector('.program-row') : null;
var groupLabel = selectedGroup.closest('.group-radio-option'); var progName = progRow ? progRow.querySelector('div[style*="font-weight:700"]').textContent.trim() : '';
var groupName = groupLabel.querySelector('div[style*="font-weight:600"]').textContent.trim();
var discEl = groupLabel.querySelector('div[style*="color:#6B7280"]'); var groupCard = selectedGroup.closest('.group-radio-card');
var discText = discEl ? discEl.textContent.trim().split('—') : ['']; var groupName = groupCard.querySelector('div[style*="font-weight:600"]').textContent.trim();
var amountEl = groupLabel.querySelector('div[style*="color:#059669"]'); var feeEl = groupCard.querySelector('div[style*="color:#059669"]');
var discName = '';
<?php foreach ($programsByDisc as $dId => $dData): ?>
if (progItem && progItem.dataset.discId === '<?= $dId ?>') discName = '<?= e($dData['name']) ?>';
<?php endforeach; ?>
document.getElementById('confGroup').textContent = groupName; document.getElementById('confGroup').textContent = groupName;
document.getElementById('confDisc').textContent = (discText[1] || discText[0] || '').trim().split('|')[0].trim(); document.getElementById('confDisc').textContent = discName;
document.getElementById('confProg').textContent = progName; document.getElementById('confProg').textContent = progName;
document.getElementById('confLevel').textContent = levelLabels[selectedLevel.value] || selectedLevel.value; document.getElementById('confLevel').textContent = levelLabels[selectedLevel.value] || selectedLevel.value;
document.getElementById('confAmount').textContent = amountEl ? amountEl.textContent.trim() : '—'; document.getElementById('confAmount').textContent = feeEl ? feeEl.textContent.trim() : '—';
overlay.style.display = 'flex'; overlay.style.display = 'flex';
if (typeof lucide !== 'undefined') lucide.createIcons(); if (typeof lucide !== 'undefined') lucide.createIcons();
...@@ -412,9 +465,19 @@ document.addEventListener('DOMContentLoaded', function() { ...@@ -412,9 +465,19 @@ document.addEventListener('DOMContentLoaded', function() {
btnCancel.addEventListener('click', function() { overlay.style.display = 'none'; }); btnCancel.addEventListener('click', function() { overlay.style.display = 'none'; });
overlay.addEventListener('click', function(e) { if (e.target === overlay) overlay.style.display = 'none'; }); overlay.addEventListener('click', function(e) { if (e.target === overlay) overlay.style.display = 'none'; });
// Auto-select first discipline if only one // Close create modal on backdrop click
var createModal = document.getElementById('createGroupModal');
createModal.addEventListener('click', function(e) { if (e.target === createModal) closeCreateGroupModal(); });
// Auto-expand first discipline if only one
var discBtns = document.querySelectorAll('.disc-filter-btn'); var discBtns = document.querySelectorAll('.disc-filter-btn');
if (discBtns.length === 1) discBtns[0].click(); if (discBtns.length === 1) discBtns[0].click();
}); });
</script> </script>
<style>
@keyframes spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
.program-row:hover { border-color: #B2DFDB !important; background: #FAFFFE !important; }
.group-radio-card:hover { border-color: #B2DFDB !important; }
</style>
<?php $__template->endSection(); ?> <?php $__template->endSection(); ?>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment