Use Case
/
التطوير السريع
إنشاء نماذج أولية وظيفية بسرعة
Model
•
كلود 3.7 سونيت
إنشاء نموذج أولي لتطبيق دردشة في الوقت الفعلي باستخدام React وNode.js وSocket.io — الغرف الأساسية والمراسلة ووجود المستخدم
النموذج الأولي لتطبيق الدردشة في الوقت الفعلي مع React وNode.js وSocket.io
سأوجهك من خلال إنشاء تطبيق دردشة أساسي في الوقت الفعلي مع دعم الغرفة والمراسلة ومؤشرات حضور المستخدم. دعونا نقسم هذا إلى مكونات الواجهة الأمامية والخلفية.
هيكل المشروع
1chat-app/
2├── client/ # React frontend
3│ ├── public/
4│ └── src/
5├── server/ # Node.js backend
6└── package.jsonالواجهة الخلفية (Node.js + Socket.io)
1. قم بإعداد الخادم
أولاً، قم بإنشاء دليل الخادم وتهيئة:
1mkdir -p chat-app/server
2cd chat-app/server
3npm init -y
4npm install express socket.io cors2. ابتكر server.js
1const express = require('express');
2const http = require('http');
3const socketIo = require('socket.io');
4const cors = require('cors');
5
6const app = express();
7app.use(cors());
8
9const server = http.createServer(app);
10const io = socketIo(server, {
11 cors: {
12 origin: "http://localhost:3000",
13 methods: ["GET", "POST"]
14 }
15});
16
17// Track users in each room
18const rooms = {};
19
20io.on('connection', (socket) => {
21 console.log('New client connected:', socket.id);
22
23 // User joins a room
24 socket.on('join_room', ({ username, room }) => {
25 socket.join(room);
26
27 // Initialize room if it doesn't exist
28 if (!rooms[room]) {
29 rooms[room] = [];
30 }
31
32 // Add user to room
33 rooms[room].push({ id: socket.id, username });
34
35 // Broadcast to room that user has joined
36 io.to(room).emit('user_joined', {
37 username,
38 users: rooms[room],
39 message: `${username} has joined the room.`
40 });
41
42 // Send room history to the new user
43 socket.emit('room_users', rooms[room]);
44
45 console.log(`${username} joined room: ${room}`);
46 });
47
48 // Handle messages
49 socket.on('send_message', ({ room, username, message }) => {
50 const timestamp = new Date().toISOString();
51 io.to(room).emit('receive_message', {
52 username,
53 message,
54 timestamp
55 });
56 });
57
58 // Handle user typing
59 socket.on('typing', ({ room, username }) => {
60 socket.to(room).emit('user_typing', { username });
61 });
62
63 // Handle user disconnect
64 socket.on('disconnect', () => {
65 console.log('Client disconnected:', socket.id);
66
67 // Find which room the user was in
68 for (const room in rooms) {
69 const userIndex = rooms[room].findIndex(user => user.id === socket.id);
70
71 if (userIndex !== -1) {
72 const username = rooms[room][userIndex].username;
73
74 // Remove user from room
75 rooms[room].splice(userIndex, 1);
76
77 // Notify room that user has left
78 io.to(room).emit('user_left', {
79 username,
80 users: rooms[room],
81 message: `${username} has left the room.`
82 });
83
84 break;
85 }
86 }
87 });
88});
89
90const PORT = process.env.PORT || 4000;
91server.listen(PORT, () => {
92 console.log(`Server running on port ${PORT}`);
93});الواجهة الأمامية (عميل React + Socket.io)
1. قم بإعداد تطبيق React
1npx create-react-app chat-app/client
2cd chat-app/client
3npm install socket.io-client2. إنشاء مكونات
src/App.js
1import React, { useState } from 'react';
2import './App.css';
3import JoinRoom from './components/JoinRoom';
4import ChatRoom from './components/ChatRoom';
5
6function App() {
7 const [joined, setJoined] = useState(false);
8 const [userData, setUserData] = useState({ username: '', room: '' });
9
10 const handleJoinRoom = (username, room) => {
11 setUserData({ username, room });
12 setJoined(true);
13 };
14
15 return (
16 <div className="App">
17 <header className="App-header">
18 <h1>Real-Time Chat App</h1>
19 </header>
20 <main>
21 {!joined ? (
22 <JoinRoom onJoin={handleJoinRoom} />
23 ) : (
24 <ChatRoom username={userData.username} room={userData.room} />
25 )}
26 </main>
27 </div>
28 );
29}
30
31export default App;src/components/JoinRoom.js
1import React, { useState } from 'react';
2
3function JoinRoom({ onJoin }) {
4 const [username, setUsername] = useState('');
5 const [room, setRoom] = useState('');
6
7 const handleSubmit = (e) => {
8 e.preventDefault();
9 if (username && room) {
10 onJoin(username, room);
11 }
12 };
13
14 return (
15 <div className="join-container">
16 <h2>Join a Chat Room</h2>
17 <form onSubmit={handleSubmit}>
18 <div className="form-group">
19 <label htmlFor="username">Username:</label>
20 <input
21 type="text"
22 id="username"
23 value={username}
24 onChange={(e) => setUsername(e.target.value)}
25 required
26 />
27 </div>
28 <div className="form-group">
29 <label htmlFor="room">Room:</label>
30 <input
31 type="text"
32 id="room"
33 value={room}
34 onChange={(e) => setRoom(e.target.value)}
35 required
36 />
37 </div>
38 <button type="submit">Join Room</button>
39 </form>
40 </div>
41 );
42}
43
44export default JoinRoom;src/components/ChatRoom.js
1import React, { useState, useEffect, useRef } from 'react';
2import io from 'socket.io-client';
3
4const ENDPOINT = 'http://localhost:4000';
5
6function ChatRoom({ username, room }) {
7 const [messages, setMessages] = useState([]);
8 const [message, setMessage] = useState('');
9 const [users, setUsers] = useState([]);
10 const [typingUsers, setTypingUsers] = useState([]);
11 const socketRef = useRef();
12 const messagesEndRef = useRef();
13
14 // Initialize socket connection
15 useEffect(() => {
16 socketRef.current = io(ENDPOINT);
17
18 // Join room
19 socketRef.current.emit('join_room', { username, room });
20
21 // Listen for messages
22 socketRef.current.on('receive_message', (data) => {
23 setMessages((prevMessages) => [...prevMessages, data]);
24 });
25
26 // Listen for user joined
27 socketRef.current.on('user_joined', (data) => {
28 setUsers(data.users);
29 setMessages((prevMessages) => [
30 ...prevMessages,
31 { system: true, message: data.message, timestamp: new Date().toISOString() }
32 ]);
33 });
34
35 // Listen for user left
36 socketRef.current.on('user_left', (data) => {
37 setUsers(data.users);
38 setMessages((prevMessages) => [
39 ...prevMessages,
40 { system: true, message: data.message, timestamp: new Date().toISOString() }
41 ]);
42 });
43
44 // Get current users in room
45 socketRef.current.on('room_users', (data) => {
46 setUsers(data);
47 });
48
49 // Listen for typing events
50 socketRef.current.on('user_typing', (data) => {
51 setTypingUsers((prevTypers) => {
52 if (!prevTypers.includes(data.username)) {
53 return [...prevTypers, data.username];
54 }
55 return prevTypers;
56 });
57
58 // Remove typing indicator after 2 seconds
59 setTimeout(() => {
60 setTypingUsers((prevTypers) =>
61 prevTypers.filter(user => user !== data.username)
62 );
63 }, 2000);
64 });
65
66 // Cleanup on unmount
67 return () => {
68 socketRef.current.disconnect();
69 };
70 }, [username, room]);
71
72 // Auto-scroll to bottom when new messages arrive
73 useEffect(() => {
74 messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
75 }, [messages]);
76
77 // Handle sending messages
78 const handleSendMessage = (e) => {
79 e.preventDefault();
80 if (message.trim()) {
81 socketRef.current.emit('send_message', {
82 room,
83 username,
84 message
85 });
86 setMessage('');
87 }
88 };
89
90 // Handle typing indicator
91 const handleTyping = () => {
92 socketRef.current.emit('typing', { room, username });
93 };
94
95 // Format timestamp
96 const formatTime = (timestamp) => {
97 return new Date(timestamp).toLocaleTimeString([], {
98 hour: '2-digit',
99 minute: '2-digit'
100 });
101 };
102
103 return (
104 <div className="chat-container">
105 <div className="chat-header">
106 <h2>Room: {room}</h2>
107 </div>
108
109 <div className="chat-main">
110 <div className="chat-sidebar">
111 <h3>Users in Room</h3>
112 <ul className="users-list">
113 {users.map((user, index) => (
114 <li key={index} className={user.username === username ? 'current-user' : ''}>
115 {user.username} {user.username === username ? '(You)' : ''}
116 </li>
117 ))}
118 </ul>
119 </div>
120
121 <div className="chat-messages">
122 {messages.map((msg, index) => (
123 <div
124 key={index}
125 className={`message ${msg.system ? 'system-message' :
126 (msg.username === username ? 'my-message' : 'other-message')}`}
127 >
128 {!msg.system && (
129 <div className="message-header">
130 <span className="username">{msg.username}</span>
131 <span className="timestamp">{formatTime(msg.timestamp)}</span>
132 </div>
133 )}
134 <p className="message-text">{msg.message}</p>
135 </div>
136 ))}
137
138 {typingUsers.length > 0 && (
139 <div className="typing-indicator">
140 {typingUsers.join(', ')} {typingUsers.length === 1 ? 'is' : 'are'} typing...
141 </div>
142 )}
143
144 <div ref={messagesEndRef} />
145 </div>
146 </div>
147
148 <form className="message-form" onSubmit={handleSendMessage}>
149 <input
150 type="text"
151 value={message}
152 onChange={(e) => setMessage(e.target.value)}
153 onKeyPress={handleTyping}
154 placeholder="Type a message..."
155 />
156 <button type="submit">Send</button>
157 </form>
158 </div>
159 );
160}
161
162export default ChatRoom;3. أضف بعض CSS الأساسية
src/App.css
1* {
2 box-sizing: border-box;
3 margin: 0;
4 padding: 0;
5}
6
7body {
8 font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
9 line-height: 1.6;
10 background-color: #f5f5f5;
11}
12
13.App {
14 max-width: 1200px;
15 margin: 0 auto;
16 padding: 1rem;
17}
18
19.App-header {
20 text-align: center;
21 margin-bottom: 2rem;
22 color: #333;
23}
24
25/* Join Room Styles */
26.join-container {
27 max-width: 500px;
28 margin: 0 auto;
29 background: white;
30 border-radius: 8px;
31 padding: 2rem;
32 box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
33}
34
35.join-container h2 {
36 margin-bottom: 1.5rem;
37 text-align: center;
38}
39
40.form-group {
41 margin-bottom: 1rem;
42}
43
44.form-group label {
45 display: block;
46 margin-bottom: 0.5rem;
47 font-weight: 500;
48}
49
50.form-group input {
51 width: 100%;
52 padding: 0.75rem;
53 border: 1px solid #ddd;
54 border-radius: 4px;
55 font-size: 1rem;
56}
57
58button {
59 background-color: #4caf50;
60 color: white;
61 border: none;
62 padding: 0.75rem 1.5rem;
63 font-size: 1rem;
64 border-radius: 4px;
65 cursor: pointer;
66 transition: background-color 0.2s;
67}
68
69button:hover {
70 background-color: #45a049;
71}
72
73/* Chat Room Styles */
74.chat-container {
75 display: flex;
76 flex-direction: column;
77 height: 80vh;
78 background: white;
79 border-radius: 8px;
80 box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
81}
82
83.chat-header {
84 padding: 1rem;
85 background: #4caf50;
86 color: white;
87 border-top-left-radius: 8px;
88 border-top-right-radius: 8px;
89}
90
91.chat-main {
92 display: flex;
93 flex: 1;
94 overflow: hidden;
95}
96
97.chat-sidebar {
98 width: 200px;
99 background: #f8f8f8;
100 padding: 1rem;
101 border-right: 1px solid #ddd;
102 overflow-y: auto;
103}
104
105.chat-sidebar h3 {
106 margin-bottom: 1rem;
107 font-size: 1.1rem;
108}
109
110.users-list {
111 list-style: none;
112}
113
114.users-list li {
115 padding: 0.5rem 0;
116 border-bottom: 1px solid #eee;
117}
118
119.current-user {
120 font-weight: bold;
121 color: #4caf50;
122}
123
124.chat-messages {
125 flex: 1;
126 padding: 1rem;
127 overflow-y: auto;
128}
129
130.message {
131 margin-bottom: 1rem;
132 padding: 0.75rem;
133 border-radius: 8px;
134 max-width: 80%;
135}
136
137.my-message {
138 background-color: #e3f2fd;
139 margin-left: auto;
140}
141
142.other-message {
143 background-color: #f1f1f1;
144}
145
146.system-message {
147 background-color: #fffde7;
148 text-align: center;
149 font-style: italic;
150 padding: 0.5rem;
151 margin: 0.5rem auto;
152 max-width: 90%;
153 color: #666;
154}
155
156.message-header {
157 display: flex;
158 justify-content: space-between;
159 margin-bottom: 0.5rem;
160 font-size: 0.85rem;
161}
162
163.username {
164 font-weight: bold;
165}
166
167.timestamp {
168 color: #777;
169}
170
171.typing-indicator {
172 font-style: italic;
173 color: #777;
174 padding: 0.5rem;
175}
176
177.message-form {
178 display: flex;
179 padding: 1rem;
180 border-top: 1px solid #ddd;
181}
182
183.message-form input {
184 flex: 1;
185 padding: 0.75rem;
186 border: 1px solid #ddd;
187 border-radius: 4px;
188 margin-right: 0.5rem;
189 font-size: 1rem;
190}تشغيل التطبيق
1. بدء تشغيل الخادم:
1cd chat-app/server
2node server.js2. ابدأ تشغيل عميل React:
1cd chat-app/client
2npm start3. افتح المتصفح الخاص بك إلى http://localhost:3000
الميزات التي تم تنفيذها
- الدردشة القائمة على الغرفة:
- يمكن للمستخدمين الانضمام إلى غرف دردشة محددة
- يمكن أن توجد غرف متعددة في وقت واحد
- المراسلة في الوقت الفعلي:
- يتم تسليم الرسائل على الفور لجميع المستخدمين في الغرفة
- حضور المستخدم:
- يُظهر الأشخاص الموجودين حاليًا في الغرفة
- إشعارات عند انضمام المستخدمين أو مغادرتهم
- مؤشرات الكتابة:
- يظهر عندما يكتب شخص ما رسالة
- تنسيق الرسائل:
- أنماط مختلفة لرسائلك مقابل الآخرين
- رسائل النظام لأحداث الانضمام/المغادرة
- الطوابع الزمنية على الرسائل
يوفر هذا النموذج الأولي أساسًا متينًا لتطبيق الدردشة في الوقت الفعلي. يمكنك توسيعه بميزات مثل:
- مصادقة المستخدم
- سجل الرسائل الدائم
- المراسلة الخاصة
- مشاركة الملفات
- اقرأ الإيصالات
- الرموز التعبيرية المخصصة/ردود الفعل
Explore Related Use Cases
Experience Ninja's AI Assistant
Try for free today. Plans starting at $19/month.


