added new start page

This commit is contained in:
SlimusMinus
2026-07-06 23:59:48 +03:00
parent 538a7f65eb
commit abdb7c021c
17 changed files with 705 additions and 24 deletions

148
src/pages/ChatPage.jsx Normal file
View File

@@ -0,0 +1,148 @@
import { useState, useEffect, useCallback, useRef } from "react";
import { useParams, useNavigate } from "react-router-dom";
import { useChats } from "../hooks/useChats";
import { useChatSocket } from "../hooks/useChatSocket";
import { getPostForChat } from "../stores/chatPostStore";
import { setActiveChatId } from "../stores/activeChatStore";
import { useUnread } from "../context/UnreadContext";
import { API_URL } from "../config/authConstants";
import Picker from "@emoji-mart/react";
import emojiData from "@emoji-mart/data";
export default function ChatPage() {
const { chatId } = useParams();
const navigate = useNavigate();
const { fetchMessages, markAsRead } = useChats();
const { clearChatUnread } = useUnread();
const [messages, setMessages] = useState([]);
const [input, setInput] = useState("");
const [showEmoji, setShowEmoji] = useState(false);
const messagesEndRef = useRef(null);
const emojiPickerRef = useRef(null);
useEffect(() => {
const handleClick = (e) => {
if (emojiPickerRef.current && !emojiPickerRef.current.contains(e.target)) {
setShowEmoji(false);
}
};
document.addEventListener("mousedown", handleClick);
return () => document.removeEventListener("mousedown", handleClick);
}, []);
const myUserId = (() => {
try { return JSON.parse(localStorage.getItem("user"))?.id; }
catch { return null; }
})();
const handleIncoming = useCallback((msg) => {
setMessages((prev) => [...prev, msg]);
}, []);
const { sendMessage, connected } = useChatSocket(chatId, handleIncoming);
useEffect(() => {
if (chatId) {
setActiveChatId(chatId);
fetchMessages(chatId).then(setMessages);
markAsRead(chatId);
clearChatUnread(chatId);
}
return () => setActiveChatId(null);
}, [chatId, fetchMessages, markAsRead, clearChatUnread]);
useEffect(() => {
messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
}, [messages]);
const handleSend = (e) => {
e.preventDefault();
if (!input.trim()) return;
sendMessage(input);
setInput("");
};
const handleEmojiSelect = (emoji) => {
setInput((prev) => prev + emoji.native);
};
const post = getPostForChat(chatId);
const postImg = post?.images?.[0] ? `${API_URL}${post.images[0]}` : null;
return (
<div className="f-app">
<div className="chat-page">
<div className="chat-header">
<button className="chat-back-btn" onClick={() => navigate("/chats")}>
←
</button>
<div className="chat-header-avatar">
{postImg ? (
<img src={postImg} alt="" className="chat-header-avatar-img" />
) : (
post?.emoji || "📋"
)}
</div>
<div className="chat-header-title">{post?.title || "Чат"}</div>
<div className={`chat-status${connected ? " connected" : ""}`}>
{connected ? "В сети" : "Отключено"}
</div>
</div>
<div className="chat-messages">
{messages.length === 0 && (
<div className="chat-empty">Нет сообщений</div>
)}
{messages.map((m) => (
<div
key={m.id}
className={`chat-bubble${m.senderId === myUserId ? " mine" : ""}`}
>
{m.content}
</div>
))}
<div ref={messagesEndRef} />
</div>
<div className="chat-input-area">
{showEmoji && (
<div className="chat-emoji-picker" ref={emojiPickerRef}>
<Picker
data={emojiData}
onEmojiSelect={handleEmojiSelect}
theme="dark"
previewPosition="none"
skinTonePosition="none"
searchPosition="sticky"
maxSearchResults={30}
perLine={8}
/>
</div>
)}
<form onSubmit={handleSend} className="chat-input-row">
<input
value={input}
onChange={(e) => setInput(e.target.value)}
placeholder="Сообщение..."
className="chat-input"
/>
<button
type="button"
className={`chat-emoji-btn${showEmoji ? " active" : ""}`}
onClick={() => setShowEmoji((v) => !v)}
>
😊
</button>
<button
type="submit"
className="chat-send-btn"
disabled={!connected}
>
➤
</button>
</form>
</div>
</div>
</div>
);
}