fix: Image and video upload modals
This commit is contained in:
parent
be14c77dd3
commit
18508bff5d
@ -11,30 +11,30 @@ export const CropIcon: FC = () => (
|
||||
<path
|
||||
d="M6 6H2.25"
|
||||
stroke="white"
|
||||
stroke-width="1.5"
|
||||
strokeWidth="1.5"
|
||||
strokeLinecap="round"
|
||||
stroke-linejoin="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M6 2.25V18H21.75"
|
||||
stroke="white"
|
||||
stroke-width="1.5"
|
||||
strokeWidth="1.5"
|
||||
strokeLinecap="round"
|
||||
stroke-linejoin="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M18 15V6H9"
|
||||
stroke="white"
|
||||
stroke-width="1.5"
|
||||
strokeWidth="1.5"
|
||||
strokeLinecap="round"
|
||||
stroke-linejoin="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M18 21.75V18"
|
||||
stroke="white"
|
||||
stroke-width="1.5"
|
||||
strokeWidth="1.5"
|
||||
strokeLinecap="round"
|
||||
stroke-linejoin="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
|
||||
@ -18,16 +18,16 @@ export const ResetIcon: FC<Iporps> = ({ style, onClick }) => (
|
||||
<path
|
||||
d="M22.0254 12.4609H28.0254V6.46094"
|
||||
stroke="#9A9AAF"
|
||||
stroke-width="2"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
stroke-linejoin="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M23.7755 23.775C22.2375 25.3143 20.2775 26.3628 18.1434 26.788C16.0094 27.2132 13.7972 26.9958 11.7867 26.1635C9.77619 25.3312 8.05769 23.9213 6.8486 22.1122C5.63951 20.3031 4.99414 18.176 4.99414 16C4.99414 13.824 5.63951 11.6969 6.8486 9.8878C8.05769 8.07866 9.77619 6.66877 11.7867 5.83647C13.7972 5.00417 16.0094 4.78686 18.1434 5.21202C20.2775 5.63719 22.2375 6.68573 23.7755 8.22501L28.0255 12.4625"
|
||||
stroke="#9A9AAF"
|
||||
stroke-width="2"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
stroke-linejoin="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
|
||||
@ -40,16 +40,16 @@ const AddImage: FC<Iprops> = ({ onClick }) => {
|
||||
<path
|
||||
d="M30.9583 10H8.04167C7.46637 10 7 10.4477 7 11V29C7 29.5523 7.46637 30 8.04167 30H30.9583C31.5336 30 32 29.5523 32 29V11C32 10.4477 31.5336 10 30.9583 10Z"
|
||||
stroke="#7E2AEA"
|
||||
stroke-width="2"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
stroke-linejoin="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M7 24.9035L13.5495 18.3127C13.6464 18.2137 13.7619 18.135 13.8894 18.0813C14.0168 18.0276 14.1535 18 14.2917 18C14.4298 18 14.5666 18.0276 14.694 18.0813C14.8214 18.135 14.9369 18.2137 15.0339 18.3127L20.8411 24.1567C20.9381 24.2557 21.0536 24.3343 21.181 24.388C21.3084 24.4417 21.4452 24.4694 21.5833 24.4694C21.7215 24.4694 21.8582 24.4417 21.9856 24.388C22.1131 24.3343 22.2286 24.2557 22.3255 24.1567L25.0078 21.4574C25.1047 21.3584 25.2203 21.2797 25.3477 21.2261C25.4751 21.1724 25.6119 21.1447 25.75 21.1447C25.8881 21.1447 26.0249 21.1724 26.1523 21.2261C26.2797 21.2797 26.3953 21.3584 26.4922 21.4574L32 27"
|
||||
stroke="#7E2AEA"
|
||||
stroke-width="2"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
stroke-linejoin="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M22.5 18C23.3284 18 24 17.3284 24 16.5C24 15.6716 23.3284 15 22.5 15C21.6716 15 21 15.6716 21 16.5C21 17.3284 21.6716 18 22.5 18Z"
|
||||
|
||||
@ -1,10 +1,13 @@
|
||||
import { useState } from "react";
|
||||
import { Box, Typography, useTheme } from "@mui/material";
|
||||
import ButtonsOptions from "../ButtonsOptions";
|
||||
import React from "react";
|
||||
import CustomTextField from "@ui_kit/CustomTextField";
|
||||
import AddImage from "../../../assets/icons/questionsPage/addImage";
|
||||
import AddVideofile from "../../../assets/icons/questionsPage/addVideofile";
|
||||
import SwitchPageOptions from "./switchPageOptions";
|
||||
import { questionStore, updateQuestionsList } from "@root/questions";
|
||||
import { UploadImageModal } from "../UploadImage/UploadImageModal";
|
||||
import { UploadVideoModal } from "../UploadVideoModal";
|
||||
|
||||
type Props = {
|
||||
disableInput?: boolean;
|
||||
@ -12,11 +15,16 @@ type Props = {
|
||||
};
|
||||
|
||||
export default function PageOptions({ disableInput, totalIndex }: Props) {
|
||||
const [openImageModal, setOpenImageModal] = useState<boolean>(false);
|
||||
const [openVideoModal, setOpenVideoModal] = useState<boolean>(false);
|
||||
const [switchState, setSwitchState] = useState("setting");
|
||||
const { listQuestions } = questionStore();
|
||||
const theme = useTheme();
|
||||
const [switchState, setSwitchState] = React.useState("setting");
|
||||
|
||||
const SSHC = (data: string) => {
|
||||
setSwitchState(data);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Box
|
||||
@ -30,10 +38,26 @@ export default function PageOptions({ disableInput, totalIndex }: Props) {
|
||||
}}
|
||||
>
|
||||
<Box sx={{ display: disableInput ? "none" : "" }}>
|
||||
<CustomTextField placeholder={"Можно добавить текст"} text={""} />
|
||||
<CustomTextField
|
||||
placeholder={"Можно добавить текст"}
|
||||
text={listQuestions[totalIndex].content.text}
|
||||
onChange={({ target }) => {
|
||||
const clonContent = listQuestions[totalIndex].content;
|
||||
clonContent.text = target.value;
|
||||
updateQuestionsList(totalIndex, { content: clonContent });
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
|
||||
<Box sx={{ display: "flex", alignItems: "center", gap: "12px" }}>
|
||||
<Box
|
||||
onClick={() => setOpenImageModal(true)}
|
||||
sx={{
|
||||
cursor: "pointer",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
gap: "10px",
|
||||
}}
|
||||
>
|
||||
<AddImage />
|
||||
<Typography
|
||||
sx={{
|
||||
@ -45,7 +69,28 @@ export default function PageOptions({ disableInput, totalIndex }: Props) {
|
||||
>
|
||||
Изображение
|
||||
</Typography>
|
||||
</Box>
|
||||
<UploadImageModal
|
||||
open={openImageModal}
|
||||
onClose={() => setOpenImageModal(false)}
|
||||
imgHC={(fileList) => {
|
||||
if (fileList?.length) {
|
||||
const clonContent = listQuestions[totalIndex].content;
|
||||
clonContent.picture = URL.createObjectURL(fileList[0]);
|
||||
updateQuestionsList(totalIndex, { content: clonContent });
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<Typography> или</Typography>
|
||||
<Box
|
||||
onClick={() => setOpenVideoModal(true)}
|
||||
sx={{
|
||||
cursor: "pointer",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
gap: "10px",
|
||||
}}
|
||||
>
|
||||
<AddVideofile />
|
||||
<Typography
|
||||
sx={{
|
||||
@ -58,6 +103,17 @@ export default function PageOptions({ disableInput, totalIndex }: Props) {
|
||||
Видео
|
||||
</Typography>
|
||||
</Box>
|
||||
<UploadVideoModal
|
||||
open={openVideoModal}
|
||||
onClose={() => setOpenVideoModal(false)}
|
||||
video={listQuestions[totalIndex].content.video}
|
||||
onUpload={(url) => {
|
||||
const clonContent = listQuestions[totalIndex].content;
|
||||
clonContent.video = url;
|
||||
updateQuestionsList(totalIndex, { content: clonContent });
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
<ButtonsOptions
|
||||
switchState={switchState}
|
||||
|
||||
@ -1,234 +0,0 @@
|
||||
import { useState } from "react";
|
||||
import {
|
||||
Typography,
|
||||
Box,
|
||||
useTheme,
|
||||
ButtonBase,
|
||||
Modal,
|
||||
TextField,
|
||||
InputAdornment,
|
||||
} from "@mui/material";
|
||||
import UploadBox from "@ui_kit/UploadBox";
|
||||
import { CroppingModal } from "@ui_kit/Modal/CroppingModal";
|
||||
import UploadIcon from "../../assets/icons/UploadIcon";
|
||||
import SearchIcon from "../../assets/icons/SearchIcon";
|
||||
import * as React from "react";
|
||||
import { questionStore, updateQuestionsList } from "@root/questions";
|
||||
|
||||
import UnsplashIcon from "../../assets/icons/Unsplash.svg";
|
||||
|
||||
import type { DragEvent } from "react";
|
||||
|
||||
interface ModalkaProps {
|
||||
imgHC: (imgInp: FileList | null) => void;
|
||||
}
|
||||
|
||||
type UploadImageProps = {
|
||||
totalIndex: number;
|
||||
};
|
||||
|
||||
const Modalka: React.FC<ModalkaProps> = ({ imgHC }) => {
|
||||
const theme = useTheme();
|
||||
|
||||
const dropZone = React.useRef<HTMLDivElement>(null);
|
||||
const [ready, setReady] = React.useState(false);
|
||||
|
||||
const handleDragEnter = (event: React.DragEvent<HTMLDivElement>) => {
|
||||
event.preventDefault();
|
||||
setReady(true);
|
||||
};
|
||||
|
||||
const handleDrop = (event: DragEvent<HTMLDivElement>) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
imgHC(event.dataTransfer.files);
|
||||
};
|
||||
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
position: "absolute",
|
||||
top: "50%",
|
||||
left: "50%",
|
||||
transform: "translate(-50%, -50%)",
|
||||
maxWidth: "690px",
|
||||
bgcolor: "background.paper",
|
||||
borderRadius: "12px",
|
||||
boxShadow: 24,
|
||||
p: 0,
|
||||
overflow: "hidden",
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
padding: "20px",
|
||||
background: theme.palette.background.default,
|
||||
}}
|
||||
>
|
||||
<Typography
|
||||
sx={{ marginBottom: "20px", fontWeight: "bold", color: "#4D4D4D" }}
|
||||
>
|
||||
Добавьте изображение
|
||||
</Typography>
|
||||
<ButtonBase component="label" sx={{ justifyContent: "flex-start" }}>
|
||||
<input
|
||||
onChange={(event) => imgHC(event.target.files)}
|
||||
hidden
|
||||
accept="image/*"
|
||||
multiple
|
||||
type="file"
|
||||
/>
|
||||
<Box
|
||||
onDragOver={(event: DragEvent<HTMLDivElement>) =>
|
||||
event.preventDefault()
|
||||
}
|
||||
onDrop={handleDrop}
|
||||
ref={dropZone}
|
||||
sx={{
|
||||
width: "580px",
|
||||
padding: "33px 10px 33px 55px",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
backgroundColor: theme.palette.background.default,
|
||||
border: `1px solid ${ready ? "red" : theme.palette.grey2.main}`,
|
||||
borderRadius: "8px",
|
||||
gap: "55px",
|
||||
}}
|
||||
onDragEnter={handleDragEnter} // Применяем обработчик onDragEnter напрямую
|
||||
>
|
||||
<UploadIcon />
|
||||
<Box>
|
||||
<Typography sx={{ color: "#9A9AAF", fontWeight: "bold" }}>
|
||||
Загрузите или перетяните сюда файл
|
||||
</Typography>
|
||||
<Typography sx={{ color: "#9A9AAF", fontSize: "16px" }}>
|
||||
Принимает JPG, PNG, и GIF формат — максимум 5mb
|
||||
</Typography>
|
||||
</Box>
|
||||
</Box>
|
||||
</ButtonBase>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
margin: "20px 0",
|
||||
}}
|
||||
>
|
||||
<Typography
|
||||
sx={{
|
||||
fontWeight: "bold",
|
||||
color: "#4D4D4D",
|
||||
}}
|
||||
>
|
||||
Или выберите на фотостоке
|
||||
</Typography>
|
||||
<img src={UnsplashIcon} alt="" />
|
||||
</Box>
|
||||
<TextField
|
||||
id="search-in-unsplash"
|
||||
placeholder="Ищите изображения на английском языка"
|
||||
sx={{
|
||||
"& .MuiInputBase-input": {
|
||||
height: "48px",
|
||||
padding: "0 10px 0 0",
|
||||
},
|
||||
"& .MuiOutlinedInput-notchedOutline": {
|
||||
borderRadius: "8px",
|
||||
},
|
||||
"& .Mui-focused .MuiOutlinedInput-notchedOutline": {
|
||||
border: "1px solid rgba(0, 0, 0, 0.23)",
|
||||
},
|
||||
"& .MuiInputBase-root.MuiOutlinedInput-root .MuiOutlinedInput-notchedOutline":
|
||||
{
|
||||
borderColor: "rgba(0, 0, 0, 0.23)",
|
||||
},
|
||||
}}
|
||||
InputProps={{
|
||||
startAdornment: (
|
||||
<InputAdornment
|
||||
position="start"
|
||||
sx={{
|
||||
outline: "none",
|
||||
"& svg > path": { stroke: "#9A9AAF" },
|
||||
}}
|
||||
>
|
||||
<SearchIcon />
|
||||
</InputAdornment>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export default function UploadImage({ totalIndex }: UploadImageProps) {
|
||||
const theme = useTheme();
|
||||
const [open, setOpen] = React.useState(false);
|
||||
const { listQuestions } = questionStore();
|
||||
|
||||
const handleOpen = () => setOpen(true);
|
||||
const handleClose = () => setOpen(false);
|
||||
const imgHC = (files: FileList | null) => {
|
||||
if (files?.length) {
|
||||
const [file] = Array.from(files);
|
||||
|
||||
let clonContent = listQuestions[totalIndex].content;
|
||||
clonContent.back = URL.createObjectURL(file);
|
||||
updateQuestionsList(totalIndex, { content: clonContent });
|
||||
|
||||
handleClose();
|
||||
setOpened(true);
|
||||
}
|
||||
};
|
||||
const [opened, setOpened] = useState<boolean>(false);
|
||||
|
||||
const handleDrop = (event: DragEvent<HTMLDivElement>) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
imgHC(event.dataTransfer.files);
|
||||
};
|
||||
|
||||
return (
|
||||
<Box sx={{ padding: "20px" }}>
|
||||
<Typography
|
||||
sx={{
|
||||
fontWeight: 500,
|
||||
color: theme.palette.grey3.main,
|
||||
mt: "11px",
|
||||
mb: "14px",
|
||||
}}
|
||||
>
|
||||
Загрузить изображение
|
||||
</Typography>
|
||||
<ButtonBase
|
||||
onClick={handleOpen}
|
||||
sx={{ width: "100%", maxWidth: "260px" }}
|
||||
>
|
||||
<UploadBox
|
||||
handleDrop={handleDrop}
|
||||
sx={{ maxWidth: "260px" }}
|
||||
icon={<UploadIcon />}
|
||||
text="5 MB максимум"
|
||||
/>
|
||||
</ButtonBase>
|
||||
<Modal
|
||||
open={open}
|
||||
onClose={handleClose}
|
||||
aria-labelledby="modal-modal-title"
|
||||
aria-describedby="modal-modal-description"
|
||||
>
|
||||
<Modalka imgHC={imgHC} />
|
||||
</Modal>
|
||||
<CroppingModal
|
||||
opened={opened}
|
||||
onClose={() => setOpened(false)}
|
||||
picture={listQuestions[totalIndex].content.back}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
171
src/pages/Questions/UploadImage/UploadImageModal.tsx
Normal file
171
src/pages/Questions/UploadImage/UploadImageModal.tsx
Normal file
@ -0,0 +1,171 @@
|
||||
import {
|
||||
Typography,
|
||||
Box,
|
||||
useTheme,
|
||||
ButtonBase,
|
||||
Modal,
|
||||
TextField,
|
||||
InputAdornment,
|
||||
} from "@mui/material";
|
||||
import UploadIcon from "../../../assets/icons/UploadIcon";
|
||||
import SearchIcon from "../../../assets/icons/SearchIcon";
|
||||
import * as React from "react";
|
||||
|
||||
import UnsplashIcon from "../../../assets/icons/Unsplash.svg";
|
||||
|
||||
import type { DragEvent } from "react";
|
||||
|
||||
interface ModalkaProps {
|
||||
open: boolean;
|
||||
onClose: () => void;
|
||||
imgHC: (imgInp: FileList | null) => void;
|
||||
}
|
||||
|
||||
export const UploadImageModal: React.FC<ModalkaProps> = ({
|
||||
open,
|
||||
onClose,
|
||||
imgHC,
|
||||
}) => {
|
||||
const theme = useTheme();
|
||||
|
||||
const dropZone = React.useRef<HTMLDivElement>(null);
|
||||
const [ready, setReady] = React.useState(false);
|
||||
|
||||
const handleDragEnter = (event: React.DragEvent<HTMLDivElement>) => {
|
||||
event.preventDefault();
|
||||
setReady(true);
|
||||
};
|
||||
|
||||
const handleDrop = (event: DragEvent<HTMLDivElement>) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
imgHC(event.dataTransfer.files);
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal
|
||||
open={open}
|
||||
onClose={onClose}
|
||||
aria-labelledby="modal-modal-title"
|
||||
aria-describedby="modal-modal-description"
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
position: "absolute",
|
||||
top: "50%",
|
||||
left: "50%",
|
||||
transform: "translate(-50%, -50%)",
|
||||
maxWidth: "690px",
|
||||
bgcolor: "background.paper",
|
||||
borderRadius: "12px",
|
||||
boxShadow: 24,
|
||||
p: 0,
|
||||
overflow: "hidden",
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
padding: "20px",
|
||||
background: theme.palette.background.default,
|
||||
}}
|
||||
>
|
||||
<Typography
|
||||
sx={{ marginBottom: "20px", fontWeight: "bold", color: "#4D4D4D" }}
|
||||
>
|
||||
Добавьте изображение
|
||||
</Typography>
|
||||
<ButtonBase component="label" sx={{ justifyContent: "flex-start" }}>
|
||||
<input
|
||||
onChange={(event) => imgHC(event.target.files)}
|
||||
hidden
|
||||
accept="image/*"
|
||||
multiple
|
||||
type="file"
|
||||
/>
|
||||
<Box
|
||||
onDragOver={(event: DragEvent<HTMLDivElement>) =>
|
||||
event.preventDefault()
|
||||
}
|
||||
onDrop={handleDrop}
|
||||
ref={dropZone}
|
||||
sx={{
|
||||
width: "580px",
|
||||
padding: "33px 10px 33px 55px",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
backgroundColor: theme.palette.background.default,
|
||||
border: `1px solid ${ready ? "red" : theme.palette.grey2.main}`,
|
||||
borderRadius: "8px",
|
||||
gap: "55px",
|
||||
}}
|
||||
onDragEnter={handleDragEnter} // Применяем обработчик onDragEnter напрямую
|
||||
>
|
||||
<UploadIcon />
|
||||
<Box>
|
||||
<Typography sx={{ color: "#9A9AAF", fontWeight: "bold" }}>
|
||||
Загрузите или перетяните сюда файл
|
||||
</Typography>
|
||||
<Typography sx={{ color: "#9A9AAF", fontSize: "16px" }}>
|
||||
Принимает JPG, PNG, и GIF формат — максимум 5mb
|
||||
</Typography>
|
||||
</Box>
|
||||
</Box>
|
||||
</ButtonBase>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
margin: "20px 0",
|
||||
}}
|
||||
>
|
||||
<Typography
|
||||
sx={{
|
||||
fontWeight: "bold",
|
||||
color: "#4D4D4D",
|
||||
}}
|
||||
>
|
||||
Или выберите на фотостоке
|
||||
</Typography>
|
||||
<img src={UnsplashIcon} alt="" />
|
||||
</Box>
|
||||
<TextField
|
||||
id="search-in-unsplash"
|
||||
placeholder="Ищите изображения на английском языка"
|
||||
sx={{
|
||||
"& .MuiInputBase-input": {
|
||||
height: "48px",
|
||||
padding: "0 10px 0 0",
|
||||
},
|
||||
"& .MuiOutlinedInput-notchedOutline": {
|
||||
borderRadius: "8px",
|
||||
},
|
||||
"& .Mui-focused .MuiOutlinedInput-notchedOutline": {
|
||||
border: "1px solid rgba(0, 0, 0, 0.23)",
|
||||
},
|
||||
"& .MuiInputBase-root.MuiOutlinedInput-root .MuiOutlinedInput-notchedOutline":
|
||||
{
|
||||
borderColor: "rgba(0, 0, 0, 0.23)",
|
||||
},
|
||||
}}
|
||||
InputProps={{
|
||||
startAdornment: (
|
||||
<InputAdornment
|
||||
position="start"
|
||||
sx={{
|
||||
outline: "none",
|
||||
"& svg > path": { stroke: "#9A9AAF" },
|
||||
}}
|
||||
>
|
||||
<SearchIcon />
|
||||
</InputAdornment>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
75
src/pages/Questions/UploadImage/index.tsx
Normal file
75
src/pages/Questions/UploadImage/index.tsx
Normal file
@ -0,0 +1,75 @@
|
||||
import { useState } from "react";
|
||||
import { Typography, Box, useTheme, ButtonBase } from "@mui/material";
|
||||
import UploadBox from "@ui_kit/UploadBox";
|
||||
import { CroppingModal } from "@ui_kit/Modal/CroppingModal";
|
||||
import UploadIcon from "../../../assets/icons/UploadIcon";
|
||||
import * as React from "react";
|
||||
import { questionStore, updateQuestionsList } from "@root/questions";
|
||||
import { UploadImageModal } from "./UploadImageModal";
|
||||
|
||||
import type { DragEvent } from "react";
|
||||
|
||||
type UploadImageProps = {
|
||||
totalIndex: number;
|
||||
};
|
||||
|
||||
export default function UploadImage({ totalIndex }: UploadImageProps) {
|
||||
const theme = useTheme();
|
||||
const [open, setOpen] = React.useState(false);
|
||||
const { listQuestions } = questionStore();
|
||||
|
||||
const handleOpen = () => setOpen(true);
|
||||
const handleClose = () => setOpen(false);
|
||||
const imgHC = (files: FileList | null) => {
|
||||
if (files?.length) {
|
||||
const [file] = Array.from(files);
|
||||
|
||||
let clonContent = listQuestions[totalIndex].content;
|
||||
clonContent.back = URL.createObjectURL(file);
|
||||
updateQuestionsList(totalIndex, { content: clonContent });
|
||||
|
||||
handleClose();
|
||||
setOpened(true);
|
||||
}
|
||||
};
|
||||
const [opened, setOpened] = useState<boolean>(false);
|
||||
|
||||
const handleDrop = (event: DragEvent<HTMLDivElement>) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
imgHC(event.dataTransfer.files);
|
||||
};
|
||||
|
||||
return (
|
||||
<Box sx={{ padding: "20px" }}>
|
||||
<Typography
|
||||
sx={{
|
||||
fontWeight: 500,
|
||||
color: theme.palette.grey3.main,
|
||||
mt: "11px",
|
||||
mb: "14px",
|
||||
}}
|
||||
>
|
||||
Загрузить изображение
|
||||
</Typography>
|
||||
<ButtonBase
|
||||
onClick={handleOpen}
|
||||
sx={{ width: "100%", maxWidth: "260px" }}
|
||||
>
|
||||
<UploadBox
|
||||
handleDrop={handleDrop}
|
||||
sx={{ maxWidth: "260px" }}
|
||||
icon={<UploadIcon />}
|
||||
text="5 MB максимум"
|
||||
/>
|
||||
</ButtonBase>
|
||||
<UploadImageModal open={open} onClose={handleClose} imgHC={imgHC} />
|
||||
<CroppingModal
|
||||
opened={opened}
|
||||
onClose={() => setOpened(false)}
|
||||
picture={listQuestions[totalIndex].content.back}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
157
src/pages/Questions/UploadVideoModal.tsx
Normal file
157
src/pages/Questions/UploadVideoModal.tsx
Normal file
@ -0,0 +1,157 @@
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
ButtonBase,
|
||||
Modal,
|
||||
Typography,
|
||||
useTheme,
|
||||
} from "@mui/material";
|
||||
import SelectableButton from "@ui_kit/SelectableButton";
|
||||
import CustomTextField from "@ui_kit/CustomTextField";
|
||||
import { useState } from "react";
|
||||
import UploadIcon from "../../assets/icons/UploadIcon";
|
||||
|
||||
import type { DragEvent } from "react";
|
||||
|
||||
type BackgroundTypeModal = "linkVideo" | "ownVideo";
|
||||
|
||||
type HelpQuestionsProps = {
|
||||
open: boolean;
|
||||
onClose: () => void;
|
||||
video: string;
|
||||
onUpload: (number: string) => void;
|
||||
};
|
||||
|
||||
export const UploadVideoModal = ({
|
||||
open,
|
||||
onClose,
|
||||
video,
|
||||
onUpload,
|
||||
}: HelpQuestionsProps) => {
|
||||
const [backgroundTypeModal, setBackgroundTypeModal] =
|
||||
useState<BackgroundTypeModal>("linkVideo");
|
||||
const theme = useTheme();
|
||||
|
||||
const handleDrop = (event: DragEvent<HTMLDivElement>) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
if (event.dataTransfer.files.length) {
|
||||
onUpload(URL.createObjectURL(event.dataTransfer.files[0]));
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal
|
||||
open={open}
|
||||
onClose={onClose}
|
||||
aria-labelledby="modal-modal-title"
|
||||
aria-describedby="modal-modal-description"
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
position: "absolute",
|
||||
top: "50%",
|
||||
left: "50%",
|
||||
transform: "translate(-50%, -50%)",
|
||||
maxWidth: "690px",
|
||||
bgcolor: "background.paper",
|
||||
borderRadius: "12px",
|
||||
boxShadow: 24,
|
||||
p: 0,
|
||||
overflow: "hidden",
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
padding: "20px",
|
||||
background: theme.palette.background.default,
|
||||
}}
|
||||
>
|
||||
<Typography sx={{ color: "#9A9AAF" }}>
|
||||
Видео можно вставить с любого хостинга: YouTube, Vimeo или загрузить
|
||||
собственное
|
||||
</Typography>
|
||||
<Button variant="contained">Готово</Button>
|
||||
</Box>
|
||||
<Box sx={{ padding: "20px", gap: "10px", display: "flex" }}>
|
||||
<SelectableButton
|
||||
isSelected={backgroundTypeModal === "linkVideo"}
|
||||
onClick={() => setBackgroundTypeModal("linkVideo")}
|
||||
sx={{ maxWidth: "170px", padding: "10px" }}
|
||||
>
|
||||
Ссылка на видео
|
||||
</SelectableButton>
|
||||
<SelectableButton
|
||||
isSelected={backgroundTypeModal === "ownVideo"}
|
||||
onClick={() => setBackgroundTypeModal("ownVideo")}
|
||||
sx={{ maxWidth: "170px", padding: "10px" }}
|
||||
>
|
||||
Загрузить свое
|
||||
</SelectableButton>
|
||||
</Box>
|
||||
{backgroundTypeModal === "linkVideo" ? (
|
||||
<Box sx={{ padding: "20px" }}>
|
||||
<Typography sx={{ paddingBottom: "15px", fontWeight: "500" }}>
|
||||
Ссылка на видео
|
||||
</Typography>
|
||||
<CustomTextField
|
||||
placeholder={"http://example.com"}
|
||||
text={video}
|
||||
onChange={({ target }) => onUpload(target.value)}
|
||||
/>
|
||||
</Box>
|
||||
) : (
|
||||
<Box sx={{ padding: "20px" }}>
|
||||
<Typography sx={{ paddingBottom: "15px", fontWeight: "500" }}>
|
||||
Загрузите видео
|
||||
</Typography>
|
||||
<ButtonBase
|
||||
component="label"
|
||||
sx={{ justifyContent: "flex-start", width: "100%" }}
|
||||
>
|
||||
<input
|
||||
onChange={({ target }) => {
|
||||
if (target.files?.length) {
|
||||
onUpload(URL.createObjectURL(target.files[0]));
|
||||
}
|
||||
}}
|
||||
hidden
|
||||
accept="video/*"
|
||||
multiple
|
||||
type="file"
|
||||
/>
|
||||
<Box
|
||||
onDragOver={(event: DragEvent<HTMLDivElement>) =>
|
||||
event.preventDefault()
|
||||
}
|
||||
onDrop={handleDrop}
|
||||
sx={{
|
||||
width: "580px",
|
||||
padding: "33px 33px 33px 50px",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
backgroundColor: theme.palette.background.default,
|
||||
border: `1px solid ${theme.palette.grey2.main}`,
|
||||
borderRadius: "8px",
|
||||
gap: "50px",
|
||||
}}
|
||||
>
|
||||
<UploadIcon />
|
||||
<Box sx={{ color: "#9A9AAF" }}>
|
||||
<Typography sx={{ fontWeight: "500" }}>
|
||||
Добавить видео
|
||||
</Typography>
|
||||
<Typography sx={{ fontSize: "16px" }}>
|
||||
Принимает .mp4 и .mov формат — максимум 100мб
|
||||
</Typography>
|
||||
</Box>
|
||||
</Box>
|
||||
</ButtonBase>
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
@ -1,11 +1,4 @@
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
ButtonBase,
|
||||
Modal,
|
||||
Typography,
|
||||
useTheme,
|
||||
} from "@mui/material";
|
||||
import { Box, ButtonBase, Typography } from "@mui/material";
|
||||
import * as React from "react";
|
||||
import SelectableButton from "@ui_kit/SelectableButton";
|
||||
import CustomTextField from "@ui_kit/CustomTextField";
|
||||
@ -13,11 +6,9 @@ import { useState } from "react";
|
||||
import UploadIcon from "../../assets/icons/UploadIcon";
|
||||
import UploadBox from "@ui_kit/UploadBox";
|
||||
import { questionStore, updateQuestionsList } from "@root/questions";
|
||||
|
||||
import type { DragEvent } from "react";
|
||||
import { UploadVideoModal } from "./UploadVideoModal";
|
||||
|
||||
type BackgroundType = "text" | "video";
|
||||
type BackgroundTypeModal = "linkVideo" | "ownVideo";
|
||||
|
||||
type HelpQuestionsProps = {
|
||||
totalIndex: number;
|
||||
@ -27,27 +18,11 @@ export default function HelpQuestions({ totalIndex }: HelpQuestionsProps) {
|
||||
const [open, setOpen] = useState(false);
|
||||
const [backgroundType, setBackgroundType] = useState<BackgroundType>("text");
|
||||
const { listQuestions } = questionStore();
|
||||
const [backgroundTypeModal, setBackgroundTypeModal] =
|
||||
useState<BackgroundTypeModal>("linkVideo");
|
||||
const theme = useTheme();
|
||||
|
||||
const handleOpen = () => setOpen(true);
|
||||
const handleClose = () => setOpen(false);
|
||||
|
||||
const videoHC = (fileList: FileList | null) => {
|
||||
if (fileList?.length) {
|
||||
const videoHC = (url: string) => {
|
||||
const clonContent = listQuestions[totalIndex].content;
|
||||
clonContent.hint.video = URL.createObjectURL(fileList[0]);
|
||||
clonContent.hint.video = url;
|
||||
updateQuestionsList(totalIndex, { content: clonContent });
|
||||
handleClose();
|
||||
}
|
||||
};
|
||||
|
||||
const handleDrop = (event: DragEvent<HTMLDivElement>) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
videoHC(event.dataTransfer.files);
|
||||
};
|
||||
|
||||
return (
|
||||
@ -99,7 +74,7 @@ export default function HelpQuestions({ totalIndex }: HelpQuestionsProps) {
|
||||
Загрузите видео
|
||||
</Typography>
|
||||
<ButtonBase
|
||||
onClick={handleOpen}
|
||||
onClick={() => setOpen(true)}
|
||||
sx={{ justifyContent: "flex-start" }}
|
||||
>
|
||||
{listQuestions[totalIndex].content.hint.video ? (
|
||||
@ -120,118 +95,13 @@ export default function HelpQuestions({ totalIndex }: HelpQuestionsProps) {
|
||||
</>
|
||||
)}
|
||||
</ButtonBase>
|
||||
<Modal
|
||||
<UploadVideoModal
|
||||
open={open}
|
||||
onClose={handleClose}
|
||||
aria-labelledby="modal-modal-title"
|
||||
aria-describedby="modal-modal-description"
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
position: "absolute",
|
||||
top: "50%",
|
||||
left: "50%",
|
||||
transform: "translate(-50%, -50%)",
|
||||
maxWidth: "690px",
|
||||
bgcolor: "background.paper",
|
||||
borderRadius: "12px",
|
||||
boxShadow: 24,
|
||||
p: 0,
|
||||
overflow: "hidden",
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
padding: "20px",
|
||||
background: theme.palette.background.default,
|
||||
}}
|
||||
>
|
||||
<Typography sx={{ color: "#9A9AAF" }}>
|
||||
Видео можно вставить с любого хостинга: YouTube, Vimeo или
|
||||
загрузить собственное
|
||||
</Typography>
|
||||
<Button variant="contained">Готово</Button>
|
||||
</Box>
|
||||
<Box sx={{ padding: "20px", gap: "10px", display: "flex" }}>
|
||||
<SelectableButton
|
||||
isSelected={backgroundTypeModal === "linkVideo"}
|
||||
onClick={() => setBackgroundTypeModal("linkVideo")}
|
||||
sx={{ maxWidth: "170px", padding: "10px" }}
|
||||
>
|
||||
Ссылка на видео
|
||||
</SelectableButton>
|
||||
<SelectableButton
|
||||
isSelected={backgroundTypeModal === "ownVideo"}
|
||||
onClick={() => setBackgroundTypeModal("ownVideo")}
|
||||
sx={{ maxWidth: "170px", padding: "10px" }}
|
||||
>
|
||||
Загрузить свое
|
||||
</SelectableButton>
|
||||
</Box>
|
||||
{backgroundTypeModal === "linkVideo" ? (
|
||||
<Box sx={{ padding: "20px" }}>
|
||||
<Typography sx={{ paddingBottom: "15px", fontWeight: "500" }}>
|
||||
Ссылка на видео
|
||||
</Typography>
|
||||
<CustomTextField
|
||||
placeholder={"http://example.com"}
|
||||
text={listQuestions[totalIndex].content.hint.video}
|
||||
onChange={({ target }) => {
|
||||
let clonContent = listQuestions[totalIndex].content;
|
||||
clonContent.hint.video = target.value;
|
||||
updateQuestionsList(totalIndex, { content: clonContent });
|
||||
}}
|
||||
onClose={() => setOpen(false)}
|
||||
video={listQuestions[totalIndex].content.hint.video}
|
||||
onUpload={videoHC}
|
||||
/>
|
||||
</Box>
|
||||
) : (
|
||||
<Box sx={{ padding: "20px" }}>
|
||||
<Typography sx={{ paddingBottom: "15px", fontWeight: "500" }}>
|
||||
Загрузите видео
|
||||
</Typography>
|
||||
<ButtonBase
|
||||
component="label"
|
||||
sx={{ justifyContent: "flex-start", width: "100%" }}
|
||||
>
|
||||
<input
|
||||
onChange={(event) => videoHC(event.target.files)}
|
||||
hidden
|
||||
accept="video/*"
|
||||
multiple
|
||||
type="file"
|
||||
/>
|
||||
<Box
|
||||
onDragOver={(event: DragEvent<HTMLDivElement>) =>
|
||||
event.preventDefault()
|
||||
}
|
||||
onDrop={handleDrop}
|
||||
sx={{
|
||||
width: "580px",
|
||||
padding: "33px 33px 33px 50px",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
backgroundColor: theme.palette.background.default,
|
||||
border: `1px solid ${theme.palette.grey2.main}`,
|
||||
borderRadius: "8px",
|
||||
gap: "50px",
|
||||
}}
|
||||
>
|
||||
<UploadIcon />
|
||||
<Box sx={{ color: "#9A9AAF" }}>
|
||||
<Typography sx={{ fontWeight: "500" }}>
|
||||
Добавить видео
|
||||
</Typography>
|
||||
<Typography sx={{ fontSize: "16px" }}>
|
||||
Принимает .mp4 и .mov формат — максимум 100мб
|
||||
</Typography>
|
||||
</Box>
|
||||
</Box>
|
||||
</ButtonBase>
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
</Modal>
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
);
|
||||
|
||||
@ -51,6 +51,9 @@ export interface Question {
|
||||
number: boolean;
|
||||
xy: string;
|
||||
format: "carousel" | "masonry";
|
||||
text: string;
|
||||
picture: string;
|
||||
video: string;
|
||||
};
|
||||
version: number;
|
||||
parent_ids: number[];
|
||||
@ -124,6 +127,9 @@ export const createQuestion = (id: number) => {
|
||||
single: false,
|
||||
xy: "",
|
||||
format: "carousel",
|
||||
text: "",
|
||||
picture: "",
|
||||
video: "",
|
||||
variants: [
|
||||
{
|
||||
answer: "",
|
||||
|
||||
Loading…
Reference in New Issue
Block a user