add side widget installation setup

minor fixes
This commit is contained in:
nflnkr 2024-05-27 12:23:28 +03:00
parent 313e4626d3
commit d503d83fce
10 changed files with 420 additions and 21 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 135 KiB

@ -13,6 +13,7 @@ import BannerWidgetSetup from "./WidgetSetupByType/BannerWidgetSetup";
import ButtonWidgetSetup from "./WidgetSetupByType/ButtonWidgetSetup"; import ButtonWidgetSetup from "./WidgetSetupByType/ButtonWidgetSetup";
import ContainerWidgetSetup from "./WidgetSetupByType/ContainerWidgetSetup"; import ContainerWidgetSetup from "./WidgetSetupByType/ContainerWidgetSetup";
import PopupWidgetSetup from "./WidgetSetupByType/PopupWidgetSetup"; import PopupWidgetSetup from "./WidgetSetupByType/PopupWidgetSetup";
import SideWidgetSetup from "./WidgetSetupByType/SideWidgetSetup/SideWidgetSetup";
import WidgetTypeButton from "./WidgetTypeButton"; import WidgetTypeButton from "./WidgetTypeButton";
import BannerWidgetPreview from "./previewIcons/BannerWidgetPreview"; import BannerWidgetPreview from "./previewIcons/BannerWidgetPreview";
import ButtonWidgetPreview from "./previewIcons/ButtonWidgetPreview"; import ButtonWidgetPreview from "./previewIcons/ButtonWidgetPreview";
@ -209,6 +210,12 @@ export default function QuizInstallationCard() {
nextButton={nextButton} nextButton={nextButton}
/> />
)} )}
{widgetSetupSettings.widgetType === "side" && (
<SideWidgetSetup
step={widgetSetupSettings.step}
nextButton={nextButton}
/>
)}
</> </>
)} )}
</Box> </Box>

@ -14,9 +14,10 @@ const TextField = MuiTextField as unknown as FC<TextFieldProps>;
interface Props { interface Props {
scriptText: string; scriptText: string;
helperText: string;
} }
export default function WidgetScript({ scriptText }: Props) { export default function WidgetScript({ scriptText, helperText }: Props) {
const theme = useTheme(); const theme = useTheme();
return ( return (
@ -25,9 +26,7 @@ export default function WidgetScript({ scriptText }: Props) {
p: "20px", p: "20px",
}} }}
> >
<Typography color="#9A9AAF"> <Typography color="#9A9AAF">{helperText}</Typography>
Установите код в место, в котором должен быть квиз
</Typography>
<TextField <TextField
multiline multiline
value={scriptText} value={scriptText}

@ -1,4 +1,6 @@
import { BannerWidgetParams } from "@frontend/squzanswerer"; import { BannerWidgetParams } from "@frontend/squzanswerer";
import BannerWidgetPreviewIcon from "@icons/BannerWidgetPreviewIcon";
import CloseIcon from "@mui/icons-material/Close";
import { import {
Box, Box,
Button, Button,
@ -18,13 +20,11 @@ import CustomCheckbox from "@ui_kit/CustomCheckbox";
import PenaTextField from "@ui_kit/PenaTextField"; import PenaTextField from "@ui_kit/PenaTextField";
import RadioCheck from "@ui_kit/RadioCheck"; import RadioCheck from "@ui_kit/RadioCheck";
import RadioIcon from "@ui_kit/RadioIcon"; import RadioIcon from "@ui_kit/RadioIcon";
import RunningStripe from "@ui_kit/RunningStripe";
import { ReactNode, useState } from "react"; import { ReactNode, useState } from "react";
import fixedButtonWidgetPreview from "../../../../assets/banner-widget-preview.png"; import fixedButtonWidgetPreview from "../../../../assets/banner-widget-preview.png";
import WidgetScript from "../WidgetScript"; import WidgetScript from "../WidgetScript";
import { createBannerWidgetScriptText } from "../createWidgetScriptText"; import { createBannerWidgetScriptText } from "../createWidgetScriptText";
import BannerWidgetPreviewIcon from "@icons/BannerWidgetPreviewIcon";
import CloseIcon from "@mui/icons-material/Close";
import RunningStripe from "@ui_kit/RunningStripe";
interface Props { interface Props {
step: 2 | 3; step: 2 | 3;
@ -79,7 +79,12 @@ export default function BannerWidgetSetup({ step, nextButton }: Props) {
pulsation: pulsation || undefined, pulsation: pulsation || undefined,
}); });
return <WidgetScript scriptText={scriptText} />; return (
<WidgetScript
scriptText={scriptText}
helperText="Установите код внутрь тэга head"
/>
);
} }
return ( return (
@ -161,7 +166,7 @@ export default function BannerWidgetSetup({ step, nextButton }: Props) {
backgroundColor: theme.palette.brightPurple.main, backgroundColor: theme.palette.brightPurple.main,
containerType: "size", containerType: "size",
gap: "calc(5 / 196 * 100%)", gap: "calc(5 / 196 * 100%)",
borderRadius: rounded ? "30px" : 0, borderRadius: rounded && !bannerFullWidth ? "30px" : 0,
boxShadow: withShadow boxShadow: withShadow
? "3px 6px 25px 3px rgba(25, 6, 50, 0.4), 0 3px 13px 0 rgba(35, 17, 58, 0.1)" ? "3px 6px 25px 3px rgba(25, 6, 50, 0.4), 0 3px 13px 0 rgba(35, 17, 58, 0.1)"
: "none", : "none",

@ -21,13 +21,13 @@ import CustomCheckbox from "@ui_kit/CustomCheckbox";
import PenaTextField from "@ui_kit/PenaTextField"; import PenaTextField from "@ui_kit/PenaTextField";
import RadioCheck from "@ui_kit/RadioCheck"; import RadioCheck from "@ui_kit/RadioCheck";
import RadioIcon from "@ui_kit/RadioIcon"; import RadioIcon from "@ui_kit/RadioIcon";
import RunningStripe from "@ui_kit/RunningStripe";
import { nanoid } from "nanoid"; import { nanoid } from "nanoid";
import { ReactNode, useState } from "react"; import { ReactNode, useState } from "react";
import Dots from "../../../../assets/dots.png"; import Dots from "../../../../assets/dots.png";
import fixedButtonWidgetPreview from "../../../../assets/fixed-button-widget-preview.png"; import fixedButtonWidgetPreview from "../../../../assets/fixed-button-widget-preview.png";
import WidgetScript from "../WidgetScript"; import WidgetScript from "../WidgetScript";
import { createButtonWidgetScriptText } from "../createWidgetScriptText"; import { createButtonWidgetScriptText } from "../createWidgetScriptText";
import RunningStripe from "@ui_kit/RunningStripe";
interface Props { interface Props {
step: 2 | 3; step: 2 | 3;
@ -96,7 +96,16 @@ export default function ButtonWidgetSetup({ step, nextButton }: Props) {
const scriptText = createButtonWidgetScriptText(params); const scriptText = createButtonWidgetScriptText(params);
return <WidgetScript scriptText={scriptText} />; return (
<WidgetScript
scriptText={scriptText}
helperText={
fixedSide === null
? "Установите код в место, в котором должна быть кнопка"
: "Установите код внутрь тэга head"
}
/>
);
} }
return ( return (

@ -69,7 +69,12 @@ export default function ContainerWidgetSetup({ step, nextButton }: Props) {
openOnLeaveAttempt: openOnLeaveAttempt || undefined, openOnLeaveAttempt: openOnLeaveAttempt || undefined,
}); });
return <WidgetScript scriptText={scriptText} />; return (
<WidgetScript
scriptText={scriptText}
helperText="Установите код в место, в котором должен быть квиз"
/>
);
} }
return ( return (

@ -1,11 +1,4 @@
import { import { Box, Typography, useMediaQuery, useTheme } from "@mui/material";
Box,
Collapse,
Divider,
Typography,
useMediaQuery,
useTheme,
} from "@mui/material";
import { useCurrentQuiz } from "@root/quizes/hooks"; import { useCurrentQuiz } from "@root/quizes/hooks";
import CustomCheckbox from "@ui_kit/CustomCheckbox"; import CustomCheckbox from "@ui_kit/CustomCheckbox";
import PenaTextField from "@ui_kit/PenaTextField"; import PenaTextField from "@ui_kit/PenaTextField";
@ -46,7 +39,12 @@ export default function PopupWidgetSetup({ step, nextButton }: Props) {
: undefined, : undefined,
}); });
return <WidgetScript scriptText={scriptText} />; return (
<WidgetScript
scriptText={scriptText}
helperText="Установите код внутрь тэга head"
/>
);
} }
return ( return (

@ -0,0 +1,61 @@
import { Button } from "@mui/material";
interface Props {
isSelected: boolean;
position: "left" | "right";
onClick: () => void;
}
export default function SideWidgetPositionButton({
isSelected,
position,
onClick,
}: Props) {
return (
<Button
onClick={onClick}
sx={{
aspectRatio: "204 / 134",
width: "100%",
height: "auto",
borderRadius: "6px",
display: "flex",
alignItems: "center",
justifyContent: "center",
flexShrink: 0,
color: isSelected ? "#7E2AEA" : "#9A9AAF",
p: 0,
}}
>
<svg viewBox="0 0 204 134" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect
x="1.25"
y="1.25"
width="201.5"
height="131.5"
rx="6.75"
stroke="currentColor"
strokeWidth="1.5"
/>
<rect
x={position === "left" ? "7.5" : "147.5"}
y="62.5"
width="49"
height="64"
rx="3.5"
fill="currentColor"
stroke="currentColor"
/>
<path
d="M202 14.75H202.75V14V8C202.75 4.27208 199.728 1.25 196 1.25H8C4.27208 1.25 1.25 4.27208 1.25 8V14V14.75H2H202Z"
fill="#F2F3F7"
stroke="currentColor"
strokeWidth="1.5"
/>
<circle cx="169.5" cy="8" r="2.5" fill="currentColor" />
<circle cx="177.5" cy="8" r="2.5" fill="currentColor" />
<circle cx="185.5" cy="8" r="2.5" fill="currentColor" />
</svg>
</Button>
);
}

@ -0,0 +1,315 @@
import { SideWidgetParams } from "@frontend/squzanswerer";
import {
Box,
Collapse,
Typography,
useMediaQuery,
useTheme,
} from "@mui/material";
import { useCurrentQuiz } from "@root/quizes/hooks";
import CircleColorPicker from "@ui_kit/CircleColorPicker";
import CustomCheckbox from "@ui_kit/CustomCheckbox";
import PenaTextField from "@ui_kit/PenaTextField";
import { ReactNode, useState } from "react";
import sideWidgetPreviewLeft from "../../../../../assets/side-widget-preview-left.png";
import sideWidgetPreviewRight from "../../../../../assets/side-widget-preview-right.png";
import WidgetScript from "../../WidgetScript";
import { createSideWidgetScriptText } from "../../createWidgetScriptText";
import SideWidgetPositionButton from "./SideWidgetPositionButton";
interface Props {
step: 2 | 3;
nextButton: ReactNode;
}
export default function SideWidgetSetup({ step, nextButton }: Props) {
const theme = useTheme();
const isSmallMonitor = useMediaQuery(theme.breakpoints.down(1065));
const quiz = useCurrentQuiz();
const [widgetWidth, setWidgetWidth] = useState<string>("");
const [widgetHeight, setWidgetHeight] = useState<string>("");
const [hideOnMobile, setHideOnMobile] = useState<boolean>(false);
const [autoShowQuiz, setAutoShowQuiz] = useState<boolean>(false);
const [autoShowQuizTime, setAutoShowQuizTime] = useState<number>(10);
const [autoShowWidgetTime, setAutoShowWidgetTime] = useState<number>(10);
const [position, setPosition] =
useState<SideWidgetParams["position"]>("left");
const [fullScreen, setFullScreen] = useState<boolean>(false);
const [buttonFlash, setButtonFlash] = useState<boolean>(false);
const [buttonBackgroundColor, setButtonBackgroundColor] = useState<string>(
theme.palette.brightPurple.main,
);
const [buttonTextColor, setButtonTextColor] = useState<string>("#FFFFFF");
if (!quiz) return null;
if (step === 3) {
const scriptText = createSideWidgetScriptText({
quizId: quiz.qid,
position: position,
hideOnMobile: hideOnMobile || undefined,
autoShowQuizTime: autoShowQuiz ? autoShowQuizTime : undefined,
autoShowWidgetTime: autoShowWidgetTime || undefined,
fullScreen: fullScreen || undefined,
buttonFlash: buttonFlash || undefined,
buttonTextColor,
buttonBackgroundColor,
dialogDimensions:
!fullScreen && (widgetWidth || widgetHeight)
? {
width: widgetWidth ? `${widgetWidth}px` : "100%",
height: widgetHeight ? `${widgetHeight}px` : "100%",
}
: undefined,
});
return (
<WidgetScript
scriptText={scriptText}
helperText="Установите код внутрь тэга head"
/>
);
}
return (
<Box
sx={{
display: "flex",
flexDirection: isSmallMonitor ? "column" : "row",
gap: "40px",
p: "20px",
}}
>
<Box
sx={{
flex: "1 1 0",
}}
>
<Box
sx={{
p: "20px",
pt: "40px",
}}
>
<img
src={
position === "left"
? sideWidgetPreviewLeft
: sideWidgetPreviewRight
}
style={{
display: "block",
width: "100%",
height: "100%",
}}
/>
</Box>
</Box>
<Box
sx={{
display: "flex",
flexDirection: "column",
gap: "15px",
flex: "1 1 0",
}}
>
<Typography color={theme.palette.grey2.main}>Расположение</Typography>
<Box
sx={{
display: "flex",
gap: "40px",
}}
>
<Box
sx={{
display: "flex",
flexDirection: "column",
gap: "14px",
flex: "1 0 0",
}}
>
<SideWidgetPositionButton
isSelected={position === "left"}
position="left"
onClick={() => setPosition("left")}
/>
<Typography color={theme.palette.grey2.main}>
Слева снизу
</Typography>
</Box>
<Box
sx={{
display: "flex",
flexDirection: "column",
gap: "14px",
flex: "1 0 0",
}}
>
<SideWidgetPositionButton
isSelected={position === "right"}
position="right"
onClick={() => setPosition("right")}
/>
<Typography color={theme.palette.grey2.main}>
Справа снизу
</Typography>
</Box>
</Box>
<CustomCheckbox
label="Квиз на весь экран"
checked={fullScreen}
handleChange={(e) => setFullScreen(e.target.checked)}
/>
<Collapse in={!fullScreen}>
<Box
sx={{
display: "flex",
gap: "40px",
}}
>
<Box
sx={{
display: "flex",
flexDirection: "column",
gap: "20px",
}}
>
<Typography sx={{ color: theme.palette.grey2.main }}>
Ширина окна (px)
</Typography>
<PenaTextField
type="number"
value={widgetWidth}
onChange={(e) => setWidgetWidth(e.target.value)}
FormControlSx={{ maxWidth: "160px" }}
placeholder="auto"
/>
</Box>
<Box
sx={{
display: "flex",
flexDirection: "column",
gap: "20px",
}}
>
<Typography sx={{ color: theme.palette.grey2.main }}>
Высота окна (px)
</Typography>
<PenaTextField
type="number"
value={widgetHeight}
onChange={(e) => setWidgetHeight(e.target.value)}
FormControlSx={{ maxWidth: "160px" }}
placeholder="auto"
/>
</Box>
</Box>
</Collapse>
<Box
sx={{
display: "flex",
gap: "40px",
alignItems: "center",
}}
>
<Typography sx={{ color: theme.palette.grey2.main }}>
Цвет кнопки
</Typography>
<CircleColorPicker
color={buttonBackgroundColor}
onChange={(color) => setButtonBackgroundColor(color)}
/>
<Typography sx={{ color: theme.palette.grey2.main }}>
Цвет текста кнопки
</Typography>
<CircleColorPicker
color={buttonTextColor}
onChange={(color) => setButtonTextColor(color)}
/>
</Box>
<Box
sx={{
display: "flex",
gap: "10px",
alignItems: "center",
}}
>
<Typography sx={{ color: theme.palette.grey2.main }}>
Показывать кнопку через
</Typography>
<PenaTextField
type="number"
value={autoShowWidgetTime}
onChange={(e) => setAutoShowWidgetTime(parseInt(e.target.value))}
FormControlSx={{
width: "90px",
}}
/>
<Typography sx={{ color: theme.palette.grey2.main }}>
секунд
</Typography>
</Box>
<CustomCheckbox
label="С бликом"
checked={buttonFlash}
handleChange={(e) => setButtonFlash(e.target.checked)}
/>
<Box>
<CustomCheckbox
label="Автооткрытие виджета при входе на сайт"
checked={autoShowQuiz}
handleChange={(e) => setAutoShowQuiz(e.target.checked)}
/>
<Collapse in={autoShowQuiz}>
<Box
sx={{
display: "flex",
gap: "10px",
alignItems: "center",
mt: "14px",
}}
>
<Typography sx={{ color: theme.palette.grey2.main }}>
Показывать через
</Typography>
<PenaTextField
type="number"
value={autoShowQuizTime}
onChange={(e) => setAutoShowQuizTime(parseInt(e.target.value))}
FormControlSx={{
width: "90px",
}}
/>
<Typography sx={{ color: theme.palette.grey2.main }}>
секунд
</Typography>
</Box>
<Typography
sx={{
color: theme.palette.grey2.main,
fontSize: "14px",
mt: "8px",
}}
>
Время, через которое квиз автоматически откроется
</Typography>
</Collapse>
</Box>
<CustomCheckbox
label="Отключить на мобильных устройствах"
checked={hideOnMobile}
handleChange={(e) => setHideOnMobile(e.target.checked)}
/>
<Box
sx={{
display: "flex",
justifyContent: "end",
pt: "10px",
}}
>
{nextButton}
</Box>
</Box>
</Box>
);
}