Merge branch 'refactoring-applications-page' into dev
This commit is contained in:
commit
30e97416fa
@ -1,7 +1,36 @@
|
||||
import { makeRequest } from "@frontend/kitui";
|
||||
import { RawResult } from "@model/result/result";
|
||||
|
||||
async function getResultList(quizId, page: number, body: any) {
|
||||
return makeRequest<unknown, unknown>({
|
||||
interface IResultListBody {
|
||||
to: number;
|
||||
from: string;
|
||||
new: boolean;
|
||||
page: number;
|
||||
limit: number;
|
||||
}
|
||||
|
||||
export interface IAnswerResult {
|
||||
Browser: string;
|
||||
CreatedAt: string;
|
||||
Deleted: boolean;
|
||||
Device: string;
|
||||
DeviceType: string;
|
||||
Email: string;
|
||||
Fingerprint: string;
|
||||
IP: string;
|
||||
Id: number;
|
||||
OS: string;
|
||||
QuizId: number;
|
||||
Result: boolean;
|
||||
Session: string;
|
||||
Start: boolean;
|
||||
content: string;
|
||||
new: boolean;
|
||||
question_id: number;
|
||||
}
|
||||
|
||||
async function getResultList(quizId: number, page: number, body: any) {
|
||||
return makeRequest<IResultListBody, RawResult>({
|
||||
url: process.env.REACT_APP_DOMAIN + `/squiz/results/getResults/${quizId}`,
|
||||
method: "POST",
|
||||
body: { page: page, limit: 10, ...body },
|
||||
@ -31,7 +60,7 @@ function deleteResult(resultId: number) {
|
||||
// }
|
||||
// };
|
||||
|
||||
function obsolescenceResult(idResultArray: string[]) {
|
||||
function obsolescenceResult(idResultArray: number[]) {
|
||||
return makeRequest<unknown, unknown>({
|
||||
url: process.env.REACT_APP_DOMAIN + `/squiz/result/seen`,
|
||||
body: {
|
||||
@ -42,7 +71,7 @@ function obsolescenceResult(idResultArray: string[]) {
|
||||
}
|
||||
|
||||
function getAnswerResultList(resultId: number) {
|
||||
return makeRequest<unknown, unknown>({
|
||||
return makeRequest<unknown, IAnswerResult[]>({
|
||||
url: process.env.REACT_APP_DOMAIN + `/squiz/result/${resultId}`,
|
||||
method: "GET",
|
||||
});
|
||||
|
@ -1,11 +1,13 @@
|
||||
export interface RawResult {
|
||||
total_count: number;
|
||||
results: {
|
||||
content: string;
|
||||
id: number;
|
||||
new: boolean;
|
||||
created_at: string;
|
||||
};
|
||||
results: RawResultItem[];
|
||||
}
|
||||
|
||||
export interface RawResultItem {
|
||||
content: string;
|
||||
id: number;
|
||||
new: boolean;
|
||||
created_at: string;
|
||||
}
|
||||
export interface ResultContent {
|
||||
name?: string;
|
||||
@ -35,12 +37,11 @@ export const defaultResultContent: ResultContent = {
|
||||
messenger: "",
|
||||
};
|
||||
|
||||
export function rawResultToResult(rawResult): RawResult {
|
||||
export function rawResultToResult(rawResult: RawResultItem) {
|
||||
let content = defaultResultContent;
|
||||
|
||||
try {
|
||||
content = JSON.parse(rawResult.content);
|
||||
console.log("Content", content);
|
||||
} catch (error) {
|
||||
console.warn(
|
||||
"Cannot parse result from string, using default config",
|
||||
|
71
src/pages/QuizAnswersPage/AnswerList.tsx
Normal file
71
src/pages/QuizAnswersPage/AnswerList.tsx
Normal file
@ -0,0 +1,71 @@
|
||||
import { FC } from "react";
|
||||
import { Box, Typography } from "@mui/material";
|
||||
import { DateDefinition, TimeDefinition } from "./helper";
|
||||
import { CardAnswer } from "./CardAnswer";
|
||||
import { Result } from "@root/results/store";
|
||||
|
||||
interface AnswerListProps {
|
||||
isTablet: boolean;
|
||||
results: Result[] | [];
|
||||
setPrePaymentModalOpen: (value: boolean) => void;
|
||||
}
|
||||
export const AnswerList: FC<AnswerListProps> = ({
|
||||
isTablet,
|
||||
results,
|
||||
setPrePaymentModalOpen,
|
||||
}) => {
|
||||
return (
|
||||
<>
|
||||
{!isTablet && (
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
width: "100%",
|
||||
alignItems: "center",
|
||||
mb: "15px",
|
||||
}}
|
||||
>
|
||||
<Typography sx={{ fontSize: "18px", color: "#9A9AAF", mr: "40px" }}>
|
||||
№ заявки
|
||||
</Typography>
|
||||
<Typography sx={{ fontSize: "18px", color: "#9A9AAF" }}>
|
||||
Дата
|
||||
</Typography>
|
||||
<Typography sx={{ fontSize: "18px", color: "#9A9AAF", ml: "288px" }}>
|
||||
Контакты
|
||||
</Typography>
|
||||
</Box>
|
||||
)}
|
||||
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
alignItems: "flex-start",
|
||||
flexDirection: isTablet ? "-moz-initial" : "column",
|
||||
flexWrap: isTablet ? "wrap" : "nowrap",
|
||||
gap: "20px",
|
||||
}}
|
||||
>
|
||||
{results &&
|
||||
results.map((result) => {
|
||||
const dayResult = DateDefinition(result.created_at);
|
||||
const timeResult = TimeDefinition(result.created_at);
|
||||
return (
|
||||
<CardAnswer
|
||||
key={result.id}
|
||||
name={result.content.name}
|
||||
email={result.content.email}
|
||||
phone={result.content.phone}
|
||||
address={result.content.address}
|
||||
isNew={result.new}
|
||||
idResult={result.id}
|
||||
dayResult={dayResult}
|
||||
timeResult={timeResult}
|
||||
openPrePaymentModal={() => setPrePaymentModalOpen(true)}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</Box>
|
||||
</>
|
||||
);
|
||||
};
|
@ -1,25 +1,20 @@
|
||||
import { ArrowDownIcon } from "@icons/questionsPage/ArrowDownIcon";
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
IconButton,
|
||||
Link,
|
||||
Modal,
|
||||
Typography,
|
||||
useMediaQuery,
|
||||
useTheme,
|
||||
} from "@mui/material";
|
||||
import { FC, useState } from "react";
|
||||
import { FC, MouseEvent, useState } from "react";
|
||||
import { ContactIcon } from "./icons/ContactIcon";
|
||||
import { MessageIcon } from "./icons/MessageIcon";
|
||||
import { PhoneIcon } from "./icons/PhoneIcon";
|
||||
import { DeleteIcon } from "@icons/questionsPage/deleteIcon";
|
||||
|
||||
import homeImg from "./images/home.png";
|
||||
import videoFrame from "./images/videoFrame.png";
|
||||
import { EyeIcon } from "./icons/EyeIcon";
|
||||
import { deleteResult, obsolescenceResult } from "@root/results/actions";
|
||||
import { resultApi } from "@api/result";
|
||||
import { IAnswerResult, resultApi } from "@api/result";
|
||||
import { useQuizStore } from "@root/quizes/store";
|
||||
import { useQuestionsStore } from "@root/questions/store";
|
||||
import AddressIcon from "@icons/ContactFormIcon/AddressIcon";
|
||||
@ -27,21 +22,19 @@ import AddressIcon from "@icons/ContactFormIcon/AddressIcon";
|
||||
import type { AxiosError } from "axios";
|
||||
import { DeleteModal } from "./DeleteModal";
|
||||
|
||||
interface Props {
|
||||
interface CardAnswerProps {
|
||||
isNew: boolean;
|
||||
idResult: string;
|
||||
onClick: () => void;
|
||||
idResult: number;
|
||||
dayResult: string;
|
||||
timeResult: string;
|
||||
name?: string;
|
||||
phone?: string;
|
||||
email?: string;
|
||||
address?: string;
|
||||
onLossNew?: (id: string) => void;
|
||||
openPrePaymentModal: () => void;
|
||||
}
|
||||
|
||||
export const CardAnswer = ({
|
||||
export const CardAnswer: FC<CardAnswerProps> = ({
|
||||
name,
|
||||
phone,
|
||||
email,
|
||||
@ -50,35 +43,29 @@ export const CardAnswer = ({
|
||||
idResult,
|
||||
timeResult,
|
||||
dayResult,
|
||||
onLossNew,
|
||||
openPrePaymentModal,
|
||||
}: Props) => {
|
||||
}) => {
|
||||
const [isOpen, setIsOpen] = useState<boolean>(false);
|
||||
const [openDelete, setOpenDelete] = useState<boolean>(false);
|
||||
const theme = useTheme();
|
||||
const isTablet = useMediaQuery(theme.breakpoints.down(1000));
|
||||
const [resultsAnswer, setResultsAnswer] = useState([]);
|
||||
const [resultQuiz, setResultQuiz] = useState([]);
|
||||
const [resultsAnswer, setResultsAnswer] = useState<IAnswerResult[]>([]);
|
||||
const [questionsResultState, setQuestionsResultState] = useState([]);
|
||||
const { editQuizId } = useQuizStore();
|
||||
const { questions } = useQuestionsStore();
|
||||
|
||||
const openResults = async () => {
|
||||
setIsOpen(!isOpen);
|
||||
if (!isOpen) {
|
||||
try {
|
||||
let resAnswer = await resultApi.getAnswerList(Number(idResult));
|
||||
|
||||
let resAnswerOnly = resAnswer.filter((res) => res.Result !== true);
|
||||
let resQuiz = resAnswer.filter((res) => res.Result === true);
|
||||
setResultQuiz(resQuiz);
|
||||
const resAnswer = await resultApi.getAnswerList(idResult);
|
||||
const resAnswerOnly = resAnswer.filter((res) => res.Result !== true);
|
||||
const resQuiz = resAnswer.filter((res) => res.Result === true);
|
||||
setResultsAnswer(resAnswerOnly);
|
||||
let idResults = resQuiz[0].question_id;
|
||||
let questionsResult = questions.filter(
|
||||
const idResults = resQuiz[0].question_id;
|
||||
const questionsResult = questions.filter(
|
||||
(q) => q.backendId === idResults,
|
||||
);
|
||||
setQuestionsResultState(questionsResult);
|
||||
console.log("тут хранятся ответы", resAnswerOnly);
|
||||
} catch (nativeError) {
|
||||
const error = nativeError as AxiosError;
|
||||
|
||||
@ -89,167 +76,152 @@ export const CardAnswer = ({
|
||||
}
|
||||
};
|
||||
|
||||
const onClickDelete = (e: MouseEvent) => {
|
||||
e.stopPropagation();
|
||||
setOpenDelete(true);
|
||||
};
|
||||
|
||||
return (
|
||||
<Box
|
||||
onClick={() => {
|
||||
obsolescenceResult(idResult, editQuizId);
|
||||
openResults();
|
||||
}}
|
||||
sx={{
|
||||
borderRadius: "12px",
|
||||
maxWidth: isTablet ? "450px" : "auto",
|
||||
width: "100%",
|
||||
boxShadow:
|
||||
"0px 2.767px 8.551px 0px rgba(210, 208, 225, 0.07), 0px 6.65px 20.549px 0px rgba(210, 208, 225, 0.10), 0px 12.522px 38.692px 0px rgba(210, 208, 225, 0.12), 0px 22.336px 69.019px 0px rgba(210, 208, 225, 0.14), 0px 41.778px 129.093px 0px rgba(210, 208, 225, 0.17), 0px 100px 309px 0px rgba(210, 208, 225, 0.24)",
|
||||
}}
|
||||
>
|
||||
<>
|
||||
<Box
|
||||
onClick={() => {
|
||||
if (editQuizId !== null) {
|
||||
obsolescenceResult(idResult, editQuizId);
|
||||
openResults();
|
||||
}
|
||||
}}
|
||||
sx={{
|
||||
borderRadius: "12px",
|
||||
maxWidth: isTablet ? "450px" : "auto",
|
||||
width: "100%",
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
flexDirection: isTablet ? "column" : "-moz-initial",
|
||||
boxShadow:
|
||||
"0px 2.767px 8.551px 0px rgba(210, 208, 225, 0.07), 0px 6.65px 20.549px 0px rgba(210, 208, 225, 0.10), 0px 12.522px 38.692px 0px rgba(210, 208, 225, 0.12), 0px 22.336px 69.019px 0px rgba(210, 208, 225, 0.14), 0px 41.778px 129.093px 0px rgba(210, 208, 225, 0.17), 0px 100px 309px 0px rgba(210, 208, 225, 0.24)",
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
flexDirection: isTablet ? "column" : "-moz-initial",
|
||||
cursor: "pointer",
|
||||
p: "20px",
|
||||
borderRadius: isTablet
|
||||
? "12px 12px 0 0"
|
||||
: isOpen
|
||||
? "12px 0 0 0"
|
||||
: "12px 0 0 12px",
|
||||
display: "flex",
|
||||
alignItems: "flex-start",
|
||||
background: "#FFF",
|
||||
width: "100%",
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
flexDirection: isTablet ? "column" : "-moz-initial",
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
width: isTablet ? "100%" : "auto",
|
||||
flexDirection: isTablet ? "column" : "-moz-initial",
|
||||
cursor: "pointer",
|
||||
p: "20px",
|
||||
borderRadius: isTablet
|
||||
? "12px 12px 0 0"
|
||||
: isOpen
|
||||
? "12px 0 0 0"
|
||||
: "12px 0 0 12px",
|
||||
display: "flex",
|
||||
alignItems: "flex-start",
|
||||
flexDirection: isTablet ? "row-reverse" : "-moz-initial",
|
||||
justifyContent: isTablet ? "space-between" : "-moz-initial",
|
||||
pb: isTablet ? "20px" : "0",
|
||||
mb: isTablet ? "20px" : "0",
|
||||
borderBottom: isTablet
|
||||
? "1px solid rgba(154, 154, 175, 0.50)"
|
||||
: "0",
|
||||
background: "#FFF",
|
||||
width: "100%",
|
||||
}}
|
||||
>
|
||||
<Box sx={{ display: "flex", alignItems: "center", gap: "6px" }}>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
width: "30px",
|
||||
height: "30px",
|
||||
borderRadius: "50%",
|
||||
background: "#EEE4FC",
|
||||
color: "#7E2AEA",
|
||||
}}
|
||||
>
|
||||
{idResult}
|
||||
</Box>
|
||||
<IconButton onClick={openResults}>
|
||||
<ArrowDownIcon
|
||||
style={{
|
||||
transform: isOpen ? "rotate(180deg)" : "rotate(360deg)",
|
||||
}}
|
||||
fontSize="10px"
|
||||
/>
|
||||
</IconButton>
|
||||
</Box>
|
||||
|
||||
<Typography
|
||||
<Box
|
||||
sx={{
|
||||
ml: isTablet ? "0" : "50px",
|
||||
mr: isTablet ? "0" : "188px",
|
||||
fontSize: "18px",
|
||||
color: "#7E2AEA",
|
||||
maxWidth: "143px",
|
||||
width: "100%",
|
||||
}}
|
||||
>
|
||||
{dayResult} в {timeResult}
|
||||
</Typography>
|
||||
</Box>
|
||||
|
||||
<Box sx={{ display: "flex", flexDirection: "column", gap: "10px" }}>
|
||||
{name && (
|
||||
<Box sx={{ display: "flex", alignItems: "center", gap: "13px" }}>
|
||||
<ContactIcon />
|
||||
<Typography sx={{ fontSize: "18px", color: "#4D4D4D" }}>
|
||||
{name}
|
||||
</Typography>
|
||||
</Box>
|
||||
)}
|
||||
{email && (
|
||||
<Box sx={{ display: "flex", alignItems: "center", gap: "13px" }}>
|
||||
<MessageIcon />
|
||||
<Typography sx={{ fontSize: "18px", color: "#4D4D4D" }}>
|
||||
{email}
|
||||
</Typography>
|
||||
</Box>
|
||||
)}
|
||||
{phone && (
|
||||
<Box sx={{ display: "flex", alignItems: "center", gap: "13px" }}>
|
||||
<PhoneIcon />
|
||||
<Typography sx={{ fontSize: "18px", color: "#4D4D4D" }}>
|
||||
{phone}
|
||||
</Typography>
|
||||
</Box>
|
||||
)}
|
||||
{address && (
|
||||
<Box sx={{ display: "flex", alignItems: "center", gap: "13px" }}>
|
||||
<AddressIcon color={"#9A9AAF"} />
|
||||
<Typography sx={{ fontSize: "18px", color: "#4D4D4D" }}>
|
||||
{address}
|
||||
</Typography>
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
|
||||
{!isTablet && isNew && (
|
||||
<Typography
|
||||
sx={{
|
||||
ml: "auto",
|
||||
width: isTablet ? "100%" : "auto",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
background: "#FB5607",
|
||||
borderRadius: "8px",
|
||||
width: "77px",
|
||||
height: "36px",
|
||||
color: "white",
|
||||
alignItems: "flex-start",
|
||||
flexDirection: isTablet ? "row-reverse" : "-moz-initial",
|
||||
justifyContent: isTablet ? "space-between" : "-moz-initial",
|
||||
pb: isTablet ? "20px" : "0",
|
||||
mb: isTablet ? "20px" : "0",
|
||||
borderBottom: isTablet
|
||||
? "1px solid rgba(154, 154, 175, 0.50)"
|
||||
: "0",
|
||||
}}
|
||||
>
|
||||
Новая
|
||||
</Typography>
|
||||
)}
|
||||
</Box>
|
||||
<Box sx={{ display: "flex", alignItems: "center", gap: "6px" }}>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
width: "30px",
|
||||
height: "30px",
|
||||
borderRadius: "50%",
|
||||
background: "#EEE4FC",
|
||||
color: "#7E2AEA",
|
||||
}}
|
||||
>
|
||||
{idResult}
|
||||
</Box>
|
||||
<IconButton onClick={openResults}>
|
||||
<ArrowDownIcon
|
||||
style={{
|
||||
transform: isOpen ? "rotate(180deg)" : "rotate(360deg)",
|
||||
}}
|
||||
fontSize="10px"
|
||||
/>
|
||||
</IconButton>
|
||||
</Box>
|
||||
|
||||
<Box
|
||||
sx={{
|
||||
borderRadius: "8px",
|
||||
p: isTablet ? "20px" : "0",
|
||||
cursor: "pointer",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: isTablet ? "space-between" : "center",
|
||||
width: isTablet ? "100%" : "100px",
|
||||
background: "#F2F3F7",
|
||||
}}
|
||||
>
|
||||
{isTablet && isNew ? (
|
||||
<>
|
||||
<Typography
|
||||
sx={{
|
||||
ml: isTablet ? "0" : "50px",
|
||||
mr: isTablet ? "0" : "188px",
|
||||
fontSize: "18px",
|
||||
color: "#7E2AEA",
|
||||
maxWidth: "143px",
|
||||
width: "100%",
|
||||
}}
|
||||
>
|
||||
{dayResult} в {timeResult}
|
||||
</Typography>
|
||||
</Box>
|
||||
|
||||
<Box sx={{ display: "flex", flexDirection: "column", gap: "10px" }}>
|
||||
{name && (
|
||||
<Box
|
||||
sx={{ display: "flex", alignItems: "center", gap: "13px" }}
|
||||
>
|
||||
<ContactIcon />
|
||||
<Typography sx={{ fontSize: "18px", color: "#4D4D4D" }}>
|
||||
{name}
|
||||
</Typography>
|
||||
</Box>
|
||||
)}
|
||||
{email && (
|
||||
<Box
|
||||
sx={{ display: "flex", alignItems: "center", gap: "13px" }}
|
||||
>
|
||||
<MessageIcon />
|
||||
<Typography sx={{ fontSize: "18px", color: "#4D4D4D" }}>
|
||||
{email}
|
||||
</Typography>
|
||||
</Box>
|
||||
)}
|
||||
{phone && (
|
||||
<Box
|
||||
sx={{ display: "flex", alignItems: "center", gap: "13px" }}
|
||||
>
|
||||
<PhoneIcon />
|
||||
<Typography sx={{ fontSize: "18px", color: "#4D4D4D" }}>
|
||||
{phone}
|
||||
</Typography>
|
||||
</Box>
|
||||
)}
|
||||
{address && (
|
||||
<Box
|
||||
sx={{ display: "flex", alignItems: "center", gap: "13px" }}
|
||||
>
|
||||
<AddressIcon color={"#9A9AAF"} />
|
||||
<Typography sx={{ fontSize: "18px", color: "#4D4D4D" }}>
|
||||
{address}
|
||||
</Typography>
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
|
||||
{!isTablet && isNew && (
|
||||
<Typography
|
||||
sx={{
|
||||
ml: "auto",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
@ -262,202 +234,241 @@ export const CardAnswer = ({
|
||||
>
|
||||
Новая
|
||||
</Typography>
|
||||
<Box sx={{ display: "flex", alignItems: "center" }}>
|
||||
<IconButton onClick={() => setOpenDelete(true)}>
|
||||
<DeleteIcon color="#4D4D4D" fontSize="34px" />
|
||||
</IconButton>
|
||||
</Box>
|
||||
</>
|
||||
) : (
|
||||
<IconButton onClick={() => setOpenDelete(true)}>
|
||||
<DeleteIcon color="#4D4D4D" fontSize="34px" />
|
||||
</IconButton>
|
||||
)}
|
||||
<DeleteModal
|
||||
openDelete={openDelete}
|
||||
handleClose={() => setOpenDelete(false)}
|
||||
onClick={() => {
|
||||
deleteResult(Number(idResult));
|
||||
setOpenDelete(false);
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
{isOpen && (
|
||||
<Box
|
||||
sx={{
|
||||
borderRadius: "12px",
|
||||
maxWidth: isTablet ? "450px" : "auto",
|
||||
width: "100%",
|
||||
boxShadow:
|
||||
"0px 2.767px 8.551px 0px rgba(210, 208, 225, 0.07), 0px 6.65px 20.549px 0px rgba(210, 208, 225, 0.10), 0px 12.522px 38.692px 0px rgba(210, 208, 225, 0.12), 0px 22.336px 69.019px 0px rgba(210, 208, 225, 0.14), 0px 41.778px 129.093px 0px rgba(210, 208, 225, 0.17), 0px 100px 309px 0px rgba(210, 208, 225, 0.24)",
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
p: "20px",
|
||||
borderTop: "1px solid #F1F2F6",
|
||||
background: "#FFF",
|
||||
borderRadius: "0 0 12px 12px",
|
||||
}}
|
||||
>
|
||||
<Typography sx={{ fontSize: "18px", color: "#9A9AAF" }}>
|
||||
Ответы
|
||||
</Typography>
|
||||
)}
|
||||
</Box>
|
||||
|
||||
<Box
|
||||
sx={{
|
||||
borderRadius: "8px",
|
||||
p: isTablet ? "20px" : "0",
|
||||
cursor: "pointer",
|
||||
display: "flex",
|
||||
gap: isTablet ? "0" : "149px",
|
||||
p: "20px",
|
||||
flexDirection: isTablet ? "column" : "-moz-initial",
|
||||
alignItems: "center",
|
||||
justifyContent: isTablet ? "space-between" : "center",
|
||||
width: isTablet ? "100%" : "100px",
|
||||
background: "#F2F3F7",
|
||||
}}
|
||||
>
|
||||
{isTablet && isNew ? (
|
||||
<>
|
||||
<Typography
|
||||
sx={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
background: "#FB5607",
|
||||
borderRadius: "8px",
|
||||
width: "77px",
|
||||
height: "36px",
|
||||
color: "white",
|
||||
}}
|
||||
>
|
||||
Новая
|
||||
</Typography>
|
||||
<Box sx={{ display: "flex", alignItems: "center" }}>
|
||||
<IconButton onClick={onClickDelete}>
|
||||
<DeleteIcon color="#4D4D4D" fontSize="34px" />
|
||||
</IconButton>
|
||||
</Box>
|
||||
</>
|
||||
) : (
|
||||
<IconButton onClick={onClickDelete}>
|
||||
<DeleteIcon color="#4D4D4D" fontSize="34px" />
|
||||
</IconButton>
|
||||
)}
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
{isOpen && (
|
||||
<Box
|
||||
sx={{
|
||||
borderRadius: "12px",
|
||||
maxWidth: isTablet ? "450px" : "auto",
|
||||
width: "100%",
|
||||
boxShadow:
|
||||
"0px 2.767px 8.551px 0px rgba(210, 208, 225, 0.07), 0px 6.65px 20.549px 0px rgba(210, 208, 225, 0.10), 0px 12.522px 38.692px 0px rgba(210, 208, 225, 0.12), 0px 22.336px 69.019px 0px rgba(210, 208, 225, 0.14), 0px 41.778px 129.093px 0px rgba(210, 208, 225, 0.17), 0px 100px 309px 0px rgba(210, 208, 225, 0.24)",
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
gap: "15px",
|
||||
mt: "20px",
|
||||
p: "20px",
|
||||
borderTop: "1px solid #F1F2F6",
|
||||
background: "#FFF",
|
||||
borderRadius: "0 0 12px 12px",
|
||||
}}
|
||||
>
|
||||
{resultsAnswer.map((answer, id) => {
|
||||
let titleQuestion;
|
||||
let typeOuestion;
|
||||
let typeQuestionFile;
|
||||
let quest = questions; //массив с вопросами
|
||||
let i;
|
||||
let idAnswer = answer.question_id; //айди вопроса у ответа
|
||||
for (i in quest) {
|
||||
if (quest[i].backendId === idAnswer) {
|
||||
titleQuestion = quest[i].title;
|
||||
typeOuestion = quest[i].type;
|
||||
typeQuestionFile = quest[i].content.type;
|
||||
}
|
||||
}
|
||||
return (
|
||||
<Box
|
||||
sx={{ display: "flex", alignItems: "center", gap: "13px" }}
|
||||
>
|
||||
<Typography sx={{ fontSize: "18px", color: "#9A9AAF" }}>
|
||||
{id + 1}. {titleQuestion}.
|
||||
</Typography>
|
||||
{typeOuestion === "file" && (
|
||||
<Link
|
||||
download
|
||||
href={answer.content}
|
||||
style={{
|
||||
color: "#7E2AEA",
|
||||
display: "flex",
|
||||
gap: "10px",
|
||||
}}
|
||||
>
|
||||
{typeQuestionFile === "video" && (
|
||||
<video
|
||||
src={answer.content}
|
||||
width={40}
|
||||
height={40}
|
||||
></video>
|
||||
)}
|
||||
{typeQuestionFile === "picture" && (
|
||||
<img src={answer.content} width={40} height={40} />
|
||||
)}
|
||||
клик для скачивания
|
||||
</Link>
|
||||
)}
|
||||
{(typeOuestion === "images" ||
|
||||
typeOuestion === "varimg") && (
|
||||
<>
|
||||
<img
|
||||
width={40}
|
||||
height={40}
|
||||
src={
|
||||
answer.content
|
||||
.split("<")[1]
|
||||
.split('src="')[1]
|
||||
.split('"/>')[0]
|
||||
}
|
||||
/>
|
||||
|
||||
<Typography sx={{ fontSize: "18px" }}>
|
||||
{answer.content.split("<")[0]}
|
||||
</Typography>
|
||||
</>
|
||||
)}
|
||||
{!(
|
||||
typeOuestion === "file" ||
|
||||
typeOuestion === "images" ||
|
||||
typeOuestion === "varimg"
|
||||
) && (
|
||||
<Typography sx={{ fontSize: "18px" }}>
|
||||
{answer.content}
|
||||
</Typography>
|
||||
)}
|
||||
</Box>
|
||||
);
|
||||
})}
|
||||
<Typography sx={{ fontSize: "18px", color: "#9A9AAF" }}>
|
||||
Ответы
|
||||
</Typography>
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
<Box
|
||||
sx={{
|
||||
p: "20px",
|
||||
borderTop: "1px solid #F1F2F6",
|
||||
background: "#FFF",
|
||||
borderRadius: "0 0 12px 12px",
|
||||
}}
|
||||
>
|
||||
<Typography sx={{ fontSize: "18px", color: "#9A9AAF" }}>
|
||||
Результаты
|
||||
</Typography>
|
||||
</Box>
|
||||
{questionsResultState.map((res) => {
|
||||
console.log(questionsResultState, "что за результат тут");
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
gap: isTablet ? "0" : "149px",
|
||||
p: "20px",
|
||||
flexDirection: isTablet ? "column" : "-moz-initial",
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
gap: "15px",
|
||||
p: "20px",
|
||||
mt: "20px",
|
||||
}}
|
||||
>
|
||||
<Typography
|
||||
{resultsAnswer.map((answer, id) => {
|
||||
let titleQuestion;
|
||||
let typeOuestion;
|
||||
let typeQuestionFile;
|
||||
let quest = questions; //массив с вопросами
|
||||
let i;
|
||||
let idAnswer = answer.question_id; //айди вопроса у ответа
|
||||
for (i in quest) {
|
||||
if (quest[i].backendId === idAnswer) {
|
||||
titleQuestion = quest[i].title;
|
||||
typeOuestion = quest[i].type;
|
||||
typeQuestionFile = quest[i].content.type;
|
||||
}
|
||||
}
|
||||
return (
|
||||
<Box
|
||||
key={answer.id}
|
||||
sx={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
gap: "13px",
|
||||
}}
|
||||
>
|
||||
<Typography sx={{ fontSize: "18px", color: "#9A9AAF" }}>
|
||||
{id + 1}. {titleQuestion}.
|
||||
</Typography>
|
||||
{typeOuestion === "file" && (
|
||||
<Link
|
||||
download
|
||||
href={answer.content}
|
||||
style={{
|
||||
color: "#7E2AEA",
|
||||
display: "flex",
|
||||
gap: "10px",
|
||||
}}
|
||||
>
|
||||
{typeQuestionFile === "video" && (
|
||||
<video
|
||||
src={answer.content}
|
||||
width={40}
|
||||
height={40}
|
||||
></video>
|
||||
)}
|
||||
{typeQuestionFile === "picture" && (
|
||||
<img src={answer.content} width={40} height={40} />
|
||||
)}
|
||||
клик для скачивания
|
||||
</Link>
|
||||
)}
|
||||
{(typeOuestion === "images" ||
|
||||
typeOuestion === "varimg") && (
|
||||
<>
|
||||
<img
|
||||
width={40}
|
||||
height={40}
|
||||
src={
|
||||
answer.content
|
||||
.split("<")[1]
|
||||
.split('src="')[1]
|
||||
.split('"/>')[0]
|
||||
}
|
||||
/>
|
||||
|
||||
<Typography sx={{ fontSize: "18px" }}>
|
||||
{answer.content.split("<")[0]}
|
||||
</Typography>
|
||||
</>
|
||||
)}
|
||||
{!(
|
||||
typeOuestion === "file" ||
|
||||
typeOuestion === "images" ||
|
||||
typeOuestion === "varimg"
|
||||
) && (
|
||||
<Typography sx={{ fontSize: "18px" }}>
|
||||
{answer.content}
|
||||
</Typography>
|
||||
)}
|
||||
</Box>
|
||||
);
|
||||
})}
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
<Box
|
||||
sx={{
|
||||
p: "20px",
|
||||
borderTop: "1px solid #F1F2F6",
|
||||
background: "#FFF",
|
||||
borderRadius: "0 0 12px 12px",
|
||||
}}
|
||||
>
|
||||
<Typography sx={{ fontSize: "18px", color: "#9A9AAF" }}>
|
||||
Результаты
|
||||
</Typography>
|
||||
</Box>
|
||||
{questionsResultState.map((res) => {
|
||||
return (
|
||||
<Box
|
||||
key={res.id}
|
||||
sx={{
|
||||
fontSize: "18px",
|
||||
fontWeight: "500",
|
||||
wordBreak: "break-word",
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
gap: "15px",
|
||||
p: "20px",
|
||||
}}
|
||||
>
|
||||
{res.description}
|
||||
</Typography>
|
||||
<Typography sx={{ fontSize: "18px", wordBreak: "break-word" }}>
|
||||
{res.title}
|
||||
</Typography>
|
||||
{res.content.useImage &&
|
||||
res.content.back &&
|
||||
res.content.back !== " " && (
|
||||
<img
|
||||
src={res.content.back}
|
||||
style={{ width: "40px", height: "40px" }}
|
||||
alt={""}
|
||||
/>
|
||||
)}
|
||||
{!res.content.useImage &&
|
||||
res.content.back &&
|
||||
res.content.back !== " " && (
|
||||
<video
|
||||
src={res.content.back}
|
||||
style={{ width: "40px", height: "40px" }}
|
||||
></video>
|
||||
)}
|
||||
</Box>
|
||||
);
|
||||
})}
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
<Typography
|
||||
sx={{
|
||||
fontSize: "18px",
|
||||
fontWeight: "500",
|
||||
wordBreak: "break-word",
|
||||
}}
|
||||
>
|
||||
{res.description}
|
||||
</Typography>
|
||||
<Typography
|
||||
sx={{ fontSize: "18px", wordBreak: "break-word" }}
|
||||
>
|
||||
{res.title}
|
||||
</Typography>
|
||||
{res.content.useImage &&
|
||||
res.content.back &&
|
||||
res.content.back !== " " && (
|
||||
<img
|
||||
src={res.content.back}
|
||||
style={{ width: "40px", height: "40px" }}
|
||||
alt={""}
|
||||
/>
|
||||
)}
|
||||
{!res.content.useImage &&
|
||||
res.content.back &&
|
||||
res.content.back !== " " && (
|
||||
<video
|
||||
src={res.content.back}
|
||||
style={{ width: "40px", height: "40px" }}
|
||||
></video>
|
||||
)}
|
||||
</Box>
|
||||
);
|
||||
})}
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
<DeleteModal
|
||||
openDelete={openDelete}
|
||||
handleClose={() => setOpenDelete(false)}
|
||||
onClick={() => {
|
||||
deleteResult(Number(idResult));
|
||||
setOpenDelete(false);
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
@ -1,37 +1,22 @@
|
||||
import {
|
||||
Box,
|
||||
Typography,
|
||||
useTheme,
|
||||
useMediaQuery,
|
||||
Skeleton,
|
||||
} from "@mui/material";
|
||||
import { Box, Skeleton, useMediaQuery, useTheme } from "@mui/material";
|
||||
import HeaderFull from "@ui_kit/Header/HeaderFull";
|
||||
import SectionWrapper from "@ui_kit/SectionWrapper";
|
||||
import { FC, useEffect, useState } from "react";
|
||||
import { CardAnswer } from "./CardAnswer";
|
||||
import { ChangeEvent, FC, useEffect, useState } from "react";
|
||||
import { PrePaymentModal } from "./PrePaymentModal";
|
||||
import { FilterModal } from "@ui_kit/Modal/FilterModal/FilterModal";
|
||||
|
||||
import { resultApi } from "@api/result";
|
||||
import { useResultStore } from "@root/results/store";
|
||||
import { ExportResults, setResults } from "@root/results/actions";
|
||||
|
||||
import { quizApi } from "@api/quiz";
|
||||
import { setQuizes } from "@root/quizes/actions";
|
||||
import { setResults } from "@root/results/actions";
|
||||
import { useCurrentQuiz } from "@root/quizes/hooks";
|
||||
import { useQuizStore } from "@root/quizes/store";
|
||||
import { questionApi } from "@api/question";
|
||||
import { setQuestions } from "@root/questions/actions";
|
||||
import { useUserStore } from "@root/user";
|
||||
|
||||
import CustomPagination from "@ui_kit/CustomPagination";
|
||||
import SettingResults from "./SettingResults";
|
||||
import { DateDefinition, parseFilters, TimeDefinition } from "./helper";
|
||||
|
||||
const itemsCities = [
|
||||
{ label: "Муром (1)", value: "option1" },
|
||||
{ label: "Москва (1)", value: "option2" },
|
||||
];
|
||||
import { parseFilters } from "./helper";
|
||||
import { QuizSettingsMenu } from "./QuizSettingsMenu";
|
||||
import { AnswerList } from "./AnswerList";
|
||||
import { useGetData } from "./useGetData";
|
||||
|
||||
const itemsTime = [
|
||||
"За всё время",
|
||||
@ -50,8 +35,6 @@ export const QuizAnswersPage: FC = () => {
|
||||
|
||||
const [filterModalOpen, setFilterModalOpen] = useState<boolean>(false);
|
||||
const [page, setPage] = useState(1);
|
||||
const [exportContactsModalOpen, setExportContactsModalOpen] =
|
||||
useState<boolean>(false);
|
||||
const [filterNew, setFilterNew] = useState<string>("Все заявки");
|
||||
const [filterDate, setFilterDate] = useState<string>("За всё время");
|
||||
const [prePaymentModalOpen, setPrePaymentModalOpen] =
|
||||
@ -68,14 +51,13 @@ export const QuizAnswersPage: FC = () => {
|
||||
const quiz = useCurrentQuiz();
|
||||
const { editQuizId } = useQuizStore();
|
||||
const { results, total_count } = useResultStore();
|
||||
const countPagination =
|
||||
typeof total_count === "number" ? Math.ceil(total_count / 10) : 0;
|
||||
useGetData(filterNew, filterDate);
|
||||
|
||||
console.log("Перерендер компонента ", results);
|
||||
|
||||
const countPagination = Math.ceil(total_count / 10);
|
||||
// const {idResultArray, addIdResult, clearIdResultArray} = useObsolescenceIdResult()
|
||||
useEffect(() => {
|
||||
getData();
|
||||
}, [filterNew, filterDate]);
|
||||
return setResults([]);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (!userAccount) {
|
||||
@ -94,31 +76,20 @@ export const QuizAnswersPage: FC = () => {
|
||||
setPrePaymentModalOpen(false);
|
||||
}, [userAccount]);
|
||||
|
||||
const getData = async () => {
|
||||
if (editQuizId !== null) {
|
||||
const quizes = await quizApi.getList();
|
||||
setQuizes(quizes);
|
||||
|
||||
const questions = await questionApi.getList({ quiz_id: editQuizId });
|
||||
setQuestions(questions);
|
||||
|
||||
const result = await resultApi.getList(
|
||||
editQuizId,
|
||||
0,
|
||||
parseFilters(filterNew, filterDate),
|
||||
);
|
||||
setResults(result);
|
||||
}
|
||||
};
|
||||
|
||||
const PaginationHC = async (e, value) => {
|
||||
const PaginationHC = async (e: ChangeEvent<unknown>, value: number) => {
|
||||
setPage(value);
|
||||
const result = await resultApi.getList(
|
||||
editQuizId,
|
||||
value - 1,
|
||||
parseFilters(filterNew, filterDate),
|
||||
);
|
||||
setResults(result);
|
||||
try {
|
||||
if (editQuizId !== null) {
|
||||
const result = await resultApi.getList(
|
||||
editQuizId,
|
||||
value - 1,
|
||||
parseFilters(filterNew, filterDate),
|
||||
);
|
||||
setResults(result);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("An error occurred while receiving data: ", error);
|
||||
}
|
||||
};
|
||||
|
||||
if (quiz === undefined)
|
||||
@ -133,137 +104,34 @@ export const QuizAnswersPage: FC = () => {
|
||||
sx={{ padding: isMobile ? "115px 16px" : "115px 20px 20px" }}
|
||||
maxWidth="lg"
|
||||
>
|
||||
<Typography
|
||||
sx={{
|
||||
fontSize: "36px",
|
||||
fontWeight: "500",
|
||||
mb: "50px",
|
||||
|
||||
lineHeight: "normal",
|
||||
wordBreak: "break-word",
|
||||
}}
|
||||
>
|
||||
{quiz.name}
|
||||
</Typography>
|
||||
|
||||
<Box
|
||||
sx={{
|
||||
width: "100%",
|
||||
display: isTablet ? "flex" : "-moz-initial",
|
||||
alignItems: "center",
|
||||
justifyContent: "space-between",
|
||||
}}
|
||||
>
|
||||
<Box sx={{ display: "flex", alignItems: "center", gap: "8px" }}>
|
||||
<Typography sx={{ fontSize: "18px", color: "#4D4D4D" }}>
|
||||
Ответы на квиз
|
||||
</Typography>
|
||||
<Typography sx={{ fontSize: "18px", color: "#9A9AAF" }}>
|
||||
({total_count})
|
||||
</Typography>
|
||||
</Box>
|
||||
|
||||
<Box
|
||||
sx={{
|
||||
mt: "20px",
|
||||
mb: "31px",
|
||||
gap: "30px",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "space-between",
|
||||
width: isTablet ? "auto" : "100%",
|
||||
}}
|
||||
>
|
||||
<SettingResults
|
||||
onclickExport={() =>
|
||||
ExportResults(
|
||||
filterNew,
|
||||
filterDate,
|
||||
() => setPrePaymentModalOpen(true),
|
||||
editQuizId,
|
||||
)
|
||||
}
|
||||
onclickUpdate={async () => {
|
||||
const result = await resultApi.getList(
|
||||
editQuizId,
|
||||
page - 1,
|
||||
parseFilters(filterNew, filterDate),
|
||||
);
|
||||
setResults(result);
|
||||
}}
|
||||
onclickFilterTablet={() => setFilterModalOpen(true)}
|
||||
onclickResetFilers={() => {
|
||||
setFilterNew("Все заявки");
|
||||
setFilterDate("За всё время");
|
||||
}}
|
||||
filterNewHC={filterNewHC}
|
||||
filterDateHC={filterDateHC}
|
||||
itemsTime={itemsTime}
|
||||
itemsNews={itemsNews}
|
||||
filterDate={filterDate}
|
||||
filterNew={filterNew}
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
<QuizSettingsMenu
|
||||
quiz={quiz}
|
||||
total_count={total_count}
|
||||
isTablet={isTablet}
|
||||
filterNew={filterNew}
|
||||
filterDate={filterDate}
|
||||
setPrePaymentModalOpen={setPrePaymentModalOpen}
|
||||
editQuizId={editQuizId}
|
||||
page={page}
|
||||
setFilterModalOpen={setFilterModalOpen}
|
||||
setFilterNew={setFilterNew}
|
||||
setFilterDate={setFilterDate}
|
||||
filterNewHC={filterNewHC}
|
||||
filterDateHC={filterDateHC}
|
||||
itemsTime={itemsTime}
|
||||
itemsNews={itemsNews}
|
||||
/>
|
||||
<CustomPagination
|
||||
countPagination={countPagination}
|
||||
page={page}
|
||||
onChange={PaginationHC}
|
||||
/>
|
||||
|
||||
{!isTablet && (
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
width: "100%",
|
||||
alignItems: "center",
|
||||
mb: "15px",
|
||||
}}
|
||||
>
|
||||
<Typography sx={{ fontSize: "18px", color: "#9A9AAF", mr: "40px" }}>
|
||||
№ заявки
|
||||
</Typography>
|
||||
<Typography sx={{ fontSize: "18px", color: "#9A9AAF" }}>
|
||||
Дата
|
||||
</Typography>
|
||||
<Typography
|
||||
sx={{ fontSize: "18px", color: "#9A9AAF", ml: "288px" }}
|
||||
>
|
||||
Контакты
|
||||
</Typography>
|
||||
</Box>
|
||||
)}
|
||||
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
alignItems: "flex-start",
|
||||
flexDirection: isTablet ? "-moz-initial" : "column",
|
||||
flexWrap: isTablet ? "wrap" : "nowrap",
|
||||
gap: "20px",
|
||||
}}
|
||||
>
|
||||
{results.map((result) => {
|
||||
const dataResult = new Date(result.created_at);
|
||||
let dayResult = DateDefinition(result.created_at);
|
||||
let timeResult = TimeDefinition(result.created_at);
|
||||
return (
|
||||
<CardAnswer
|
||||
name={result.content.name}
|
||||
email={result.content.email}
|
||||
phone={result.content.phone}
|
||||
address={result.content.address}
|
||||
isNew={result.new}
|
||||
idResult={result.id}
|
||||
dayResult={dayResult}
|
||||
timeResult={timeResult}
|
||||
openPrePaymentModal={() => setPrePaymentModalOpen(true)}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</Box>
|
||||
<AnswerList
|
||||
isTablet={isTablet}
|
||||
results={results}
|
||||
setPrePaymentModalOpen={setPrePaymentModalOpen}
|
||||
/>
|
||||
</SectionWrapper>
|
||||
|
||||
<FilterModal
|
||||
open={filterModalOpen}
|
||||
handleClose={() => setFilterModalOpen(false)}
|
||||
|
127
src/pages/QuizAnswersPage/QuizSettingsMenu.tsx
Normal file
127
src/pages/QuizAnswersPage/QuizSettingsMenu.tsx
Normal file
@ -0,0 +1,127 @@
|
||||
import SettingResults from "./SettingResults";
|
||||
import { ExportResults, setResults } from "@root/results/actions";
|
||||
import { resultApi } from "@api/result";
|
||||
import { parseFilters } from "./helper";
|
||||
import { Box, Typography } from "@mui/material";
|
||||
import { FC } from "react";
|
||||
import { Quiz } from "@model/quiz/quiz";
|
||||
|
||||
interface QuizSettingsMenuProps {
|
||||
quiz: Quiz;
|
||||
total_count: number;
|
||||
isTablet: boolean;
|
||||
filterNew: string;
|
||||
filterDate: string;
|
||||
setPrePaymentModalOpen: (value: boolean) => void;
|
||||
editQuizId: number | null;
|
||||
page: number;
|
||||
setFilterModalOpen: (value: boolean) => void;
|
||||
setFilterNew: (value: string) => void;
|
||||
setFilterDate: (value: string) => void;
|
||||
filterNewHC: (value: string) => void;
|
||||
filterDateHC: (value: string) => void;
|
||||
itemsTime: string[];
|
||||
itemsNews: string[];
|
||||
}
|
||||
|
||||
export const QuizSettingsMenu: FC<QuizSettingsMenuProps> = ({
|
||||
quiz,
|
||||
total_count,
|
||||
isTablet,
|
||||
filterNew,
|
||||
filterDate,
|
||||
setPrePaymentModalOpen,
|
||||
editQuizId,
|
||||
page,
|
||||
setFilterModalOpen,
|
||||
setFilterNew,
|
||||
setFilterDate,
|
||||
filterNewHC,
|
||||
filterDateHC,
|
||||
itemsTime,
|
||||
itemsNews,
|
||||
}) => {
|
||||
return (
|
||||
<>
|
||||
<Typography
|
||||
sx={{
|
||||
fontSize: "36px",
|
||||
fontWeight: "500",
|
||||
mb: "50px",
|
||||
|
||||
lineHeight: "normal",
|
||||
wordBreak: "break-word",
|
||||
}}
|
||||
>
|
||||
{quiz.name}
|
||||
</Typography>
|
||||
|
||||
<Box
|
||||
sx={{
|
||||
width: "100%",
|
||||
display: isTablet ? "flex" : "-moz-initial",
|
||||
alignItems: "center",
|
||||
justifyContent: "space-between",
|
||||
}}
|
||||
>
|
||||
<Box sx={{ display: "flex", alignItems: "center", gap: "8px" }}>
|
||||
<Typography sx={{ fontSize: "18px", color: "#4D4D4D" }}>
|
||||
Ответы на квиз
|
||||
</Typography>
|
||||
<Typography sx={{ fontSize: "18px", color: "#9A9AAF" }}>
|
||||
({total_count})
|
||||
</Typography>
|
||||
</Box>
|
||||
<Box
|
||||
sx={{
|
||||
mt: "20px",
|
||||
mb: "31px",
|
||||
gap: "30px",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "space-between",
|
||||
width: isTablet ? "auto" : "100%",
|
||||
}}
|
||||
>
|
||||
<SettingResults
|
||||
onclickExport={() => {
|
||||
if (editQuizId !== null) {
|
||||
ExportResults(
|
||||
filterNew,
|
||||
filterDate,
|
||||
() => setPrePaymentModalOpen(true),
|
||||
editQuizId,
|
||||
);
|
||||
} else {
|
||||
console.error("editQuizId is null");
|
||||
}
|
||||
}}
|
||||
onclickUpdate={async () => {
|
||||
if (editQuizId !== null) {
|
||||
const result = await resultApi.getList(
|
||||
editQuizId,
|
||||
page - 1,
|
||||
parseFilters(filterNew, filterDate),
|
||||
);
|
||||
setResults(result);
|
||||
} else {
|
||||
console.error("editQuizId is null");
|
||||
}
|
||||
}}
|
||||
onclickFilterTablet={() => setFilterModalOpen(true)}
|
||||
onclickResetFilers={() => {
|
||||
setFilterNew("Все заявки");
|
||||
setFilterDate("За всё время");
|
||||
}}
|
||||
filterNewHC={filterNewHC}
|
||||
filterDateHC={filterDateHC}
|
||||
itemsTime={itemsTime}
|
||||
itemsNews={itemsNews}
|
||||
filterDate={filterDate}
|
||||
filterNew={filterNew}
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
</>
|
||||
);
|
||||
};
|
@ -37,7 +37,6 @@ export default function SettingResults({
|
||||
}: Props) {
|
||||
const theme = useTheme();
|
||||
const isTablet = useMediaQuery(theme.breakpoints.down(1000));
|
||||
const isMobile = useMediaQuery(theme.breakpoints.down(600));
|
||||
return (
|
||||
<>
|
||||
<Box sx={{ display: "flex", alignItems: "center", gap: "10px" }}>
|
||||
|
@ -9,8 +9,6 @@ export const parseFilters = (filterNew: string, filterDate: string) => {
|
||||
|
||||
if (filterNew === "Новые") filters.new = true;
|
||||
if (filterDate.length !== 0 && filterDate !== "За всё время") {
|
||||
console.log(filterDate);
|
||||
|
||||
filters.to = new Date();
|
||||
|
||||
let resetedCurrentTime = Number(resetTime());
|
||||
|
@ -1,16 +0,0 @@
|
||||
export const EyeIcon = () => (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="30"
|
||||
height="30"
|
||||
viewBox="0 0 30 30"
|
||||
fill="none"
|
||||
>
|
||||
<path
|
||||
d="M3.26743 16.0459C2.91085 15.3939 2.91086 14.6059 3.26744 13.9539C5.53334 9.8107 9.93781 7 15 7C20.0622 7 24.4667 9.81079 26.7326 13.9541C27.0891 14.6061 27.0891 15.3941 26.7326 16.0461C24.4667 20.1893 20.0622 23 15 23C9.93782 23 5.53329 20.1892 3.26743 16.0459Z"
|
||||
stroke="#4D4D4D"
|
||||
strokeWidth="1.5"
|
||||
/>
|
||||
<circle cx="15" cy="15" r="4" stroke="#4D4D4D" strokeWidth="1.5" />
|
||||
</svg>
|
||||
);
|
Binary file not shown.
Before Width: | Height: | Size: 42 KiB |
Binary file not shown.
Before Width: | Height: | Size: 64 KiB |
41
src/pages/QuizAnswersPage/useGetData.ts
Normal file
41
src/pages/QuizAnswersPage/useGetData.ts
Normal file
@ -0,0 +1,41 @@
|
||||
import { useEffect } from "react";
|
||||
import { useQuizStore } from "@root/quizes/store";
|
||||
import { quizApi } from "@api/quiz";
|
||||
import { setQuizes } from "@root/quizes/actions";
|
||||
import { questionApi } from "@api/question";
|
||||
import { setQuestions } from "@root/questions/actions";
|
||||
import { resultApi } from "@api/result";
|
||||
import { parseFilters } from "./helper";
|
||||
import { setResults } from "@root/results/actions";
|
||||
|
||||
export const useGetData = (filterNew: string, filterDate: string): void => {
|
||||
const { editQuizId } = useQuizStore();
|
||||
|
||||
useEffect(() => {
|
||||
const getData = async (): Promise<void> => {
|
||||
try {
|
||||
if (editQuizId !== null) {
|
||||
const quizes = await quizApi.getList();
|
||||
setQuizes(quizes);
|
||||
|
||||
const questions = await questionApi.getList({ quiz_id: editQuizId });
|
||||
setQuestions(questions);
|
||||
|
||||
const result = await resultApi.getList(
|
||||
editQuizId,
|
||||
0,
|
||||
parseFilters(filterNew, filterDate),
|
||||
);
|
||||
if (result.total_count === 0) {
|
||||
console.log("No results found");
|
||||
}
|
||||
setResults(result);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("An error occurred while receiving data: ", error);
|
||||
}
|
||||
};
|
||||
|
||||
getData();
|
||||
}, [editQuizId, filterNew, filterDate, setResults]);
|
||||
};
|
@ -5,7 +5,6 @@ import { RequestQueue } from "@utils/requestQueue";
|
||||
import { resultApi } from "@api/result";
|
||||
import { devlog, getMessageFromFetchError } from "@frontend/kitui";
|
||||
import { enqueueSnackbar } from "notistack";
|
||||
import { useQuizStore } from "@root/quizes/store";
|
||||
import { AxiosError } from "axios";
|
||||
import { parseFilters } from "../../pages/QuizAnswersPage/helper";
|
||||
|
||||
@ -13,7 +12,7 @@ const REQUEST_DEBOUNCE = 200;
|
||||
const requestQueue = new RequestQueue();
|
||||
let requestTimeoutId: ReturnType<typeof setTimeout>;
|
||||
|
||||
export const setResults = (results: RawResult[] | null) =>
|
||||
export const setResults = (results: RawResult | []) =>
|
||||
setProducedState(
|
||||
(state) => {
|
||||
state.results = Object.values(results)[1]?.map(rawResultToResult) ?? [];
|
||||
@ -22,11 +21,10 @@ export const setResults = (results: RawResult[] | null) =>
|
||||
{
|
||||
type: "setResults",
|
||||
results,
|
||||
// total_count
|
||||
},
|
||||
);
|
||||
|
||||
const removeResult = (resultId: string) =>
|
||||
const removeResult = (resultId: number) =>
|
||||
setProducedState((state) => {
|
||||
const index = state.results.findIndex((r) => r.id === resultId);
|
||||
if (index === -1) return;
|
||||
@ -53,9 +51,9 @@ export const deleteResult = async (resultId: number) =>
|
||||
});
|
||||
|
||||
export const obsolescenceResult = async (
|
||||
resultId: string,
|
||||
resultId: number,
|
||||
editQuizId: number,
|
||||
) =>
|
||||
) => {
|
||||
requestQueue.enqueue(
|
||||
`obsolescenceResult-${resultId}-${editQuizId}`,
|
||||
async () => {
|
||||
@ -65,7 +63,7 @@ export const obsolescenceResult = async (
|
||||
if (!result) return;
|
||||
if (result.new === false) return;
|
||||
let lossDebouncer: null | ReturnType<typeof setTimeout> = null;
|
||||
let lossId: string[] = [] as string[];
|
||||
let lossId: number[] = [];
|
||||
if (!lossId.includes(resultId)) lossId.push(resultId);
|
||||
if (typeof lossDebouncer === "number") clearTimeout(lossDebouncer);
|
||||
lossDebouncer = setTimeout(async () => {
|
||||
@ -85,12 +83,13 @@ export const obsolescenceResult = async (
|
||||
setResults(resultList);
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
export const ExportResults = async (
|
||||
filterNew: string,
|
||||
filterDate: string,
|
||||
openPrePaymentModal: () => void,
|
||||
editQuizId: number | null,
|
||||
editQuizId: number,
|
||||
) => {
|
||||
try {
|
||||
const data = await resultApi.export(
|
||||
@ -101,7 +100,7 @@ export const ExportResults = async (
|
||||
|
||||
const blob = data;
|
||||
const link = document.createElement("a");
|
||||
link.href = window.URL.createObjectURL(blob);
|
||||
link.href = window.URL.createObjectURL(blob as Blob);
|
||||
link.download = `report_${new Date().getTime()}.xlsx`;
|
||||
link.click();
|
||||
} catch (nativeError) {
|
||||
|
@ -1,20 +1,19 @@
|
||||
import { create } from "zustand";
|
||||
import { devtools, persist } from "zustand/middleware";
|
||||
import { ResultContent } from "@model/result/result";
|
||||
|
||||
export type ResultStore = {
|
||||
results: [
|
||||
{
|
||||
results: {
|
||||
content: string;
|
||||
id: number;
|
||||
new: boolean;
|
||||
created_at: string;
|
||||
};
|
||||
},
|
||||
];
|
||||
results: Result[];
|
||||
total_count: number;
|
||||
};
|
||||
|
||||
export type Result = {
|
||||
content: ResultContent;
|
||||
id: number;
|
||||
new: boolean;
|
||||
created_at: string;
|
||||
};
|
||||
|
||||
const initialState: ResultStore = {
|
||||
results: [],
|
||||
total_count: 0,
|
||||
@ -40,7 +39,6 @@ export const useObsolescenceIdResult = create()(
|
||||
idResultArray: [],
|
||||
addIdResult: (idResult: number) => {
|
||||
const state = get()["idResultArray"] || [];
|
||||
console.log(state);
|
||||
const newState = [...state, idResult];
|
||||
set({ idResultArray: newState });
|
||||
},
|
||||
|
@ -1,9 +1,10 @@
|
||||
import { Pagination } from "@mui/material";
|
||||
import { ChangeEvent } from "react";
|
||||
|
||||
interface Props {
|
||||
countPagination: number;
|
||||
page: number;
|
||||
onChange: (e: ChangeEvent, value: number) => void;
|
||||
onChange: (e: ChangeEvent<unknown>, value: number) => void;
|
||||
}
|
||||
|
||||
export default function CustomPagination({
|
||||
|
Loading…
Reference in New Issue
Block a user