From 070e80ea307f793b5bbb31de131fbf5f817fbb3c Mon Sep 17 00:00:00 2001 From: Hamza-Ayed Date: Fri, 28 Aug 2026 15:19:58 +0300 Subject: [PATCH] Update Saqel Platform: 2026-08-28 15:19:58 --- backend/app/Controllers/AuthController.php | 31 +++++++++---------- backend/app/Controllers/TeacherController.php | 31 ++++++------------- backend/app/Views/StudentPortal.php | 4 +-- backend/app/Views/TeacherPortal.php | 4 +++ 4 files changed, 30 insertions(+), 40 deletions(-) diff --git a/backend/app/Controllers/AuthController.php b/backend/app/Controllers/AuthController.php index 29ba325..177e27a 100644 --- a/backend/app/Controllers/AuthController.php +++ b/backend/app/Controllers/AuthController.php @@ -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 ]; diff --git a/backend/app/Controllers/TeacherController.php b/backend/app/Controllers/TeacherController.php index b5c587f..a4b7b6d 100644 --- a/backend/app/Controllers/TeacherController.php +++ b/backend/app/Controllers/TeacherController.php @@ -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', ], diff --git a/backend/app/Views/StudentPortal.php b/backend/app/Views/StudentPortal.php index fd3ad7f..5f13328 100644 --- a/backend/app/Views/StudentPortal.php +++ b/backend/app/Views/StudentPortal.php @@ -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') { diff --git a/backend/app/Views/TeacherPortal.php b/backend/app/Views/TeacherPortal.php index 6c3734e..3c3eb25 100644 --- a/backend/app/Views/TeacherPortal.php +++ b/backend/app/Views/TeacherPortal.php @@ -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 })); }