менюшка для удаления, нумерация вопросов, селект в превью

This commit is contained in:
Nastya 2023-11-30 09:27:15 +03:00
parent a169dd0a49
commit 8b252dc6bc
5 changed files with 190 additions and 60 deletions

@ -66,6 +66,7 @@ function DraggableListItem({ question, isDragging, index }: Props) {
question={question} question={question}
draggableProps={provided.dragHandleProps} draggableProps={provided.dragHandleProps}
isDragging={isDragging} isDragging={isDragging}
index={index}
/> />
</Box> </Box>
)} )}

@ -45,9 +45,10 @@ interface Props {
question: AnyTypedQuizQuestion | UntypedQuizQuestion; question: AnyTypedQuizQuestion | UntypedQuizQuestion;
draggableProps: DraggableProvidedDragHandleProps | null | undefined; draggableProps: DraggableProvidedDragHandleProps | null | undefined;
isDragging: boolean; isDragging: boolean;
index: number;
} }
export default function QuestionsPageCard({ question, draggableProps, isDragging }: Props) { export default function QuestionsPageCard({ question, draggableProps, isDragging, index }: Props) {
const [plusVisible, setPlusVisible] = useState<boolean>(false); const [plusVisible, setPlusVisible] = useState<boolean>(false);
const [open, setOpen] = useState<boolean>(false); const [open, setOpen] = useState<boolean>(false);
const theme = useTheme(); const theme = useTheme();
@ -96,7 +97,7 @@ export default function QuestionsPageCard({ question, draggableProps, isDragging
<TextField <TextField
defaultValue={question.title} defaultValue={question.title}
placeholder={"Заголовок вопроса"} placeholder={"Заголовок вопроса"}
onChange={({ target }: {target: HTMLInputElement}) => setTitle(target.value)} onChange={({ target }: { target: HTMLInputElement }) => setTitle(target.value)}
InputProps={{ InputProps={{
startAdornment: ( startAdornment: (
<Box> <Box>
@ -262,17 +263,26 @@ export default function QuestionsPageCard({ question, draggableProps, isDragging
</IconButton> </IconButton>
</Box> </Box>
)} )}
<Box
<OneIcon
style={{ style={{
fontSize: "30px", display: "flex",
alignItems: "center",
justifyContent: "center",
height: "30px",
width: "30px",
marginLeft: "3px", marginLeft: "3px",
color: !question.expanded ? "#FFF" : "", borderRadius: "50%",
fill: question.expanded fontSize: "16px",
color: question.expanded
? theme.palette.brightPurple.main
: "#FFF",
background: question.expanded
? "#EEE4FC" ? "#EEE4FC"
: theme.palette.brightPurple.main, : theme.palette.brightPurple.main,
}} }}
/> >
{index + 1}
</Box>
<IconButton <IconButton
disableRipple disableRipple
sx={{ sx={{

@ -1,3 +1,4 @@
import { useState, useRef } from "react";
import ChartIcon from "@icons/ChartIcon"; import ChartIcon from "@icons/ChartIcon";
import LinkIcon from "@icons/LinkIcon"; import LinkIcon from "@icons/LinkIcon";
import PencilIcon from "@icons/PencilIcon"; import PencilIcon from "@icons/PencilIcon";
@ -10,6 +11,8 @@ import {
Typography, Typography,
useMediaQuery, useMediaQuery,
useTheme, useTheme,
Popover,
} from "@mui/material"; } from "@mui/material";
import { deleteQuiz, setEditQuizId } from "@root/quizes/actions"; import { deleteQuiz, setEditQuizId } from "@root/quizes/actions";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
@ -31,6 +34,8 @@ export default function QuizCard({
const theme = useTheme(); const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down(600)); const isMobile = useMediaQuery(theme.breakpoints.down(600));
const navigate = useNavigate(); const navigate = useNavigate();
const [subMenuOpen, setSubMenuOpen] = useState<boolean>(false);
const subMenuRef = useRef<HTMLButtonElement | null>(null);
function handleEditClick() { function handleEditClick() {
setEditQuizId(quiz.backendId); setEditQuizId(quiz.backendId);
@ -134,15 +139,45 @@ export default function QuizCard({
}} }}
/> />
<IconButton <IconButton
ref={subMenuRef}
sx={{ sx={{
color: theme.palette.brightPurple.main, color: theme.palette.brightPurple.main,
ml: "auto", ml: "auto",
}} }}
onClick={() => deleteQuiz(quiz.id)} onClick={() => setSubMenuOpen(true)}
data-cy="delete-quiz" data-cy="delete-quiz"
> >
<MoreHorizIcon sx={{ transform: "scale(1.75)" }} /> <MoreHorizIcon sx={{ transform: "scale(1.75)" }} />
</IconButton> </IconButton>
<Popover
open={subMenuOpen}
anchorEl={subMenuRef.current}
onClose={() => setSubMenuOpen(false)}
anchorOrigin={{ vertical: "top", horizontal: "right" }}
>
<Box onClick={() => setSubMenuOpen(false)}>
<Button
sx={{
display: "block",
width: "100%",
padding: "15px 30px",
}}
onClick={()=>{}}
>
Копировать
</Button>
<Button
sx={{
display: "block",
width: "100%",
padding: "15px 30px",
}}
onClick={() => deleteQuiz(quiz.id)}
>
Удалить
</Button>
</Box>
</Popover>
</Box> </Box>
</Box> </Box>
); );

@ -28,6 +28,10 @@ export const toggleQuizPreview = () => useQuizPreviewStore.setState(
state => ({ isPreviewShown: !state.isPreviewShown }) state => ({ isPreviewShown: !state.isPreviewShown })
); );
export const setCurrentQuestionIndex = (step: number) => useQuizPreviewStore.setState(
state => ({ currentQuestionIndex:state.currentQuestionIndex = step })
);
export const incrementCurrentQuestionIndex = (maxStep: number) => useQuizPreviewStore.setState( export const incrementCurrentQuestionIndex = (maxStep: number) => useQuizPreviewStore.setState(
state => ({ currentQuestionIndex: Math.min(state.currentQuestionIndex + 1, maxStep) }) state => ({ currentQuestionIndex: Math.min(state.currentQuestionIndex + 1, maxStep) })
); );

@ -1,9 +1,10 @@
import { Box, Button, LinearProgress, Paper, Typography } from "@mui/material"; import { Box, Button, LinearProgress, Paper, Typography, FormControl, Select as MuiSelect, MenuItem, useTheme } from "@mui/material";
import { useQuestionsStore } from "@root/questions/store"; import { useQuestionsStore } from "@root/questions/store";
import { import {
decrementCurrentQuestionIndex, decrementCurrentQuestionIndex,
incrementCurrentQuestionIndex, incrementCurrentQuestionIndex,
useQuizPreviewStore, useQuizPreviewStore,
setCurrentQuestionIndex
} from "@root/quizPreview"; } from "@root/quizPreview";
import { AnyTypedQuizQuestion, UntypedQuizQuestion } from "model/questionTypes/shared"; import { AnyTypedQuizQuestion, UntypedQuizQuestion } from "model/questionTypes/shared";
import { useEffect } from "react"; import { useEffect } from "react";
@ -20,9 +21,10 @@ import Text from "./QuizPreviewQuestionTypes/Text";
import Variant from "./QuizPreviewQuestionTypes/Variant"; import Variant from "./QuizPreviewQuestionTypes/Variant";
import Varimg from "./QuizPreviewQuestionTypes/Varimg"; import Varimg from "./QuizPreviewQuestionTypes/Varimg";
import { notReachable } from "../../utils/notReachable"; import { notReachable } from "../../utils/notReachable";
import ArrowDownIcon from "@icons/ArrowDownIcon";
export default function QuizPreviewLayout() { export default function QuizPreviewLayout() {
const theme = useTheme();
const questions = useQuestionsStore(state => state.questions); const questions = useQuestionsStore(state => state.questions);
const currentQuizStep = useQuizPreviewStore( const currentQuizStep = useQuizPreviewStore(
(state) => state.currentQuestionIndex (state) => state.currentQuestionIndex
@ -67,7 +69,9 @@ export default function QuizPreviewLayout() {
whiteSpace: "break-spaces", whiteSpace: "break-spaces",
overflowY: "auto", overflowY: "auto",
flexGrow: 1, flexGrow: 1,
"&::-webkit-scrollbar": { width: 0 }, "&::-webkit-scrollbar": { width: 0, display: "none" },
msOverflowStyle: "none",
scrollbarWidth: "none",
}} }}
> >
<QuestionPreviewComponent question={currentQuestion} /> <QuestionPreviewComponent question={currentQuestion} />
@ -76,62 +80,138 @@ export default function QuizPreviewLayout() {
sx={{ sx={{
mt: "auto", mt: "auto",
p: "16px", p: "16px",
display: "flex",
borderTop: "1px solid #E3E3E3", borderTop: "1px solid #E3E3E3",
alignItems: "center",
}} }}
> >
<Box <Box sx={{ marginBottom: "10px" }}>
sx={{ <FormControl
flexGrow: 1, fullWidth
display: "flex", size="small"
flexDirection: "column", sx={{ width: "100%", minWidth: "200px", height: "48px" }}
gap: 1, >
}} <MuiSelect
> id="category-select"
<Typography> variant="outlined"
{nonDeletedQuizQuestions.length > 0 value={currentQuizStep}
? `Вопрос ${currentQuizStep + 1} из ${nonDeletedQuizQuestions.length placeholder="Заголовок вопроса"
}` onChange={({ target }) =>
: "Нет вопросов"} setCurrentQuestionIndex(window.Number(target.value))
</Typography> }
{nonDeletedQuizQuestions.length > 0 && (
<LinearProgress
variant="determinate"
value={currentProgress}
sx={{ sx={{
"&.MuiLinearProgress-colorPrimary": { height: "48px",
backgroundColor: "fadePurple.main", borderRadius: "8px",
}, "& .MuiOutlinedInput-notchedOutline": {
"& .MuiLinearProgress-barColorPrimary": { border: `1px solid ${theme.palette.brightPurple.main} !important`,
backgroundColor: "brightPurple.main",
}, },
}} }}
/> MenuProps={{
)} PaperProps: {
</Box> sx: {
<Box mt: "8px",
sx={{ p: "4px",
ml: 2, borderRadius: "8px",
display: "flex", border: "1px solid #EEE4FC",
gap: 1, boxShadow: "0px 8px 24px rgba(210, 208, 225, 0.4)",
}} },
> },
<Button MenuListProps: {
variant="outlined" sx: {
onClick={decrementCurrentQuestionIndex} py: 0,
disabled={currentQuizStep === 0} display: "flex",
sx={{ px: 1, minWidth: 0 }} flexDirection: "column",
gap: "8px",
"& .Mui-selected": {
backgroundColor: theme.palette.background.default,
color: theme.palette.brightPurple.main,
},
},
},
}}
inputProps={{
sx: {
color: theme.palette.brightPurple.main,
display: "flex",
alignItems: "center",
px: "9px",
gap: "20px",
},
}}
IconComponent={(props) => <ArrowDownIcon {...props} />}
>
{Object.values(questions).map(
({ id, title }, index) => (
<MenuItem
key={id}
value={index}
sx={{
display: "flex",
alignItems: "center",
gap: "20px",
p: "4px",
borderRadius: "5px",
color: theme.palette.grey2.main,
}}
>
{`${index + 1}. ${title}`}
</MenuItem>
)
)}
</MuiSelect>
</FormControl>
</Box>
<Box sx={{ display: "flex", alignItems: "center" }}>
<Box
sx={{
flexGrow: 1,
display: "flex",
flexDirection: "column",
gap: 1,
}}
> >
<ArrowLeft /> <Typography>
</Button> {nonDeletedQuizQuestions.length > 0
<Button ? `Вопрос ${currentQuizStep + 1} из ${nonDeletedQuizQuestions.length
variant="contained" }`
onClick={() => incrementCurrentQuestionIndex(maxCurrentQuizStep)} : "Нет вопросов"}
disabled={currentQuizStep >= maxCurrentQuizStep} </Typography>
{nonDeletedQuizQuestions.length > 0 && (
<LinearProgress
variant="determinate"
value={currentProgress}
sx={{
"&.MuiLinearProgress-colorPrimary": {
backgroundColor: "fadePurple.main",
},
"& .MuiLinearProgress-barColorPrimary": {
backgroundColor: "brightPurple.main",
},
}}
/>
)}
</Box>
<Box
sx={{
ml: 2,
display: "flex",
gap: 1,
}}
> >
Далее <Button
</Button> variant="outlined"
onClick={decrementCurrentQuestionIndex}
disabled={currentQuizStep === 0}
sx={{ px: 1, minWidth: 0 }}
>
<ArrowLeft />
</Button>
<Button
variant="contained"
onClick={() => incrementCurrentQuestionIndex(maxCurrentQuizStep)}
disabled={currentQuizStep >= maxCurrentQuizStep}
>
Далее
</Button>
</Box>
</Box> </Box>
</Box> </Box>
</Paper> </Paper>