починка тг
This commit is contained in:
15
db1.js
15
db1.js
@@ -2,15 +2,22 @@ require('dotenv').config();
|
|||||||
const { Pool } = require('pg');
|
const { Pool } = require('pg');
|
||||||
|
|
||||||
const connectionString =
|
const connectionString =
|
||||||
process.env.DATABASE_URL_VIRTUAL_WORLD || process.env.DATABASE_URL;
|
process.env.DATABASE_URL_VIRTUAL_WORLD;
|
||||||
|
console.log('<27><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: ', connectionString);
|
||||||
const virtualWorldPool = new Pool({
|
const virtualWorldPool = new Pool({
|
||||||
connectionString,
|
connectionString,
|
||||||
ssl: false
|
ssl: false
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||||
|
virtualWorldPool.on('error', (err) => {
|
||||||
|
console.error('<27><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:', err);
|
||||||
|
});
|
||||||
|
|
||||||
|
virtualWorldPool.on('connect', () => {
|
||||||
|
console.log('<27><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>');
|
||||||
|
});
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
virtualWorldPool: {
|
|
||||||
query: (text, params) => virtualWorldPool.query(text, params)
|
query: (text, params) => virtualWorldPool.query(text, params)
|
||||||
}
|
|
||||||
};
|
};
|
||||||
87
server.js
87
server.js
@@ -1,4 +1,4 @@
|
|||||||
let dotenv, express, db, Economy, GameTime, pathLib, fs, virtualWorldPool;
|
let dotenv, express, db, Economy, GameTime, pathLib, fs, virtualWorldPool, new_quest_Base;
|
||||||
try {
|
try {
|
||||||
dotenv = require('dotenv').config();
|
dotenv = require('dotenv').config();
|
||||||
console.log('dotenv успешно импортирован');
|
console.log('dotenv успешно импортирован');
|
||||||
@@ -24,6 +24,25 @@ try {
|
|||||||
console.error('Ошибка при импорте express:', e);
|
console.error('Ошибка при импорте express:', e);
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
virtualWorldPool = require('./db1');
|
||||||
|
console.log('db1 - virtualWorld - успешно импротирован');
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
console.error('Ошибка при импорте db1 - virtual_World:', e);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
new_quest_Base = require('./db2');
|
||||||
|
console.log('db2 - new_quest_Base - успешно импортирован');
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
console.error('Ошибка при импорте db2 - new_quest_Base: ', e);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
db = require('./db');
|
db = require('./db');
|
||||||
console.log('db успешно импортирован');
|
console.log('db успешно импортирован');
|
||||||
@@ -424,10 +443,9 @@ app.get('/api/users', authenticate, async (req, res) => {
|
|||||||
app.get('/api/messages/:contactId', authenticate, async (req, res) => {
|
app.get('/api/messages/:contactId', authenticate, async (req, res) => {
|
||||||
const userId = req.user.id;
|
const userId = req.user.id;
|
||||||
const contactId = parseInt(req.params.contactId, 10);
|
const contactId = parseInt(req.params.contactId, 10);
|
||||||
const pool = (typeof virtualWorldPool !== 'undefined' && virtualWorldPool) ? virtualWorldPool : db;
|
|
||||||
try {
|
try {
|
||||||
// Ensure table exists
|
// Ensure table exists
|
||||||
await pool.query(`
|
await virtualWorldPool.query(`
|
||||||
CREATE TABLE IF NOT EXISTS messages (
|
CREATE TABLE IF NOT EXISTS messages (
|
||||||
id SERIAL PRIMARY KEY,
|
id SERIAL PRIMARY KEY,
|
||||||
sender_id INT NOT NULL,
|
sender_id INT NOT NULL,
|
||||||
@@ -445,7 +463,7 @@ app.get('/api/messages/:contactId', authenticate, async (req, res) => {
|
|||||||
WHERE (sender_id = $1 AND receiver_id = $2)
|
WHERE (sender_id = $1 AND receiver_id = $2)
|
||||||
OR (sender_id = $2 AND receiver_id = $1)
|
OR (sender_id = $2 AND receiver_id = $1)
|
||||||
ORDER BY created_at ASC`;
|
ORDER BY created_at ASC`;
|
||||||
const messagesRes = await pool.query(sql, [userId, contactId]);
|
const messagesRes = await virtualWorldPool.query(sql, [userId, contactId]);
|
||||||
res.json(messagesRes.rows);
|
res.json(messagesRes.rows);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('[GET /api/messages/:contactId] error:', err);
|
console.error('[GET /api/messages/:contactId] error:', err);
|
||||||
@@ -457,7 +475,6 @@ app.post('/api/messages/send', authenticate, async (req, res) => {
|
|||||||
const senderId = req.user.id;
|
const senderId = req.user.id;
|
||||||
const { receiverId, message } = req.body || {};
|
const { receiverId, message } = req.body || {};
|
||||||
const recvId = parseInt(receiverId, 10);
|
const recvId = parseInt(receiverId, 10);
|
||||||
const pool = (typeof virtualWorldPool !== 'undefined' && virtualWorldPool) ? virtualWorldPool : db;
|
|
||||||
console.log('[POST /api/messages/send] sender:', senderId, 'receiver:', recvId);
|
console.log('[POST /api/messages/send] sender:', senderId, 'receiver:', recvId);
|
||||||
try {
|
try {
|
||||||
const receiverCheck = await db.query('SELECT id FROM users WHERE id = $1', [recvId]);
|
const receiverCheck = await db.query('SELECT id FROM users WHERE id = $1', [recvId]);
|
||||||
@@ -465,7 +482,7 @@ app.post('/api/messages/send', authenticate, async (req, res) => {
|
|||||||
return res.status(404).json({ error: 'Пользователь не найден' });
|
return res.status(404).json({ error: 'Пользователь не найден' });
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
await pool.query(`
|
await virtualWorldPool.query(`
|
||||||
CREATE TABLE IF NOT EXISTS messages (
|
CREATE TABLE IF NOT EXISTS messages (
|
||||||
id SERIAL PRIMARY KEY,
|
id SERIAL PRIMARY KEY,
|
||||||
sender_id INT NOT NULL,
|
sender_id INT NOT NULL,
|
||||||
@@ -478,7 +495,7 @@ app.post('/api/messages/send', authenticate, async (req, res) => {
|
|||||||
console.warn('[POST /api/messages/send] ensure table failed:', e.message);
|
console.warn('[POST /api/messages/send] ensure table failed:', e.message);
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = await pool.query(
|
const result = await virtualWorldPool.query(
|
||||||
`INSERT INTO messages (sender_id, receiver_id, message, created_at)
|
`INSERT INTO messages (sender_id, receiver_id, message, created_at)
|
||||||
VALUES ($1, $2, $3, NOW())
|
VALUES ($1, $2, $3, NOW())
|
||||||
RETURNING id, created_at, is_read`,
|
RETURNING id, created_at, is_read`,
|
||||||
@@ -505,9 +522,8 @@ app.post('/api/messages/send', authenticate, async (req, res) => {
|
|||||||
|
|
||||||
app.get('/api/messages', authenticate, async (req, res) => {
|
app.get('/api/messages', authenticate, async (req, res) => {
|
||||||
const userId = req.user.id;
|
const userId = req.user.id;
|
||||||
const pool = (typeof virtualWorldPool !== 'undefined' && virtualWorldPool) ? virtualWorldPool : db;
|
|
||||||
try {
|
try {
|
||||||
await pool.query(`
|
await virtualWorldPool.query(`
|
||||||
CREATE TABLE IF NOT EXISTS messages (
|
CREATE TABLE IF NOT EXISTS messages (
|
||||||
id SERIAL PRIMARY KEY,
|
id SERIAL PRIMARY KEY,
|
||||||
sender_id INT NOT NULL,
|
sender_id INT NOT NULL,
|
||||||
@@ -520,7 +536,7 @@ app.get('/api/messages', authenticate, async (req, res) => {
|
|||||||
console.warn('[GET /api/messages] ensure table failed:', e.message);
|
console.warn('[GET /api/messages] ensure table failed:', e.message);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const messagesRes = await pool.query(
|
const messagesRes = await virtualWorldPool.query(
|
||||||
`SELECT * FROM messages
|
`SELECT * FROM messages
|
||||||
WHERE sender_id = $1 OR receiver_id = $1
|
WHERE sender_id = $1 OR receiver_id = $1
|
||||||
ORDER BY created_at DESC`,
|
ORDER BY created_at DESC`,
|
||||||
@@ -531,7 +547,7 @@ app.get('/api/messages', authenticate, async (req, res) => {
|
|||||||
}
|
}
|
||||||
const userIds = new Set();
|
const userIds = new Set();
|
||||||
messagesRes.rows.forEach(msg => { userIds.add(msg.sender_id); userIds.add(msg.receiver_id); });
|
messagesRes.rows.forEach(msg => { userIds.add(msg.sender_id); userIds.add(msg.receiver_id); });
|
||||||
const usersRes = await db.query(
|
const usersRes = await virtualWorldPool.query(
|
||||||
`SELECT id, first_name, last_name, avatar_url FROM users WHERE id = ANY($1)`,
|
`SELECT id, first_name, last_name, avatar_url FROM users WHERE id = ANY($1)`,
|
||||||
[Array.from(userIds)]
|
[Array.from(userIds)]
|
||||||
);
|
);
|
||||||
@@ -559,9 +575,8 @@ app.get('/api/messages', authenticate, async (req, res) => {
|
|||||||
app.patch('/api/messages/:id/read', authenticate, async (req, res) => {
|
app.patch('/api/messages/:id/read', authenticate, async (req, res) => {
|
||||||
const messageId = req.params.id;
|
const messageId = req.params.id;
|
||||||
const userId = req.user.id;
|
const userId = req.user.id;
|
||||||
const pool = (typeof virtualWorldPool !== 'undefined' && virtualWorldPool) ? virtualWorldPool : db;
|
|
||||||
try {
|
try {
|
||||||
await pool.query(`
|
await virtualWorldPool.query(`
|
||||||
CREATE TABLE IF NOT EXISTS messages (
|
CREATE TABLE IF NOT EXISTS messages (
|
||||||
id SERIAL PRIMARY KEY,
|
id SERIAL PRIMARY KEY,
|
||||||
sender_id INT NOT NULL,
|
sender_id INT NOT NULL,
|
||||||
@@ -574,11 +589,11 @@ app.patch('/api/messages/:id/read', authenticate, async (req, res) => {
|
|||||||
console.warn('[PATCH /api/messages/:id/read] ensure table failed:', e.message);
|
console.warn('[PATCH /api/messages/:id/read] ensure table failed:', e.message);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const checkRes = await pool.query(`SELECT id FROM messages WHERE id = $1 AND receiver_id = $2`, [messageId, userId]);
|
const checkRes = await virtualWorldPool.query(`SELECT id FROM messages WHERE id = $1 AND receiver_id = $2`, [messageId, userId]);
|
||||||
if (checkRes.rows.length === 0) {
|
if (checkRes.rows.length === 0) {
|
||||||
return res.status(404).json({ error: 'Сообщение не найдено или доступ запрещен' });
|
return res.status(404).json({ error: 'Сообщение не найдено или доступ запрещен' });
|
||||||
}
|
}
|
||||||
await pool.query(`UPDATE messages SET is_read = true WHERE id = $1`, [messageId]);
|
await virtualWorldPool.query(`UPDATE messages SET is_read = true WHERE id = $1`, [messageId]);
|
||||||
res.status(204).end();
|
res.status(204).end();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('[PATCH /api/messages/:id/read] error:', err);
|
console.error('[PATCH /api/messages/:id/read] error:', err);
|
||||||
@@ -979,10 +994,9 @@ app.post('/api/listen', authenticate, async (req, res) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Выбираем пул: если есть отдельный пул, берём его, иначе общий db
|
// Выбираем пул: если есть отдельный пул, берём его, иначе общий db
|
||||||
const pool = (typeof virtualWorldPool !== 'undefined' && virtualWorldPool) ? virtualWorldPool : db;
|
|
||||||
try {
|
try {
|
||||||
// Создаём таблицу при необходимости
|
// Создаём таблицу при необходимости
|
||||||
await pool.query(`
|
await virtualWorldPool.query(`
|
||||||
CREATE TABLE IF NOT EXISTS json_listened (
|
CREATE TABLE IF NOT EXISTS json_listened (
|
||||||
id SERIAL PRIMARY KEY,
|
id SERIAL PRIMARY KEY,
|
||||||
player_id TEXT NOT NULL,
|
player_id TEXT NOT NULL,
|
||||||
@@ -994,7 +1008,7 @@ app.post('/api/listen', authenticate, async (req, res) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const q = `INSERT INTO json_listened (player_id, json_filename, listened_at) VALUES ($1, $2, NOW())`;
|
const q = `INSERT INTO json_listened (player_id, json_filename, listened_at) VALUES ($1, $2, NOW())`;
|
||||||
await pool.query(q, [String(effectivePlayerId), String(json_filename)]);
|
await virtualWorldPool.query(q, [String(effectivePlayerId), String(json_filename)]);
|
||||||
console.log('[API /api/listen] Saved listened:', { player: effectivePlayerId, json: json_filename });
|
console.log('[API /api/listen] Saved listened:', { player: effectivePlayerId, json: json_filename });
|
||||||
return res.status(200).json({ success: true });
|
return res.status(200).json({ success: true });
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -1179,50 +1193,29 @@ app.get('/api/quests/progress', authenticate, async (req, res) => {
|
|||||||
console.log("Загрузка на сервере. ID пользователя:", req.user.id);
|
console.log("Загрузка на сервере. ID пользователя:", req.user.id);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Получаем email пользователя из основной БД (или из токена)
|
// ВМЕСТО получения email, используем напрямую ID пользователя
|
||||||
const fallbackEmail = req.user?.email || req.user?.username || null;
|
const userId = req.user.id.toString(); // Преобразуем в строку для consistency
|
||||||
const userRes = await db.query('SELECT email FROM users WHERE id = $1', [req.user.id]);
|
|
||||||
if (userRes.rows.length === 0) {
|
|
||||||
if (!fallbackEmail) {
|
|
||||||
return res.status(404).json({ error: 'Пользователь не найден' });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const userEmail = userRes.rows[0]?.email || fallbackEmail;
|
|
||||||
|
|
||||||
// Получаем список всех квестов с их JSON файлами
|
// Получаем список всех квестов с их JSON файлами
|
||||||
const pool = (typeof virtualWorldPool !== 'undefined' && virtualWorldPool) ? virtualWorldPool : db;
|
const questsQuery = await virtualWorldPool.query(`
|
||||||
const questsQuery = await pool.query(`
|
|
||||||
SELECT q.id, q.title, qj.json_filename
|
SELECT q.id, q.title, qj.json_filename
|
||||||
FROM quests q
|
FROM quests q
|
||||||
JOIN quest_jsons qj ON q.id = qj.quest_id
|
JOIN quest_jsons qj ON q.id = qj.quest_id
|
||||||
ORDER BY q.id
|
ORDER BY q.id
|
||||||
`);
|
`);
|
||||||
|
|
||||||
// Получаем JSON файлы, которые прослушал игрок
|
// Получаем JSON файлы, которые прослушал игрок по его ID
|
||||||
// Гарантируем наличие таблицы json_listened
|
const listenedQuery = await virtualWorldPool.query(`
|
||||||
try {
|
|
||||||
await pool.query(`
|
|
||||||
CREATE TABLE IF NOT EXISTS json_listened (
|
|
||||||
id SERIAL PRIMARY KEY,
|
|
||||||
player_id TEXT NOT NULL,
|
|
||||||
json_filename TEXT NOT NULL,
|
|
||||||
listened_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
||||||
)`);
|
|
||||||
} catch (e) {
|
|
||||||
console.warn('[/api/quests/progress] ensure table json_listened failed:', e.message);
|
|
||||||
}
|
|
||||||
|
|
||||||
const listenedQuery = await pool.query(`
|
|
||||||
SELECT json_filename FROM json_listened
|
SELECT json_filename FROM json_listened
|
||||||
WHERE player_id = $1
|
WHERE player_id = $1
|
||||||
`, [userEmail]);
|
`, [userId]); // Используем ID вместо email
|
||||||
|
|
||||||
console.log("Результат запроса listenedQuery:", listenedQuery.rows);
|
console.log("Результат запроса listenedQuery для ID", userId, ":", listenedQuery.rows);
|
||||||
|
|
||||||
const listenedFiles = new Set(listenedQuery.rows.map(row => row.json_filename));
|
const listenedFiles = new Set(listenedQuery.rows.map(row => row.json_filename));
|
||||||
console.log("Прослушанные файлы:", Array.from(listenedFiles));
|
console.log("Прослушанные файлы:", Array.from(listenedFiles));
|
||||||
|
|
||||||
// Остальной код остается без изменений...
|
// Остальной код без изменений...
|
||||||
const questsMap = new Map();
|
const questsMap = new Map();
|
||||||
questsQuery.rows.forEach(row => {
|
questsQuery.rows.forEach(row => {
|
||||||
if (!questsMap.has(row.id)) {
|
if (!questsMap.has(row.id)) {
|
||||||
|
|||||||
30
src/Game.js
30
src/Game.js
@@ -1,18 +1,19 @@
|
|||||||
/*
|
/*
|
||||||
|
gjhghjhgjghj
|
||||||
- Проблема с игроками они множатся
|
- Проблема с игроками они множатся
|
||||||
- Проблема с перемещением между городами (исчезновение и появление игроков)
|
- Проблема с перемещением между городами (исчезновение и появление игроков)
|
||||||
- Проблема с Null полусферами
|
- Проблема с Null полусферами
|
||||||
*/
|
*/
|
||||||
import React, { useState, useEffect, useRef } from 'react';
|
import PF from 'pathfinding';
|
||||||
|
import React, { useEffect, useRef, useState } from 'react';
|
||||||
|
import { io } from 'socket.io-client';
|
||||||
import * as THREE from 'three';
|
import * as THREE from 'three';
|
||||||
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
|
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
|
||||||
import PF from 'pathfinding';
|
|
||||||
import { io } from 'socket.io-client';
|
|
||||||
import DoubleTapWrapper from './pages/DoubleTapWrapper';
|
|
||||||
import OrgControlPanel from './components/OrgControlPanel';
|
|
||||||
import Inventory from './components/Inventory';
|
|
||||||
import { useDialogManager } from './components/DialogSystem/DialogManager';
|
import { useDialogManager } from './components/DialogSystem/DialogManager';
|
||||||
import { DialogWindow } from './components/DialogSystem/DialogWindow';
|
import { DialogWindow } from './components/DialogSystem/DialogWindow';
|
||||||
|
import Inventory from './components/Inventory';
|
||||||
|
import OrgControlPanel from './components/OrgControlPanel';
|
||||||
|
import DoubleTapWrapper from './pages/DoubleTapWrapper';
|
||||||
import WaveformPlayer from './pages/WaveformPlayer';
|
import WaveformPlayer from './pages/WaveformPlayer';
|
||||||
function Game({ avatarUrl, gender }) {
|
function Game({ avatarUrl, gender }) {
|
||||||
|
|
||||||
@@ -1273,7 +1274,6 @@ function Game({ avatarUrl, gender }) {
|
|||||||
headers: { Authorization: `Bearer ${token}` }
|
headers: { Authorization: `Bearer ${token}` }
|
||||||
});
|
});
|
||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
console.log("Попытка не удалась");
|
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
setQuestsProgress(data);
|
setQuestsProgress(data);
|
||||||
} else {
|
} else {
|
||||||
@@ -2998,11 +2998,9 @@ useEffect(() => {
|
|||||||
const isFemale = gender === 'female';
|
const isFemale = gender === 'female';
|
||||||
const animGender = isFemale ? 'feminine' : 'masculine';
|
const animGender = isFemale ? 'feminine' : 'masculine';
|
||||||
|
|
||||||
const idlePath = `/animations/${animGender}/glb/idle/${
|
const idlePath = `/animations/${animGender}/glb/idle/${isFemale ? 'F_Standing_Idle_001.glb' : 'M_Standing_Idle_001.glb'
|
||||||
isFemale ? 'F_Standing_Idle_001.glb' : 'M_Standing_Idle_001.glb'
|
|
||||||
}`;
|
}`;
|
||||||
const walkPath = `/animations/${animGender}/glb/locomotion/${
|
const walkPath = `/animations/${animGender}/glb/locomotion/${isFemale ? 'F_Walk_002.glb' : 'M_Walk_001.glb'
|
||||||
isFemale ? 'F_Walk_002.glb' : 'M_Walk_001.glb'
|
|
||||||
}`;
|
}`;
|
||||||
|
|
||||||
console.log('Загружаем анимации:', { idlePath, walkPath });
|
console.log('Загружаем анимации:', { idlePath, walkPath });
|
||||||
@@ -5612,8 +5610,14 @@ useEffect(() => {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div style={{ padding: 8, display: 'flex', gap: 8, borderTop: '1px solid #eee', background: '#fff' }}>
|
<div style={{ padding: 8, display: 'flex', gap: 8, borderTop: '1px solid #eee', background: '#fff' }}>
|
||||||
<input type="text" value={newMessage} onChange={(e) => setNewMessage(e.target.value)} placeholder="Сообщение" onKeyDown={(e) => { if (e.key === 'Enter') sendMessage(); }} style={{ flex: 1, padding: '10px 12px', borderRadius: 12, border: '1px solid #ddd' }} />
|
<input
|
||||||
<button onClick={sendMessage} style={{ padding: '10px 14px', background: '#0084ff', color: '#fff', border: 'none', borderRadius: 12, cursor: 'pointer' }}>Отправить</button>
|
type="text"
|
||||||
|
value={newMessage}
|
||||||
|
onChange={(e) => setNewMessage(e.target.value)}
|
||||||
|
placeholder="Сообщение"
|
||||||
|
onKeyDown={(e) => { if (e.key === 'Enter') sendMessage(); }}
|
||||||
|
style={{ flex: 1, width: '80%', padding: '8px 8px', borderRadius: 12, border: '1px solid #ddd' }} />
|
||||||
|
<button onClick={sendMessage} style={{ padding: '8px 8px', background: '#0084ff', color: '#fff', border: 'none', borderRadius: 12, cursor: 'pointer' }}>➤</button>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|||||||
Reference in New Issue
Block a user