149 lines
4.3 KiB
TypeScript
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>
|
|
);
|
|
}
|