fix: 4 critical bugs — worker argv, student dashboard visibility, teacher onboarding flow, password validation

This commit is contained in:
Hamza-Ayed
2026-08-28 23:08:15 +03:00
parent abe862f04d
commit 1401db11d0
3 changed files with 41 additions and 39 deletions
@@ -73,9 +73,10 @@ class CurriculumController
error_reporting(E_ALL);
ob_start();
// Execute the script logic natively by setting argv
$argv = ['curriculum_worker.php', $taskId];
$_SERVER['argv'] = $argv;
// CRITICAL: Set $GLOBALS['argv'] so the required worker script can access $argv[1]
// (In a web request, $argv is empty — we must set it globally before requiring the worker)
$GLOBALS['argv'] = ['curriculum_worker.php', $taskId];
$_SERVER['argv'] = $GLOBALS['argv'];
require $scriptPath;
+2 -8
View File
@@ -637,7 +637,7 @@ class StudentPortal
</div>
<!-- 2. STUDENT DASHBOARD (100% REAL DATABASE DATA) -->
<div id="dashboard_container" style="width: 100%;">
<div id="dashboard_container" style="width: 100%; display: none;">
<!-- Hero & Tawjihi Readiness Score -->
<div class="dashboard-hero">
@@ -1119,15 +1119,9 @@ class StudentPortal
document.addEventListener('DOMContentLoaded', async () => {
const token = localStorage.getItem('saqel_student_jwt');
const cachedUser = localStorage.getItem('saqel_student_user');
if (token) {
if (cachedUser) {
try {
const u = JSON.parse(cachedUser);
renderDashboard(u);
} catch (e) {}
}
// Always verify session with server — don't render from cache directly
initWebSocket(token);
await checkStudentSession(token);
}
+35 -28
View File
@@ -391,10 +391,8 @@ class TeacherPortal
</select>
</div>
<div class="form-group">
<label class="form-label">تعيين كلمة المرور السرية <span style="color: #EF4444;">*</span></label>
<input type="password" id="onboard_password" placeholder="8 خانات على الأقل" class="input-text">
</div>
<!-- Password field removed: OTP-based auth, no password needed for initial setup -->
<button type="button" id="btn_complete_onboarding" onclick="handleCompleteOnboarding(event)" class="btn-primary">
<span id="btn_onboard_text">حفظ وتفعيل لوحة التحكم 🚀</span>
@@ -665,14 +663,9 @@ class TeacherPortal
document.addEventListener('DOMContentLoaded', async () => {
const token = localStorage.getItem('saqel_teacher_jwt');
const cachedUser = localStorage.getItem('saqel_teacher_user');
if (token) {
if (cachedUser) {
try {
const u = JSON.parse(cachedUser);
renderDashboard(u, { specialization: u.specialization || 'المعلم المعتمد' });
} catch (e) {}
}
// Always verify session first — don't blindly render from cache
// checkTeacherSession will render dashboard or show onboarding based on profile status
initWebSocket(token);
await checkTeacherSession(token);
}
@@ -1120,6 +1113,10 @@ class TeacherPortal
}
function switchToOnboardingStep() {
// Restore auth container, hide dashboard (renderDashboard may have hidden auth_container)
document.getElementById('auth_container').style.display = 'block';
document.getElementById('dashboard_container').style.display = 'none';
// Show only onboarding step
document.getElementById('step_phone_container').style.display = 'none';
document.getElementById('step_otp_container').style.display = 'none';
document.getElementById('step_onboarding_container').style.display = 'block';
@@ -1217,21 +1214,14 @@ class TeacherPortal
if (res.ok && data.status === 'success' && data.data?.token) {
const token = data.data.token;
const user = data.data.user;
const profile = data.data.profile || {};
localStorage.setItem('saqel_teacher_jwt', token);
document.cookie = "saqel_teacher_jwt=" + token + "; path=/; max-age=2592000; SameSite=Lax";
initWebSocket(token);
const isNewTeacher = user?.is_new || user?.full_name === 'معلم جديد' || user?.name === 'معلم جديد' || user?.name === 'الأستاذ المعتمد';
if (isNewTeacher) {
switchToOnboardingStep();
} else {
if (user) {
localStorage.setItem('saqel_teacher_user', JSON.stringify({ ...user, ...profile }));
}
renderDashboard(user, profile);
await checkTeacherSession(token);
if (user) {
localStorage.setItem('saqel_teacher_user', JSON.stringify(user));
}
initWebSocket(token);
// Let checkTeacherSession decide: if profile is incomplete → onboarding, else → dashboard
await checkTeacherSession(token);
} else {
showError(data.message || 'رمز التحقق غير صحيح');
}
@@ -1249,12 +1239,22 @@ class TeacherPortal
const token = localStorage.getItem('saqel_teacher_jwt');
const fullName = document.getElementById('onboard_fullname').value.trim();
const spec = document.getElementById('onboard_specialization').value;
const password = document.getElementById('onboard_password').value.trim();
if (!fullName || !password || password.length < 8) {
showError('يرجى تعبئة كافة الحقول وكلمة مرور 8 خانات على الأقل');
if (!fullName || fullName.length < 3) {
showError('يرجى إدخال الاسم الكامل للمعلم');
return;
}
if (!spec) {
showError('يرجى تحديد التخصص والمادة');
return;
}
const onboardBtn = document.getElementById('btn_complete_onboarding');
const onboardText = document.getElementById('btn_onboard_text');
const onboardSpinner = document.getElementById('btn_onboard_spinner');
onboardBtn.disabled = true;
onboardText.style.display = 'none';
onboardSpinner.style.display = 'inline-block';
try {
const res = await fetch('/api/teacher/profile/setup', {
@@ -1263,16 +1263,23 @@ class TeacherPortal
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + token
},
body: JSON.stringify({ full_name: fullName, specialization: spec, password: password })
body: JSON.stringify({ full_name: fullName, specialization: spec })
});
const data = await res.json();
if (res.ok && data.status === 'success') {
const u = { full_name: fullName, specialization: spec };
localStorage.setItem('saqel_teacher_user', JSON.stringify(u));
renderDashboard(u, { specialization: spec });
showLuxuryToast('أهلاً بك أستاذنا! 🎓', 'تم تفعيل ملفك الأكاديمي بنجاح.');
} else {
showError(data.message || 'فشل حفظ البيانات');
}
} catch (e) {
showError('فشل حفظ الملف.');
showError('تعذر الاتصال بالسيرفر. يرجى المحاولة مجدداً.');
} finally {
onboardBtn.disabled = false;
onboardText.style.display = 'inline';
onboardSpinner.style.display = 'none';
}
}