Merge branch 'dev' into 'staging'

ссылка на главную квиза во всех шильдиках, вписанное имя квиза до выбора типа...

See merge request frontend/squiz!173
This commit is contained in:
Nastya 2024-02-11 19:29:06 +00:00
commit 015cf35353
18 changed files with 126 additions and 64 deletions

@ -48,9 +48,9 @@ function getAnswerResultList(resultId: number) {
}); });
} }
function AnswerResultListEx(quizId: number, body:any) { function AnswerResultListEx(quizId: number, body: any) {
return makeRequest<unknown, unknown>({ return makeRequest<unknown, unknown>({
responseType: 'blob', responseType: "blob",
url: process.env.REACT_APP_DOMAIN + `/squiz/results/${quizId}/export`, url: process.env.REACT_APP_DOMAIN + `/squiz/results/${quizId}/export`,
method: "POST", method: "POST",
body: body, body: body,

@ -1,4 +1,4 @@
import { Box, Button, Typography, useTheme } from "@mui/material"; import { Box, Button, Divider, Typography, useTheme } from "@mui/material";
import { import {
decrementCurrentStep, decrementCurrentStep,
incrementCurrentStep, incrementCurrentStep,
@ -58,6 +58,7 @@ export default function FormQuestionsPage() {
}} }}
> >
<FormDraggableList /> <FormDraggableList />
<Divider />
<Box <Box
sx={{ sx={{
cursor: "pointer", cursor: "pointer",

@ -98,6 +98,7 @@ export default function SettingOptionsAndPict({
width: "100%", width: "100%",
mr: isMobile ? "0px" : "16px", mr: isMobile ? "0px" : "16px",
}} }}
maxLength={60}
placeholder={"Пример текста"} placeholder={"Пример текста"}
text={question.content.replText} text={question.content.replText}
onChange={({ target }) => setReplText(target.value)} onChange={({ target }) => setReplText(target.value)}
@ -182,6 +183,7 @@ export default function SettingOptionsAndPict({
sx={{ maxWidth: "360px", width: "100%" }} sx={{ maxWidth: "360px", width: "100%" }}
placeholder={"Пример текста"} placeholder={"Пример текста"}
text={question.content.replText} text={question.content.replText}
maxLength={60}
onChange={({ target }) => setReplText(target.value)} onChange={({ target }) => setReplText(target.value)}
/> />
</> </>

@ -46,7 +46,7 @@ export const Select = ({
setActiveItem(activeItemIndex); setActiveItem(activeItemIndex);
}, [activeItemIndex]); }, [activeItemIndex]);
useEffect(() => { useEffect(() => {
if (data) setActiveItem(items.indexOf(data)) if (data) setActiveItem(items.indexOf(data));
}, [data]); }, [data]);
const handleChange = (event: SelectChangeEvent) => { const handleChange = (event: SelectChangeEvent) => {

@ -439,10 +439,16 @@ export const CardAnswer = ({
p: "20px", p: "20px",
}} }}
> >
<Typography sx={{ fontSize: "18px", fontWeight: "500" }}> <Typography
sx={{
fontSize: "18px",
fontWeight: "500",
wordBreak: "break-word",
}}
>
{res.description || "нет заголовка"} {res.description || "нет заголовка"}
</Typography> </Typography>
<Typography sx={{ fontSize: "18px" }}> <Typography sx={{ fontSize: "18px", wordBreak: "break-word" }}>
{res.title || "нет текста"} {res.title || "нет текста"}
</Typography> </Typography>
<img <img

@ -31,6 +31,7 @@ import { setQuizes } from "@root/quizes/actions";
import { useCurrentQuiz, useQuizes } from "@root/quizes/hooks"; import { useCurrentQuiz, useQuizes } from "@root/quizes/hooks";
import { useQuizStore } from "@root/quizes/store"; import { useQuizStore } from "@root/quizes/store";
import { questionApi } from "@api/question"; import { questionApi } from "@api/question";
import { setQuestions } from "@root/questions/actions";
const itemsCities = [ const itemsCities = [
{ label: "Муром (1)", value: "option1" }, { label: "Муром (1)", value: "option1" },
@ -45,7 +46,7 @@ const itemsTime = [
"Последние 30 дней", "Последние 30 дней",
"Этот месяц", "Этот месяц",
]; ];
const itemsNews = ["Все заявки", "Новые"] const itemsNews = ["Все заявки", "Новые"];
const resetTime = () => { const resetTime = () => {
return Math.round(Number(moment().format("X")) / 86400 - 1) * 86400 - 0; return Math.round(Number(moment().format("X")) / 86400 - 1) * 86400 - 0;
@ -57,16 +58,16 @@ export const QuizAnswersPage: FC = () => {
const isMobile = useMediaQuery(theme.breakpoints.down(600)); const isMobile = useMediaQuery(theme.breakpoints.down(600));
const [filterModalOpen, setFilterModalOpen] = useState<boolean>(false); const [filterModalOpen, setFilterModalOpen] = useState<boolean>(false);
const [exportContactsModalOpen, setExportContactsModalOpen] = useState<boolean>(false); const [exportContactsModalOpen, setExportContactsModalOpen] =
useState<boolean>(false);
const [filterNew, setFilterNew] = useState<string>("Все заявки"); const [filterNew, setFilterNew] = useState<string>("Все заявки");
const [filterDate, setFilterDate] = useState<string>("За всё время"); const [filterDate, setFilterDate] = useState<string>("За всё время");
const filterNewHC = (value: string) => { const filterNewHC = (value: string) => {
setFilterNew(value) setFilterNew(value);
};
}
const filterDateHC = (value: string) => { const filterDateHC = (value: string) => {
setFilterDate(value) setFilterDate(value);
} };
const quizList = useQuizStore(); const quizList = useQuizStore();
const quiz = useCurrentQuiz(); const quiz = useCurrentQuiz();
@ -75,7 +76,6 @@ export const QuizAnswersPage: FC = () => {
const { total_count } = useResultStore(); const { total_count } = useResultStore();
// const {idResultArray, addIdResult, clearIdResultArray} = useObsolescenceIdResult() // const {idResultArray, addIdResult, clearIdResultArray} = useObsolescenceIdResult()
useEffect(() => { useEffect(() => {
getData(); getData();
}, [filterNew, filterDate]); }, [filterNew, filterDate]);
@ -101,31 +101,40 @@ export const QuizAnswersPage: FC = () => {
return timeResult; return timeResult;
}; };
const parseFilters = () => { const parseFilters = () => {
const filters: any = {} const filters: any = {};
if (filterNew === "Новые") filters.new = true if (filterNew === "Новые") filters.new = true;
if (filterDate.length !== 0 && filterDate !== "За всё время") { if (filterDate.length !== 0 && filterDate !== "За всё время") {
console.log(filterDate) console.log(filterDate);
filters.to = new Date filters.to = new Date();
let resetedCurrentTime = Number(resetTime()) let resetedCurrentTime = Number(resetTime());
if (filterDate === "Сегодня") filters.from = moment.unix(resetedCurrentTime)._d if (filterDate === "Сегодня")
if (filterDate === "Вчера") filters.from = moment.unix(resetedCurrentTime - 86400)._d filters.from = moment.unix(resetedCurrentTime)._d;
if (filterDate === "Последние 7 дней") filters.from = moment.unix(resetedCurrentTime - 604800)._d if (filterDate === "Вчера")
if (filterDate === "Последние 30 дней") filters.from = moment.unix(resetedCurrentTime - 2592000)._d filters.from = moment.unix(resetedCurrentTime - 86400)._d;
if (filterDate === "Последние 7 дней")
filters.from = moment.unix(resetedCurrentTime - 604800)._d;
if (filterDate === "Последние 30 дней")
filters.from = moment.unix(resetedCurrentTime - 2592000)._d;
if (filterDate === "Этот месяц") { if (filterDate === "Этот месяц") {
let date = new Date(), y = date.getFullYear(), m = date.getMonth(); let date = new Date(),
filters.from = new Date(y, m, 1) y = date.getFullYear(),
m = date.getMonth();
filters.from = new Date(y, m, 1);
} }
} }
return filters return filters;
} };
const getData = async () => { const getData = async () => {
if (editQuizId !== null) { if (editQuizId !== null) {
const quizes = await quizApi.getList(); const quizes = await quizApi.getList();
setQuizes(quizes); setQuizes(quizes);
const questions = await questionApi.getList({ quiz_id: editQuizId });
setQuestions(questions);
const result = await resultApi.getList(editQuizId, parseFilters()); const result = await resultApi.getList(editQuizId, parseFilters());
setResults(result); setResults(result);
} }
@ -144,7 +153,13 @@ export const QuizAnswersPage: FC = () => {
maxWidth="lg" maxWidth="lg"
> >
<Typography <Typography
sx={{ fontSize: "36px", fontWeight: "500", mb: "50px", mt: "60px" }} sx={{
fontSize: "36px",
fontWeight: "500",
mb: "50px",
mt: "60px",
lineHeight: "normal",
}}
> >
{quiz.name} {quiz.name}
</Typography> </Typography>
@ -180,15 +195,17 @@ export const QuizAnswersPage: FC = () => {
<Box sx={{ display: "flex", alignItems: "center", gap: "10px" }}> <Box sx={{ display: "flex", alignItems: "center", gap: "10px" }}>
<IconButton <IconButton
onClick={async () => { onClick={async () => {
const data = await resultApi.export(editQuizId, parseFilters()) const data = await resultApi.export(
console.log(typeof data) editQuizId,
parseFilters(),
);
console.log(typeof data);
const blob = data; const blob = data;
const link = document.createElement("a"); const link = document.createElement("a");
link.href = window.URL.createObjectURL(blob); link.href = window.URL.createObjectURL(blob);
link.download = `report_${new Date().getTime()}.xlsx`; link.download = `report_${new Date().getTime()}.xlsx`;
link.click(); link.click();
}} }}
sx={{ sx={{
width: "44px", width: "44px",
@ -207,7 +224,10 @@ const blob = data;
border: "1px solid #7E2AEA", border: "1px solid #7E2AEA",
}} }}
onClick={async () => { onClick={async () => {
const result = await resultApi.getList(editQuizId, parseFilters()); const result = await resultApi.getList(
editQuizId,
parseFilters(),
);
console.log(result); console.log(result);
setResults(result); setResults(result);
}} }}

@ -281,15 +281,20 @@ export const ResultCard = ({ resultContract, resultData }: Props) => {
}} }}
> >
<CustomTextField <CustomTextField
id="heading-result" id="headline-is-bolder"
value={resultData.title} value={resultData.description}
placeholder={"Заголовок результата"}
onChange={({ target }: { target: HTMLInputElement }) => onChange={({ target }: { target: HTMLInputElement }) =>
updateQuestion( updateQuestion(
resultData.id, resultData.id,
(question) => (question.title = target.value), (question) => (question.description = target.value),
) )
} }
placeholder={"Заголовок пожирнее"}
sx={{
borderRadius: "8px",
height: "48px",
width: "100%",
}}
/> />
<IconButton <IconButton
sx={{ padding: "0", margin: "5px" }} sx={{ padding: "0", margin: "5px" }}
@ -308,20 +313,15 @@ export const ResultCard = ({ resultContract, resultData }: Props) => {
}} }}
> >
<CustomTextField <CustomTextField
id="headline-is-bolder" id="heading-result"
value={resultData.description} value={resultData.title}
placeholder={"Заголовок результата"}
onChange={({ target }: { target: HTMLInputElement }) => onChange={({ target }: { target: HTMLInputElement }) =>
updateQuestion( updateQuestion(
resultData.id, resultData.id,
(question) => (question.description = target.value), (question) => (question.title = target.value),
) )
} }
placeholder={"Заголовок пожирнее"}
sx={{
borderRadius: "8px",
height: "48px",
width: "100%",
}}
/> />
</Box> </Box>

@ -258,7 +258,7 @@ function TariffPage() {
component="h2" component="h2"
mb="20px" mb="20px"
> >
Вы подтверждаете платёж в сумму {openModal.price} Вы подтверждаете платёж в сумму {openModal.price}
</Typography> </Typography>
<Button variant="contained" onClick={() => tryBuy(openModal)}> <Button variant="contained" onClick={() => tryBuy(openModal)}>
купить купить

@ -47,7 +47,10 @@ export const createTariffElements = (
buttonProps={{ buttonProps={{
text: "Выбрать", text: "Выбрать",
onClick: () => onClick: () =>
onclick({ id: tariff._id, price: priceAfterDiscounts / 100 }), onclick({
id: tariff._id,
price: currencyFormatter.format(priceAfterDiscounts / 100),
}),
}} }}
headerText={tariff.name} headerText={tariff.name}
text={tariff.privileges.map((p) => `${p.name} - ${p.amount}`)} text={tariff.privileges.map((p) => `${p.name} - ${p.amount}`)}

@ -239,11 +239,15 @@ export const ContactForm = ({
</Typography> </Typography>
</Box> </Box>
<Box <Box
component={Link}
target={"_blank"}
href={"https://quiz.pena.digital"}
sx={{ sx={{
display: "flex", display: "flex",
alignItems: "center", alignItems: "center",
mt: "20px", mt: "20px",
gap: "15px", gap: "15px",
textDecoration: "none",
}} }}
> >
<NameplateLogo <NameplateLogo

@ -1,5 +1,5 @@
import { useState, useEffect } from "react"; import { useState, useEffect } from "react";
import { Box, useMediaQuery, useTheme } from "@mui/material"; import { Box, Link, useMediaQuery, useTheme } from "@mui/material";
import { useCurrentQuiz } from "@root/quizes/hooks"; import { useCurrentQuiz } from "@root/quizes/hooks";
import { getQuestionByContentId } from "@root/questions/actions"; import { getQuestionByContentId } from "@root/questions/actions";
@ -94,13 +94,17 @@ export const Question = ({ questions }: QuestionProps) => {
<QuestionComponent currentQuestion={currentQuestion} /> <QuestionComponent currentQuestion={currentQuestion} />
<Box> <Box>
{mode[quiz.config.theme] ? ( {mode[quiz.config.theme] ? (
<NameplateLogoFQ <Link target={"_blank"} href={"https://quiz.pena.digital"}>
style={{ fontSize: "34px", width: "200px", height: "auto" }} <NameplateLogoFQ
/> style={{ fontSize: "34px", width: "200px", height: "auto" }}
/>
</Link>
) : ( ) : (
<NameplateLogoFQDark <Link target={"_blank"} href={"https://quiz.pena.digital"}>
style={{ fontSize: "34px", width: "200px", height: "auto" }} <NameplateLogoFQDark
/> style={{ fontSize: "34px", width: "200px", height: "auto" }}
/>
</Link>
)} )}
</Box> </Box>
</Box> </Box>

@ -4,6 +4,7 @@ import {
Button, Button,
useMediaQuery, useMediaQuery,
useTheme, useTheme,
Link,
} from "@mui/material"; } from "@mui/material";
import { getQuestionByContentId } from "@root/questions/actions"; import { getQuestionByContentId } from "@root/questions/actions";
@ -156,11 +157,15 @@ export const ResultForm = ({
}} }}
> >
<Box <Box
component={Link}
target={"_blank"}
href={"https://quiz.pena.digital"}
sx={{ sx={{
display: "flex", display: "flex",
alignItems: "center", alignItems: "center",
mt: "15px", mt: "15px",
gap: "10px", gap: "10px",
textDecoration: "none",
}} }}
> >
<NameplateLogo <NameplateLogo

@ -281,6 +281,8 @@ export const StartPageViewPublication = ({ setVisualStartPage }: Props) => {
overflowWrap: "break-word", overflowWrap: "break-word",
fontSize: "12px", fontSize: "12px",
textAlign: isTablet ? "start" : "end", textAlign: isTablet ? "start" : "end",
maxHeight: "120px",
overflow: "auto",
color: color:
quiz.config.startpageType === "expanded" && !isMobile quiz.config.startpageType === "expanded" && !isMobile
? "white" ? "white"
@ -292,10 +294,14 @@ export const StartPageViewPublication = ({ setVisualStartPage }: Props) => {
</Box> </Box>
<Box <Box
component={Link}
target={"_blank"}
href={"https://quiz.pena.digital"}
sx={{ sx={{
display: "flex", display: "flex",
alignItems: "center", alignItems: "center",
gap: "15px", gap: "15px",
textDecoration: "none",
}} }}
> >
<NameplateLogo <NameplateLogo
@ -371,6 +377,8 @@ function QuizPreviewLayoutByType({
alignItems: "flex-start", alignItems: "flex-start",
p: "25px", p: "25px",
height: "80%", height: "80%",
overflowY: "auto",
overflowX: "hidden",
}} }}
> >
{quizHeaderBlock} {quizHeaderBlock}

@ -149,6 +149,12 @@ export const Varimg = ({ currentQuestion }: VarimgProps) => {
style={{ width: "100%", height: "100%", objectFit: "cover" }} style={{ width: "100%", height: "100%", objectFit: "cover" }}
alt="" alt=""
/> />
) : currentQuestion.content.back !== " " ? (
<img
src={currentQuestion.content.back || gag}
style={{ width: "100%", height: "100%", objectFit: "cover" }}
alt=""
/>
) : currentQuestion.content.replText !== " " && ) : currentQuestion.content.replText !== " " &&
currentQuestion.content.replText.length > 0 ? ( currentQuestion.content.replText.length > 0 ? (
currentQuestion.content.replText currentQuestion.content.replText

@ -39,7 +39,7 @@ const validationSchema = object({
password: string() password: string()
.min(8, "Минимум 8 символов") .min(8, "Минимум 8 символов")
.matches( .matches(
/^[.,:;\-_+!&()<>\[\]\{\}`@"#$\%\^\=?\d\w]+$/, /^[.,:;\-_+!&()<>\[\]{}`@"~*|#$%^=?\d\w]+$/,
"Некорректные символы", "Некорректные символы",
) )
.required("Поле обязательно"), .required("Поле обязательно"),

@ -94,7 +94,6 @@ export default function QuizCard({
overflow: "hidden", overflow: "hidden",
whiteSpace: "nowrap", whiteSpace: "nowrap",
widows: "100%", widows: "100%",
maxWidth: "280px",
}} }}
variant="h5" variant="h5"
> >

@ -70,9 +70,11 @@ export default function StepOne() {
data-cy="create-quiz-card" data-cy="create-quiz-card"
onClick={() => { onClick={() => {
setQuizType(quiz.id, "quiz"); setQuizType(quiz.id, "quiz");
updateQuiz(quiz.id, (quiz) => { if (quiz.name === "" || quiz.name === " ") {
quiz.name = QuizgenegationName({ quiz }); updateQuiz(quiz.id, (quiz) => {
}); quiz.name = QuizgenegationName({ quiz });
});
}
}} }}
> >
<CreationCard <CreationCard
@ -88,9 +90,11 @@ export default function StepOne() {
variant="text" variant="text"
onClick={() => { onClick={() => {
setQuizType(quiz.id, "form"); setQuizType(quiz.id, "form");
updateQuiz(quiz.id, (quiz) => { if (quiz.name === "" || quiz.name === " ") {
quiz.name = QuizgenegationName({ quiz }); updateQuiz(quiz.id, (quiz) => {
}); quiz.name = QuizgenegationName({ quiz });
});
}
}} }}
> >
<CreationCard <CreationCard

@ -35,7 +35,7 @@ export const FilterModal: FC<Iprops> = ({
setFilterNew, setFilterNew,
setFilterDate, setFilterDate,
itemsTime, itemsTime,
itemsNews itemsNews,
}) => { }) => {
const theme = useTheme(); const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down(650)); const isMobile = useMediaQuery(theme.breakpoints.down(650));