Chat popup
This commit is contained in:
@@ -0,0 +1,188 @@
|
||||
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";
|
||||
|
||||
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: "1",
|
||||
timestamp: "12:22",
|
||||
content: message,
|
||||
},
|
||||
]);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex flex-col w-full h-full relative">
|
||||
<MessageFeed messages={messages} />
|
||||
<MessageInput onMessageSend={onMessageSend} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
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 h-[calc(100%-4.444vw)] bg-[#F0F0F0] p-[1.111vw] pb-[0] overflow-y-auto"
|
||||
style={{ scrollbarWidth: "none", msOverflowStyle: "none" }}
|
||||
>
|
||||
<style>
|
||||
{`
|
||||
.flex::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
`}
|
||||
</style>
|
||||
{messages.length === 0 ? (
|
||||
<div className="w-full flex flex-col gap-[1.667vw] items-center justify-center px-[2.778vw] m-auto">
|
||||
<img
|
||||
src="/img/popups/EmptyMessageFeed.svg"
|
||||
className="size-[8.333vw]"
|
||||
/>
|
||||
<span className="text-center text-s">
|
||||
Здесь пока нет сообщений. <br /> Можно начать беседу с приветствия
|
||||
</span>
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex flex-col gap-[1.111vw] 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 gap-[0.556vw] justify-end",
|
||||
isFromMe ? "" : "flex-row-reverse"
|
||||
)}
|
||||
>
|
||||
<div
|
||||
className={clsx(
|
||||
"p-[1.111vw] w-[16.667vw] flex items-end justify-between",
|
||||
isFromMe
|
||||
? "bg-[#7B60F3] rounded-[1.111vw_1.111vw_0_1.111vw] text-white"
|
||||
: "bg-[#FFFFFF] rounded-[1.111vw_1.111vw_1.111vw_0] c text-[#141414]"
|
||||
)}
|
||||
>
|
||||
<div className="break-words text-s w-[12.917vw]">
|
||||
{!isFromMe && (
|
||||
<div className="caption-s text-[#7B60F3] mb-[0.278vw]">
|
||||
{user?.fullName}
|
||||
</div>
|
||||
)}
|
||||
<div>{content}</div>
|
||||
</div>
|
||||
<span className="caption-xs opacity-30">{timestamp}</span>
|
||||
</div>
|
||||
|
||||
<div className="size-[2.222vw 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 min-h-[4.444vw] p-[1.111vw] 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}
|
||||
className="size-[2.222vw]"
|
||||
onClick={sendMessage}
|
||||
>
|
||||
<div className="size-full">
|
||||
<SendIcon />
|
||||
</div>
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
+1
-1
@@ -2,7 +2,7 @@ import Button from "../ui/Button";
|
||||
import LinkShare from "../ui/LinkShare";
|
||||
import ShareFilledIcon from "../icons/ShareFilledIcon";
|
||||
|
||||
export default function ShareModal() {
|
||||
export default function SharePopup() {
|
||||
return (
|
||||
<>
|
||||
<div className="mb-[1.389vw]">
|
||||
@@ -1,4 +1,4 @@
|
||||
import ShareModal from "../components/modals/ShareModal";
|
||||
import ChatPopup from "../components/popups/ChatPopup";
|
||||
import Button from "../components/ui/Button";
|
||||
import { useMe, useLogout } from "../hooks/useAuth";
|
||||
import { useNavigate } from "react-router";
|
||||
@@ -19,12 +19,6 @@ function HomePage() {
|
||||
<div className="p-8 bg-white rounded-lg shadow-md">
|
||||
<h1 className="mb-6 text-3xl font-bold">Главная страница</h1>
|
||||
|
||||
{/* Потестить модалки */}
|
||||
|
||||
{/* <div className="w-[21.667vw] outline-1 outline">
|
||||
<ShareModal />
|
||||
</div> */}
|
||||
|
||||
<div className="space-y-4">
|
||||
<div className="p-4 bg-blue-50 rounded-lg border border-blue-200">
|
||||
<h2 className="mb-2 text-xl font-semibold">
|
||||
|
||||
Reference in New Issue
Block a user