Files
stream.graff.tech-new/client/src/components/popups/ChatPopup.tsx
T

183 lines
5.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { useRef, useState, useEffect } from "react";
import SendIcon from "../icons/SendIcon";
import Button from "../ui/Button";
import { useMe } from "../../hooks/useAuth";
import clsx from "clsx";
import PopupWrapper from "../PopupWrapper";
export default function ChatPopup() {
const [messages, setMessages] = useState<MessageItemProps[]>([
{
senderId: "1",
timestamp: "12:22",
content:
"У меня все сломалось, ничего не работает, картинки нет, все пошло по пизде, помогите мне кто-нибудь, пожалуйста",
},
{
senderId: "2",
timestamp: "12:22",
content: "🤡🤡🤡",
},
]);
function onMessageSend(message: string) {
setMessages([
...messages,
{
senderId: "2",
timestamp: "12:22",
content: message,
},
]);
}
return (
<PopupWrapper title="Чат" draggable className="sm:overflow-hidden">
<div className="flex flex-col 2xl:h-[27.778vw] relative 2xl:-m-[1.389vw] -m-5">
<MessageFeed messages={messages} />
<MessageInput onMessageSend={onMessageSend} />
</div>
</PopupWrapper>
);
}
function MessageFeed({ messages }: { messages: MessageItemProps[] }) {
const messagesEndRef = useRef<HTMLDivElement>(null);
// Скролл к концу при получении нового сообщения
useEffect(() => {
messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
}, [messages]);
return (
<div
className="flex flex-col w-full 2xl:h-[calc(100%-4.444vw)] bg-[#F0F0F0] 2xl:p-[1.111vw] p-4 pb-0 overflow-y-auto [-webkit-scrollbar]:hidden"
style={{ scrollbarWidth: "none", msOverflowStyle: "none" }}
>
{messages.length === 0 ? (
<div className="w-full flex flex-col 2xl:gap-[1.667vw] gap-6 items-center justify-center 2xl:px-[2.778vw] px-10 m-auto">
<img
src="/img/popups/EmptyMessageFeed.svg"
className="2xl:size-[8.333vw] size-[120px]"
/>
<span className="text-center text-s">
Здесь пока нет сообщений. <br /> Можно начать беседу с приветствия
</span>
</div>
) : (
<div className="flex flex-col 2xl:gap-[1.111vw] gap-4 items-end mt-auto">
{messages.map((message, index) => (
<MessageItem key={index} {...message} />
))}
<div ref={messagesEndRef} />
</div>
)}
</div>
);
}
interface MessageItemProps {
senderId: string;
timestamp: string;
content: string;
}
function MessageItem({ senderId, timestamp, content }: MessageItemProps) {
const { data: user } = useMe();
const isFromMe = senderId === "1";
return (
<div
className={clsx(
"flex w-full items-end 2xl:gap-[0.556vw] gap-2 justify-end",
isFromMe ? "" : "flex-row-reverse"
)}
>
<div
className={clsx(
"2xl:p-[1.111vw] p-4 2xl:w-[16.667vw] w-[240px] flex items-end justify-between",
isFromMe
? "bg-[#7B60F3] 2xl:rounded-[1.111vw_1.111vw_0_1.111vw] rounded-[16px_16px_0_16px] text-white"
: "bg-[#FFFFFF] 2xl:rounded-[1.111vw_1.111vw_1.111vw_0] rounded-[16px_16px_16px_0] text-[#141414]"
)}
>
<div className="break-words text-s 2xl:space-y-[0.278vw] space-y-1">
{!isFromMe && (
<div className="caption-s text-[#7B60F3]">{user?.fullName}</div>
)}
<div>{content}</div>
</div>
<span className="caption-xs opacity-30">{timestamp}</span>
</div>
<div className="2xl:size-[2.222vw] size-8 rounded-full">
<img
src="/img/popups/MessageUserPfp.png"
className="size-full object-cover"
alt="user"
/>
</div>
</div>
);
}
function MessageInput({
onMessageSend,
}: {
onMessageSend: (message: string) => void;
}) {
const [message, setMessage] = useState("");
const textareaRef = useRef<HTMLTextAreaElement>(null);
useEffect(() => {
const textarea = textareaRef.current;
if (!textarea) return;
textarea.style.height = "auto";
const computedStyle = window.getComputedStyle(textarea);
const lineHeight = parseInt(computedStyle.lineHeight);
const maxHeight = lineHeight * 4;
const newHeight = Math.min(textarea.scrollHeight, maxHeight);
textarea.style.height = `${newHeight}px`;
textarea.style.overflowY =
textarea.scrollHeight > maxHeight ? "auto" : "hidden";
}, [message]);
function handleChange(e: React.ChangeEvent<HTMLTextAreaElement>) {
setMessage(e.target.value);
}
function sendMessage() {
setMessage("");
onMessageSend(message);
}
return (
<div
onClick={() => textareaRef.current?.focus()}
className="flex w-full 2xl:min-h-[4.444vw] min-h-16 2xl:p-[1.111vw] p-4 items-end justify-between absolute bottom-0 left-0 bg-white"
>
<textarea
ref={textareaRef}
value={message}
onChange={handleChange}
className="w-[80%] resize-none focus:outline-none my-auto text-s"
rows={1}
placeholder="Сообщение..."
/>
<Button
size="small"
variant="cta"
disabled={message.length === 0}
onClick={sendMessage}
>
<div className="2xl:size-[1.111vw] size-4">
<SendIcon />
</div>
</Button>
</div>
);
}