diff --git a/backend/app/Controllers/AuthController.php b/backend/app/Controllers/AuthController.php index 177e27a..04412f3 100644 --- a/backend/app/Controllers/AuthController.php +++ b/backend/app/Controllers/AuthController.php @@ -359,37 +359,183 @@ class AuthController ]); } - /** + /** * Get Current Authenticated User Data * GET /api/auth/me */ public function me(Request $request, Response $response): void { - $userId = $request->user_id; + $userId = (int)$request->user_id; + $role = $request->role ?? 'student'; - $user = Database::selectOne( - "SELECT uuid, full_name, phone_number, role, grade_level, stream, status, created_at FROM users WHERE id = ? LIMIT 1", - [$userId] - ); + $userData = null; - if (!$user) { + if ($role === 'teacher') { + $user = Database::selectOne( + "SELECT t.id, t.uuid, t.full_name, t.specialization, t.bio, t.school_id, ai.phone_number, ai.status, t.created_at + FROM teachers t + JOIN auth_identities ai ON t.identity_id = ai.id + WHERE t.id = ? LIMIT 1", + [$userId] + ); + if ($user) { + $isCompleted = !empty($user['full_name']) && $user['full_name'] !== 'معلم جديد' && !empty($user['specialization']) && $user['specialization'] !== 'بانتظار تحديد التخصص'; + $userData = [ + 'id' => $user['id'], + 'uuid' => $user['uuid'], + 'full_name' => $user['full_name'], + 'name' => $user['full_name'], + 'role' => 'teacher', + 'specialization' => $user['specialization'], + 'bio' => $user['bio'], + 'phone' => Security::decrypt($user['phone_number']), + 'status' => $user['status'], + 'is_completed' => $isCompleted, + 'is_teacher' => true, + 'is_student' => false, + ]; + } + } elseif ($role === 'guardian') { + $user = Database::selectOne( + "SELECT g.id, g.uuid, g.full_name, g.national_id, ai.phone_number, ai.status, g.created_at + FROM guardians g + JOIN auth_identities ai ON g.identity_id = ai.id + WHERE g.id = ? LIMIT 1", + [$userId] + ); + if ($user) { + $userData = [ + 'id' => $user['id'], + 'uuid' => $user['uuid'], + 'full_name' => $user['full_name'], + 'name' => $user['full_name'], + 'role' => 'guardian', + 'phone' => Security::decrypt($user['phone_number']), + 'status' => $user['status'], + 'is_completed' => true, + 'is_teacher' => false, + 'is_student' => false, + ]; + } + } else { + // Student + $user = Database::selectOne( + "SELECT s.id, s.uuid, s.full_name, s.national_id, s.grade_level, s.stream, s.readiness_score, s.school_id, ai.phone_number, ai.status, s.created_at + FROM students s + JOIN auth_identities ai ON s.identity_id = ai.id + WHERE s.id = ? LIMIT 1", + [$userId] + ); + if ($user) { + $isCompleted = !empty($user['full_name']) && $user['full_name'] !== 'طالب جديد' && $user['full_name'] !== 'الطالب المتميز' && !empty($user['grade_level']); + $userData = [ + 'id' => $user['id'], + 'uuid' => $user['uuid'], + 'full_name' => $user['full_name'], + 'name' => $user['full_name'], + 'role' => 'student', + 'national_id' => $user['national_id'], + 'grade_level' => $user['grade_level'], + 'stream' => $user['stream'], + 'readiness_score' => $user['readiness_score'], + 'phone' => Security::decrypt($user['phone_number']), + 'status' => $user['status'], + 'is_completed' => $isCompleted, + 'is_teacher' => false, + 'is_student' => true, + ]; + } + } + + if (!$userData) { $response->status(404)->json([ 'status' => 'error', - 'message' => 'المستخدم غير موجود' + 'message' => 'المستخدم غير موجود أو تم إعادة تهيئة قاعدة البيانات' ]); return; } - $user['full_name'] = Security::decrypt($user['full_name']); - $user['phone_number'] = Security::decrypt($user['phone_number']); - $response->json([ 'status' => 'success', - 'data' => $user + 'data' => $userData ]); } /** + * Check if Student Profile is complete + * GET /api/student/profile/status + */ + public function studentProfileStatus(Request $request, Response $response): void + { + $studentId = (int)$request->user_id; + $student = Database::selectOne( + "SELECT s.*, ai.phone_number FROM students s JOIN auth_identities ai ON s.identity_id = ai.id WHERE s.id = ? LIMIT 1", + [$studentId] + ); + + if (!$student) { + $response->status(401)->json(['status' => 'error', 'message' => 'طالب غير مسجل']); + return; + } + + $isCompleted = !empty($student['full_name']) && $student['full_name'] !== 'طالب جديد' && $student['full_name'] !== 'الطالب المتميز' && !empty($student['grade_level']); + + $response->json([ + 'status' => 'success', + 'is_completed' => $isCompleted, + 'user' => [ + 'id' => $student['id'], + 'uuid' => $student['uuid'], + 'full_name' => $student['full_name'], + 'national_id' => $student['national_id'], + 'grade_level' => $student['grade_level'], + 'stream' => $student['stream'], + 'role' => 'student' + ] + ]); + } + + /** + * Setup Student Profile + * POST /api/student/profile/setup + */ + public function studentProfileSetup(Request $request, Response $response): void + { + $studentId = (int)$request->user_id; + $body = $request->getBody(); + + $fullName = trim((string)($body['full_name'] ?? '')); + $gradeLevel = trim((string)($body['grade_level'] ?? 'grade_10')); + $stream = trim((string)($body['stream'] ?? 'scientific')); + $nationalId = trim((string)($body['national_id'] ?? '')); + + if (empty($fullName)) { + $response->status(400)->json(['status' => 'error', 'message' => 'الاسم الكامل مطلوب']); + return; + } + + Database::query( + "UPDATE students SET full_name = ?, grade_level = ?, stream = ?, national_id = IF(? != '', ?, national_id), updated_at = NOW() WHERE id = ?", + [$fullName, $gradeLevel, $stream, $nationalId, $nationalId, $studentId] + ); + + $student = Database::selectOne("SELECT * FROM students WHERE id = ? LIMIT 1", [$studentId]); + + $response->json([ + 'status' => 'success', + 'message' => 'تم استكمال ملف الطالب بنجاح! مرحباً بك في منصة صَقِل', + 'user' => [ + 'id' => $student['id'], + 'uuid' => $student['uuid'], + 'full_name' => $student['full_name'], + 'grade_level' => $student['grade_level'], + 'stream' => $student['stream'], + 'role' => 'student' + ] + ]); + } + +/** * Logout and destroy Redis active session * POST /api/auth/logout */ diff --git a/backend/app/Controllers/TeacherController.php b/backend/app/Controllers/TeacherController.php index a4b7b6d..e322dec 100644 --- a/backend/app/Controllers/TeacherController.php +++ b/backend/app/Controllers/TeacherController.php @@ -53,20 +53,19 @@ class TeacherController */ public function setupProfile(Request $request, Response $response): void { - $userId = $request->user_id; + $teacherId = (int)$request->user_id; $body = $request->getBody(); $validator = new Validator(); $isValid = $validator->validate($body, [ 'full_name' => 'required', 'specialization' => 'required', - 'password' => 'required|min:8', ]); if (!$isValid) { $response->status(400)->json([ 'status' => 'error', - 'message' => 'بيانات الملف الشخصي غير مكتملة أو كلمة المرور قصيرة (أقل من 8 خانات)', + 'message' => 'بيانات الملف الشخصي غير مكتملة', 'errors' => $validator->getErrors() ]); return; @@ -75,45 +74,26 @@ class TeacherController $fullName = trim((string)$body['full_name']); $specialization = trim((string)$body['specialization']); $bio = trim((string)($body['bio'] ?? '')); - $gradeLevels = is_array($body['grade_levels'] ?? null) ? implode(',', $body['grade_levels']) : (string)($body['grade_levels'] ?? 'tawjihi_2008'); - $passwordHash = Security::hashPassword((string)$body['password']); - // 1. Update User table - $encryptedName = Security::encrypt($fullName); + // Update Teachers Table Directly Database::query( - "UPDATE users SET full_name = ?, password_hash = ?, grade_level = ?, status = 'active' WHERE id = ?", - [$encryptedName, $passwordHash, $gradeLevels, $userId] + "UPDATE teachers SET full_name = ?, specialization = ?, bio = ?, updated_at = NOW() WHERE id = ?", + [$fullName, $specialization, $bio, $teacherId] ); - // 2. Upsert Teacher Profile - $existingProfile = Database::selectOne("SELECT id FROM teacher_profiles WHERE user_id = ? LIMIT 1", [$userId]); - if ($existingProfile) { - Database::query( - "UPDATE teacher_profiles SET bio = ?, specialization = ? WHERE user_id = ?", - [$bio, $specialization, $userId] - ); - } else { - Database::insert( - "INSERT INTO teacher_profiles (user_id, bio, specialization, revenue_share_pct, contract_type) VALUES (?, ?, ?, 50.00, 'exclusive')", - [$userId, $bio, $specialization] - ); - } + $teacher = Database::selectOne("SELECT * FROM teachers WHERE id = ? LIMIT 1", [$teacherId]); $response->json([ 'status' => 'success', - 'message' => 'تم توثيق بيانات المعلم وإعداد كلمة المرور بنجاح!', + 'message' => 'تم توثيق بيانات المعلم واعتماد ملفك بنجاح!', 'data' => [ - 'full_name' => $fullName, - 'specialization' => $specialization, - 'grade_levels' => $gradeLevels + 'full_name' => $teacher['full_name'] ?? $fullName, + 'specialization' => $teacher['specialization'] ?? $specialization, + 'bio' => $teacher['bio'] ?? $bio ] ]); } - /** - * Teacher Dashboard Statistics - * GET /api/teacher/dashboard - */ public function getDashboard(Request $request, Response $response): void { $userId = $request->user_id; diff --git a/backend/app/Views/CurriculumStudio.php b/backend/app/Views/CurriculumStudio.php index 5bfe951..fcae40a 100644 --- a/backend/app/Views/CurriculumStudio.php +++ b/backend/app/Views/CurriculumStudio.php @@ -32,7 +32,9 @@ class CurriculumStudio :root { --bg-base: #0B0F19; --bg-card: rgba(22, 27, 34, 0.85); + --bg-hover: rgba(255, 255, 255, 0.05); --border: rgba(255, 255, 255, 0.08); + --border-color: rgba(255, 255, 255, 0.12); --accent-cyan: #00F5D4; --accent-gold: #FFD166; --accent-purple: #7B2CBF; @@ -110,6 +112,12 @@ class CurriculumStudio font-size: 11.5px; font-family: monospace; color: var(--accent-cyan); margin-bottom: 14px; display: flex; align-items: center; justify-content: space-between; } + + @keyframes pulse { + 0% { transform: scale(1); opacity: 1; } + 50% { transform: scale(1.1); opacity: 0.7; } + 100% { transform: scale(1); opacity: 1; } + }
@@ -121,7 +129,10 @@ class CurriculumStudio صَقِل Enterprise استوديو تفريغ وفهرسة المناهج الحية 📚 -اختر ملف كتاب المنهاج (PDF) ليقوم الخادم بتفريغه وفهرسة وحداته ودروسه الحقيقية على القرص وتوليد ملفات المارك داون.
+اختر ملف كتاب المنهاج (PDF) ليقوم الخادم والذكاء الاصطناعي بتفريغ الوحدات والدروس والمصادر كملفات Markdown حية.