front-hub/src/components/FloatingSupportChat/FloatingSupportChat.tsx
Nastya 7c12c70f90
All checks were successful
Deploy / CreateImage (push) Successful in 4m18s
Deploy / DeployService (push) Successful in 21s
shown consultant to last message
2025-05-13 18:25:13 +03:00

197 lines
5.1 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 { useState, useEffect, forwardRef, useMemo } from "react";
import {
Box,
Fab,
Typography,
Badge,
Dialog,
Slide,
useTheme,
useMediaQuery,
} from "@mui/material";
import CircleDoubleDown from "./CircleDoubleDownIcon";
import Chat from "./Chat";
import { useUserStore } from "@root/stores/user";
import { useTicketStore } from "@root/stores/tickets";
import type { ReactNode } from "react";
import type { TransitionProps } from "@mui/material/transitions";
const Transition = forwardRef(function Transition(
props: TransitionProps & {
children: ReactNode;
},
ref: React.Ref<unknown>
) {
return (
<Slide direction="up" ref={ref} {...props}>
{props.children ? (
<Box sx={{ height: "100%" }}>{props.children}</Box>
) : (
<Box />
)}
</Slide>
);
});
export default function FloatingSupportChat() {
const [monitorType, setMonitorType] = useState<"desktop" | "mobile" | "">("");
const [isChatOpened, setIsChatOpened] = useState<boolean>(false);
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down(800));
const user = useUserStore((state) => state.user?._id);
const { messages } = useTicketStore(
(state) => state[user ? "authData" : "unauthData"]
);
const animation = {
"@keyframes runningStripe": {
"0%": {
left: "10%",
backgroundColor: "transparent",
},
"10%": {
backgroundColor: "#ffffff",
},
"50%": {
backgroundColor: "#ffffff",
transform: "translate(400px, 0)",
},
"80%": {
backgroundColor: "#ffffff",
},
"100%": {
backgroundColor: "transparent",
boxShadow: "none",
left: "100%",
},
},
};
const unreadMessagesCount = useMemo(() => {
let count = 0;
// Идём с конца массива к началу
for (let i = messages.length - 1; i >= 0; i--) {
const message = messages[i];
// Пропускаем сообщение с id "111"
if (message.id === "111") continue;
// Если сообщение не прочитано (shown.me !== 1)
if (message.shown.me !== 1) {
count++;
} else {
// Встретили прочитанное сообщение - прекращаем подсчёт
break;
}
}
return count;
}, [messages]); // Зависимость от messages - пересчитывается при их изменении
useEffect(() => {
const onResize = () => {
if (document.fullscreenElement) {
setMonitorType(isMobile ? "mobile" : "desktop");
return;
}
setMonitorType("");
};
window.addEventListener("resize", onResize);
return () => {
window.removeEventListener("resize", onResize);
};
}, [isMobile]);
return (
<Box
sx={{
position: "fixed",
right: "20px",
bottom: "10px",
display: "flex",
flexDirection: "column",
gap: "8px",
width: "clamp(200px, 100% - 40px, 454px)",
zIndex: 10,
}}
>
<Chat
open={isChatOpened && (monitorType === "desktop" || !isMobile)}
sx={{ alignSelf: "start", width: "clamp(200px, 100%, 400px)" }}
/>
<Dialog
fullScreen
open={isChatOpened && (monitorType === "mobile" || isMobile)}
onClose={() => setIsChatOpened(false)}
TransitionComponent={Transition}
>
<Chat
open={isChatOpened && (monitorType === "mobile" || isMobile)}
onclickArrow={() => setIsChatOpened(false)}
/>
</Dialog>
<Fab
disableRipple
sx={{
position: "relative",
backgroundColor: "rgba(255, 255, 255, 0.7)",
pl: "11px",
pr: !isChatOpened ? "15px" : "11px",
gap: "11px",
height: "54px",
borderRadius: "27px",
alignSelf: "end",
overflow: "hidden",
"&:hover": {
background: "rgba(255, 255, 255, 0.7)",
},
}}
variant={"extended"}
onClick={() => setIsChatOpened((prev) => !prev)}
>
{!isChatOpened && (
<Box
sx={{
position: "absolute",
bgcolor: "#FFFFFF",
height: "100px",
width: "25px",
animation: "runningStripe linear 3s infinite",
transform:
" skew(-10deg) rotate(70deg) skewX(20deg) skewY(10deg)",
boxShadow: "0px 3px 12px rgba(126, 42, 234, 0.1)",
opacity: "0.4",
...animation,
}}
/>
)}
<Badge
badgeContent={unreadMessagesCount}
sx={{
"& .MuiBadge-badge": {
display: isChatOpened ? "none" : "flex",
color: "#FFFFFF",
background: theme.palette.purple.main,
},
}}
>
<CircleDoubleDown isUp={isChatOpened} />
</Badge>
{!isChatOpened && (
<Typography sx={{ zIndex: "10000" }}>Задайте нам вопрос</Typography>
)}
</Fab>
</Box>
);
}