fix startpage preview layout types

This commit is contained in:
nflnkr 2023-12-11 19:54:35 +03:00
parent 6482598841
commit e58df2173e
5 changed files with 228 additions and 102 deletions

@ -64,11 +64,11 @@ export default function StartPageSettings() {
const [mobileVersion, setMobileVersion] = useState(false); const [mobileVersion, setMobileVersion] = useState(false);
if (!quiz) return null; // TODO throw and catch with error boundary if (!quiz) return null; // TODO throw and catch with error boundary
const MobileVersionHC = (bool: boolean) => { const MobileVersionHC = (bool: boolean) => {
setMobileVersion(bool); setMobileVersion(bool);
}; };
const designType = quiz?.config?.startpageType; const designType = quiz?.config?.startpageType;
const favIconDropZoneElement = ( const favIconDropZoneElement = (
@ -475,36 +475,37 @@ export default function StartPageSettings() {
> >
Расположение элементов Расположение элементов
</Typography> </Typography>
<Box {designType !== "centered" &&
sx={{ <Box
display: "flex", sx={{
gap: "10px", display: "flex",
}} gap: "10px",
> }}
<SelectableIconButton >
onClick={() => updateQuiz(quiz.id, quiz => { <SelectableIconButton
quiz.config.startpage.position = "left"; onClick={() => updateQuiz(quiz.id, quiz => {
})} quiz.config.startpage.position = "left";
isActive={quiz.config.startpage.position === "left"} })}
Icon={AlignLeftIcon} isActive={quiz.config.startpage.position === "left"}
/> Icon={AlignLeftIcon}
<SelectableIconButton />
onClick={() => updateQuiz(quiz.id, quiz => { <SelectableIconButton
quiz.config.startpage.position = "center"; onClick={() => updateQuiz(quiz.id, quiz => {
})} quiz.config.startpage.position = "center";
isActive={quiz.config.startpage.position === "center"} })}
Icon={AlignCenterIcon} isActive={quiz.config.startpage.position === "center"}
sx={{ display: designType === "centered" ? "flex" : "none" }} Icon={AlignCenterIcon}
/> sx={{ display: designType === "standard" ? "none" : "flex" }}
<SelectableIconButton />
onClick={() => updateQuiz(quiz.id, quiz => { <SelectableIconButton
quiz.config.startpage.position = "right"; onClick={() => updateQuiz(quiz.id, quiz => {
})} quiz.config.startpage.position = "right";
isActive={quiz.config.startpage.position === "right"} })}
Icon={AlignRightIcon} isActive={quiz.config.startpage.position === "right"}
/> Icon={AlignRightIcon}
</Box> />
</Box>
}
{(isTablet || !isSmallMonitor) && ( {(isTablet || !isSmallMonitor) && (
<> <>
<Box <Box

@ -1,6 +1,8 @@
import { import {
Box, Box,
Button, Button,
ButtonBase,
Link,
Paper, Paper,
Typography, Typography,
useMediaQuery, useMediaQuery,
@ -8,51 +10,53 @@ import {
} from "@mui/material"; } from "@mui/material";
import { useCurrentQuiz } from "@root/quizes/hooks"; import { useCurrentQuiz } from "@root/quizes/hooks";
import YoutubeEmbedIframe from "./YoutubeEmbedIframe"; import YoutubeEmbedIframe from "./YoutubeEmbedIframe";
import { QuizStartpageAlignType, QuizStartpageType } from "@model/quizSettings";
import { notReachable } from "../../utils/notReachable";
import { useUADevice } from "../../utils/hooks/useUADevice";
export default function QuizPreviewLayout() { export default function QuizPreviewLayout() {
const theme = useTheme(); const theme = useTheme();
const quiz = useCurrentQuiz(); const quiz = useCurrentQuiz();
const isTablet = useMediaQuery(theme.breakpoints.down(630)); const { isMobileDevice } = useUADevice();
if (!quiz) return null; if (!quiz) return null;
const isMediaFileExist = const handleCopyNumber = () => {
(quiz.config.startpage.background.type === "image" && navigator.clipboard.writeText(quiz.config.info.phonenumber);
quiz.config.startpage.background.desktop) || };
(quiz.config.startpage.background.type === "video" &&
quiz.config.startpage.background.video); const background = quiz.config.startpage.background.type === "image"
? quiz.config.startpage.background.desktop
? (
<img
src={quiz.config.startpage.background.desktop}
alt=""
style={{
width: "100%",
height: "100%",
objectFit: "cover",
}}
/>
)
: null
: quiz.config.startpage.background.type === "video"
? quiz.config.startpage.background.video
? (
<YoutubeEmbedIframe videoUrl={quiz.config.startpage.background.video} />
)
: null
: null;
return ( return (
<Paper className="quiz-preview-draghandle" sx={{ height: "100%" }}> <Paper className="quiz-preview-draghandle" sx={{ height: "100%" }}>
<Box <QuizPreviewLayoutByType
sx={{ quizHeaderBlock={<>
display: "flex", <Box sx={{
flexDirection:
quiz.config.startpage.position === "left"
? "row"
: "row-reverse",
flexGrow: 1,
height: "100%",
"&::-webkit-scrollbar": { width: 0 },
}}
>
<Box
sx={{
width: isMediaFileExist && !isTablet ? "40%" : "100%",
padding: "16px",
display: "flex", display: "flex",
flexDirection: "column", alignItems: "center",
alignItems: isMediaFileExist && !isTablet ? "flex-start" : "center", gap: "20px",
}} }}>
>
<Box
sx={{
display: "flex",
alignItems: "center",
gap: "20px",
}}
>
{quiz.config.startpage.logo && ( {quiz.config.startpage.logo && (
<img <img
src={quiz.config.startpage.logo} src={quiz.config.startpage.logo}
@ -68,15 +72,17 @@ export default function QuizPreviewLayout() {
{quiz.config.info.orgname} {quiz.config.info.orgname}
</Typography> </Typography>
</Box> </Box>
<Box </>}
sx={{ quizMainBlock={<>
flexGrow: 1, <Box sx={{
display: "flex", display: "flex",
gap: "10px", gap: "10px",
flexDirection: "column", flexDirection: "column",
justifyContent: "center", justifyContent: "center",
}} alignItems: (quiz.config.startpageType === "expanded" && quiz.config.startpage.position === "center")
> ? "center"
: "start",
}}>
<Typography sx={{ fontWeight: "bold" }}>{quiz.name}</Typography> <Typography sx={{ fontWeight: "bold" }}>{quiz.name}</Typography>
<Typography sx={{ fontSize: "12px" }}> <Typography sx={{ fontSize: "12px" }}>
{quiz.config.startpage.description} {quiz.config.startpage.description}
@ -89,42 +95,146 @@ export default function QuizPreviewLayout() {
padding: "10px 15px", padding: "10px 15px",
}} }}
> >
{quiz.config.startpage.button ? quiz.config.startpage.button : "Пройти тест"} {quiz.config.startpage.button.trim() ? quiz.config.startpage.button : "Пройти тест"}
</Button> </Button>
</Box> </Box>
</Box> </Box>
<Box> <Box>
<Typography {quiz.config.info.clickable ? (
sx={{ fontSize: "16px", color: theme.palette.brightPurple.main }} isMobileDevice ? (
> <Link href={`tel:${quiz.config.info.phonenumber}`}>
{quiz.config.info.phonenumber} <Typography sx={{ fontSize: "16px", color: theme.palette.brightPurple.main }}>
</Typography> {quiz.config.info.phonenumber}
</Typography>
</Link>
) : (
<ButtonBase onClick={handleCopyNumber}>
<Typography sx={{ fontSize: "16px", color: theme.palette.brightPurple.main }}>
{quiz.config.info.phonenumber}
</Typography>
</ButtonBase>
)
) : (
<Typography sx={{ fontSize: "16px", color: theme.palette.brightPurple.main }}>
{quiz.config.info.phonenumber}
</Typography>
)}
<Typography sx={{ fontSize: "12px" }}> <Typography sx={{ fontSize: "12px" }}>
{quiz.config.info.law} {quiz.config.info.law}
</Typography> </Typography>
</Box> </Box>
</Box> </>}
{!isTablet && isMediaFileExist && ( backgroundBlock={background}
<Box sx={{ width: "60%" }}> startpageType={quiz.config.startpageType}
{quiz.config.startpage.background.type === "image" && alignType={quiz.config.startpage.position}
quiz.config.startpage.background.desktop && ( />
<img
src={quiz.config.startpage.background.desktop}
alt=""
style={{
width: "100%",
height: "100%",
objectFit: "cover",
}}
/>
)}
{quiz.config.startpage.background.type === "video" &&
quiz.config.startpage.background.video && (
<YoutubeEmbedIframe videoUrl={quiz.config.startpage.background.video} />
)}
</Box>
)}
</Box>
</Paper> </Paper>
); );
} }
function QuizPreviewLayoutByType({ quizHeaderBlock, quizMainBlock, backgroundBlock, startpageType, alignType }: {
quizHeaderBlock: JSX.Element;
quizMainBlock: JSX.Element;
backgroundBlock: JSX.Element | null;
startpageType: QuizStartpageType;
alignType: QuizStartpageAlignType;
}) {
const theme = useTheme();
const isTablet = useMediaQuery(theme.breakpoints.down(630));
switch (startpageType) {
case null:
case "standard": {
return (
<Box sx={{
display: "flex",
flexDirection: alignType === "left" ? "row" : "row-reverse",
flexGrow: 1,
height: "100%",
"&::-webkit-scrollbar": { width: 0 },
}}>
<Box sx={{
width: !isTablet ? "40%" : "100%",
padding: "16px",
display: "flex",
flexDirection: "column",
justifyContent: "space-between",
alignItems: !isTablet ? "flex-start" : "center",
}}>
{quizHeaderBlock}
{quizMainBlock}
</Box>
<Box sx={{
width: "60%",
}}>
{backgroundBlock}
</Box>
</Box>
);
}
case "expanded": {
return (
<Box sx={{
position: "relative",
display: "flex",
justifyContent: startpageAlignTypeToJustifyContent[alignType],
flexGrow: 1,
height: "100%",
"&::-webkit-scrollbar": { width: 0 },
}}>
<Box sx={{
width: "40%",
position: "relative",
padding: "16px",
zIndex: 2,
display: "flex",
flexDirection: "column",
justifyContent: "space-between",
alignItems: alignType === "center" ? "center" : "start",
}}>
{quizHeaderBlock}
{quizMainBlock}
</Box>
<Box sx={{
position: "absolute",
left: 0,
top: 0,
height: "100%",
width: "100%",
zIndex: 1,
}}>
{backgroundBlock}
</Box>
</Box>
);
}
case "centered": {
return (
<Box sx={{
padding: "16px",
display: "flex",
flexDirection: "column",
justifyContent: "space-between",
alignItems: "center",
height: "100%",
"&::-webkit-scrollbar": { width: 0 },
}}>
{quizHeaderBlock}
{backgroundBlock &&
<Box>
{backgroundBlock}
</Box>
}
{quizMainBlock}
</Box>
);
}
default: notReachable(startpageType);
}
}
const startpageAlignTypeToJustifyContent: Record<QuizStartpageAlignType, "start" | "center" | "end"> = {
left: "start",
center: "center",
right: "end",
};

@ -17,6 +17,7 @@ export default function YoutubeEmbedIframe({ videoUrl }: Props) {
<Box sx={{ <Box sx={{
width: "100%", width: "100%",
height: "100%", height: "100%",
pointerEvents: "none",
"& iframe": { "& iframe": {
width: "100%", width: "100%",
height: "100%", height: "100%",

@ -107,6 +107,7 @@ export const StartPagePreview = () => {
topLeft: { topLeft: {
top: "-1px", top: "-1px",
left: "-1px", left: "-1px",
zIndex: 100,
}, },
}} }}
style={{ style={{

@ -0,0 +1,13 @@
import { useEffect, useState } from "react";
export function useUADevice(): { isMobileDevice: boolean; } {
const [isMobileDevice, setIsMobileDevice] = useState<boolean>(false);
useEffect(() => {
const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
setIsMobileDevice(isMobile);
}, [navigator.userAgent]);
return { isMobileDevice };
}