-- Créer la base de données
CREATE DATABASE IF NOT EXISTS chat_app;
USE chat_app;
-- Table des utilisateurs
CREATE TABLE IF NOT EXISTS users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL,
room VARCHAR(50) NOT NULL,
last_active DATETIME NOT NULL,
UNIQUE KEY unique_user_room (username, room)
);
-- Table des messages
CREATE TABLE IF NOT EXISTS messages (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL,
room VARCHAR(50) NOT NULL,
message TEXT NOT NULL,
created_at DATETIME NOT NULL
);
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-
scale=1.0">
<title>Application de Chat</title>
<link rel="stylesheet" href="[Link]">
</head>
<body>
<div class="chat-container">
<header class="chat-header">
<h1><i class="fas fa-smile"></i> Chat en Ligne</h1>
</header>
<main class="chat-main">
<div class="chat-sidebar">
<h3><i class="fas fa-users"></i> Utilisateurs</h3>
<ul id="users"></ul>
</div>
<div class="chat-messages" id="chat-messages"></div>
</main>
<div class="chat-form-container">
<form id="chat-form">
<input type="text" id="msg" placeholder="Entrez votre
message..." required autocomplete="off">
<button class="btn"><i class="fas fa-paper-plane"></i>
Envoyer</button>
</form>
</div>
<div class="login-container" id="login-container">
<form id="login-form">
<h2>Connexion au Chat</h2>
<div class="form-group">
<label for="username">Nom d'utilisateur</label>
<input type="text" id="username" placeholder="Entrez votre
nom..." required>
</div>
<div class="form-group">
<label for="room">Salon</label>
<select id="room" required>
<option value="" disabled selected>Sélectionnez un
salon</option>
<option value="Général">Général</option>
<option value="Aide">Aide</option>
<option value="Jeux">Jeux</option>
</select>
</div>
<button type="submit" class="btn">Rejoindre</button>
</form>
</div>
</div>
<script src="[Link]
<script src="[Link]"></script>
</body>
</html>
:root {
--primary-color: #3a86ff;
--secondary-color: #8338ec;
--dark-color: #1a1a2e;
--light-color: #f8f9fa;
--success-color: #28a745;
--error-color: #dc3545;
*{
box-sizing: border-box;
margin: 0;
padding: 0;
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
line-height: 1.6;
background-color: #f5f5f5;
color: #333;
.chat-container {
max-width: 1100px;
margin: 30px auto;
overflow: hidden;
border-radius: 10px;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
.chat-header {
background: linear-gradient(to right, var(--primary-color), var(--
secondary-color));
color: #fff;
padding: 15px;
text-align: center;
.chat-main {
display: grid;
grid-template-columns: 1fr 3fr;
height: 500px;
.chat-sidebar {
background: var(--dark-color);
color: #fff;
padding: 20px;
overflow-y: auto;
.chat-sidebar h3 {
margin-bottom: 15px;
text-align: center;
.chat-sidebar ul {
list-style: none;
.chat-sidebar ul li {
padding: 10px 0;
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
.chat-messages {
padding: 30px;
overflow-y: auto;
background-color: #fff;
}
.message {
padding: 10px;
margin-bottom: 15px;
background-color: #f1f1f1;
border-radius: 5px;
.message .meta {
font-size: 12px;
color: var(--dark-color);
opacity: 0.8;
margin-bottom: 5px;
.message .meta span {
color: var(--secondary-color);
font-weight: bold;
.chat-form-container {
padding: 20px;
background-color: var(--dark-color);
.chat-form-container form {
display: flex;
}
.chat-form-container input {
flex: 1;
padding: 10px;
border: none;
border-radius: 5px 0 0 5px;
font-size: 16px;
.chat-form-container .btn {
padding: 10px 20px;
border: none;
background: var(--primary-color);
color: #fff;
border-radius: 0 5px 5px 0;
cursor: pointer;
font-size: 16px;
transition: background 0.3s;
.chat-form-container .btn:hover {
background: var(--secondary-color);
.login-container {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.7);
display: flex;
justify-content: center;
align-items: center;
z-index: 100;
.login-container form {
background: #fff;
padding: 30px;
border-radius: 10px;
width: 100%;
max-width: 400px;
.login-container h2 {
text-align: center;
margin-bottom: 20px;
color: var(--dark-color);
.form-group {
margin-bottom: 20px;
.form-group label {
display: block;
margin-bottom: 5px;
color: var(--dark-color);
}
.form-group input,
.form-group select {
width: 100%;
padding: 10px;
border: 1px solid #ddd;
border-radius: 5px;
font-size: 16px;
.btn {
display: block;
width: 100%;
padding: 10px;
border: none;
background: var(--primary-color);
color: #fff;
border-radius: 5px;
cursor: pointer;
font-size: 16px;
transition: background 0.3s;
.btn:hover {
background: var(--secondary-color);
.hidden {
display: none;
/* Responsive */
@media (max-width: 768px) {
.chat-main {
grid-template-columns: 1fr;
.chat-sidebar {
display: none;
[Link]('DOMContentLoaded', () => {
const chatForm = [Link]('chat-form');
const chatMessages = [Link]('chat-messages');
const userList = [Link]('users');
const loginForm = [Link]('login-form');
const loginContainer = [Link]('login-container');
let username = '';
let room = '';
// Afficher le formulaire de connexion
[Link]('hidden');
// Gestion de la connexion
[Link]('submit', (e) => {
[Link]();
username = [Link]();
room = [Link];
if (username && room) {
// Envoyer les données de connexion au serveur
fetch('[Link]', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: [Link]({
action: 'login',
username: username,
room: room
})
})
.then(response => [Link]())
.then(data => {
if ([Link]) {
// Masquer le formulaire de connexion
[Link]('hidden');
// Charger les messages précédents
loadMessages();
// Simuler une connexion WebSocket (dans une vraie app,
utiliser [Link] ou similaire)
setInterval(loadMessages, 2000);
setInterval(updateUserList, 3000);
} else {
alert([Link]);
});
});
// Envoyer un message
[Link]('submit', (e) => {
[Link]();
const msgInput = [Link];
const message = [Link]();
if (message) {
// Envoyer le message au serveur
fetch('[Link]', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: [Link]({
action: 'send_message',
username: username,
room: room,
message: message
})
})
.then(response => [Link]())
.then(data => {
if ([Link]) {
[Link] = '';
loadMessages();
} else {
alert([Link]);
});
});
// Charger les messages
function loadMessages() {
fetch('[Link]', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: [Link]({
action: 'get_messages',
room: room
})
})
.then(response => [Link]())
.then(data => {
if ([Link]) {
[Link] = '';
[Link](msg => {
outputMessage(msg);
});
// Faire défiler vers le bas
[Link] = [Link];
});
// Mettre à jour la liste des utilisateurs
function updateUserList() {
fetch('[Link]', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: [Link]({
action: 'get_users',
room: room
})
})
.then(response => [Link]())
.then(data => {
if ([Link]) {
[Link] = '';
[Link](user => {
const li = [Link]('li');
[Link] = user;
[Link](li);
});
});
// Afficher un message dans le chat
function outputMessage(message) {
const div = [Link]('div');
[Link]('message');
const meta = [Link]('p');
[Link]('meta');
[Link] = `${[Link]} <span>$
{[Link]}</span>`;
const text = [Link]('p');
[Link]('text');
[Link] = [Link];
[Link](meta);
[Link](text);
[Link](div);
});
<?php
header('Content-Type: application/json');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST');
header('Access-Control-Allow-Headers: Content-Type');
// Configurer la connexion à la base de données
$host = 'localhost';
$dbname = 'chat_app';
$username = 'root';
$password = '';
try {
$pdo = new PDO("mysql:host=$host;dbname=$dbname", $username,
$password);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
echo json_encode(['success' => false, 'message' => 'Erreur de
connexion à la base de données']);
exit;
// Récupérer les données POST
$data = json_decode(file_get_contents('php://input'), true);
$action = $data['action'] ?? '';
switch ($action) {
case 'login':
handleLogin($pdo, $data);
break;
case 'send_message':
handleSendMessage($pdo, $data);
break;
case 'get_messages':
handleGetMessages($pdo, $data);
break;
case 'get_users':
handleGetUsers($pdo, $data);
break;
default:
echo json_encode(['success' => false, 'message' => 'Action non
reconnue']);
}
function handleLogin($pdo, $data) {
$username = $data['username'] ?? '';
$room = $data['room'] ?? '';
if (empty($username) {
echo json_encode(['success' => false, 'message' => 'Le nom
d\'utilisateur est requis']);
return;
if (empty($room)) {
echo json_encode(['success' => false, 'message' => 'Le salon est
requis']);
return;
// Vérifier si l'utilisateur existe déjà dans la salle
$stmt = $pdo->prepare("SELECT * FROM users WHERE username = ?
AND room = ?");
$stmt->execute([$username, $room]);
$user = $stmt->fetch();
if ($user) {
// Mettre à jour le timestamp de l'utilisateur
$stmt = $pdo->prepare("UPDATE users SET last_active = NOW()
WHERE id = ?");
$stmt->execute([$user['id']]);
} else {
// Ajouter un nouvel utilisateur
$stmt = $pdo->prepare("INSERT INTO users (username, room,
last_active) VALUES (?, ?, NOW())");
$stmt->execute([$username, $room]);
echo json_encode(['success' => true, 'message' => 'Connexion
réussie']);
function handleSendMessage($pdo, $data) {
$username = $data['username'] ?? '';
$room = $data['room'] ?? '';
$message = $data['message'] ?? '';
if (empty($username) || empty($room) || empty($message)) {
echo json_encode(['success' => false, 'message' => 'Données
manquantes']);
return;
// Insérer le message dans la base de données
$stmt = $pdo->prepare("INSERT INTO messages (username, room,
message, created_at) VALUES (?, ?, ?, NOW())");
$stmt->execute([$username, $room, $message]);
echo json_encode(['success' => true, 'message' => 'Message
envoyé']);
function handleGetMessages($pdo, $data) {
$room = $data['room'] ?? '';
if (empty($room)) {
echo json_encode(['success' => false, 'message' => 'Le salon est
requis']);
return;
// Récupérer les messages de la salle
$stmt = $pdo->prepare("SELECT username, message,
DATE_FORMAT(created_at, '%H:%i') as time FROM messages WHERE room
= ? ORDER BY created_at ASC");
$stmt->execute([$room]);
$messages = $stmt->fetchAll(PDO::FETCH_ASSOC);
echo json_encode(['success' => true, 'messages' => $messages]);
function handleGetUsers($pdo, $data) {
$room = $data['room'] ?? '';
if (empty($room)) {
echo json_encode(['success' => false, 'message' => 'Le salon est
requis']);
return;
// Récupérer les utilisateurs actifs (connectés dans les 5 dernières
minutes)
$stmt = $pdo->prepare("SELECT DISTINCT username FROM users
WHERE room = ? AND last_active > DATE_SUB(NOW(), INTERVAL 5
MINUTE)");
$stmt->execute([$room]);
$users = $stmt->fetchAll(PDO::FETCH_COLUMN, 0);
echo json_encode(['success' => true, 'users' => $users]);
?>