front-hub/src/components/FloatingSupportChat/FloatingSupportChat.tsx

175 lines
4.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 { useState, useEffect, forwardRef } 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%",
},
},
};
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={messages.filter(({ shown }) => shown.me !== 1).length}
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>
);
}