fix: Rewrite getConversations query to guarantee all students appear for teacher without complex join dependencies
This commit is contained in:
@@ -69,84 +69,73 @@ class ChatController
|
||||
self::ensureSeedUsers();
|
||||
|
||||
$userId = (int)$request->user_id;
|
||||
$userRole = (string)($request->role ?? 'student');
|
||||
|
||||
// 1. Fetch users with conversation history
|
||||
$activeConvs = [];
|
||||
// 1. Fetch all other users in the system
|
||||
$users = [];
|
||||
try {
|
||||
$rows = Database::select("
|
||||
SELECT
|
||||
u.id as user_id,
|
||||
u.uuid as user_uuid,
|
||||
u.full_name as encrypted_name,
|
||||
u.role as user_role,
|
||||
tp.specialization,
|
||||
m.message as last_message,
|
||||
m.message_type as last_message_type,
|
||||
m.created_at as last_message_at,
|
||||
(SELECT COUNT(*) FROM chat_messages WHERE sender_id = u.id AND receiver_id = ? AND is_read = 0) as unread_count
|
||||
$users = Database::select("
|
||||
SELECT u.id as user_id, u.uuid as user_uuid, u.full_name as encrypted_name, u.role as user_role, tp.specialization
|
||||
FROM users u
|
||||
LEFT JOIN teacher_profiles tp ON tp.user_id = u.id
|
||||
JOIN chat_messages m ON m.id = (
|
||||
SELECT MAX(id) FROM chat_messages
|
||||
WHERE (sender_id = ? AND receiver_id = u.id) OR (sender_id = u.id AND receiver_id = ?)
|
||||
)
|
||||
WHERE u.id != ?
|
||||
ORDER BY m.created_at DESC
|
||||
", [$userId, $userId, $userId, $userId]);
|
||||
$activeConvs = $rows ?: [];
|
||||
} catch (\Exception $e) {
|
||||
error_log("Active convs query note: " . $e->getMessage());
|
||||
}
|
||||
|
||||
$existingUserIds = array_column($activeConvs, 'user_id');
|
||||
$existingUserIds[] = $userId;
|
||||
|
||||
// 2. Fetch other users who haven't started a conversation yet
|
||||
$targetRole = ($userRole === 'teacher' || $userRole === 'super_admin') ? 'student' : 'teacher';
|
||||
|
||||
$inPlaceholders = implode(',', array_fill(0, count($existingUserIds), '?'));
|
||||
$otherUsers = [];
|
||||
try {
|
||||
$otherUsers = Database::select("
|
||||
SELECT
|
||||
u.id as user_id,
|
||||
u.uuid as user_uuid,
|
||||
u.full_name as encrypted_name,
|
||||
u.role as user_role,
|
||||
tp.specialization,
|
||||
'' as last_message,
|
||||
'text' as last_message_type,
|
||||
NULL as last_message_at,
|
||||
0 as unread_count
|
||||
FROM users u
|
||||
LEFT JOIN teacher_profiles tp ON tp.user_id = u.id
|
||||
WHERE u.role = ? AND u.id NOT IN ({$inPlaceholders})
|
||||
ORDER BY u.id DESC
|
||||
LIMIT 50
|
||||
", array_merge([$targetRole], $existingUserIds));
|
||||
LIMIT 100
|
||||
", [$userId]);
|
||||
} catch (\Exception $e) {
|
||||
error_log("Other users query note: " . $e->getMessage());
|
||||
error_log("Users select in getConversations error: " . $e->getMessage());
|
||||
}
|
||||
|
||||
$allRows = array_merge($activeConvs, $otherUsers ?: []);
|
||||
$conversations = [];
|
||||
foreach ($users as $row) {
|
||||
$otherId = (int)$row['user_id'];
|
||||
|
||||
// Get latest message between $userId and $otherId
|
||||
$lastMsg = null;
|
||||
$unreadCount = 0;
|
||||
try {
|
||||
$lastMsg = Database::selectOne("
|
||||
SELECT message, message_type, created_at
|
||||
FROM chat_messages
|
||||
WHERE (sender_id = ? AND receiver_id = ?) OR (sender_id = ? AND receiver_id = ?)
|
||||
ORDER BY id DESC
|
||||
LIMIT 1
|
||||
", [$userId, $otherId, $otherId, $userId]);
|
||||
|
||||
$unreadRow = Database::selectOne("
|
||||
SELECT COUNT(*) as cnt
|
||||
FROM chat_messages
|
||||
WHERE sender_id = ? AND receiver_id = ? AND is_read = 0
|
||||
", [$otherId, $userId]);
|
||||
$unreadCount = (int)($unreadRow['cnt'] ?? 0);
|
||||
} catch (\Exception $e) {
|
||||
// Ignore per-user message query issue if any
|
||||
}
|
||||
|
||||
$conversations = array_map(function ($row) {
|
||||
$rawName = (string)($row['encrypted_name'] ?? '');
|
||||
$decryptedName = Security::decrypt($rawName) ?: $rawName;
|
||||
|
||||
return [
|
||||
'user_id' => (int)$row['user_id'],
|
||||
$conversations[] = [
|
||||
'user_id' => $otherId,
|
||||
'user_uuid' => $row['user_uuid'] ?? '',
|
||||
'full_name' => $decryptedName ?: ($row['user_role'] === 'teacher' ? 'الأستاذ حمزة الغويري' : 'طالب صَقِل'),
|
||||
'role' => $row['user_role'] ?? 'student',
|
||||
'specialization' => $row['specialization'] ?? ($row['user_role'] === 'teacher' ? 'الرياضيات العلمي' : null),
|
||||
'last_message' => $row['last_message'] ?: ($row['user_role'] === 'teacher' ? 'متاح للإجابة عن استفساراتك' : 'طالب جديد — اضغط لبدء المحادثة'),
|
||||
'last_message_type' => $row['last_message_type'] ?? 'text',
|
||||
'last_message_at' => $row['last_message_at'] ?? null,
|
||||
'unread_count' => (int)($row['unread_count'] ?? 0),
|
||||
'last_message' => $lastMsg['message'] ?? ($row['user_role'] === 'teacher' ? 'متاح للإجابة عن استفساراتك' : 'طالب جديد — اضغط لبدء المحادثة'),
|
||||
'last_message_type' => $lastMsg['message_type'] ?? 'text',
|
||||
'last_message_at' => $lastMsg['created_at'] ?? null,
|
||||
'unread_count' => $unreadCount,
|
||||
];
|
||||
}, $allRows);
|
||||
}
|
||||
|
||||
// Sort: users with active messages first, then by last_message_at DESC
|
||||
usort($conversations, function ($a, $b) {
|
||||
if ($a['last_message_at'] && !$b['last_message_at']) return -1;
|
||||
if (!$a['last_message_at'] && $b['last_message_at']) return 1;
|
||||
if ($a['last_message_at'] && $b['last_message_at']) {
|
||||
return strcmp($b['last_message_at'], $a['last_message_at']);
|
||||
}
|
||||
return $b['user_id'] <=> $a['user_id'];
|
||||
});
|
||||
|
||||
$response->json([
|
||||
'status' => 'success',
|
||||
|
||||
@@ -671,9 +671,19 @@ class TeacherPortal
|
||||
const data = await res.json();
|
||||
if (res.ok && data.status === 'success') {
|
||||
renderConversations(data.data);
|
||||
} else {
|
||||
console.warn('Load convs returned:', data);
|
||||
const container = document.getElementById('conv_list_container');
|
||||
if (container) {
|
||||
container.innerHTML = '<div style="padding: 20px; text-align: center; color: var(--text-muted); font-size: 12px;">' + (data.message || 'لا توجد محادثات نشطة') + '</div>';
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Load convs error:', e);
|
||||
const container = document.getElementById('conv_list_container');
|
||||
if (container) {
|
||||
container.innerHTML = '<div style="padding: 20px; text-align: center; color: #F87171; font-size: 12px;">تعذر تحميل المحادثات (خطأ في الاتصال)</div>';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user