Contacts
This commit is contained in:
parent
a37fc59b93
commit
ca7f5831fa
32
api/send_message.php
Normal file
32
api/send_message.php
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
session_start();
|
||||||
|
header('Content-Type: application/json');
|
||||||
|
|
||||||
|
if (!isset($_SESSION['user_id'])) {
|
||||||
|
echo json_encode(['success' => false, 'error' => 'Not logged in']);
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||||
|
echo json_encode(['success' => false, 'error' => 'Invalid request method']);
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
require_once '../db/config.php';
|
||||||
|
|
||||||
|
$sender_id = $_SESSION['user_id'];
|
||||||
|
$receiver_id = isset($_POST['receiver_id']) ? (int)$_POST['receiver_id'] : 0;
|
||||||
|
$message = isset($_POST['message']) ? trim($_POST['message']) : '';
|
||||||
|
|
||||||
|
if ($receiver_id && !empty($message)) {
|
||||||
|
try {
|
||||||
|
$pdo = db();
|
||||||
|
$stmt = $pdo->prepare('INSERT INTO messages (sender_id, receiver_id, message) VALUES (?, ?, ?)');
|
||||||
|
$stmt->execute([$sender_id, $receiver_id, $message]);
|
||||||
|
echo json_encode(['success' => true]);
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
echo json_encode(['success' => false, 'error' => $e->getMessage()]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
echo json_encode(['success' => false, 'error' => 'Invalid input']);
|
||||||
|
}
|
||||||
@ -1,51 +1,3 @@
|
|||||||
|
html, body {
|
||||||
body {
|
height: 100%;
|
||||||
font-family: 'Inter', sans-serif;
|
|
||||||
background-color: #121212;
|
|
||||||
color: #E0E0E0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.navbar-dark .navbar-nav .nav-link {
|
|
||||||
color: rgba(255, 255, 255, .75);
|
|
||||||
}
|
|
||||||
|
|
||||||
.navbar-dark .navbar-nav .nav-link.active,
|
|
||||||
.navbar-dark .navbar-nav .nav-link:hover {
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card {
|
|
||||||
background-color: #1E1E1E;
|
|
||||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-control {
|
|
||||||
background-color: #2a2a2a;
|
|
||||||
color: #fff;
|
|
||||||
border: 1px solid #444;
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-control:focus {
|
|
||||||
background-color: #2a2a2a;
|
|
||||||
color: #fff;
|
|
||||||
border-color: #0D6EFD;
|
|
||||||
box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, .25);
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-control::placeholder {
|
|
||||||
color: #888;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-primary {
|
|
||||||
background-color: #0D6EFD;
|
|
||||||
border-color: #0D6EFD;
|
|
||||||
}
|
|
||||||
|
|
||||||
.text-muted {
|
|
||||||
color: #A0A0A0 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.feature-icon {
|
|
||||||
font-size: 2.5rem;
|
|
||||||
color: #0D6EFD;
|
|
||||||
}
|
}
|
||||||
142
dashboard.php
142
dashboard.php
@ -1,58 +1,112 @@
|
|||||||
<?php
|
<?php
|
||||||
session_start();
|
session_start();
|
||||||
|
|
||||||
// If user is not logged in, redirect to login page
|
|
||||||
if (!isset($_SESSION['user_id'])) {
|
if (!isset($_SESSION['user_id'])) {
|
||||||
header("Location: login.php");
|
header('Location: login.php');
|
||||||
exit;
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
require_once 'db/config.php';
|
||||||
include 'header.php';
|
include 'header.php';
|
||||||
?>
|
|
||||||
|
|
||||||
<main class="container flex-grow-1 my-5">
|
$pdo = db();
|
||||||
<div class="row">
|
$current_user_id = $_SESSION['user_id'];
|
||||||
<div class="col-md-4">
|
|
||||||
<div class="card">
|
// Check if we are viewing a specific chat
|
||||||
<div class="card-header">
|
$chat_with_id = isset($_GET['chat_with_id']) ? (int)$_GET['chat_with_id'] : null;
|
||||||
Conversations
|
|
||||||
</div>
|
if ($chat_with_id) {
|
||||||
<ul class="list-group list-group-flush">
|
// Chat view
|
||||||
<li class="list-group-item"><a href="#">User 1</a></li>
|
$stmt = $pdo->prepare('SELECT display_name FROM users WHERE id = ?');
|
||||||
<li class="list-group-item"><a href="#">User 2</a></li>
|
$stmt->execute([$chat_with_id]);
|
||||||
<li class="list-group-item"><a href="#">User 3</a></li>
|
$chat_with_user = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||||
</ul>
|
|
||||||
|
// Fetch messages
|
||||||
|
$stmt = $pdo->prepare('SELECT * FROM messages WHERE (sender_id = ? AND receiver_id = ?) OR (sender_id = ? AND receiver_id = ?) ORDER BY created_at ASC');
|
||||||
|
$stmt->execute([$current_user_id, $chat_with_id, $chat_with_id, $current_user_id]);
|
||||||
|
$messages = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
|
?>
|
||||||
|
<div class="d-flex flex-column" style="height: calc(100vh - 56px);">
|
||||||
|
<header class="p-3 bg-light border-bottom">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="d-flex justify-content-between align-items-center">
|
||||||
|
<a href="dashboard.php" class="btn btn-secondary">< Back</a>
|
||||||
|
<h1 class="h5 mb-0">Chat with <?php echo htmlspecialchars($chat_with_user['display_name']); ?></h1>
|
||||||
|
<div></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-8">
|
</header>
|
||||||
<div class="card">
|
|
||||||
<div class="card-header">
|
<main class="flex-grow-1" style="overflow-y: auto;">
|
||||||
Chat with User 1
|
<div class="container-fluid p-3">
|
||||||
</div>
|
<div class="d-flex flex-column gap-3">
|
||||||
<div class="card-body" style="height: 400px; overflow-y: auto;">
|
<?php foreach ($messages as $message): ?>
|
||||||
<!-- Chat messages will go here -->
|
<div class="p-2 rounded <?php echo $message['sender_id'] == $current_user_id ? 'bg-light text-dark align-self-end text-end' : 'bg-primary text-white align-self-start'; ?> col-8">
|
||||||
<div class="d-flex justify-content-end mb-3">
|
<?php echo htmlspecialchars($message['message']); ?>
|
||||||
<div class="bg-primary text-white p-2 rounded">
|
|
||||||
Hello!
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="d-flex justify-content-start mb-3">
|
|
||||||
<div class="bg-light p-2 rounded">
|
|
||||||
Hi there!
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="card-footer">
|
|
||||||
<form>
|
|
||||||
<div class="input-group">
|
|
||||||
<input type="text" class="form-control" placeholder="Type a message...">
|
|
||||||
<button class="btn btn-primary" type="button">Send</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
<?php endforeach; ?>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<?php include 'footer.php'; ?>
|
<footer class="p-3 bg-light border-top">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<form id="message-form">
|
||||||
|
<div class="input-group">
|
||||||
|
<input type="hidden" name="receiver_id" value="<?php echo $chat_with_id; ?>">
|
||||||
|
<input type="text" name="message" class="form-control" placeholder="Type a message..." required>
|
||||||
|
<button class="btn btn-primary" type="submit">Send</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
|
<?php
|
||||||
|
} else {
|
||||||
|
// Contact list view
|
||||||
|
$stmt = $pdo->prepare('SELECT id, display_name FROM users WHERE id != ?');
|
||||||
|
$stmt->execute([$current_user_id]);
|
||||||
|
$users = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
?>
|
||||||
|
<div class="container mt-4">
|
||||||
|
<h1 class="h3 mb-3">Contacts</h1>
|
||||||
|
<div class="list-group">
|
||||||
|
<?php foreach ($users as $user): ?>
|
||||||
|
<a href="dashboard.php?chat_with_id=<?php echo $user['id']; ?>" class="list-group-item list-group-item-action">
|
||||||
|
<?php echo htmlspecialchars($user['display_name']); ?>
|
||||||
|
</a>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
<script>
|
||||||
|
if (document.getElementById('message-form')) {
|
||||||
|
document.getElementById('message-form').addEventListener('submit', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
const form = e.target;
|
||||||
|
const formData = new FormData(form);
|
||||||
|
|
||||||
|
fetch('api/send_message.php', {
|
||||||
|
method: 'POST',
|
||||||
|
body: formData
|
||||||
|
})
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
if (data.success) {
|
||||||
|
location.reload();
|
||||||
|
} else {
|
||||||
|
alert('Error sending message: ' + data.error);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Error:', error);
|
||||||
|
alert('An unexpected error occurred.');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<?php
|
||||||
|
include 'footer.php';
|
||||||
|
?>
|
||||||
|
|||||||
21
db/migrations/001_create_messages_table.php
Normal file
21
db/migrations/001_create_messages_table.php
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
require_once __DIR__ . '/../config.php';
|
||||||
|
|
||||||
|
try {
|
||||||
|
$pdo = db();
|
||||||
|
$sql = "
|
||||||
|
CREATE TABLE IF NOT EXISTS messages (
|
||||||
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
sender_id INT NOT NULL,
|
||||||
|
receiver_id INT NOT NULL,
|
||||||
|
message TEXT NOT NULL,
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
FOREIGN KEY (sender_id) REFERENCES users(id) ON DELETE CASCADE,
|
||||||
|
FOREIGN KEY (receiver_id) REFERENCES users(id) ON DELETE CASCADE
|
||||||
|
);";
|
||||||
|
$pdo->exec($sql);
|
||||||
|
echo "Table 'messages' created successfully (if it didn't exist).\n";
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
die("DB MIGRATION ERROR: " . $e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
@ -22,7 +22,14 @@ try {
|
|||||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||||
);";
|
);";
|
||||||
$pdo->exec($sql);
|
$pdo->exec($sql);
|
||||||
echo "Table 'users' created successfully (if it didn't exist).\n";
|
echo "Table 'users' created successfully (if it didn\'t exist).\n";
|
||||||
|
|
||||||
|
// 4. Run migrations
|
||||||
|
$migration_files = glob(__DIR__ . '/migrations/*.php');
|
||||||
|
foreach ($migration_files as $file) {
|
||||||
|
require_once $file;
|
||||||
|
echo "Ran migration: $file\n";
|
||||||
|
}
|
||||||
|
|
||||||
} catch (PDOException $e) {
|
} catch (PDOException $e) {
|
||||||
die("DB SETUP ERROR: " . $e->getMessage());
|
die("DB SETUP ERROR: " . $e->getMessage());
|
||||||
|
|||||||
@ -1,9 +1,5 @@
|
|||||||
|
|
||||||
<footer class="footer mt-auto py-3 bg-dark text-white">
|
|
||||||
<div class="container text-center">
|
|
||||||
<small>harmony3 © 2025</small>
|
|
||||||
</div>
|
|
||||||
</footer>
|
|
||||||
|
|
||||||
<!-- <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script> -->
|
<!-- <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script> -->
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
30
header.php
30
header.php
@ -23,14 +23,14 @@
|
|||||||
<body class="d-flex flex-column min-vh-100">
|
<body class="d-flex flex-column min-vh-100">
|
||||||
|
|
||||||
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
|
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
|
||||||
<div class="container">
|
<div class="container-fluid">
|
||||||
|
<button class="navbar-toggler" type="button" data-bs-toggle="offcanvas" data-bs-target="#offcanvasExample" aria-controls="offcanvasExample">
|
||||||
|
<span class="navbar-toggler-icon"></span>
|
||||||
|
</button>
|
||||||
<a class="navbar-brand" href="index.php">
|
<a class="navbar-brand" href="index.php">
|
||||||
<i class="bi bi-chat-quote-fill"></i>
|
<i class="bi bi-chat-quote-fill"></i>
|
||||||
harmony3
|
harmony3
|
||||||
</a>
|
</a>
|
||||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
|
|
||||||
<span class="navbar-toggler-icon"></span>
|
|
||||||
</button>
|
|
||||||
<div class="collapse navbar-collapse" id="navbarNav">
|
<div class="collapse navbar-collapse" id="navbarNav">
|
||||||
<ul class="navbar-nav ms-auto">
|
<ul class="navbar-nav ms-auto">
|
||||||
<?php if (isset($_SESSION['user_id'])): ?>
|
<?php if (isset($_SESSION['user_id'])): ?>
|
||||||
@ -52,3 +52,25 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
|
<div class="offcanvas offcanvas-start" tabindex="-1" id="offcanvasExample" aria-labelledby="offcanvasExampleLabel">
|
||||||
|
<div class="offcanvas-header">
|
||||||
|
<h5 class="offcanvas-title" id="offcanvasExampleLabel">Chats</h5>
|
||||||
|
<button type="button" class="btn-close text-reset" data-bs-dismiss="offcanvas" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<div class="offcanvas-body">
|
||||||
|
<div>
|
||||||
|
Select a user to start a conversation.
|
||||||
|
</div>
|
||||||
|
<div class="dropdown mt-3">
|
||||||
|
<button class="btn btn-secondary dropdown-toggle" type="button" id="dropdownMenuButton" data-bs-toggle="dropdown">
|
||||||
|
Select User
|
||||||
|
</button>
|
||||||
|
<ul class="dropdown-menu" aria-labelledby="dropdownMenuButton">
|
||||||
|
<li><a class="dropdown-item" href="#">User 1</a></li>
|
||||||
|
<li><a class="dropdown-item" href="#">User 2</a></li>
|
||||||
|
<li><a class="dropdown-item" href="#">User 3</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|||||||
@ -15,7 +15,7 @@ include 'header.php';
|
|||||||
|
|
||||||
// If user is already logged in, redirect to dashboard
|
// If user is already logged in, redirect to dashboard
|
||||||
if (isset($_SESSION['user_id'])) {
|
if (isset($_SESSION['user_id'])) {
|
||||||
echo '<script>window.top.location.href = "dashboard.php";</script>';
|
header("Location: dashboard.php");
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,8 +47,8 @@ if ($_SERVER["REQUEST_METHOD"] == "POST") {
|
|||||||
if ($user && password_verify($password, $user['password_hash'])) {
|
if ($user && password_verify($password, $user['password_hash'])) {
|
||||||
$_SESSION['user_id'] = $user['id'];
|
$_SESSION['user_id'] = $user['id'];
|
||||||
$_SESSION['display_name'] = $user['display_name'];
|
$_SESSION['display_name'] = $user['display_name'];
|
||||||
// Use JS redirect for consistency
|
// Standard PHP redirect
|
||||||
echo '<script>window.top.location.href = "dashboard.php";</script>';
|
header("Location: dashboard.php");
|
||||||
exit;
|
exit;
|
||||||
} else {
|
} else {
|
||||||
$errors[] = 'Invalid email or password.';
|
$errors[] = 'Invalid email or password.';
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user