frontAnswerer/src/widgets/button/OpenQuizButton.tsx
2025-02-24 01:38:33 +03:00

149 lines
4.3 KiB
TypeScript

import { useQuizData } from "@/api/hooks";
import { ButtonWidgetComponentProps } from "@/model/widget/button";
import lightTheme from "@/utils/themes/light";
import { Button, ThemeProvider, useMediaQuery } from "@mui/material";
import { useEffect, useRef, useState } from "react";
import QuizDialog from "../shared/QuizDialog";
import RunningStripe from "../shared/RunningStripe";
import { colorArrayToHex, darkenColor, parseColor } from "../shared/colorUtils";
export default function OpenQuizButton({
quizId,
fixedSide,
autoShowQuizTime = null,
dialogDimensions,
hideOnMobile,
openOnLeaveAttempt,
buttonFlash = false,
withShadow = false,
rounded = false,
buttonText = "Take the quiz",
buttonTextColor,
buttonBackgroundColor,
fullScreen = false,
}: ButtonWidgetComponentProps) {
const isMobile = useMediaQuery("(max-width: 600px)");
const [isQuizShown, setIsQuizShown] = useState<boolean>(false);
const { data: quizData } = useQuizData(quizId);
const [isFlashEnabled, setIsFlashEnabled] = useState<boolean>(buttonFlash);
const preventQuizAutoShowRef = useRef<boolean>(false);
const preventOpenOnLeaveAttemptRef = useRef<boolean>(false);
useEffect(
function setAutoShowQuizTimer() {
if (autoShowQuizTime === null || openOnLeaveAttempt) return;
const timeout = setTimeout(() => {
setIsQuizShown(true);
}, autoShowQuizTime * 1000);
return () => {
clearTimeout(timeout);
};
},
[autoShowQuizTime, openOnLeaveAttempt]
);
useEffect(
function attachLeaveListener() {
if (!openOnLeaveAttempt) return;
const handleMouseLeave = () => {
if (!preventOpenOnLeaveAttemptRef.current) {
preventOpenOnLeaveAttemptRef.current = true;
setIsQuizShown(true);
}
};
document.addEventListener("mouseleave", handleMouseLeave);
return () => {
document.removeEventListener("mouseleave", handleMouseLeave);
};
},
[openOnLeaveAttempt]
);
function openQuiz() {
preventQuizAutoShowRef.current = true;
setIsQuizShown(true);
setIsFlashEnabled(false);
}
if (hideOnMobile && isMobile) return null;
if (!quizData) return null;
const isQuizCompleted = quizData.settings.cfg.antifraud ? quizData.recentlyCompleted : false;
const showButtonFlash = !isQuizCompleted && isFlashEnabled;
let hoverBackgroundColor = buttonBackgroundColor;
if (buttonBackgroundColor) {
const color = parseColor(buttonBackgroundColor);
if (color) hoverBackgroundColor = colorArrayToHex(darkenColor(color, 0.7));
}
return (
<ThemeProvider theme={lightTheme}>
<Button
className="pena-quiz-widget-button"
onClick={openQuiz}
variant="contained"
disableFocusRipple
sx={[
{
overflow: "hidden",
py: "23px",
px: "40px",
fontSize: "20px",
color: buttonTextColor,
backgroundColor: buttonBackgroundColor,
boxShadow: withShadow
? "2px 5px 20px 2px rgba(25, 6, 50, 0.4), 0 2px 10px 0 rgba(35, 17, 58, 0.1)"
: "none",
borderRadius: rounded ? "30px" : 0,
":hover": {
backgroundColor: hoverBackgroundColor,
},
},
Boolean(fixedSide) && {
position: "fixed",
bottom: "50%",
},
fixedSide === "left" && {
left: 0,
transformOrigin: "left",
transform: "rotate(-90deg) translateY(50%) translateX(-50%)",
},
fixedSide === "right" && {
right: 0,
transformOrigin: "right",
transform: "rotate(-90deg) translateY(-50%) translateX(50%)",
},
]}
>
{buttonText}
{showButtonFlash && <RunningStripe />}
</Button>
<QuizDialog
open={isQuizShown}
quizId={quizId}
onClose={() => setIsQuizShown(false)}
paperSx={[
isMobile || fullScreen
? {
width: "100%",
height: "100%",
maxHeight: "100%",
borderRadius: 0,
m: 0,
}
: {
width: dialogDimensions?.width,
height: dialogDimensions?.height,
},
]}
/>
</ThemeProvider>
);
}