id вопроса и результата для копирования

This commit is contained in:
Tamara 2024-05-12 20:10:14 +03:00
parent 686c9316ce
commit bc5d6b781f
4 changed files with 315 additions and 260 deletions

@ -4,9 +4,10 @@ interface Props {
color?: string;
bgcolor?: string;
marL?: string;
width?: string
}
export default function CopyIcon({ color, bgcolor, marL }: Props) {
export default function CopyIcon({ color, bgcolor, marL, width = "36px" }: Props) {
const theme = useTheme();
return (
@ -14,8 +15,8 @@ export default function CopyIcon({ color, bgcolor, marL }: Props) {
sx={{
bgcolor,
borderRadius: "6px",
height: "36px",
width: "36px",
height: width,
width: width,
display: "flex",
justifyContent: "center",
alignItems: "center",

@ -46,6 +46,7 @@ export default function QuestionsPageCard({
draggableProps={draggableProps}
quizId={question.quizId}
questionId={question.id}
questionBackendId={question.backendId}
questionContentId={"content" in question ? question.content.id : null}
title={question.title}
questionType={question.type}

@ -1,5 +1,6 @@
import { ArrowDownIcon } from "@icons/questionsPage/ArrowDownIcon";
import { CopyIcon } from "@icons/questionsPage/CopyIcon";
import CopyIconPurple from "@icons/CopyIcon";
import { PointsIcon } from "@icons/questionsPage/PointsIcon";
import Answer from "@icons/questionsPage/answer";
import Date from "@icons/questionsPage/date";
@ -50,6 +51,7 @@ interface Props {
draggableProps: DraggableProvidedDragHandleProps | null | undefined;
quizId: number;
questionId: string;
questionBackendId: number;
questionContentId: string | null;
title: string;
questionType: QuestionType | null;
@ -62,6 +64,7 @@ const QuestionPageCardTitle = memo<Props>(function ({
draggableProps,
quizId,
questionId,
questionBackendId,
questionContentId,
title,
questionType,
@ -95,258 +98,285 @@ const QuestionPageCardTitle = memo<Props>(function ({
};
return (
<Box
sx={{
display: "flex",
alignItems: "center",
padding: isMobile ? "10px" : "20px 10px 20px 20px",
flexDirection: "row",
flexWrap: isMobile && isExpanded ? "wrap" : "nowrap",
}}
>
<FormControl
variant="standard"
sx={{
p: 0,
maxWidth: isTablet ? "549px" : "640px",
width: "100%",
marginRight: isMobile ? "0px" : "16.1px",
display: "flex",
flexDirection: "row",
flexBasis: isMobile && isExpanded ? "calc(100% - 30px)" : null,
}}
>
<TextField
id="questionTitle"
value={title}
placeholder={"Заголовок вопроса"}
onChange={({ target }) => setTitle(target.value || " ")}
onFocus={handleInputFocus}
onBlur={handleInputBlur}
inputProps={{
maxLength: maxLengthTextField,
}}
InputProps={{
startAdornment: (
<Box>
<InputAdornment
ref={anchorRef}
position="start"
sx={{ cursor: "pointer" }}
onClick={() => setOpen((isOpened) => !isOpened)}
>
{IconAndrom(isExpanded, questionType)}
</InputAdornment>
<ChooseAnswerModal
open={open}
onClose={() => setOpen(false)}
anchorRef={anchorRef}
questionId={questionId}
questionContentId={questionContentId}
questionType={questionType}
/>
</Box>
),
endAdornment: isTextFieldtActive &&
title.length >= maxLengthTextField - 7 && (
<Box
sx={{
display: "flex",
marginTop: "5px",
marginLeft: "auto",
position: "absolute",
bottom: "-28px",
right: "0",
}}
>
<Typography fontSize="14px">{title.length}</Typography>
<span>/</span>
<Typography fontSize="14px">{maxLengthTextField}</Typography>
</Box>
),
}}
sx={{
flexGrow: 1,
margin: isMobile ? "10px 0" : 0,
"& .MuiInputBase-root": {
color: "#000000",
backgroundColor: isExpanded
? theme.palette.background.default
: "transparent",
height: "48px",
borderRadius: "10px",
".MuiOutlinedInput-notchedOutline": {
borderWidth: "1px !important",
border: !isExpanded ? "none" : null,
},
"& .MuiInputBase-input::placeholder": {
color: "#4D4D4D",
opacity: 0.8,
},
},
}}
/>
</FormControl>
<IconButton
disableRipple
sx={{
order: isMobile && isExpanded ? "0" : "1",
padding: isMobile ? "0" : "0 5px",
right: isMobile ? "0" : null,
bottom: isMobile ? "0" : null,
marginLeft: !isMobile && isExpanded ? "10px" : null,
}}
{...draggableProps}
onMouseDown={collapseAllQuestions}
onTouchStart={collapseAllQuestions}
>
<PointsIcon style={{ color: "#4D4D4D", fontSize: "30px" }} />
</IconButton>
<Box
sx={{
display: "flex",
alignItems: "center",
justifyContent: "flex-end",
width: isMobile ? "100%" : "auto",
position: "relative",
}}
>
<IconButton
sx={{ padding: "0", margin: "5px" }}
disableRipple
data-cy="expand-question"
onClick={() => toggleExpandQuestion(questionId)}
>
{isExpanded ? (
<ArrowDownIcon
style={{
width: "18px",
color: "#4D4D4D",
}}
/>
) : (
<ExpandLessIcon
sx={{
boxSizing: "border-box",
fill: theme.palette.brightPurple.main,
background: "#FFF",
borderRadius: "6px",
height: "30px",
width: "30px",
}}
/>
)}
</IconButton>
{isExpanded ? (
<></>
) : (
<Box
<>
<Box
sx={{
display: "flex",
height: "30px",
borderRight: "solid 1px #4D4D4D",
display: "flex",
alignItems: "center",
padding: isMobile ? "10px" : "20px 10px 20px 20px",
flexDirection: "row",
flexWrap: isMobile && isExpanded ? "wrap" : "nowrap",
}}
>
<IconButton
sx={{ padding: "0" }}
onClick={() => copyQuestion(questionId, quizId)}
>
<CopyIcon style={{ color: theme.palette.brightPurple.main }} />
</IconButton>
<IconButton
sx={{
cursor: "pointer",
borderRadius: "6px",
padding: "0",
margin: "0 5px 0 10px",
}}
onClick={() => {
if (questionType === null) {
deleteQuestion(questionId);
return;
}
if (questionHasParent) {
setOpenDelete(true);
} else {
deleteQuestionWithTimeout(questionId, () =>
DeleteFunction(questionId),
);
}
}}
data-cy="delete-question"
>
<DeleteIcon style={{ color: theme.palette.brightPurple.main }} />
</IconButton>
<Modal open={openDelete} onClose={() => setOpenDelete(false)}>
<Box
>
<FormControl
variant="standard"
sx={{
position: "absolute",
top: "50%",
left: "50%",
transform: "translate(-50%, -50%)",
padding: "30px",
borderRadius: "10px",
background: "#FFFFFF",
}}
>
<Typography variant="h6" sx={{ textAlign: "center" }}>
Вы удаляете вопрос, участвующий в ветвлении. Все его потомки
потеряют данные ветвления. Вы уверены, что хотите удалить
вопрос?
</Typography>
<Box
sx={{
marginTop: "30px",
p: 0,
maxWidth: isTablet ? "549px" : "640px",
width: "100%",
marginRight: isMobile ? "0px" : "16.1px",
display: "flex",
justifyContent: "center",
gap: "15px",
}}
>
<Button
variant="contained"
sx={{ minWidth: "150px" }}
onClick={() => setOpenDelete(false)}
>
Отмена
</Button>
<Button
variant="contained"
sx={{ minWidth: "150px" }}
onClick={() => {
deleteQuestionWithTimeout(questionId, () =>
DeleteFunction(questionId),
);
flexDirection: "row",
flexBasis: isMobile && isExpanded ? "calc(100% - 30px)" : null,
}}
>
<TextField
id="questionTitle"
value={title}
placeholder={"Заголовок вопроса"}
onChange={({ target }) => setTitle(target.value || " ")}
onFocus={handleInputFocus}
onBlur={handleInputBlur}
inputProps={{
maxLength: maxLengthTextField,
}}
>
Подтвердить
</Button>
</Box>
</Box>
</Modal>
</Box>
)}
{page !== null && (
<Box
style={{
display: "flex",
alignItems: "center",
justifyContent: "center",
height: "30px",
width: "30px",
marginLeft: "3px",
borderRadius: "50%",
fontSize: "16px",
color: isExpanded ? theme.palette.brightPurple.main : "#FFF",
background: isExpanded
? "#EEE4FC"
: theme.palette.brightPurple.main,
}}
>
{page + 1}
</Box>
)}
</Box>
</Box>
InputProps={{
startAdornment: (
<Box>
<InputAdornment
ref={anchorRef}
position="start"
sx={{ cursor: "pointer" }}
onClick={() => setOpen((isOpened) => !isOpened)}
>
{IconAndrom(isExpanded, questionType)}
</InputAdornment>
<ChooseAnswerModal
open={open}
onClose={() => setOpen(false)}
anchorRef={anchorRef}
questionId={questionId}
questionContentId={questionContentId}
questionType={questionType}
/>
</Box>
),
endAdornment: isTextFieldtActive &&
title.length >= maxLengthTextField - 7 && (
<Box
sx={{
display: "flex",
marginTop: "5px",
marginLeft: "auto",
position: "absolute",
bottom: "-28px",
right: "0",
}}
>
<Typography fontSize="14px">{title.length}</Typography>
<span>/</span>
<Typography fontSize="14px">{maxLengthTextField}</Typography>
</Box>
),
}}
sx={{
flexGrow: 1,
margin: isMobile ? "10px 0" : 0,
"& .MuiInputBase-root": {
color: "#000000",
backgroundColor: isExpanded
? theme.palette.background.default
: "transparent",
height: "48px",
borderRadius: "10px",
".MuiOutlinedInput-notchedOutline": {
borderWidth: "1px !important",
border: !isExpanded ? "none" : null,
},
"& .MuiInputBase-input::placeholder": {
color: "#4D4D4D",
opacity: 0.8,
},
},
}}
/>
</FormControl>
<IconButton
disableRipple
sx={{
order: isMobile && isExpanded ? "0" : "1",
padding: isMobile ? "0" : "0 5px",
right: isMobile ? "0" : null,
bottom: isMobile ? "0" : null,
marginLeft: !isMobile && isExpanded ? "10px" : null,
}}
{...draggableProps}
onMouseDown={collapseAllQuestions}
onTouchStart={collapseAllQuestions}
>
<PointsIcon style={{ color: "#4D4D4D", fontSize: "30px" }} />
</IconButton>
<Box
sx={{
display: "flex",
alignItems: "center",
justifyContent: "flex-end",
width: isMobile ? "100%" : "auto",
position: "relative",
}}
>
<IconButton
sx={{ padding: "0", margin: "5px" }}
disableRipple
data-cy="expand-question"
onClick={() => toggleExpandQuestion(questionId)}
>
{isExpanded ? (
<ArrowDownIcon
style={{
width: "18px",
color: "#4D4D4D",
}}
/>
) : (
<ExpandLessIcon
sx={{
boxSizing: "border-box",
fill: theme.palette.brightPurple.main,
background: "#FFF",
borderRadius: "6px",
height: "30px",
width: "30px",
}}
/>
)}
</IconButton>
{isExpanded ? (
<></>
) : (
<Box
sx={{
display: "flex",
height: "30px",
borderRight: "solid 1px #4D4D4D",
}}
>
<IconButton
sx={{ padding: "0" }}
onClick={() => copyQuestion(questionId, quizId)}
>
<CopyIcon style={{ color: theme.palette.brightPurple.main }} />
</IconButton>
<IconButton
sx={{
cursor: "pointer",
borderRadius: "6px",
padding: "0",
margin: "0 5px 0 10px",
}}
onClick={() => {
if (questionType === null) {
deleteQuestion(questionId);
return;
}
if (questionHasParent) {
setOpenDelete(true);
} else {
deleteQuestionWithTimeout(questionId, () =>
DeleteFunction(questionId),
);
}
}}
data-cy="delete-question"
>
<DeleteIcon style={{ color: theme.palette.brightPurple.main }} />
</IconButton>
<Modal open={openDelete} onClose={() => setOpenDelete(false)}>
<Box
sx={{
position: "absolute",
top: "50%",
left: "50%",
transform: "translate(-50%, -50%)",
padding: "30px",
borderRadius: "10px",
background: "#FFFFFF",
}}
>
<Typography variant="h6" sx={{ textAlign: "center" }}>
Вы удаляете вопрос, участвующий в ветвлении. Все его потомки
потеряют данные ветвления. Вы уверены, что хотите удалить
вопрос?
</Typography>
<Box
sx={{
marginTop: "30px",
display: "flex",
justifyContent: "center",
gap: "15px",
}}
>
<Button
variant="contained"
sx={{ minWidth: "150px" }}
onClick={() => setOpenDelete(false)}
>
Отмена
</Button>
<Button
variant="contained"
sx={{ minWidth: "150px" }}
onClick={() => {
deleteQuestionWithTimeout(questionId, () =>
DeleteFunction(questionId),
);
}}
>
Подтвердить
</Button>
</Box>
</Box>
</Modal>
</Box>
)}
{page !== null && (
<Box
style={{
display: "flex",
alignItems: "center",
justifyContent: "center",
height: "30px",
width: "30px",
marginLeft: "3px",
borderRadius: "50%",
fontSize: "16px",
color: isExpanded ? theme.palette.brightPurple.main : "#FFF",
background: isExpanded
? "#EEE4FC"
: theme.palette.brightPurple.main,
}}
>
{page + 1}
</Box>
)}
</Box>
</Box>
{questionType !== null &&
<Box sx={{
display: "flex",
alignItems: "center",
flexWrap: isMobile ? "wrap" : undefined,
gap: "10px",
padding: "0 20px 20px 20px"
}}>
<Typography>ID Вопроса</Typography>
<Typography
id={"id-copy"}
>{questionBackendId}</Typography>
<IconButton
edge="end"
onClick={() => navigator.clipboard.writeText(document.querySelector("#id-copy").innerText)
}
>
<CopyIconPurple
color={"#ffffff"}
width={"30px"}
bgcolor={theme.palette.brightPurple.main}
/>
</IconButton>
</Box>}
</>
);
});

@ -9,16 +9,16 @@ import { useCurrentQuiz } from "@root/quizes/hooks";
import CustomTextField from "@ui_kit/CustomTextField";
import {
Box,
IconButton,
Paper,
Button,
Typography,
TextField,
useMediaQuery,
useTheme,
FormControl,
Popover,
Box,
IconButton,
Paper,
Button,
Typography,
TextField,
useMediaQuery,
useTheme,
FormControl,
Popover, InputAdornment,
} from "@mui/material";
import MiniButtonSetting from "@ui_kit/MiniButtonSetting";
@ -32,6 +32,7 @@ import { MediaSelectionAndDisplay } from "@ui_kit/MediaSelectionAndDisplay";
import type { MouseEvent } from "react";
import type { QuizQuestionResult } from "@model/questionTypes/result";
import CopyIcon from "@icons/CopyIcon";
interface Props {
resultContract: boolean;
@ -259,6 +260,28 @@ export const ResultCard = ({ resultContract, resultData }: Props) => {
}}
>
<Box sx={{ p: "0 20px", pt: "10px" }}>
<Box sx={{
display: "flex",
alignItems: "center",
gap: "10px",
mb: "19px",
}}>
<Typography>ID результата</Typography>
<Typography
id={"id-copy"}
>{resultData.backendId}</Typography>
<IconButton
edge="end"
onClick={() => navigator.clipboard.writeText(document.querySelector("#id-copy").innerText)
}
>
<CopyIcon
color={"#ffffff"}
width={"30px"}
bgcolor={theme.palette.brightPurple.main}
/>
</IconButton>
</Box>
<Box
sx={{
width: "100%",