Update Saqel Platform: 2026-08-28 15:19:58

This commit is contained in:
Hamza-Ayed
2026-08-28 15:19:58 +03:00
parent 06461635bf
commit 070e80ea30
4 changed files with 30 additions and 40 deletions
+14 -17
View File
@@ -21,16 +21,14 @@ class AuthController
$body = $request->getBody();
$validator = new Validator();
if (!$validator->validate($body, ['phone_number' => 'required'])) {
$rawPhone = trim((string)($body['phone_number'] ?? $body['phone'] ?? ''));
if (empty($rawPhone)) {
$response->status(400)->json([
'status' => 'error',
'message' => 'رقم الهاتف مطلوب',
'errors' => $validator->getErrors()
'message' => 'رقم الهاتف مطلوب'
]);
return;
}
$rawPhone = trim((string)$body['phone_number']);
$cleanPhone = preg_replace('/\D+/', '', $rawPhone);
// Normalize Jordanian numbers (e.g. 079XXXXXXX -> 96279XXXXXXX)
@@ -141,27 +139,23 @@ class AuthController
$body = $request->getBody();
$validator = new Validator();
if (!$validator->validate($body, [
'phone_number' => 'required',
'otp' => 'required'
])) {
$rawPhone = trim((string)($body['phone_number'] ?? $body['phone'] ?? ''));
$inputOtp = trim((string)($body['otp'] ?? $body['otp_code'] ?? ''));
if (empty($rawPhone) || empty($inputOtp)) {
$response->status(400)->json([
'status' => 'error',
'message' => 'رقم الهاتف ورمز التحقق مطلوبان',
'errors' => $validator->getErrors()
'message' => 'رقم الهاتف ورمز التحقق مطلوبان'
]);
return;
}
$rawPhone = trim((string)$body['phone_number']);
$cleanPhone = preg_replace('/\D+/', '', $rawPhone);
if (str_starts_with($cleanPhone, '07')) {
$cleanPhone = '962' . substr($cleanPhone, 1);
} elseif (str_starts_with($cleanPhone, '7') && strlen($cleanPhone) === 9) {
$cleanPhone = '962' . $cleanPhone;
}
$inputOtp = trim((string)$body['otp']);
$role = $body['role'] ?? 'student';
$fullName = trim((string)($body['full_name'] ?? ''));
$deviceFingerprint = trim((string)($body['device_fingerprint'] ?? 'browser_default'));
@@ -219,14 +213,16 @@ class AuthController
// Resolve or create specific Persona entity (Teacher, Student, Guardian)
if ($role === 'teacher') {
$teacher = Database::selectOne("SELECT * FROM teachers WHERE identity_id = ? LIMIT 1", [$identityId]);
$isNewTeacher = false;
if (!$teacher) {
$isNewTeacher = true;
$tUuid = sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x', mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0x0fff) | 0x4000, mt_rand(0, 0x3fff) | 0x8000, mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff));
$tId = Database::insert(
"INSERT INTO teachers (uuid, identity_id, full_name, specialization, bio, is_school_exclusive, is_marketplace_public)
VALUES (?, ?, ?, 'الرياضيات العلمي', 'معلم معتمد في منصة صَقِل', 0, 1)",
[$tUuid, $identityId, $resolvedName]
VALUES (?, ?, ?, 'بانتظار تحديد التخصص', '', 0, 1)",
[$tUuid, $identityId, $fullName ?: 'معلم جديد']
);
$teacher = ['id' => $tId, 'uuid' => $tUuid, 'full_name' => $resolvedName];
$teacher = ['id' => $tId, 'uuid' => $tUuid, 'full_name' => $fullName ?: 'معلم جديد', 'specialization' => 'بانتظار تحديد التخصص'];
}
$user = [
'id' => $teacher['id'],
@@ -234,6 +230,7 @@ class AuthController
'full_name' => $teacher['full_name'],
'role' => 'teacher',
'status' => 'active',
'is_new' => $isNewTeacher,
'token_version' => $identity['token_version'],
'school_id' => $teacher['school_id'] ?? null
];
+10 -21
View File
@@ -21,33 +21,22 @@ class TeacherController
$teacher = Database::selectOne("SELECT id, uuid, full_name, specialization, bio, is_marketplace_public FROM teachers WHERE id = ? LIMIT 1", [$teacherId]);
if (!$teacher) {
// Auto create teacher record if not exists
$tUuid = sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x', mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0x0fff) | 0x4000, mt_rand(0, 0x3fff) | 0x8000, mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff));
$tId = Database::insert(
"INSERT INTO teachers (uuid, full_name, specialization, bio, is_marketplace_public) VALUES (?, 'الأستاذ المعتمد', 'الرياضيات العلمي', 'معلم معتمد في منصة صَقِل', 1)",
[$tUuid]
);
$teacher = [
'id' => $tId,
'uuid' => $tUuid,
'full_name' => 'الأستاذ المعتمد',
'specialization' => 'الرياضيات العلمي',
'bio' => 'معلم معتمد في منصة صَقِل'
];
$response->status(401)->json([
'status' => 'error',
'message' => 'حساب المعلم غير مسجل أو يتطلب تسجيل الدخول',
'is_completed' => false
]);
return;
}
$rawName = (string)($teacher['full_name'] ?? '');
$decryptedName = Security::decrypt($rawName) ?: $rawName;
if (empty($decryptedName)) {
$decryptedName = 'الأستاذ المعتمد';
}
$isCompleted = !empty($teacher['full_name']) && $teacher['full_name'] !== 'معلم جديد' && !empty($teacher['specialization']) && $teacher['specialization'] !== 'بانتظار تحديد التخصص';
$response->json([
'status' => 'success',
'is_completed' => true,
'is_completed' => $isCompleted,
'user' => [
'uuid' => $teacher['uuid'],
'full_name' => $decryptedName,
'full_name' => $teacher['full_name'],
'role' => 'teacher',
'status' => 'active',
],
+2 -2
View File
@@ -1923,7 +1923,7 @@ class StudentPortal
const res = await fetch('/api/auth/otp/request', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ phone: phone, role: 'student' })
body: JSON.stringify({ phone_number: phone, phone: phone, role: 'student' })
});
const data = await res.json();
if (res.ok && data.status === 'success') {
@@ -1950,7 +1950,7 @@ class StudentPortal
const res = await fetch('/api/auth/otp/verify', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ phone: phone, otp_code: otp, role: 'student' })
body: JSON.stringify({ phone_number: phone, phone: phone, otp: otp, otp_code: otp, role: 'student' })
});
const data = await res.json();
if (res.ok && data.status === 'success') {
+4
View File
@@ -1281,6 +1281,10 @@ class TeacherPortal
}
const data = await res.json();
if (res.ok && data.status === 'success') {
if (!data.is_completed) {
switchToOnboardingStep();
return;
}
if (data.user) {
localStorage.setItem('saqel_teacher_user', JSON.stringify({ ...data.user, ...data.profile }));
}