3
This commit is contained in:
parent
3db6af498b
commit
2516f4214e
159
api.php
Normal file
159
api.php
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
<?php
|
||||||
|
session_start();
|
||||||
|
require_once __DIR__ . '/db/config.php';
|
||||||
|
|
||||||
|
if (!isset($_SESSION['user_id'])) {
|
||||||
|
http_response_code(401);
|
||||||
|
echo json_encode(['error' => 'User not authenticated']);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$action = $_GET['action'] ?? '';
|
||||||
|
|
||||||
|
switch ($action) {
|
||||||
|
case 'search_users':
|
||||||
|
search_users();
|
||||||
|
break;
|
||||||
|
case 'start_conversation':
|
||||||
|
start_conversation();
|
||||||
|
break;
|
||||||
|
case 'get_conversations':
|
||||||
|
get_conversations();
|
||||||
|
break;
|
||||||
|
case 'get_messages':
|
||||||
|
get_messages();
|
||||||
|
break;
|
||||||
|
case 'send_message':
|
||||||
|
send_message();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
http_response_code(400);
|
||||||
|
echo json_encode(['error' => 'Invalid action']);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
function search_users() {
|
||||||
|
$term = $_GET['term'] ?? '';
|
||||||
|
if (empty($term)) {
|
||||||
|
echo json_encode([]);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$pdo = db();
|
||||||
|
$stmt = $pdo->prepare("SELECT id, username FROM users WHERE username LIKE ? AND id != ?");
|
||||||
|
$stmt->execute(['%' . $term . '%', $_SESSION['user_id']]);
|
||||||
|
$users = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
|
header('Content-Type: application/json');
|
||||||
|
echo json_encode($users);
|
||||||
|
}
|
||||||
|
|
||||||
|
function start_conversation() {
|
||||||
|
$recipient_id = $_POST['recipient_id'] ?? '';
|
||||||
|
if (empty($recipient_id)) {
|
||||||
|
http_response_code(400);
|
||||||
|
echo json_encode(['error' => 'Recipient ID is required']);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$user_id = $_SESSION['user_id'];
|
||||||
|
|
||||||
|
$pdo = db();
|
||||||
|
|
||||||
|
// Check if a conversation already exists between the two users
|
||||||
|
$stmt = $pdo->prepare("
|
||||||
|
SELECT c.id
|
||||||
|
FROM conversations c
|
||||||
|
JOIN conversation_participants cp1 ON c.id = cp1.conversation_id
|
||||||
|
JOIN conversation_participants cp2 ON c.id = cp2.conversation_id
|
||||||
|
WHERE cp1.user_id = ? AND cp2.user_id = ?
|
||||||
|
");
|
||||||
|
$stmt->execute([$user_id, $recipient_id]);
|
||||||
|
$conversation = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
|
if ($conversation) {
|
||||||
|
// Conversation already exists
|
||||||
|
header('Content-Type: application/json');
|
||||||
|
echo json_encode(['conversation_id' => $conversation['id']]);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new conversation
|
||||||
|
$pdo->beginTransaction();
|
||||||
|
try {
|
||||||
|
$stmt = $pdo->prepare("INSERT INTO conversations () VALUES ()");
|
||||||
|
$stmt->execute();
|
||||||
|
$conversation_id = $pdo->lastInsertId();
|
||||||
|
|
||||||
|
$stmt = $pdo->prepare("INSERT INTO conversation_participants (conversation_id, user_id) VALUES (?, ?), (?, ?)");
|
||||||
|
$stmt->execute([$conversation_id, $user_id, $conversation_id, $recipient_id]);
|
||||||
|
|
||||||
|
$pdo->commit();
|
||||||
|
|
||||||
|
header('Content-Type: application/json');
|
||||||
|
echo json_encode(['conversation_id' => $conversation_id]);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
$pdo->rollBack();
|
||||||
|
http_response_code(500);
|
||||||
|
echo json_encode(['error' => 'Failed to create conversation']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_conversations() {
|
||||||
|
$user_id = $_SESSION['user_id'];
|
||||||
|
$pdo = db();
|
||||||
|
|
||||||
|
$stmt = $pdo->prepare("
|
||||||
|
SELECT c.id, u.username, u.id as user_id
|
||||||
|
FROM conversations c
|
||||||
|
JOIN conversation_participants cp ON c.id = cp.conversation_id
|
||||||
|
JOIN users u ON u.id = cp.user_id
|
||||||
|
WHERE c.id IN (
|
||||||
|
SELECT conversation_id
|
||||||
|
FROM conversation_participants
|
||||||
|
WHERE user_id = ?
|
||||||
|
) AND cp.user_id != ?
|
||||||
|
");
|
||||||
|
$stmt->execute([$user_id, $user_id]);
|
||||||
|
$conversations = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
|
header('Content-Type: application/json');
|
||||||
|
echo json_encode($conversations);
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_messages() {
|
||||||
|
$conversation_id = $_GET['conversation_id'] ?? '';
|
||||||
|
if (empty($conversation_id)) {
|
||||||
|
http_response_code(400);
|
||||||
|
echo json_encode(['error' => 'Conversation ID is required']);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$pdo = db();
|
||||||
|
$stmt = $pdo->prepare("SELECT * FROM messages WHERE conversation_id = ? ORDER BY created_at ASC");
|
||||||
|
$stmt->execute([$conversation_id]);
|
||||||
|
$messages = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
|
header('Content-Type: application/json');
|
||||||
|
echo json_encode($messages);
|
||||||
|
}
|
||||||
|
|
||||||
|
function send_message() {
|
||||||
|
$conversation_id = $_POST['conversation_id'] ?? '';
|
||||||
|
$message_text = $_POST['message_text'] ?? '';
|
||||||
|
|
||||||
|
if (empty($conversation_id) || empty($message_text)) {
|
||||||
|
http_response_code(400);
|
||||||
|
echo json_encode(['error' => 'Conversation ID and message text are required']);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$sender_id = $_SESSION['user_id'];
|
||||||
|
|
||||||
|
$pdo = db();
|
||||||
|
$stmt = $pdo->prepare("INSERT INTO messages (conversation_id, sender_id, message_text) VALUES (?, ?, ?)");
|
||||||
|
$stmt->execute([$conversation_id, $sender_id, $message_text]);
|
||||||
|
|
||||||
|
header('Content-Type: application/json');
|
||||||
|
echo json_encode(['success' => true]);
|
||||||
|
}
|
||||||
@ -158,3 +158,21 @@ body {
|
|||||||
background-color: #ffffff;
|
background-color: #ffffff;
|
||||||
border-top: 1px solid #e5e7eb;
|
border-top: 1px solid #e5e7eb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.avatar-placeholder {
|
||||||
|
width: 48px;
|
||||||
|
height: 48px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: #e9ecef;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 24px;
|
||||||
|
color: #6c757d;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar-placeholder.avatar-sm {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
|||||||
@ -1,29 +1,191 @@
|
|||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
const chatForm = document.getElementById('chat-form');
|
const chatForm = document.getElementById('chat-form');
|
||||||
const messageInput = document.getElementById('message-input');
|
const messageInput = document.getElementById('message-input');
|
||||||
|
const userSearchForm = document.getElementById('user-search-form');
|
||||||
|
const userSearchInput = document.getElementById('user-search-input');
|
||||||
|
const searchResultsContainer = document.getElementById('search-results');
|
||||||
|
const conversationListContainer = document.getElementById('conversation-list-container');
|
||||||
|
const chatBody = document.querySelector('.chat-body');
|
||||||
|
const chatHeaderName = document.querySelector('.chat-header .name');
|
||||||
|
const chatHeaderStatus = document.querySelector('.chat-header .status');
|
||||||
|
|
||||||
|
let currentConversationId = null;
|
||||||
|
|
||||||
if (chatForm) {
|
if (chatForm) {
|
||||||
chatForm.addEventListener('submit', function(e) {
|
chatForm.addEventListener('submit', function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
const message = messageInput.value.trim();
|
const message = messageInput.value.trim();
|
||||||
if (message) {
|
if (message && currentConversationId) {
|
||||||
console.log('Sending message:', message);
|
sendMessage(currentConversationId, message);
|
||||||
// In a real app, you'd send this to the server.
|
}
|
||||||
// For this demo, we'll just clear the input.
|
});
|
||||||
messageInput.value = '';
|
}
|
||||||
|
|
||||||
// Optional: Add the message to the UI for instant feedback
|
if (userSearchForm) {
|
||||||
const chatBody = document.querySelector('.chat-body');
|
userSearchForm.addEventListener('submit', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
const searchTerm = userSearchInput.value.trim();
|
||||||
|
if (searchTerm) {
|
||||||
|
searchUsers(searchTerm);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function searchUsers(term) {
|
||||||
|
fetch(`api.php?action=search_users&term=${term}`)
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(users => {
|
||||||
|
displaySearchResults(users);
|
||||||
|
})
|
||||||
|
.catch(error => console.error('Error searching users:', error));
|
||||||
|
}
|
||||||
|
|
||||||
|
function displaySearchResults(users) {
|
||||||
|
searchResultsContainer.innerHTML = '';
|
||||||
|
if (users.length === 0) {
|
||||||
|
searchResultsContainer.innerHTML = '<p class="text-center text-muted p-4">No users found.</p>';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
users.forEach(user => {
|
||||||
|
const userElement = document.createElement('div');
|
||||||
|
userElement.classList.add('conversation-item');
|
||||||
|
userElement.dataset.userId = user.id;
|
||||||
|
userElement.innerHTML = `
|
||||||
|
<div class="avatar-placeholder me-3">
|
||||||
|
<i class="bi bi-person-fill"></i>
|
||||||
|
</div>
|
||||||
|
<div class="conversation-info">
|
||||||
|
<h6 class="name mb-0">${user.username}</h6>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
userElement.addEventListener('click', () => {
|
||||||
|
startConversation(user.id);
|
||||||
|
});
|
||||||
|
searchResultsContainer.appendChild(userElement);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function startConversation(recipientId) {
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append('recipient_id', recipientId);
|
||||||
|
|
||||||
|
fetch('api.php?action=start_conversation', {
|
||||||
|
method: 'POST',
|
||||||
|
body: formData
|
||||||
|
})
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
if (data.conversation_id) {
|
||||||
|
loadMessages(data.conversation_id);
|
||||||
|
userSearchInput.value = '';
|
||||||
|
searchResultsContainer.innerHTML = '';
|
||||||
|
loadConversations();
|
||||||
|
} else {
|
||||||
|
console.error('Failed to start conversation:', data.error);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => console.error('Error starting conversation:', error));
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadConversations() {
|
||||||
|
fetch('api.php?action=get_conversations')
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(conversations => {
|
||||||
|
displayConversations(conversations);
|
||||||
|
})
|
||||||
|
.catch(error => console.error('Error loading conversations:', error));
|
||||||
|
}
|
||||||
|
|
||||||
|
function displayConversations(conversations) {
|
||||||
|
conversationListContainer.innerHTML = '';
|
||||||
|
if (conversations.length === 0) {
|
||||||
|
conversationListContainer.innerHTML = '<p class="text-center text-muted p-4">No conversations yet.</p>';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
conversations.forEach(conversation => {
|
||||||
|
const conversationElement = document.createElement('div');
|
||||||
|
conversationElement.classList.add('conversation-item');
|
||||||
|
conversationElement.dataset.conversationId = conversation.id;
|
||||||
|
conversationElement.dataset.recipientId = conversation.user_id;
|
||||||
|
conversationElement.innerHTML = `
|
||||||
|
<div class="avatar-placeholder me-3">
|
||||||
|
<i class="bi bi-person-fill"></i>
|
||||||
|
</div>
|
||||||
|
<div class="conversation-info">
|
||||||
|
<h6 class="name mb-0">${conversation.username}</h6>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
conversationElement.addEventListener('click', () => {
|
||||||
|
loadMessages(conversation.id, conversation.username);
|
||||||
|
});
|
||||||
|
conversationListContainer.appendChild(conversationElement);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadMessages(conversationId, username) {
|
||||||
|
currentConversationId = conversationId;
|
||||||
|
chatHeaderName.textContent = username;
|
||||||
|
chatHeaderStatus.textContent = 'Online'; // Placeholder
|
||||||
|
|
||||||
|
fetch(`api.php?action=get_messages&conversation_id=${conversationId}`)
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(messages => {
|
||||||
|
displayMessages(messages);
|
||||||
|
})
|
||||||
|
.catch(error => console.error('Error loading messages:', error));
|
||||||
|
}
|
||||||
|
|
||||||
|
function displayMessages(messages) {
|
||||||
|
chatBody.innerHTML = '';
|
||||||
|
if (messages.length === 0) {
|
||||||
|
chatBody.innerHTML = '<div class="text-center text-muted" style="margin-top: auto; margin-bottom: auto;"><p>No messages yet. Say hi!</p></div>';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
messages.forEach(message => {
|
||||||
|
const messageElement = document.createElement('div');
|
||||||
|
const isSent = message.sender_id == window.userId;
|
||||||
|
messageElement.classList.add('message', isSent ? 'sent' : 'received');
|
||||||
|
messageElement.innerHTML = `
|
||||||
|
<div class="message-bubble">${message.message_text}</div>
|
||||||
|
<div class="message-time">${new Date(message.created_at).toLocaleTimeString()}</div>
|
||||||
|
`;
|
||||||
|
chatBody.appendChild(messageElement);
|
||||||
|
});
|
||||||
|
chatBody.scrollTop = chatBody.scrollHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
function sendMessage(conversationId, messageText) {
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append('conversation_id', conversationId);
|
||||||
|
formData.append('message_text', messageText);
|
||||||
|
|
||||||
|
fetch('api.php?action=send_message', {
|
||||||
|
method: 'POST',
|
||||||
|
body: formData
|
||||||
|
})
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
if (data.success) {
|
||||||
|
messageInput.value = '';
|
||||||
|
// Add message to UI immediately
|
||||||
const messageElement = document.createElement('div');
|
const messageElement = document.createElement('div');
|
||||||
messageElement.classList.add('message', 'sent');
|
messageElement.classList.add('message', 'sent');
|
||||||
messageElement.innerHTML = `
|
messageElement.innerHTML = `
|
||||||
<div class="message-bubble">${message}</div>
|
<div class="message-bubble">${messageText}</div>
|
||||||
<div class="message-time">Just now</div>
|
<div class="message-time">Just now</div>
|
||||||
`;
|
`;
|
||||||
chatBody.appendChild(messageElement);
|
chatBody.appendChild(messageElement);
|
||||||
chatBody.scrollTop = chatBody.scrollHeight;
|
chatBody.scrollTop = chatBody.scrollHeight;
|
||||||
|
} else {
|
||||||
|
console.error('Failed to send message:', data.error);
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
|
.catch(error => console.error('Error sending message:', error));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Load conversations on page load
|
||||||
|
loadConversations();
|
||||||
});
|
});
|
||||||
|
|||||||
@ -4,18 +4,35 @@ require_once __DIR__ . '/config.php';
|
|||||||
function run_migrations() {
|
function run_migrations() {
|
||||||
try {
|
try {
|
||||||
$pdo = db();
|
$pdo = db();
|
||||||
$migration_file = __DIR__ . '/migrations/001_create_users_table.sql';
|
|
||||||
if (file_exists($migration_file)) {
|
// Create migrations table if it doesn't exist
|
||||||
$sql = file_get_contents($migration_file);
|
$pdo->exec("CREATE TABLE IF NOT EXISTS migrations (id INT AUTO_INCREMENT PRIMARY KEY, migration_name VARCHAR(255) NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP)");
|
||||||
$pdo->exec($sql);
|
|
||||||
echo "Migration '001_create_users_table.sql' applied successfully.\n";
|
// Get all migration files
|
||||||
} else {
|
$migration_files = glob(__DIR__ . '/migrations/*.sql');
|
||||||
echo "Migration file not found.\n";
|
sort($migration_files);
|
||||||
|
|
||||||
|
// Get already run migrations
|
||||||
|
$stmt = $pdo->query("SELECT migration_name FROM migrations");
|
||||||
|
$run_migrations = $stmt->fetchAll(PDO::FETCH_COLUMN);
|
||||||
|
|
||||||
|
foreach ($migration_files as $migration_file) {
|
||||||
|
$migration_name = basename($migration_file);
|
||||||
|
|
||||||
|
if (!in_array($migration_name, $run_migrations)) {
|
||||||
|
$sql = file_get_contents($migration_file);
|
||||||
|
$pdo->exec($sql);
|
||||||
|
|
||||||
|
$stmt = $pdo->prepare("INSERT INTO migrations (migration_name) VALUES (?)");
|
||||||
|
$stmt->execute([$migration_name]);
|
||||||
|
|
||||||
|
echo "Migration '" . $migration_name . "' applied successfully.\n";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (PDOException $e) {
|
} catch (PDOException $e) {
|
||||||
die("Migration failed: " . $e->getMessage() . "\n");
|
die("Migration failed: " . $e->getMessage() . "\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
run_migrations();
|
run_migrations();
|
||||||
|
|
||||||
5
db/migrations/000_create_migrations_table.sql
Normal file
5
db/migrations/000_create_migrations_table.sql
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
CREATE TABLE IF NOT EXISTS migrations (
|
||||||
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
migration_name VARCHAR(255) NOT NULL,
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
4
db/migrations/002_create_conversations_table.sql
Normal file
4
db/migrations/002_create_conversations_table.sql
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
CREATE TABLE IF NOT EXISTS conversations (
|
||||||
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
CREATE TABLE IF NOT EXISTS conversation_participants (
|
||||||
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
conversation_id INT NOT NULL,
|
||||||
|
user_id INT NOT NULL,
|
||||||
|
FOREIGN KEY (conversation_id) REFERENCES conversations(id),
|
||||||
|
FOREIGN KEY (user_id) REFERENCES users(id)
|
||||||
|
);
|
||||||
9
db/migrations/004_create_messages_table.sql
Normal file
9
db/migrations/004_create_messages_table.sql
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
CREATE TABLE IF NOT EXISTS messages (
|
||||||
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
conversation_id INT NOT NULL,
|
||||||
|
sender_id INT NOT NULL,
|
||||||
|
message_text TEXT NOT NULL,
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
FOREIGN KEY (conversation_id) REFERENCES conversations(id),
|
||||||
|
FOREIGN KEY (sender_id) REFERENCES users(id)
|
||||||
|
);
|
||||||
21
index.php
21
index.php
@ -33,6 +33,10 @@ if (!isset($_SESSION['user_id'])) {
|
|||||||
<!-- Favicon -->
|
<!-- Favicon -->
|
||||||
<link rel="icon" href="https://flatlogic.com/favicon.ico" type="image/x-icon">
|
<link rel="icon" href="https://flatlogic.com/favicon.ico" type="image/x-icon">
|
||||||
|
|
||||||
|
<script>
|
||||||
|
window.userId = <?php echo $_SESSION['user_id']; ?>;
|
||||||
|
</script>
|
||||||
|
|
||||||
<!-- Styles -->
|
<!-- Styles -->
|
||||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css" rel="stylesheet">
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css" rel="stylesheet">
|
||||||
@ -44,16 +48,23 @@ if (!isset($_SESSION['user_id'])) {
|
|||||||
<!-- Sidebar -->
|
<!-- Sidebar -->
|
||||||
<aside class="sidebar">
|
<aside class="sidebar">
|
||||||
<div class="sidebar-header d-flex align-items-center">
|
<div class="sidebar-header d-flex align-items-center">
|
||||||
<img src="https://i.pravatar.cc/150?u=me" alt="My Avatar" class="avatar me-3">
|
<div class="avatar-placeholder me-3">
|
||||||
|
<i class="bi bi-person-fill"></i>
|
||||||
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<h5 class="mb-0 fw-bold">You</h5>
|
<h5 class="mb-0 fw-bold">You</h5>
|
||||||
<p class="text-muted mb-0 small">My status message...</p>
|
<p class="text-muted mb-0 small">My status message...</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="sidebar-search">
|
<div class="sidebar-search">
|
||||||
<input type="text" class="form-control rounded-pill" placeholder="Search or start new chat">
|
<form id="user-search-form">
|
||||||
|
<input type="text" id="user-search-input" class="form-control rounded-pill" placeholder="Search for users...">
|
||||||
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<div class="conversation-list">
|
<div id="search-results" class="conversation-list">
|
||||||
|
<!-- Search results will be injected here -->
|
||||||
|
</div>
|
||||||
|
<div class="conversation-list" id="conversation-list-container">
|
||||||
<div class="text-center text-muted p-4">
|
<div class="text-center text-muted p-4">
|
||||||
<i class="bi bi-chat-dots fs-2"></i>
|
<i class="bi bi-chat-dots fs-2"></i>
|
||||||
<p class="mt-2">No conversations yet.</p>
|
<p class="mt-2">No conversations yet.</p>
|
||||||
@ -66,7 +77,9 @@ if (!isset($_SESSION['user_id'])) {
|
|||||||
<!-- Chat Header -->
|
<!-- Chat Header -->
|
||||||
<header class="chat-header">
|
<header class="chat-header">
|
||||||
<div class="d-flex align-items-center">
|
<div class="d-flex align-items-center">
|
||||||
<img src="https://i.pravatar.cc/150?u=placeholder" alt="Avatar" class="avatar avatar-sm me-3">
|
<div class="avatar-placeholder avatar-sm me-3">
|
||||||
|
<i class="bi bi-person-fill"></i>
|
||||||
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<h5 class="mb-0 name">Select a Conversation</h5>
|
<h5 class="mb-0 name">Select a Conversation</h5>
|
||||||
<p class="mb-0 status text-muted">Offline</p>
|
<p class="mb-0 status text-muted">Offline</p>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user