diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100644 index 00000000..3ab2e13d --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,4 @@ +#!/usr/bin/env sh +. "$(dirname -- "$0")/_/husky.sh" + +yarn lint-staged --allow-empty diff --git a/package.json b/package.json index f79c3503..decf6cd8 100755 --- a/package.json +++ b/package.json @@ -1,85 +1,93 @@ { - "name": "squidward", - "version": "0.1.0", - "private": true, - "dependencies": { - "@craco/craco": "^7.0.0", - "@emotion/react": "^11.10.5", - "@emotion/styled": "^11.10.5", - "@frontend/kitui": "^1.0.55", - "@mui/icons-material": "^5.10.14", - "@mui/material": "^5.10.14", - "@mui/x-date-pickers": "^6.16.1", - "@testing-library/jest-dom": "^5.14.1", - "@testing-library/react": "^13.0.0", - "@testing-library/user-event": "^13.2.1", - "@types/cytoscape": "^3.19.16", - "@types/file-saver": "^2.0.5", - "@types/jest": "^27.0.1", - "@types/node": "^16.7.13", - "@types/react": "^18.0.0", - "@types/react-dnd": "^3.0.2", - "@types/react-dom": "^18.0.0", - "axios": "^1.5.1", - "cypress-file-upload": "^5.0.8", - "cytoscape": "^3.26.0", - "cytoscape-popper": "^2.0.0", - "date-fns": "^3.0.4", - "dayjs": "^1.11.10", - "emoji-mart": "^5.5.2", - "file-saver": "^2.0.5", - "formik": "^2.4.5", - "html-to-image": "^1.11.11", - "immer": "^10.0.3", - "jszip": "^3.10.1", - "nanoid": "^5.0.3", - "notistack": "^3.0.1", - "react": "^18.2.0", - "react-beautiful-dnd": "^13.1.1", - "react-cytoscapejs": "^2.0.0", - "react-dnd": "^16.0.1", - "react-dnd-html5-backend": "^16.0.1", - "react-dom": "^18.2.0", - "react-easy-crop": "^5.0.0", - "react-error-boundary": "^4.0.11", - "react-image-crop": "^10.1.5", - "react-image-file-resizer": "^0.4.8", - "react-rnd": "^10.4.1", - "react-router-dom": "^6.6.2", - "react-scripts": "5.0.1", - "swr": "^2.2.4", - "typescript": "^5.2.2", - "use-debounce": "^9.0.4", - "web-vitals": "^2.1.0", - "yup": "^1.3.2", - "zustand": "^4.3.8" - }, - "scripts": { - "start": "craco start", - "build": "craco build", - "test": "craco test", - "eject": "craco eject", - "cypress:open": "cypress open" - }, - "browserslist": { - "production": [ - ">0.2%", - "not dead", - "not op_mini all" - ], - "development": [ - "last 1 chrome version", - "last 1 firefox version", - "last 1 safari version" - ] - }, - "devDependencies": { - "@emoji-mart/data": "^1.1.2", - "@emoji-mart/react": "^1.1.1", - "@types/cytoscape-popper": "^2.0.4", - "@types/react-beautiful-dnd": "^13.1.4", - "@types/react-cytoscapejs": "^1.2.4", - "craco-alias": "^3.0.1", - "cypress": "^13.6.1" - } + "name": "squidward", + "version": "0.1.0", + "private": true, + "dependencies": { + "@craco/craco": "^7.0.0", + "@emotion/react": "^11.10.5", + "@emotion/styled": "^11.10.5", + "@frontend/kitui": "^1.0.55", + "@mui/icons-material": "^5.10.14", + "@mui/material": "^5.10.14", + "@mui/x-date-pickers": "^6.16.1", + "@testing-library/jest-dom": "^5.14.1", + "@testing-library/react": "^13.0.0", + "@testing-library/user-event": "^13.2.1", + "@types/cytoscape": "^3.19.16", + "@types/file-saver": "^2.0.5", + "@types/jest": "^27.0.1", + "@types/node": "^16.7.13", + "@types/react": "^18.0.0", + "@types/react-dnd": "^3.0.2", + "@types/react-dom": "^18.0.0", + "axios": "^1.5.1", + "cypress-file-upload": "^5.0.8", + "cytoscape": "^3.26.0", + "cytoscape-popper": "^2.0.0", + "date-fns": "^3.0.6", + "dayjs": "^1.11.10", + "emoji-mart": "^5.5.2", + "file-saver": "^2.0.5", + "formik": "^2.4.5", + "html-to-image": "^1.11.11", + "immer": "^10.0.3", + "jszip": "^3.10.1", + "nanoid": "^5.0.3", + "notistack": "^3.0.1", + "react": "^18.2.0", + "react-beautiful-dnd": "^13.1.1", + "react-cytoscapejs": "^2.0.0", + "react-dnd": "^16.0.1", + "react-dnd-html5-backend": "^16.0.1", + "react-dom": "^18.2.0", + "react-easy-crop": "^5.0.0", + "react-error-boundary": "^4.0.11", + "react-image-crop": "^10.1.5", + "react-image-file-resizer": "^0.4.8", + "react-rnd": "^10.4.1", + "react-router-dom": "^6.6.2", + "react-scripts": "5.0.1", + "swr": "^2.2.4", + "typescript": "^5.2.2", + "use-debounce": "^9.0.4", + "web-vitals": "^2.1.0", + "yup": "^1.3.2", + "zustand": "^4.3.8" + }, + "scripts": { + "start": "craco start", + "build": "craco build", + "test": "craco test", + "eject": "craco eject", + "cypress:open": "cypress open", + "code:format": "prettier ./src --write --ignore-unknown", + "prepare": "husky install" + }, + "browserslist": { + "production": [ + ">0.2%", + "not dead", + "not op_mini all" + ], + "development": [ + "last 1 chrome version", + "last 1 firefox version", + "last 1 safari version" + ] + }, + "devDependencies": { + "@emoji-mart/data": "^1.1.2", + "@emoji-mart/react": "^1.1.1", + "@types/cytoscape-popper": "^2.0.4", + "@types/react-beautiful-dnd": "^13.1.4", + "@types/react-cytoscapejs": "^1.2.4", + "craco-alias": "^3.0.1", + "cypress": "^13.6.1", + "husky": "^8.0.3", + "lint-staged": "^15.2.0", + "prettier": "^3.1.1" + }, + "lint-staged": { + "**/*": "yarn code:format" + } } diff --git a/prettierrc b/prettierrc new file mode 100644 index 00000000..80e56165 --- /dev/null +++ b/prettierrc @@ -0,0 +1,12 @@ +{ + "semi": true, + "trailingComma": "es5", + "singleQuote": false, + "printWidth": 120, + "tabWidth": 2, + "useTabs": false, + "endOfLine": "auto", + "bracketSpacing": true, + "arrowParens": "always", + "jsxSingleQuote": false +} diff --git a/public/index.html b/public/index.html index a96c59f9..daa88ffe 100755 --- a/public/index.html +++ b/public/index.html @@ -1,4 +1,4 @@ - + @@ -7,9 +7,12 @@ - - - + + + Pena Quiz diff --git a/public/site.webmanifest b/public/site.webmanifest index b20abb7c..fa99de77 100644 --- a/public/site.webmanifest +++ b/public/site.webmanifest @@ -1,19 +1,19 @@ { - "name": "", - "short_name": "", - "icons": [ - { - "src": "/android-chrome-192x192.png", - "sizes": "192x192", - "type": "image/png" - }, - { - "src": "/android-chrome-512x512.png", - "sizes": "512x512", - "type": "image/png" - } - ], - "theme_color": "#ffffff", - "background_color": "#ffffff", - "display": "standalone" + "name": "", + "short_name": "", + "icons": [ + { + "src": "/android-chrome-192x192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "/android-chrome-512x512.png", + "sizes": "512x512", + "type": "image/png" + } + ], + "theme_color": "#ffffff", + "background_color": "#ffffff", + "display": "standalone" } diff --git a/src/App.tsx b/src/App.tsx index 257a1892..35ccd8d3 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -6,7 +6,13 @@ import SigninDialog from "./pages/auth/Signin"; import SignupDialog from "./pages/auth/Signup"; import { ViewPage } from "./pages/ViewPublicationPage"; import { DesignPage } from "./pages/DesignPage/DesignPage"; -import { Route, Routes, useLocation, useNavigate, Navigate } from "react-router-dom"; +import { + Route, + Routes, + useLocation, + useNavigate, + Navigate, +} from "react-router-dom"; import "./index.css"; import ContactFormPage from "./pages/ContactFormPage/ContactFormPage"; import InstallQuiz from "./pages/InstallQuiz/InstallQuiz"; @@ -17,8 +23,21 @@ import { ResultSettings } from "./pages/ResultPage/ResultSettings"; import MyQuizzesFull from "./pages/createQuize/MyQuizzesFull"; import Main from "./pages/main"; import EditPage from "./pages/startPage/EditPage"; -import { clearAuthToken, getMessageFromFetchError, useUserFetcher, UserAccount, makeRequest, devlog, createUserAccount } from "@frontend/kitui"; -import { clearUserData, setUser, setUserAccount, useUserStore } from "@root/user"; +import { + clearAuthToken, + getMessageFromFetchError, + useUserFetcher, + UserAccount, + makeRequest, + devlog, + createUserAccount, +} from "@frontend/kitui"; +import { + clearUserData, + setUser, + setUserAccount, + useUserStore, +} from "@root/user"; import { enqueueSnackbar } from "notistack"; import PrivateRoute from "@ui_kit/PrivateRoute"; @@ -26,123 +45,163 @@ import { Restore } from "./pages/startPage/Restore"; import { isAxiosError } from "axios"; import { useEffect, useLayoutEffect, useRef } from "react"; -export function useUserAccountFetcher({ onError, onNewUserAccount, url, userId }: { - url: string; - userId: string | null; - onNewUserAccount: (response: UserAccount) => void; - onError?: (error: any) => void; +export function useUserAccountFetcher({ + onError, + onNewUserAccount, + url, + userId, +}: { + url: string; + userId: string | null; + onNewUserAccount: (response: UserAccount) => void; + onError?: (error: any) => void; }) { - const onNewUserAccountRef = useRef(onNewUserAccount); - const onErrorRef = useRef(onError); - useLayoutEffect(() => { - onNewUserAccountRef.current = onNewUserAccount; - onErrorRef.current = onError; - }, [onError, onNewUserAccount]); - useEffect(() => { - if (!userId) return; - const controller = new AbortController(); - makeRequest({ - url, - contentType: true, - method: "GET", - useToken: true, - withCredentials: false, - signal: controller.signal, - }).then(result => { - devlog("User account", result); - onNewUserAccountRef.current(result); - }).catch(error => { - devlog("Error fetching user account", error); - if (isAxiosError(error) && error.response?.status === 404) { - createUserAccount(controller.signal, url.replace('get','create')).then(result => { - devlog("Created user account", result); - onNewUserAccountRef.current(result); - }).catch(error => { - devlog("Error creating user account", error); - onErrorRef.current?.(error); - }); - } else { - onErrorRef.current?.(error); - } - }); - return () => controller.abort(); - }, [url, userId]); + const onNewUserAccountRef = useRef(onNewUserAccount); + const onErrorRef = useRef(onError); + useLayoutEffect(() => { + onNewUserAccountRef.current = onNewUserAccount; + onErrorRef.current = onError; + }, [onError, onNewUserAccount]); + useEffect(() => { + if (!userId) return; + const controller = new AbortController(); + makeRequest({ + url, + contentType: true, + method: "GET", + useToken: true, + withCredentials: false, + signal: controller.signal, + }) + .then((result) => { + devlog("User account", result); + onNewUserAccountRef.current(result); + }) + .catch((error) => { + devlog("Error fetching user account", error); + if (isAxiosError(error) && error.response?.status === 404) { + createUserAccount(controller.signal, url.replace("get", "create")) + .then((result) => { + devlog("Created user account", result); + onNewUserAccountRef.current(result); + }) + .catch((error) => { + devlog("Error creating user account", error); + onErrorRef.current?.(error); + }); + } else { + onErrorRef.current?.(error); + } + }); + return () => controller.abort(); + }, [url, userId]); } dayjs.locale("ru"); - const routeslink = [ - { path: "/list", page: , header: false, sidebar: false }, - { path: "/questions/:quizId", page: , header: true, sidebar: true }, - { path: "/contacts", page: , header: true, sidebar: true }, - { path: "/result", page: , header: true, sidebar: true }, - { path: "/settings", page: , header: true, sidebar: true }, + { path: "/list", page: , header: false, sidebar: false }, + { + path: "/questions/:quizId", + page: , + header: true, + sidebar: true, + }, + { path: "/contacts", page: , header: true, sidebar: true }, + { path: "/result", page: , header: true, sidebar: true }, + { path: "/settings", page: , header: true, sidebar: true }, ] as const; export default function App() { - const userId = useUserStore((state) => state.userId); - const location = useLocation(); - const navigate = useNavigate(); + const userId = useUserStore((state) => state.userId); + const location = useLocation(); + const navigate = useNavigate(); - useUserFetcher({ - url: `https://hub.pena.digital/user/${userId}`, - userId, - onNewUser: setUser, - onError: (error) => { - const errorMessage = getMessageFromFetchError(error); - if (errorMessage) { - enqueueSnackbar(errorMessage); - clearUserData(); - clearAuthToken(); - } - }, - }); + useUserFetcher({ + url: `https://hub.pena.digital/user/${userId}`, + userId, + onNewUser: setUser, + onError: (error) => { + const errorMessage = getMessageFromFetchError(error); + if (errorMessage) { + enqueueSnackbar(errorMessage); + clearUserData(); + clearAuthToken(); + } + }, + }); - useUserAccountFetcher({ - url: "https://squiz.pena.digital/squiz/account/get", - userId, - onNewUserAccount: setUserAccount, - onError: (error) => { - const errorMessage = getMessageFromFetchError(error); - if (errorMessage) { - enqueueSnackbar(errorMessage); - clearUserData(); - clearAuthToken(); - navigate("/signin"); - } - }, - }); - - if (location.state?.redirectTo) - return ; + useUserAccountFetcher({ + url: "https://squiz.pena.digital/squiz/account/get", + userId, + onNewUserAccount: setUserAccount, + onError: (error) => { + const errorMessage = getMessageFromFetchError(error); + if (errorMessage) { + enqueueSnackbar(errorMessage); + clearUserData(); + clearAuthToken(); + navigate("/signin"); + } + }, + }); + if (location.state?.redirectTo) return ( - <> - - {location.state?.backgroundLocation && ( - - } /> - } /> - } /> - - )} - - } /> - } /> - } /> - } /> - }> - {routeslink.map((e, i) => ( - } /> - ))} - - } /> - } /> - } /> - } /> - - - + ); + + return ( + <> + + {location.state?.backgroundLocation && ( + + } /> + } /> + } /> + + )} + + } /> + + } + /> + + } + /> + + } + /> + }> + {routeslink.map((e, i) => ( + + } + /> + ))} + + } /> + } /> + } /> + } /> + + + + ); } diff --git a/src/api/auth.ts b/src/api/auth.ts index 088363f4..092897f9 100644 --- a/src/api/auth.ts +++ b/src/api/auth.ts @@ -1,6 +1,5 @@ import { makeRequest } from "@frontend/kitui"; - import type { LoginRequest, LoginResponse, @@ -17,7 +16,7 @@ const apiUrl = export async function register( login: string, password: string, - phoneNumber: string + phoneNumber: string, ): Promise<[RegisterResponse | null, string?]> { try { const registerResponse = await makeRequest< @@ -40,7 +39,7 @@ export async function register( export async function login( login: string, - password: string + password: string, ): Promise<[LoginResponse | null, string?]> { try { const loginResponse = await makeRequest({ diff --git a/src/api/contactForm.ts b/src/api/contactForm.ts index 463bdaa1..f46bff5d 100644 --- a/src/api/contactForm.ts +++ b/src/api/contactForm.ts @@ -1,17 +1,19 @@ import axios from "axios"; -const domen = window.location.hostname === "localhost" ? "squiz.pena.digital" : window.location.hostname +const domen = + window.location.hostname === "localhost" + ? "squiz.pena.digital" + : window.location.hostname; export function sendContactFormRequest(body: { - - contact: string; - whoami: string; + contact: string; + whoami: string; }) { - return axios(`https://${domen}/feedback/callme`, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - data: body, - }); -} \ No newline at end of file + return axios(`https://${domen}/feedback/callme`, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + data: body, + }); +} diff --git a/src/api/question.ts b/src/api/question.ts index b59db063..e7a28fa4 100644 --- a/src/api/question.ts +++ b/src/api/question.ts @@ -1,79 +1,97 @@ import { makeRequest } from "@frontend/kitui"; import { CreateQuestionRequest } from "model/question/create"; import { RawQuestion } from "model/question/question"; -import { GetQuestionListRequest, GetQuestionListResponse } from "@model/question/getList"; -import { EditQuestionRequest, EditQuestionResponse } from "@model/question/edit"; -import { DeleteQuestionRequest, DeleteQuestionResponse } from "@model/question/delete"; -import { CopyQuestionRequest, CopyQuestionResponse } from "@model/question/copy"; +import { + GetQuestionListRequest, + GetQuestionListResponse, +} from "@model/question/getList"; +import { + EditQuestionRequest, + EditQuestionResponse, +} from "@model/question/edit"; +import { + DeleteQuestionRequest, + DeleteQuestionResponse, +} from "@model/question/delete"; +import { + CopyQuestionRequest, + CopyQuestionResponse, +} from "@model/question/copy"; import { replaceSpacesToEmptyLines } from "../utils/replaceSpacesToEmptyLines"; - -const baseUrl = process.env.NODE_ENV === "production" ? "/squiz" : "https://squiz.pena.digital/squiz"; +const baseUrl = + process.env.NODE_ENV === "production" + ? "/squiz" + : "https://squiz.pena.digital/squiz"; function createQuestion(body: CreateQuestionRequest) { - return makeRequest({ - url: `${baseUrl}/question/create`, - body, - method: "POST", - }); + return makeRequest({ + url: `${baseUrl}/question/create`, + body, + method: "POST", + }); } async function getQuestionList(body?: Partial) { - if (!body?.quiz_id) return null; + if (!body?.quiz_id) return null; - const response = await makeRequest({ - url: `${baseUrl}/question/getList`, - body: { ...defaultGetQuestionListBody, ...body }, - method: "POST", - }); - console.log(response.items) - const clearArrayFromEmptySpaceBlaBlaValue = response.items?.map(question => { - let data = question - for (let key in question) { - if (question[key] === " ") data[key] = "" - } - return data - }) + const response = await makeRequest< + GetQuestionListRequest, + GetQuestionListResponse + >({ + url: `${baseUrl}/question/getList`, + body: { ...defaultGetQuestionListBody, ...body }, + method: "POST", + }); + console.log(response.items); + const clearArrayFromEmptySpaceBlaBlaValue = response.items?.map( + (question) => { + let data = question; + for (let key in question) { + if (question[key] === " ") data[key] = ""; + } + return data; + }, + ); - return replaceSpacesToEmptyLines(clearArrayFromEmptySpaceBlaBlaValue); + return replaceSpacesToEmptyLines(clearArrayFromEmptySpaceBlaBlaValue); } function editQuestion(body: EditQuestionRequest, signal?: AbortSignal) { - return makeRequest({ - url: `${baseUrl}/question/edit`, - body, - method: "PATCH", - signal, - }); + return makeRequest({ + url: `${baseUrl}/question/edit`, + body, + method: "PATCH", + signal, + }); } function copyQuestion(questionId: number, quizId: number) { - return makeRequest({ - url: `${baseUrl}/question/copy`, - body: { id: questionId, quiz_id: quizId }, - method: "POST", - }); + return makeRequest({ + url: `${baseUrl}/question/copy`, + body: { id: questionId, quiz_id: quizId }, + method: "POST", + }); } function deleteQuestion(id: number) { - return makeRequest({ - url: `${baseUrl}/question/delete`, - body: { id }, - method: "DELETE", - }); + return makeRequest({ + url: `${baseUrl}/question/delete`, + body: { id }, + method: "DELETE", + }); } export const questionApi = { - create: createQuestion, - getList: getQuestionList, - edit: editQuestion, - copy: copyQuestion, - delete: deleteQuestion, + create: createQuestion, + getList: getQuestionList, + edit: editQuestion, + copy: copyQuestion, + delete: deleteQuestion, }; - const defaultGetQuestionListBody: GetQuestionListRequest = { - "limit": 100, - "offset": 0, - "type": "", + limit: 100, + offset: 0, + type: "", }; diff --git a/src/api/quiz.ts b/src/api/quiz.ts index 140aab14..b41c8857 100644 --- a/src/api/quiz.ts +++ b/src/api/quiz.ts @@ -8,111 +8,115 @@ import { GetQuizRequest, GetQuizResponse } from "model/quiz/get"; import { GetQuizListRequest, GetQuizListResponse } from "model/quiz/getList"; import { RawQuiz } from "model/quiz/quiz"; - -const baseUrl = process.env.NODE_ENV === "production" ? "/squiz" : "https://squiz.pena.digital/squiz"; -const imagesUrl = process.env.NODE_ENV === "production" ? "/squizstorer" : "https://squiz.pena.digital/squizstorer"; +const baseUrl = + process.env.NODE_ENV === "production" + ? "/squiz" + : "https://squiz.pena.digital/squiz"; +const imagesUrl = + process.env.NODE_ENV === "production" + ? "/squizstorer" + : "https://squiz.pena.digital/squizstorer"; function createQuiz(body?: Partial) { - return makeRequest({ - url: `${baseUrl}/quiz/create`, - body: { ...defaultCreateQuizBody, ...body }, - method: "POST", - }); + return makeRequest({ + url: `${baseUrl}/quiz/create`, + body: { ...defaultCreateQuizBody, ...body }, + method: "POST", + }); } async function getQuizList(body?: Partial) { - const response = await makeRequest({ - url: `${baseUrl}/quiz/getList`, - body: { ...defaultGetQuizListBody, ...body }, - method: "POST", - }); + const response = await makeRequest({ + url: `${baseUrl}/quiz/getList`, + body: { ...defaultGetQuizListBody, ...body }, + method: "POST", + }); - return response.items; + return response.items; } function getQuiz(body?: Partial) { - return makeRequest({ - url: `${baseUrl}/quiz/get`, - body: { ...defaultGetQuizBody, ...body }, - method: "GET", - }); + return makeRequest({ + url: `${baseUrl}/quiz/get`, + body: { ...defaultGetQuizBody, ...body }, + method: "GET", + }); } async function editQuiz(body: EditQuizRequest, signal?: AbortSignal) { - return makeRequest({ - url: `${baseUrl}/quiz/edit`, - body, - method: "PATCH", - signal, - }); + return makeRequest({ + url: `${baseUrl}/quiz/edit`, + body, + method: "PATCH", + signal, + }); } function copyQuiz(id: number) { - return makeRequest({ - url: `${baseUrl}/quiz/copy`, - body: { id }, - method: "POST", - }); + return makeRequest({ + url: `${baseUrl}/quiz/copy`, + body: { id }, + method: "POST", + }); } function deleteQuiz(id: number) { - return makeRequest({ - url: `${baseUrl}/quiz/delete`, - body: { id }, - method: "DELETE", - }); + return makeRequest({ + url: `${baseUrl}/quiz/delete`, + body: { id }, + method: "DELETE", + }); } function addQuizImages(quizId: number, image: Blob) { - const formData = new FormData(); + const formData = new FormData(); - formData.append("quiz", quizId.toString()); - formData.append("image", image); + formData.append("quiz", quizId.toString()); + formData.append("image", image); - return makeRequest({ - url: `${imagesUrl}/quiz/putImages`, - body: formData, - method: "PUT", - }); + return makeRequest({ + url: `${imagesUrl}/quiz/putImages`, + body: formData, + method: "PUT", + }); } export const quizApi = { - create: createQuiz, - getList: getQuizList, - get: getQuiz, - edit: editQuiz, - copy: copyQuiz, - delete: deleteQuiz, - addImages: addQuizImages, + create: createQuiz, + getList: getQuizList, + get: getQuiz, + edit: editQuiz, + copy: copyQuiz, + delete: deleteQuiz, + addImages: addQuizImages, }; - const defaultCreateQuizBody: CreateQuizRequest = { - "fingerprinting": true, - "repeatable": true, - "note_prevented": true, - "mail_notifications": false, - "unique_answers": true, - "name": "", - "description": "", - "config": JSON.stringify(defaultQuizConfig), - "status": "stop", - "limit": 0, - "due_to": 0, - "time_of_passing": 0, - "pausable": false, - "super": false, - "group_id": 0, + fingerprinting: true, + repeatable: true, + note_prevented: true, + mail_notifications: false, + unique_answers: true, + name: "", + description: "", + config: JSON.stringify(defaultQuizConfig), + status: "stop", + limit: 0, + due_to: 0, + time_of_passing: 0, + pausable: false, + super: false, + group_id: 0, }; const defaultGetQuizBody: GetQuizRequest = { - "quiz_id": "string", - "limit": 0, - "page": 0, - "need_config": true, + quiz_id: "string", + limit: 0, + page: 0, + need_config: true, }; const defaultGetQuizListBody: GetQuizListRequest = { - "limit": 100, - "offset": 0, + limit: 100, + offset: 0, }; diff --git a/src/api/quizRelase.ts b/src/api/quizRelase.ts index 6e78ee3a..7c32de5b 100644 --- a/src/api/quizRelase.ts +++ b/src/api/quizRelase.ts @@ -1,45 +1,56 @@ import { makeRequest } from "@frontend/kitui"; import { CreateQuestionRequest } from "model/question/create"; import { RawQuestion } from "model/question/question"; -import { GetQuestionListRequest, GetQuestionListResponse } from "@model/question/getList"; -import { EditQuestionRequest, EditQuestionResponse } from "@model/question/edit"; -import { DeleteQuestionRequest, DeleteQuestionResponse } from "@model/question/delete"; -import { CopyQuestionRequest, CopyQuestionResponse } from "@model/question/copy"; +import { + GetQuestionListRequest, + GetQuestionListResponse, +} from "@model/question/getList"; +import { + EditQuestionRequest, + EditQuestionResponse, +} from "@model/question/edit"; +import { + DeleteQuestionRequest, + DeleteQuestionResponse, +} from "@model/question/delete"; +import { + CopyQuestionRequest, + CopyQuestionResponse, +} from "@model/question/copy"; - -const baseUrl = process.env.NODE_ENV === "production" ? "/squiz" : "https://squiz.pena.digital"; +const baseUrl = + process.env.NODE_ENV === "production" + ? "/squiz" + : "https://squiz.pena.digital"; function get(quizId: string) { - return makeRequest({ - url: `${baseUrl}/question/copy`, - body: { id: questionId, quiz_id: quizId }, - method: "POST", - }); + return makeRequest({ + url: `${baseUrl}/question/copy`, + body: { id: questionId, quiz_id: quizId }, + method: "POST", + }); } - -function quizRelase(quizId: string, status: "start"|"stop") { - return makeRequest({ - url: `https://squiz.pena.digital/answer/quiz/get`, - body: { - quiz_id: quizId, - limit: 100, - page: 0, - need_config: true, - - }, - method: "POST", - }); +function quizRelase(quizId: string, status: "start" | "stop") { + return makeRequest({ + url: `https://squiz.pena.digital/answer/quiz/get`, + body: { + quiz_id: quizId, + limit: 100, + page: 0, + need_config: true, + }, + method: "POST", + }); } export const relaseApi = { - relase: quizRelase, - get: quizRelase, + relase: quizRelase, + get: quizRelase, }; - const defaultGetQuestionListBody: GetQuestionListRequest = { - "limit": 100, - "offset": 0, - "type": "", + limit: 100, + offset: 0, + type: "", }; diff --git a/src/assets/LandingPict/titleIcon.tsx b/src/assets/LandingPict/titleIcon.tsx index 29039e92..b6cc298c 100644 --- a/src/assets/LandingPict/titleIcon.tsx +++ b/src/assets/LandingPict/titleIcon.tsx @@ -1,25 +1,33 @@ import { Box } from "@mui/material"; - interface Props { - color?: string; + color?: string; } -export default function TitleIcon({color}:Props) { - - return ( - - - - - - ); -} \ No newline at end of file +export default function TitleIcon({ color }: Props) { + return ( + + + + + + ); +} diff --git a/src/assets/icons/AlignCenterIcon.tsx b/src/assets/icons/AlignCenterIcon.tsx index bddd42cd..ec2438ce 100644 --- a/src/assets/icons/AlignCenterIcon.tsx +++ b/src/assets/icons/AlignCenterIcon.tsx @@ -1,29 +1,63 @@ import { Box } from "@mui/material"; - interface Props { - color: string; + color: string; } export default function AlignCenterIcon({ color }: Props) { - - return ( - - - - - - - - - - ); -} \ No newline at end of file + return ( + + + + + + + + + + ); +} diff --git a/src/assets/icons/AlignLeftIcon.tsx b/src/assets/icons/AlignLeftIcon.tsx index ee2a80c4..f62372fd 100755 --- a/src/assets/icons/AlignLeftIcon.tsx +++ b/src/assets/icons/AlignLeftIcon.tsx @@ -1,27 +1,49 @@ import { Box } from "@mui/material"; - interface Props { - color: string; + color: string; } export default function AlignLeftIcon({ color }: Props) { - - return ( - - - - - - - - ); -} \ No newline at end of file + return ( + + + + + + + + ); +} diff --git a/src/assets/icons/AlignRightIcon.tsx b/src/assets/icons/AlignRightIcon.tsx index 5a035dbd..b404f5d6 100755 --- a/src/assets/icons/AlignRightIcon.tsx +++ b/src/assets/icons/AlignRightIcon.tsx @@ -1,27 +1,49 @@ import { Box } from "@mui/material"; - interface Props { - color: string; + color: string; } export default function AlignRightIcon({ color }: Props) { - - return ( - - - - - - - - ); -} \ No newline at end of file + return ( + + + + + + + + ); +} diff --git a/src/assets/icons/ArrowDownIcon.tsx b/src/assets/icons/ArrowDownIcon.tsx index 59392473..aed9adc6 100755 --- a/src/assets/icons/ArrowDownIcon.tsx +++ b/src/assets/icons/ArrowDownIcon.tsx @@ -1,29 +1,41 @@ -import {Box, SxProps, Theme, useTheme} from "@mui/material"; +import { Box, SxProps, Theme, useTheme } from "@mui/material"; -interface Color{ - color?: string +interface Color { + color?: string; } export default function ArrowDownIcon( - props: any, - {color = "#7E2AEA"}: Color + props: any, + { color = "#7E2AEA" }: Color, ) { - const theme = useTheme(); + const theme = useTheme(); - return ( - - - - - - ); -} \ No newline at end of file + return ( + + + + + + ); +} diff --git a/src/assets/icons/ArrowLeftSP.tsx b/src/assets/icons/ArrowLeftSP.tsx index 1ba692e1..214e7fad 100644 --- a/src/assets/icons/ArrowLeftSP.tsx +++ b/src/assets/icons/ArrowLeftSP.tsx @@ -1,27 +1,35 @@ -import {Box, SxProps, Theme, useTheme} from "@mui/material"; - +import { Box, SxProps, Theme, useTheme } from "@mui/material"; interface Props { - right: boolean + right: boolean; } -export default function ArrowLeftSP({right} : Props) { - const theme = useTheme(); +export default function ArrowLeftSP({ right }: Props) { + const theme = useTheme(); - return ( - - - - - - ); -} \ No newline at end of file + return ( + + + + + + ); +} diff --git a/src/assets/icons/BackArrowIcon.tsx b/src/assets/icons/BackArrowIcon.tsx index cbfef395..1b5b9140 100755 --- a/src/assets/icons/BackArrowIcon.tsx +++ b/src/assets/icons/BackArrowIcon.tsx @@ -11,8 +11,20 @@ export default function BackArrowIcon({ color = "black" }: { color?: string }) { alignItems: "center", }} > - - + + ( - + > = (props) => ( - - - - + + + + ); diff --git a/src/assets/icons/CalendarIcon.tsx b/src/assets/icons/CalendarIcon.tsx index 3c3544e9..6fa7e8b3 100644 --- a/src/assets/icons/CalendarIcon.tsx +++ b/src/assets/icons/CalendarIcon.tsx @@ -1,9 +1,9 @@ -import {Box, SxProps, Theme} from "@mui/material"; +import { Box, SxProps, Theme } from "@mui/material"; interface Props { - sx?: SxProps + sx?: SxProps; } -export default function CalendarIcon({sx}:Props) { +export default function CalendarIcon({ sx }: Props) { return ( - - - - - - - - - - - + + + + + + + + + + + ); diff --git a/src/assets/icons/ChartIcon.tsx b/src/assets/icons/ChartIcon.tsx index f8c2947e..893324b1 100755 --- a/src/assets/icons/ChartIcon.tsx +++ b/src/assets/icons/ChartIcon.tsx @@ -1,22 +1,45 @@ import { Box, useTheme } from "@mui/material"; - export default function ChartIcon() { - const theme = useTheme(); + const theme = useTheme(); - return ( - - - - - - - - ); -} \ No newline at end of file + return ( + + + + + + + + ); +} diff --git a/src/assets/icons/ChartPieIcon.tsx b/src/assets/icons/ChartPieIcon.tsx index 6671f740..d3e3236c 100755 --- a/src/assets/icons/ChartPieIcon.tsx +++ b/src/assets/icons/ChartPieIcon.tsx @@ -18,7 +18,13 @@ export default function ChartPieIcon({ height, width, color }: Props) { alignItems: "center", }} > - + - + @@ -41,4 +42,4 @@ export default function CheckboxIcon ({ checked = false, color = "#7E2AEA", }: C )} ); -}; +} diff --git a/src/assets/icons/CollapseMenuIcon.tsx b/src/assets/icons/CollapseMenuIcon.tsx index d1dcad34..c5d42d5c 100755 --- a/src/assets/icons/CollapseMenuIcon.tsx +++ b/src/assets/icons/CollapseMenuIcon.tsx @@ -1,31 +1,50 @@ import { Box } from "@mui/material"; - interface Props { - height: string; - width: string; - color: string; - transform: string; + height: string; + width: string; + color: string; + transform: string; } -export default function CollapseMenuIcon({ height, width, color, transform }: Props) { - - return ( - - - - - - - ); -} \ No newline at end of file +export default function CollapseMenuIcon({ + height, + width, + color, + transform, +}: Props) { + return ( + + + + + + + ); +} diff --git a/src/assets/icons/ContactBookIcon.tsx b/src/assets/icons/ContactBookIcon.tsx index 174d54e0..a586c3c4 100755 --- a/src/assets/icons/ContactBookIcon.tsx +++ b/src/assets/icons/ContactBookIcon.tsx @@ -1,34 +1,80 @@ import { Box } from "@mui/material"; - interface Props { - height: string; - width: string; - color: string; + height: string; + width: string; + color: string; } -export default function ContactBookIcon({ height, width,color }: Props) { - - return ( - - - - - - - - - - - - ); -} \ No newline at end of file +export default function ContactBookIcon({ height, width, color }: Props) { + return ( + + + + + + + + + + + + ); +} diff --git a/src/assets/icons/CountIcon.tsx b/src/assets/icons/CountIcon.tsx index ebbcbc8f..0fdbd688 100644 --- a/src/assets/icons/CountIcon.tsx +++ b/src/assets/icons/CountIcon.tsx @@ -1,6 +1,12 @@ export default function CountIcon() { return ( - + > = (props) => ( - - - - - + + + + + ); diff --git a/src/assets/icons/CrossedEyeIcon.tsx b/src/assets/icons/CrossedEyeIcon.tsx index 1d433122..c9021ca9 100644 --- a/src/assets/icons/CrossedEyeIcon.tsx +++ b/src/assets/icons/CrossedEyeIcon.tsx @@ -2,7 +2,14 @@ import { FC, SVGProps } from "react"; export const CrossedEyeIcon: FC> = (props) => { return ( - + > = (props) => ( - + - - - - ); -} \ No newline at end of file + return ( + + + + + ); +} diff --git a/src/assets/icons/EyeIcon.tsx b/src/assets/icons/EyeIcon.tsx index c323ef79..c19d25d0 100755 --- a/src/assets/icons/EyeIcon.tsx +++ b/src/assets/icons/EyeIcon.tsx @@ -13,7 +13,13 @@ export default function EyeIcon() { alignItems: "center", }} > - + - - - - - - - ); -} \ No newline at end of file + return ( + + + + + + + + ); +} diff --git a/src/assets/icons/GearIcon.tsx b/src/assets/icons/GearIcon.tsx index aa45141b..1f93a6da 100755 --- a/src/assets/icons/GearIcon.tsx +++ b/src/assets/icons/GearIcon.tsx @@ -1,29 +1,45 @@ import { Box } from "@mui/material"; - interface Props { - height: string; - width: string; - color: string; + height: string; + width: string; + color: string; } export default function GearIcon({ height, width, color }: Props) { - - return ( - - - - - - - ); -} \ No newline at end of file + return ( + + + + + + + ); +} diff --git a/src/assets/icons/ImageAddIcons.tsx b/src/assets/icons/ImageAddIcons.tsx index b1664427..a3d8c938 100644 --- a/src/assets/icons/ImageAddIcons.tsx +++ b/src/assets/icons/ImageAddIcons.tsx @@ -1,7 +1,13 @@ import { FC, SVGProps } from "react"; export const ImageAddIcons: FC> = (props) => ( - + + - + - - - - - - - - - - ); -} \ No newline at end of file + return ( + + + + + + + + + + + ); +} diff --git a/src/assets/icons/InstallQuizIcon/RDownButton.tsx b/src/assets/icons/InstallQuizIcon/RDownButton.tsx index 559b63b8..83c2b7de 100644 --- a/src/assets/icons/InstallQuizIcon/RDownButton.tsx +++ b/src/assets/icons/InstallQuizIcon/RDownButton.tsx @@ -1,30 +1,55 @@ import { Box } from "@mui/material"; - interface Props { - color: string; + color: string; } export default function RDownButton({ color }: Props) { - - return ( - - - - - - - - - - - ); -} \ No newline at end of file + return ( + + + + + + + + + + + ); +} diff --git a/src/assets/icons/LayoutCenteredIcon.tsx b/src/assets/icons/LayoutCenteredIcon.tsx index 2c587a35..e4e97c58 100755 --- a/src/assets/icons/LayoutCenteredIcon.tsx +++ b/src/assets/icons/LayoutCenteredIcon.tsx @@ -1,26 +1,56 @@ import { Box } from "@mui/material"; - interface Props { - color: string; + color: string; } export default function LayoutCenteredIcon({ color }: Props) { - - return ( - - - - - - - - - ); -} \ No newline at end of file + return ( + + + + + + + + + ); +} diff --git a/src/assets/icons/LayoutExpandedIcon.tsx b/src/assets/icons/LayoutExpandedIcon.tsx index 41789240..b5a3b23b 100755 --- a/src/assets/icons/LayoutExpandedIcon.tsx +++ b/src/assets/icons/LayoutExpandedIcon.tsx @@ -1,26 +1,56 @@ import { Box } from "@mui/material"; - interface Props { - color: string; + color: string; } export default function LayoutExpandedIcon({ color }: Props) { - - return ( - - - - - - - - - ); -} \ No newline at end of file + return ( + + + + + + + + + ); +} diff --git a/src/assets/icons/LayoutIcon.tsx b/src/assets/icons/LayoutIcon.tsx index fde94cc0..2a97274a 100755 --- a/src/assets/icons/LayoutIcon.tsx +++ b/src/assets/icons/LayoutIcon.tsx @@ -1,33 +1,61 @@ import { Box, useTheme } from "@mui/material"; - interface Props { - bgcolor?: string; - height: string; - width: string; - color: string; + bgcolor?: string; + height: string; + width: string; + color: string; } -export default function LayoutIconOld({ bgcolor, height, width, color }: Props) { - const theme = useTheme(); +export default function LayoutIconOld({ + bgcolor, + height, + width, + color, +}: Props) { + const theme = useTheme(); - return ( - - - - - - - - ); -} \ No newline at end of file + return ( + + + + + + + + ); +} diff --git a/src/assets/icons/LayoutIconBig.tsx b/src/assets/icons/LayoutIconBig.tsx index 5326f292..4b1ac41f 100755 --- a/src/assets/icons/LayoutIconBig.tsx +++ b/src/assets/icons/LayoutIconBig.tsx @@ -1,33 +1,61 @@ import { Box, useTheme } from "@mui/material"; - interface Props { - bgcolor?: string; - height: string; - width: string; - color: string; + bgcolor?: string; + height: string; + width: string; + color: string; } -export default function LayoutIconBig({ bgcolor, height, width, color }: Props) { - const theme = useTheme(); +export default function LayoutIconBig({ + bgcolor, + height, + width, + color, +}: Props) { + const theme = useTheme(); - return ( - - - - - - - - ); -} \ No newline at end of file + return ( + + + + + + + + ); +} diff --git a/src/assets/icons/LayoutStandartIcon.tsx b/src/assets/icons/LayoutStandartIcon.tsx index feaaf909..68bb796c 100755 --- a/src/assets/icons/LayoutStandartIcon.tsx +++ b/src/assets/icons/LayoutStandartIcon.tsx @@ -1,27 +1,63 @@ import { Box } from "@mui/material"; - interface Props { - color: string; + color: string; } export default function LayoutStandartIcon({ color }: Props) { - - return ( - - - - - - - - - - ); -} \ No newline at end of file + return ( + + + + + + + + + + ); +} diff --git a/src/assets/icons/LinkIcon.tsx b/src/assets/icons/LinkIcon.tsx index 303779f2..818aadd7 100755 --- a/src/assets/icons/LinkIcon.tsx +++ b/src/assets/icons/LinkIcon.tsx @@ -1,31 +1,54 @@ import { Box, useTheme } from "@mui/material"; - interface Props { - color: string; - bgcolor: string; + color: string; + bgcolor: string; } export default function LinkIcon({ color, bgcolor }: Props) { - const theme = useTheme(); + const theme = useTheme(); - return ( - - - - - - - - ); -} \ No newline at end of file + return ( + + + + + + + + ); +} diff --git a/src/assets/icons/LinkSimple.tsx b/src/assets/icons/LinkSimple.tsx index 193b7acb..30396e08 100644 --- a/src/assets/icons/LinkSimple.tsx +++ b/src/assets/icons/LinkSimple.tsx @@ -1,7 +1,14 @@ import { FC, SVGProps } from "react"; export const LinkSimple: FC> = (props) => ( - + - - - - - ); -} \ No newline at end of file + return ( + + + + + + ); +} diff --git a/src/assets/icons/MegaphoneIcon.tsx b/src/assets/icons/MegaphoneIcon.tsx index 5e28a03e..97049fdc 100755 --- a/src/assets/icons/MegaphoneIcon.tsx +++ b/src/assets/icons/MegaphoneIcon.tsx @@ -1,29 +1,45 @@ import { Box } from "@mui/material"; - interface Props { - height: string; - width: string; - color: string; + height: string; + width: string; + color: string; } export default function MegaphoneIcon({ height, width, color }: Props) { - - return ( - - - - - - - ); -} \ No newline at end of file + return ( + + + + + + + ); +} diff --git a/src/assets/icons/MenuIcon.tsx b/src/assets/icons/MenuIcon.tsx index 64567cd3..babd967a 100644 --- a/src/assets/icons/MenuIcon.tsx +++ b/src/assets/icons/MenuIcon.tsx @@ -1,6 +1,12 @@ export default function MenuIcon() { return ( - + - - - - - - - ); -} \ No newline at end of file + return ( + + + + + + + + ); +} diff --git a/src/assets/icons/NameplateLogoFQDark.tsx b/src/assets/icons/NameplateLogoFQDark.tsx index 651c17b2..b8b920fc 100644 --- a/src/assets/icons/NameplateLogoFQDark.tsx +++ b/src/assets/icons/NameplateLogoFQDark.tsx @@ -1,24 +1,58 @@ import { FC, SVGProps } from "react"; export const NameplateLogoFQDark: FC> = (props) => ( - - - - - - - - - - - - - - - - - - - - -); \ No newline at end of file + + + + + + + + + + + + + + + + + + + +); diff --git a/src/assets/icons/NumberThree.tsx b/src/assets/icons/NumberThree.tsx index d363e8b9..f9978180 100644 --- a/src/assets/icons/NumberThree.tsx +++ b/src/assets/icons/NumberThree.tsx @@ -1,26 +1,41 @@ import { Box } from "@mui/material"; - interface Props { - color: string; + color: string; } -export default function NumberThree({color}:Props) { - - return ( - - - - - - - ); -} \ No newline at end of file +export default function NumberThree({ color }: Props) { + return ( + + + + + + + ); +} diff --git a/src/assets/icons/NumberTwo.tsx b/src/assets/icons/NumberTwo.tsx index cfd7d8d3..85116206 100644 --- a/src/assets/icons/NumberTwo.tsx +++ b/src/assets/icons/NumberTwo.tsx @@ -1,26 +1,41 @@ import { Box } from "@mui/material"; - interface Props { - color: string; + color: string; } -export default function NumberTwo({color}:Props) { - - return ( - - - - - - - ); -} \ No newline at end of file +export default function NumberTwo({ color }: Props) { + return ( + + + + + + + ); +} diff --git a/src/assets/icons/OneIconBorder.tsx b/src/assets/icons/OneIconBorder.tsx index 5f51bd29..e9ac34b4 100644 --- a/src/assets/icons/OneIconBorder.tsx +++ b/src/assets/icons/OneIconBorder.tsx @@ -1,26 +1,41 @@ import { Box } from "@mui/material"; - interface Props { - color: string; + color: string; } -export default function OneIconBorder({color}:Props) { - - return ( - - - - - - - ); -} \ No newline at end of file +export default function OneIconBorder({ color }: Props) { + return ( + + + + + + + ); +} diff --git a/src/assets/icons/PencilCircleIcon.tsx b/src/assets/icons/PencilCircleIcon.tsx index 915211e4..aa7ff37c 100755 --- a/src/assets/icons/PencilCircleIcon.tsx +++ b/src/assets/icons/PencilCircleIcon.tsx @@ -1,32 +1,66 @@ import { Box } from "@mui/material"; - interface Props { - height: string; - width: string; - color: string; + height: string; + width: string; + color: string; } export default function PencilCircleIcon({ height, width, color }: Props) { - - return ( - - - - - - - - - - ); -} \ No newline at end of file + return ( + + + + + + + + + + ); +} diff --git a/src/assets/icons/PencilIcon.tsx b/src/assets/icons/PencilIcon.tsx index 4ec391af..8f320cc9 100755 --- a/src/assets/icons/PencilIcon.tsx +++ b/src/assets/icons/PencilIcon.tsx @@ -1,23 +1,52 @@ import { Box, useTheme } from "@mui/material"; - export default function PencilIcon() { - const theme = useTheme(); + const theme = useTheme(); - return ( - - - - - - - - - ); -} \ No newline at end of file + return ( + + + + + + + + + ); +} diff --git a/src/assets/icons/PuzzlePieceIcon.tsx b/src/assets/icons/PuzzlePieceIcon.tsx index 137d6e8a..4d3e335b 100755 --- a/src/assets/icons/PuzzlePieceIcon.tsx +++ b/src/assets/icons/PuzzlePieceIcon.tsx @@ -1,28 +1,38 @@ import { Box } from "@mui/material"; - interface Props { - height: string; - width: string; - color: string; + height: string; + width: string; + color: string; } export default function PuzzlePieceIcon({ height, width, color }: Props) { - - return ( - - - - - - ); -} \ No newline at end of file + return ( + + + + + + ); +} diff --git a/src/assets/icons/QuestionIcon.tsx b/src/assets/icons/QuestionIcon.tsx index 44aa33a4..d0243618 100755 --- a/src/assets/icons/QuestionIcon.tsx +++ b/src/assets/icons/QuestionIcon.tsx @@ -1,30 +1,49 @@ import { Box } from "@mui/material"; - interface Props { - height: string; - width: string; - color: string; + height: string; + width: string; + color: string; } -export default function QuestionIcon({ height, width ,color}: Props) { - - return ( - - - - - - - - ); -} \ No newline at end of file +export default function QuestionIcon({ height, width, color }: Props) { + return ( + + + + + + + + ); +} diff --git a/src/assets/icons/SearchIcon.tsx b/src/assets/icons/SearchIcon.tsx index 7d0a933e..c49c52e3 100755 --- a/src/assets/icons/SearchIcon.tsx +++ b/src/assets/icons/SearchIcon.tsx @@ -1,22 +1,38 @@ import { Box } from "@mui/material"; - export default function SearchIcon() { - - return ( - - - - - - - ); -} \ No newline at end of file + return ( + + + + + + + ); +} diff --git a/src/assets/icons/SendIcon.tsx b/src/assets/icons/SendIcon.tsx index 6dc47051..9a0f999b 100755 --- a/src/assets/icons/SendIcon.tsx +++ b/src/assets/icons/SendIcon.tsx @@ -1,12 +1,27 @@ - - export default function SendIcon() { - - return ( - - - - - - ); -} \ No newline at end of file + return ( + + + + + + ); +} diff --git a/src/assets/icons/TagIcon.tsx b/src/assets/icons/TagIcon.tsx index 5810ce0a..ff883ba5 100755 --- a/src/assets/icons/TagIcon.tsx +++ b/src/assets/icons/TagIcon.tsx @@ -1,29 +1,42 @@ import { Box } from "@mui/material"; - interface Props { - height: string; - width: string; - color: string; + height: string; + width: string; + color: string; } export default function TagIcon({ height, width, color }: Props) { - - return ( - - - - - - - ); -} \ No newline at end of file + return ( + + + + + + + ); +} diff --git a/src/assets/icons/TreeStructure.tsx b/src/assets/icons/TreeStructure.tsx index 282b22ad..fc92541d 100644 --- a/src/assets/icons/TreeStructure.tsx +++ b/src/assets/icons/TreeStructure.tsx @@ -1,5 +1,11 @@ export const TreeStructure = () => ( - + ( stroke-linecap="round" stroke-linejoin="round" /> - + - - - - - - - ); -} \ No newline at end of file + return ( + + + + + + + + ); +} diff --git a/src/assets/icons/VkIconButton.tsx b/src/assets/icons/VkIconButton.tsx index 7384ce2f..e72727d7 100644 --- a/src/assets/icons/VkIconButton.tsx +++ b/src/assets/icons/VkIconButton.tsx @@ -1,25 +1,35 @@ import { Box, useTheme } from "@mui/material"; - interface Props { - color?: string; + color?: string; } export default function VkIconButton({ color }: Props) { - const theme = useTheme(); + const theme = useTheme(); - return ( - - - - - - ); -} \ No newline at end of file + return ( + + + + + + ); +} diff --git a/src/assets/icons/WalletIcon.tsx b/src/assets/icons/WalletIcon.tsx index 32651094..79f11d6d 100755 --- a/src/assets/icons/WalletIcon.tsx +++ b/src/assets/icons/WalletIcon.tsx @@ -1,32 +1,36 @@ import { Box } from "@mui/material"; - interface Props { - color: string; - bgcolor: string; + color: string; + bgcolor: string; } export default function WalletIcon({ color, bgcolor }: Props) { - - return ( - - - - - - ); -} \ No newline at end of file + return ( + + + + + + ); +} diff --git a/src/assets/icons/messagIcon.tsx b/src/assets/icons/messagIcon.tsx index b0af0744..25b91c47 100644 --- a/src/assets/icons/messagIcon.tsx +++ b/src/assets/icons/messagIcon.tsx @@ -1,7 +1,13 @@ import { FC, SVGProps } from "react"; export const MessageIcon: FC> = (props) => ( - + > = (props) => ( strokeLinecap="round" strokeLinejoin="round" /> - - + + ); diff --git a/src/assets/icons/questionsPage/ArrowDownIcon.tsx b/src/assets/icons/questionsPage/ArrowDownIcon.tsx index 861571e5..b2f333f4 100644 --- a/src/assets/icons/questionsPage/ArrowDownIcon.tsx +++ b/src/assets/icons/questionsPage/ArrowDownIcon.tsx @@ -1,7 +1,13 @@ import { FC, SVGProps } from "react"; export const ArrowDownIcon: FC> = (props) => ( - + > = (props) => ( - + > = (props) => ( - + > = (props) => ( - + > = (props) => ( - + - + > = (props) => ( - + > = (props) => ( - + > = (props) => ( strokeLinecap="round" strokeLinejoin="round" /> - + ); diff --git a/src/assets/icons/questionsPage/addImage.tsx b/src/assets/icons/questionsPage/addImage.tsx index 3842072d..4127c704 100644 --- a/src/assets/icons/questionsPage/addImage.tsx +++ b/src/assets/icons/questionsPage/addImage.tsx @@ -20,12 +20,21 @@ const AddImage: FC = ({ onClick, sx }) => { ...sx, }} > - + - + - - - - - - - ); -} \ No newline at end of file + return ( + + + + + + + + ); +} diff --git a/src/assets/icons/questionsPage/addPlusImage.tsx b/src/assets/icons/questionsPage/addPlusImage.tsx index 3d77bf43..72d4f22a 100644 --- a/src/assets/icons/questionsPage/addPlusImage.tsx +++ b/src/assets/icons/questionsPage/addPlusImage.tsx @@ -1,9 +1,21 @@ import { FC } from "react"; export const AddPlusImage: FC = () => ( - - - + + + ( - - - + + + ( strokeLinecap="round" strokeLinejoin="round" /> - + ); diff --git a/src/assets/icons/questionsPage/arrowLeft.tsx b/src/assets/icons/questionsPage/arrowLeft.tsx index 86abbabb..e12656d6 100755 --- a/src/assets/icons/questionsPage/arrowLeft.tsx +++ b/src/assets/icons/questionsPage/arrowLeft.tsx @@ -1,25 +1,40 @@ import { Box } from "@mui/material"; - interface Props { - color: string; + color: string; } -export default function ArrowLeft({color = "#7E2AEA"}: Props) { - - return ( - - - - - - - - ); -} \ No newline at end of file +export default function ArrowLeft({ color = "#7E2AEA" }: Props) { + return ( + + + + + + + ); +} diff --git a/src/assets/icons/questionsPage/date.tsx b/src/assets/icons/questionsPage/date.tsx index 33f51b64..5529de22 100755 --- a/src/assets/icons/questionsPage/date.tsx +++ b/src/assets/icons/questionsPage/date.tsx @@ -1,40 +1,121 @@ -import {Box, SxProps, Theme} from "@mui/material"; - +import { Box, SxProps, Theme } from "@mui/material"; interface Props { - color: string; - sx?: SxProps + color: string; + sx?: SxProps; } -export default function Date({color, sx}: Props) { - - return ( - - - - - - - - - - - - - - - - - - - ); -} \ No newline at end of file +export default function Date({ color, sx }: Props) { + return ( + + + + + + + + + + + + + + + + + + ); +} diff --git a/src/assets/icons/questionsPage/deleteIcon.tsx b/src/assets/icons/questionsPage/deleteIcon.tsx index 8ebd1d62..068dcef3 100755 --- a/src/assets/icons/questionsPage/deleteIcon.tsx +++ b/src/assets/icons/questionsPage/deleteIcon.tsx @@ -2,10 +2,34 @@ import { Box } from "@mui/material"; import { FC, SVGProps } from "react"; export const DeleteIcon: FC> = (props) => ( - - - - + + + + + color: string; + sx?: SxProps; } -export default function Download({color, sx}: Props) { - - return ( - - - - - - - - - - ); -} \ No newline at end of file +export default function Download({ color, sx }: Props) { + return ( + + + + + + + + + ); +} diff --git a/src/assets/icons/questionsPage/drop_down.tsx b/src/assets/icons/questionsPage/drop_down.tsx index ff4b0eeb..d5531331 100755 --- a/src/assets/icons/questionsPage/drop_down.tsx +++ b/src/assets/icons/questionsPage/drop_down.tsx @@ -1,34 +1,86 @@ -import {Box, SxProps, Theme} from "@mui/material"; - +import { Box, SxProps, Theme } from "@mui/material"; interface Props { - color: string; - sx?: SxProps + color: string; + sx?: SxProps; } -export default function DropDown({color, sx}: Props) { - - return ( - - - - - - - - - - - - - ); -} \ No newline at end of file +export default function DropDown({ color, sx }: Props) { + return ( + + + + + + + + + + + + + ); +} diff --git a/src/assets/icons/questionsPage/emoji.tsx b/src/assets/icons/questionsPage/emoji.tsx index 497d464f..6827d7b1 100755 --- a/src/assets/icons/questionsPage/emoji.tsx +++ b/src/assets/icons/questionsPage/emoji.tsx @@ -1,30 +1,52 @@ -import {Box, SxProps, Theme} from "@mui/material"; - +import { Box, SxProps, Theme } from "@mui/material"; interface Props { - color: string; - sx?: SxProps + color: string; + sx?: SxProps; } -export default function Emoji({color, sx}: Props) { - - return ( - - - - - - - - - ); -} \ No newline at end of file +export default function Emoji({ color, sx }: Props) { + return ( + + + + + + + + + ); +} diff --git a/src/assets/icons/questionsPage/enterIcon.tsx b/src/assets/icons/questionsPage/enterIcon.tsx index b76eb3f6..fc986766 100755 --- a/src/assets/icons/questionsPage/enterIcon.tsx +++ b/src/assets/icons/questionsPage/enterIcon.tsx @@ -1,7 +1,13 @@ import { FC, SVGProps } from "react"; export const EnterIcon: FC> = (props) => ( - + > = (props) => ( - + + color: string; + sx?: SxProps; +} +export default function Input({ color, sx }: Props) { + return ( + + + + + + + + ); } -export default function Input({color, sx}: Props) { - - return ( - - - - - - - - ); -} \ No newline at end of file diff --git a/src/assets/icons/questionsPage/options_and_pict.tsx b/src/assets/icons/questionsPage/options_and_pict.tsx index acdde9d5..88f93a44 100755 --- a/src/assets/icons/questionsPage/options_and_pict.tsx +++ b/src/assets/icons/questionsPage/options_and_pict.tsx @@ -1,34 +1,62 @@ -import {Box, SxProps, Theme} from "@mui/material"; - +import { Box, SxProps, Theme } from "@mui/material"; interface Props { - color: string; - sx?: SxProps + color: string; + sx?: SxProps; } -export default function optionsAndPict({color, sx}: Props) { - - return ( - - - - - - - - - - - - - ); -} \ No newline at end of file +export default function optionsAndPict({ color, sx }: Props) { + return ( + + + + + + + + + + + + + ); +} diff --git a/src/assets/icons/questionsPage/options_pict.tsx b/src/assets/icons/questionsPage/options_pict.tsx index 6e118138..489fa71c 100755 --- a/src/assets/icons/questionsPage/options_pict.tsx +++ b/src/assets/icons/questionsPage/options_pict.tsx @@ -1,30 +1,46 @@ -import {Box, SxProps, Theme} from "@mui/material"; - +import { Box, SxProps, Theme } from "@mui/material"; interface Props { - color: string; - sx?: SxProps + color: string; + sx?: SxProps; } -export default function optionsPict({color, sx}: Props) { - - return ( - - - - - - - - - ); -} \ No newline at end of file +export default function optionsPict({ color, sx }: Props) { + return ( + + + + + + + + + ); +} diff --git a/src/assets/icons/questionsPage/page.tsx b/src/assets/icons/questionsPage/page.tsx index 09a9b03b..f8862da4 100755 --- a/src/assets/icons/questionsPage/page.tsx +++ b/src/assets/icons/questionsPage/page.tsx @@ -1,33 +1,73 @@ -import {Box, SxProps, Theme} from "@mui/material"; - +import { Box, SxProps, Theme } from "@mui/material"; interface Props { - color: string; - sx?: SxProps + color: string; + sx?: SxProps; } -export default function Page({color, sx}: Props) { - - return ( - - - - - - - - - - - - ); -} \ No newline at end of file +export default function Page({ color, sx }: Props) { + return ( + + + + + + + + + + + + ); +} diff --git a/src/assets/icons/questionsPage/rating.tsx b/src/assets/icons/questionsPage/rating.tsx index 43c6d5fd..7cd5716f 100755 --- a/src/assets/icons/questionsPage/rating.tsx +++ b/src/assets/icons/questionsPage/rating.tsx @@ -1,26 +1,36 @@ -import {Box, SxProps, Theme} from "@mui/material"; - +import { Box, SxProps, Theme } from "@mui/material"; interface Props { - color: string; - sx?: SxProps + color: string; + sx?: SxProps; +} +export default function Rating({ color, sx }: Props) { + return ( + + + + + + ); } -export default function Rating({color, sx}: Props) { - - return ( - - - - - - ); -} \ No newline at end of file diff --git a/src/assets/icons/questionsPage/slider.tsx b/src/assets/icons/questionsPage/slider.tsx index 4dbaa9b6..5296d1c1 100755 --- a/src/assets/icons/questionsPage/slider.tsx +++ b/src/assets/icons/questionsPage/slider.tsx @@ -1,28 +1,46 @@ -import {Box, SxProps, Theme} from "@mui/material"; - +import { Box, SxProps, Theme } from "@mui/material"; interface Props { - color: string; - sx?: SxProps + color: string; + sx?: SxProps; } -export default function Slider({color, sx}: Props) { - - return ( - - - - - - - ); -} \ No newline at end of file +export default function Slider({ color, sx }: Props) { + return ( + + + + + + + ); +} diff --git a/src/assets/icons/x.tsx b/src/assets/icons/x.tsx index 535f7c13..f42cea93 100644 --- a/src/assets/icons/x.tsx +++ b/src/assets/icons/x.tsx @@ -1,15 +1,24 @@ import { useTheme } from "@mui/material"; - interface Props { - width?: number; + width?: number; } export default function PenaLogo({ width }: Props) { - const theme = useTheme(); + const theme = useTheme(); - return ( - - - - )} + return ( + + + + ); +} diff --git a/src/constants/base.ts b/src/constants/base.ts index f588bfc6..5d2d57a8 100644 --- a/src/constants/base.ts +++ b/src/constants/base.ts @@ -1,30 +1,32 @@ -import type { QuizQuestionBase, QuestionBranchingRuleMain } from "../model/questionTypes/shared"; - +import type { + QuizQuestionBase, + QuestionBranchingRuleMain, +} from "../model/questionTypes/shared"; export const QUIZ_QUESTION_BASE: Omit = { - quizId: 0, - description: "", - page: 0, - title: "", - expanded: true, - openedModalSettings: false, - required: false, - deleted: false, - deleteTimeoutId: 0, - content: { - id: "", - hint: { - text: "", - video: "", - }, - rule: { - children: [], - main: [] as QuestionBranchingRuleMain[], - parentId: "", - default: "" - }, - back: "", - originalBack: "", - autofill: false, + quizId: 0, + description: "", + page: 0, + title: "", + expanded: true, + openedModalSettings: false, + required: false, + deleted: false, + deleteTimeoutId: 0, + content: { + id: "", + hint: { + text: "", + video: "", }, + rule: { + children: [], + main: [] as QuestionBranchingRuleMain[], + parentId: "", + default: "", + }, + back: "", + originalBack: "", + autofill: false, + }, }; diff --git a/src/constants/default.ts b/src/constants/default.ts index f3bcd489..e746ee18 100644 --- a/src/constants/default.ts +++ b/src/constants/default.ts @@ -13,18 +13,20 @@ import { QUIZ_QUESTION_VARIANT } from "./variant"; import { QUIZ_QUESTION_VARIMG } from "./varimg"; import { QUIZ_QUESTION_RESULT } from "./result"; - -export const defaultQuestionByType: Record> = { - "date": QUIZ_QUESTION_DATE, - "emoji": QUIZ_QUESTION_EMOJI, - "file": QUIZ_QUESTION_FILE, - "images": QUIZ_QUESTION_IMAGES, - "number": QUIZ_QUESTION_NUMBER, - "page": QUIZ_QUESTION_PAGE, - "rating": QUIZ_QUESTION_RATING, - "select": QUIZ_QUESTION_SELECT, - "text": QUIZ_QUESTION_TEXT, - "variant": QUIZ_QUESTION_VARIANT, - "varimg": QUIZ_QUESTION_VARIMG, - "result": QUIZ_QUESTION_RESULT, +export const defaultQuestionByType: Record< + QuestionType, + Omit +> = { + date: QUIZ_QUESTION_DATE, + emoji: QUIZ_QUESTION_EMOJI, + file: QUIZ_QUESTION_FILE, + images: QUIZ_QUESTION_IMAGES, + number: QUIZ_QUESTION_NUMBER, + page: QUIZ_QUESTION_PAGE, + rating: QUIZ_QUESTION_RATING, + select: QUIZ_QUESTION_SELECT, + text: QUIZ_QUESTION_TEXT, + variant: QUIZ_QUESTION_VARIANT, + varimg: QUIZ_QUESTION_VARIMG, + result: QUIZ_QUESTION_RESULT, } as const; diff --git a/src/constants/emoji.ts b/src/constants/emoji.ts index fea13ba0..67c8aa04 100644 --- a/src/constants/emoji.ts +++ b/src/constants/emoji.ts @@ -3,24 +3,25 @@ import { QUIZ_QUESTION_BASE } from "./base"; import type { QuizQuestionEmoji } from "../model/questionTypes/emoji"; import { nanoid } from "nanoid"; -export const QUIZ_QUESTION_EMOJI: Omit = { - ...QUIZ_QUESTION_BASE, - type: "emoji", - content: { - ...QUIZ_QUESTION_BASE.content, - multi: false, - own: false, - innerNameCheck: false, - innerName: "", - required: false, - variants: [ - { - id: nanoid(), - answer: "", - extendedText: "", - hints: "", - originalImageUrl: "", - }, - ], - }, -}; +export const QUIZ_QUESTION_EMOJI: Omit = + { + ...QUIZ_QUESTION_BASE, + type: "emoji", + content: { + ...QUIZ_QUESTION_BASE.content, + multi: false, + own: false, + innerNameCheck: false, + innerName: "", + required: false, + variants: [ + { + id: nanoid(), + answer: "", + extendedText: "", + hints: "", + originalImageUrl: "", + }, + ], + }, + }; diff --git a/src/constants/images.ts b/src/constants/images.ts index dd92dc9a..974b1cc1 100644 --- a/src/constants/images.ts +++ b/src/constants/images.ts @@ -3,7 +3,10 @@ import { QUIZ_QUESTION_BASE } from "./base"; import type { QuizQuestionImages } from "../model/questionTypes/images"; import { nanoid } from "nanoid"; -export const QUIZ_QUESTION_IMAGES: Omit = { +export const QUIZ_QUESTION_IMAGES: Omit< + QuizQuestionImages, + "id" | "backendId" +> = { ...QUIZ_QUESTION_BASE, type: "images", content: { @@ -22,7 +25,7 @@ export const QUIZ_QUESTION_IMAGES: Omit answer: "", extendedText: "", originalImageUrl: "", - hints: "" + hints: "", }, ], largeCheck: false, diff --git a/src/constants/number.ts b/src/constants/number.ts index 76d47ff8..f2fc09ae 100644 --- a/src/constants/number.ts +++ b/src/constants/number.ts @@ -2,7 +2,10 @@ import { QUIZ_QUESTION_BASE } from "./base"; import type { QuizQuestionNumber } from "../model/questionTypes/number"; -export const QUIZ_QUESTION_NUMBER: Omit = { +export const QUIZ_QUESTION_NUMBER: Omit< + QuizQuestionNumber, + "id" | "backendId" +> = { ...QUIZ_QUESTION_BASE, type: "number", content: { diff --git a/src/constants/rating.ts b/src/constants/rating.ts index cef8bc24..3ff92c02 100644 --- a/src/constants/rating.ts +++ b/src/constants/rating.ts @@ -2,7 +2,10 @@ import { QUIZ_QUESTION_BASE } from "./base"; import type { QuizQuestionRating } from "../model/questionTypes/rating"; -export const QUIZ_QUESTION_RATING: Omit = { +export const QUIZ_QUESTION_RATING: Omit< + QuizQuestionRating, + "id" | "backendId" +> = { ...QUIZ_QUESTION_BASE, type: "rating", content: { diff --git a/src/constants/result.ts b/src/constants/result.ts index 1e1d5c35..668c0413 100644 --- a/src/constants/result.ts +++ b/src/constants/result.ts @@ -3,7 +3,10 @@ import { QUIZ_QUESTION_BASE } from "./base"; import type { QuizQuestionResult } from "../model/questionTypes/result"; import { nanoid } from "nanoid"; -export const QUIZ_QUESTION_RESULT: Omit = { +export const QUIZ_QUESTION_RESULT: Omit< + QuizQuestionResult, + "id" | "backendId" +> = { ...QUIZ_QUESTION_BASE, type: "result", content: { @@ -13,6 +16,6 @@ export const QUIZ_QUESTION_RESULT: Omit text: "", price: [0], useImage: true, - usage: true + usage: true, }, }; diff --git a/src/constants/select.ts b/src/constants/select.ts index ff8de240..8f139aa2 100644 --- a/src/constants/select.ts +++ b/src/constants/select.ts @@ -3,7 +3,10 @@ import { QUIZ_QUESTION_BASE } from "./base"; import type { QuizQuestionSelect } from "../model/questionTypes/select"; import { nanoid } from "nanoid"; -export const QUIZ_QUESTION_SELECT: Omit = { +export const QUIZ_QUESTION_SELECT: Omit< + QuizQuestionSelect, + "id" | "backendId" +> = { ...QUIZ_QUESTION_BASE, type: "select", content: { @@ -13,6 +16,14 @@ export const QUIZ_QUESTION_SELECT: Omit innerNameCheck: false, innerName: "", default: "", - variants: [{ id: nanoid(), answer: "", extendedText: "", hints: "", originalImageUrl: "" }], + variants: [ + { + id: nanoid(), + answer: "", + extendedText: "", + hints: "", + originalImageUrl: "", + }, + ], }, }; diff --git a/src/constants/variant.ts b/src/constants/variant.ts index eaca719a..322dc169 100644 --- a/src/constants/variant.ts +++ b/src/constants/variant.ts @@ -3,7 +3,10 @@ import { QUIZ_QUESTION_BASE } from "./base"; import type { QuizQuestionVariant } from "../model/questionTypes/variant"; import { nanoid } from "nanoid"; -export const QUIZ_QUESTION_VARIANT: Omit = { +export const QUIZ_QUESTION_VARIANT: Omit< + QuizQuestionVariant, + "id" | "backendId" +> = { ...QUIZ_QUESTION_BASE, type: "variant", content: { @@ -14,6 +17,14 @@ export const QUIZ_QUESTION_VARIANT: Omit = { +export const QUIZ_QUESTION_VARIMG: Omit< + QuizQuestionVarImg, + "id" | "backendId" +> = { ...QUIZ_QUESTION_BASE, type: "varimg", content: { @@ -12,7 +15,15 @@ export const QUIZ_QUESTION_VARIMG: Omit innerNameCheck: false, innerName: "", required: false, - variants: [{ id: nanoid(), answer: "", hints: "", extendedText: "", originalImageUrl: "" }], + variants: [ + { + id: nanoid(), + answer: "", + hints: "", + extendedText: "", + originalImageUrl: "", + }, + ], largeCheck: false, replText: "", }, diff --git a/src/index.css b/src/index.css index 6f14e2b9..fcc6de79 100755 --- a/src/index.css +++ b/src/index.css @@ -1,29 +1,29 @@ body { - margin: 0; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', - 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', - sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; + margin: 0; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", + "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", + sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; } code { - font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', - monospace; + font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", + monospace; } @keyframes blinking { - 0% { - opacity: 100; - } - 50% { - opacity: 0; - } - 100% { - opacity: 100; - } + 0% { + opacity: 100; + } + 50% { + opacity: 0; + } + 100% { + opacity: 100; + } } .blink { - animation: blinking 2s infinite ; -} \ No newline at end of file + animation: blinking 2s infinite; +} diff --git a/src/index.tsx b/src/index.tsx index 52919f1d..4f78a2a2 100755 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,47 +1,51 @@ import { CssBaseline, ThemeProvider } from "@mui/material"; import { LocalizationProvider } from "@mui/x-date-pickers"; import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs"; -import { ruRU } from '@mui/x-date-pickers/locales'; +import { ruRU } from "@mui/x-date-pickers/locales"; import App from "./App"; import dayjs from "dayjs"; import "dayjs/locale/ru"; -import { SnackbarProvider } from 'notistack'; +import { SnackbarProvider } from "notistack"; import { DndProvider } from "react-dnd"; import { HTML5Backend } from "react-dnd-html5-backend"; import { createRoot } from "react-dom/client"; import "./index.css"; import lightTheme from "./utils/themes/light"; import { SWRConfig } from "swr"; -import {BrowserRouter} from "react-router-dom"; - - +import { BrowserRouter } from "react-router-dom"; dayjs.locale("ru"); -const localeText = ruRU.components.MuiLocalizationProvider.defaultProps.localeText; +const localeText = + ruRU.components.MuiLocalizationProvider.defaultProps.localeText; const root = createRoot(document.getElementById("root")!); root.render( - - - - - - - - - - - - - - - + + + + + + + + + + + + + + , ); diff --git a/src/model/question/copy.ts b/src/model/question/copy.ts index 834f2455..c74dec76 100644 --- a/src/model/question/copy.ts +++ b/src/model/question/copy.ts @@ -1,8 +1,8 @@ export interface CopyQuestionRequest { - id: number; - quiz_id: number; + id: number; + quiz_id: number; } export interface CopyQuestionResponse { - updated: number; + updated: number; } diff --git a/src/model/question/create.ts b/src/model/question/create.ts index 89190b60..f6a605ba 100644 --- a/src/model/question/create.ts +++ b/src/model/question/create.ts @@ -1,19 +1,18 @@ import { QuestionType } from "./question"; - export interface CreateQuestionRequest { - /** id of quiz for what question is creating */ - quiz_id: number; - /** title of question. max length 512 */ - title: string; - /** description of question. html/text */ - description: string; - /** type of question. allow only text, select, file, variant, images, varimg, emoji, date, number, page, rating */ - type: QuestionType; - /** set true if user MUST answer this question */ - required: boolean; - /** page of question */ - page: number; - /** json serialized of question content settings */ - content: string; -} + /** id of quiz for what question is creating */ + quiz_id: number; + /** title of question. max length 512 */ + title: string; + /** description of question. html/text */ + description: string; + /** type of question. allow only text, select, file, variant, images, varimg, emoji, date, number, page, rating */ + type: QuestionType; + /** set true if user MUST answer this question */ + required: boolean; + /** page of question */ + page: number; + /** json serialized of question content settings */ + content: string; +} diff --git a/src/model/question/delete.ts b/src/model/question/delete.ts index 441bacfd..2e9ea34a 100644 --- a/src/model/question/delete.ts +++ b/src/model/question/delete.ts @@ -1,7 +1,7 @@ export interface DeleteQuestionRequest { - id: number; + id: number; } export interface DeleteQuestionResponse { - deactivated: number; + deactivated: number; } diff --git a/src/model/question/edit.ts b/src/model/question/edit.ts index f17e84ff..3a283879 100644 --- a/src/model/question/edit.ts +++ b/src/model/question/edit.ts @@ -1,29 +1,30 @@ import { AnyTypedQuizQuestion } from "@model/questionTypes/shared"; import { QuestionType } from "./question"; - export interface EditQuestionRequest { - id: number; - title?: string; - desc?: string; - type?: QuestionType; - required?: boolean; - page?: number; - content: string; + id: number; + title?: string; + desc?: string; + type?: QuestionType; + required?: boolean; + page?: number; + content: string; } export interface EditQuestionResponse { - updated: number; + updated: number; } -export function questionToEditQuestionRequest(question: AnyTypedQuizQuestion): EditQuestionRequest { - return { - id: question.backendId, - title: question.title, - desc: question.description, - type: question.type, - required: question.required, - page: question.page, - content: JSON.stringify(question.content), - }; +export function questionToEditQuestionRequest( + question: AnyTypedQuizQuestion, +): EditQuestionRequest { + return { + id: question.backendId, + title: question.title, + desc: question.description, + type: question.type, + required: question.required, + page: question.page, + content: JSON.stringify(question.content), + }; } diff --git a/src/model/question/getList.ts b/src/model/question/getList.ts index a0af41bc..93289b3d 100644 --- a/src/model/question/getList.ts +++ b/src/model/question/getList.ts @@ -1,28 +1,27 @@ import { QuestionType, RawQuestion } from "./question"; - export interface GetQuestionListRequest { - /** max items on page */ - limit?: number; - /** page number */ - offset?: number; - /** start time of time period. timestamp in seconds */ - from?: number; - /** end time of time period. timestamp in seconds */ - to?: number; - /** string for fulltext search in titles of questions */ - search?: string; - /** allow only - text, select, file, variant, images, varimg, emoji, date, number, page, rating or empty string */ - type: "" | QuestionType; - /** get deleted quizes */ - deleted?: boolean; - /** get only require questions */ - required?: boolean; - /** relation to quiz */ - quiz_id?: number; + /** max items on page */ + limit?: number; + /** page number */ + offset?: number; + /** start time of time period. timestamp in seconds */ + from?: number; + /** end time of time period. timestamp in seconds */ + to?: number; + /** string for fulltext search in titles of questions */ + search?: string; + /** allow only - text, select, file, variant, images, varimg, emoji, date, number, page, rating or empty string */ + type: "" | QuestionType; + /** get deleted quizes */ + deleted?: boolean; + /** get only require questions */ + required?: boolean; + /** relation to quiz */ + quiz_id?: number; } export interface GetQuestionListResponse { - count: number; - items: RawQuestion[] | null; + count: number; + items: RawQuestion[] | null; } diff --git a/src/model/question/question.ts b/src/model/question/question.ts index 0a619426..955888e3 100644 --- a/src/model/question/question.ts +++ b/src/model/question/question.ts @@ -2,73 +2,78 @@ import { AnyTypedQuizQuestion } from "@model/questionTypes/shared"; import { defaultQuestionByType } from "../../constants/default"; import { nanoid } from "nanoid"; - export type QuestionType = - | "variant" - | "images" - | "varimg" - | "emoji" - | "text" - | "select" - | "date" - | "number" - | "file" - | "page" - | "rating" - | "result"; + | "variant" + | "images" + | "varimg" + | "emoji" + | "text" + | "select" + | "date" + | "number" + | "file" + | "page" + | "rating" + | "result"; /** Type that comes from server */ export interface RawQuestion { - /** Id of created question */ - id: number; - /** relation to quiz */ - quiz_id: number; - /** title of question. max 512 length */ - title: string; - /** description of question */ - description: string; - /** status of question. allow only text, select, file, variant, images, varimg, emoji, date, number, page, rating */ - type: QuestionType; - /** user must pass this question */ - required: boolean; - /** true if question is deleted */ - deleted: boolean; - /** page if question */ - page: number; - /** serialized json of created question */ - content: string; - /** version of quiz */ - version: number; - /** array of previous versions of quiz */ - parent_ids: number[]; - created_at: string; - updated_at: string; + /** Id of created question */ + id: number; + /** relation to quiz */ + quiz_id: number; + /** title of question. max 512 length */ + title: string; + /** description of question */ + description: string; + /** status of question. allow only text, select, file, variant, images, varimg, emoji, date, number, page, rating */ + type: QuestionType; + /** user must pass this question */ + required: boolean; + /** true if question is deleted */ + deleted: boolean; + /** page if question */ + page: number; + /** serialized json of created question */ + content: string; + /** version of quiz */ + version: number; + /** array of previous versions of quiz */ + parent_ids: number[]; + created_at: string; + updated_at: string; } -export function rawQuestionToQuestion(rawQuestion: RawQuestion): AnyTypedQuizQuestion { - let content = defaultQuestionByType[rawQuestion.type].content; - const frontId = nanoid() +export function rawQuestionToQuestion( + rawQuestion: RawQuestion, +): AnyTypedQuizQuestion { + let content = defaultQuestionByType[rawQuestion.type].content; + const frontId = nanoid(); - try { - content = JSON.parse(rawQuestion.content); - if (content.id.length === 0 || content.id.length === undefined) content.id = frontId - } catch (error) { - console.warn("Cannot parse question content from string, using default content", error); - } + try { + content = JSON.parse(rawQuestion.content); + if (content.id.length === 0 || content.id.length === undefined) + content.id = frontId; + } catch (error) { + console.warn( + "Cannot parse question content from string, using default content", + error, + ); + } - return { - backendId: rawQuestion.id, - id: frontId, - description: rawQuestion.description, - page: rawQuestion.page, - quizId: rawQuestion.quiz_id, - required: rawQuestion.required, - title: rawQuestion.title, - type: rawQuestion.type, - expanded: true, - openedModalSettings: false, - deleted: false, - deleteTimeoutId: 0, - content, - } as AnyTypedQuizQuestion; -} + return { + backendId: rawQuestion.id, + id: frontId, + description: rawQuestion.description, + page: rawQuestion.page, + quizId: rawQuestion.quiz_id, + required: rawQuestion.required, + title: rawQuestion.title, + type: rawQuestion.type, + expanded: true, + openedModalSettings: false, + deleted: false, + deleteTimeoutId: 0, + content, + } as AnyTypedQuizQuestion; +} diff --git a/src/model/questionTypes/date.ts b/src/model/questionTypes/date.ts index 84956e8a..5c8935ff 100644 --- a/src/model/questionTypes/date.ts +++ b/src/model/questionTypes/date.ts @@ -1,8 +1,4 @@ -import type { - QuizQuestionBase, - QuestionHint, - PreviewRule, -} from "./shared"; +import type { QuizQuestionBase, QuestionHint, PreviewRule } from "./shared"; export interface QuizQuestionDate extends QuizQuestionBase { type: "date"; diff --git a/src/model/questionTypes/file.ts b/src/model/questionTypes/file.ts index a0a1bf3c..1a66b78a 100644 --- a/src/model/questionTypes/file.ts +++ b/src/model/questionTypes/file.ts @@ -1,8 +1,4 @@ -import type { - QuizQuestionBase, - QuestionHint, - PreviewRule, -} from "./shared"; +import type { QuizQuestionBase, QuestionHint, PreviewRule } from "./shared"; export const UPLOAD_FILE_TYPES_MAP = { all: "Все типы файлов", diff --git a/src/model/questionTypes/images.ts b/src/model/questionTypes/images.ts index 24b95fd8..35550ccb 100644 --- a/src/model/questionTypes/images.ts +++ b/src/model/questionTypes/images.ts @@ -6,32 +6,32 @@ import type { } from "./shared"; export interface QuizQuestionImages extends QuizQuestionBase { - type: "images"; - content: { - id: string; - /** Чекбокс "Вариант "свой ответ"" */ - own: boolean; - /** Чекбокс "Можно несколько" */ - multi: boolean; - /** Пропорции */ - xy: "1:1" | "1:2" | "2:1"; - /** Чекбокс "Внутреннее название вопроса" */ - innerNameCheck: boolean; - /** Поле "Внутреннее название вопроса" */ - innerName: string; - /** Чекбокс "Большие картинки" */ - large: boolean; - /** Форма */ - format: "carousel" | "masonry"; - /** Чекбокс "Необязательный вопрос" */ - required: boolean; - /** Варианты (картинки) */ - variants: QuestionVariant[]; - hint: QuestionHint; - rule: QuestionBranchingRule; - back: string | null; - originalBack: string | null; - autofill: boolean; - largeCheck: boolean; - }; + type: "images"; + content: { + id: string; + /** Чекбокс "Вариант "свой ответ"" */ + own: boolean; + /** Чекбокс "Можно несколько" */ + multi: boolean; + /** Пропорции */ + xy: "1:1" | "1:2" | "2:1"; + /** Чекбокс "Внутреннее название вопроса" */ + innerNameCheck: boolean; + /** Поле "Внутреннее название вопроса" */ + innerName: string; + /** Чекбокс "Большие картинки" */ + large: boolean; + /** Форма */ + format: "carousel" | "masonry"; + /** Чекбокс "Необязательный вопрос" */ + required: boolean; + /** Варианты (картинки) */ + variants: QuestionVariant[]; + hint: QuestionHint; + rule: QuestionBranchingRule; + back: string | null; + originalBack: string | null; + autofill: boolean; + largeCheck: boolean; + }; } diff --git a/src/model/questionTypes/number.ts b/src/model/questionTypes/number.ts index 77a604cb..4b3718c2 100644 --- a/src/model/questionTypes/number.ts +++ b/src/model/questionTypes/number.ts @@ -1,8 +1,4 @@ -import type { - QuizQuestionBase, - QuestionHint, - PreviewRule, -} from "./shared"; +import type { QuizQuestionBase, QuestionHint, PreviewRule } from "./shared"; export interface QuizQuestionNumber extends QuizQuestionBase { type: "number"; diff --git a/src/model/questionTypes/rating.ts b/src/model/questionTypes/rating.ts index 38017f85..31785ddf 100644 --- a/src/model/questionTypes/rating.ts +++ b/src/model/questionTypes/rating.ts @@ -1,8 +1,4 @@ -import type { - QuizQuestionBase, - QuestionHint, - PreviewRule, -} from "./shared"; +import type { QuizQuestionBase, QuestionHint, PreviewRule } from "./shared"; export interface QuizQuestionRating extends QuizQuestionBase { type: "rating"; diff --git a/src/model/questionTypes/result.ts b/src/model/questionTypes/result.ts index 0437b2ce..80ab935a 100644 --- a/src/model/questionTypes/result.ts +++ b/src/model/questionTypes/result.ts @@ -15,9 +15,9 @@ export interface QuizQuestionResult extends QuizQuestionBase { text: string; price: [number] | [number, number]; useImage: boolean; - rule: QuestionBranchingRule, + rule: QuestionBranchingRule; hint: QuestionHint; autofill: boolean; - usage: boolean + usage: boolean; }; } diff --git a/src/model/questionTypes/shared.ts b/src/model/questionTypes/shared.ts index b0fb8084..d8fa97ce 100644 --- a/src/model/questionTypes/shared.ts +++ b/src/model/questionTypes/shared.ts @@ -101,12 +101,13 @@ type FilterQuestionsWithVariants = T extends { ? T : never; -export type QuizQuestionsWithVariants = FilterQuestionsWithVariants; +export type QuizQuestionsWithVariants = + FilterQuestionsWithVariants; -export const createBranchingRuleMain: (targetId: string, parentId: string) => QuestionBranchingRuleMain = ( - targetId, - parentId -) => ({ +export const createBranchingRuleMain: ( + targetId: string, + parentId: string, +) => QuestionBranchingRuleMain = (targetId, parentId) => ({ next: targetId, or: false, rules: [ diff --git a/src/model/questionTypes/text.ts b/src/model/questionTypes/text.ts index b2e47689..c38101aa 100644 --- a/src/model/questionTypes/text.ts +++ b/src/model/questionTypes/text.ts @@ -1,8 +1,4 @@ -import type { - QuizQuestionBase, - QuestionHint, - PreviewRule, -} from "./shared"; +import type { QuizQuestionBase, QuestionHint, PreviewRule } from "./shared"; export interface QuizQuestionText extends QuizQuestionBase { type: "text"; diff --git a/src/model/questionTypes/varimg.ts b/src/model/questionTypes/varimg.ts index 83f8381a..504db463 100644 --- a/src/model/questionTypes/varimg.ts +++ b/src/model/questionTypes/varimg.ts @@ -6,24 +6,24 @@ import type { } from "./shared"; export interface QuizQuestionVarImg extends QuizQuestionBase { - type: "varimg"; - content: { - id: string; - /** Чекбокс "Вариант "свой ответ"" */ - own: boolean; - /** Чекбокс "Внутреннее название вопроса" */ - innerNameCheck: boolean; - /** Поле "Внутреннее название вопроса" */ - innerName: string; - /** Чекбокс "Необязательный вопрос" */ - required: boolean; - variants: QuestionVariant[]; - hint: QuestionHint; - rule: QuestionBranchingRule; - back: string; - originalBack: string; - autofill: boolean; - largeCheck: boolean; - replText: string; - }; + type: "varimg"; + content: { + id: string; + /** Чекбокс "Вариант "свой ответ"" */ + own: boolean; + /** Чекбокс "Внутреннее название вопроса" */ + innerNameCheck: boolean; + /** Поле "Внутреннее название вопроса" */ + innerName: string; + /** Чекбокс "Необязательный вопрос" */ + required: boolean; + variants: QuestionVariant[]; + hint: QuestionHint; + rule: QuestionBranchingRule; + back: string; + originalBack: string; + autofill: boolean; + largeCheck: boolean; + replText: string; + }; } diff --git a/src/model/quiz/copy.ts b/src/model/quiz/copy.ts index 804777c9..0486746f 100644 --- a/src/model/quiz/copy.ts +++ b/src/model/quiz/copy.ts @@ -1,7 +1,7 @@ export interface CopyQuizRequest { - id: number; + id: number; } export interface CopyQuizResponse { - updated: number; + updated: number; } diff --git a/src/model/quiz/create.ts b/src/model/quiz/create.ts index c4271a79..081871a4 100644 --- a/src/model/quiz/create.ts +++ b/src/model/quiz/create.ts @@ -1,34 +1,34 @@ export interface CreateQuizRequest { - /** set true for save deviceId */ - fingerprinting: boolean; - /** set true for allow user to repeat quiz */ - repeatable: boolean; - /** set true for save statistic of incomplete quiz passing */ - note_prevented: boolean; - /** set true for mail notification for each quiz passing */ - mail_notifications: boolean; - /** set true for save statistics only for unique quiz passing */ - unique_answers: boolean; - /** name of quiz. max 280 length */ - name: string; - /** description of quiz */ - description: string; - /** config of quiz. serialized json for rules of quiz flow */ - config: string; - /** status of quiz. allow only '', 'draft', 'template', 'stop', 'start' */ - status: "draft" | "template" | "stop" | "start"; - /** limit is count of max quiz passing */ - limit: number; - /** last time when quiz is valid. timestamp in seconds */ - due_to: number; - /** seconds to pass quiz */ - time_of_passing: number; - /** true if it is allowed for pause quiz */ - pausable: boolean; - /** count of questions */ - question_cnt?: number; - /** set true if squiz realize group functionality */ - super: boolean; - /** group of new quiz */ - group_id: number; + /** set true for save deviceId */ + fingerprinting: boolean; + /** set true for allow user to repeat quiz */ + repeatable: boolean; + /** set true for save statistic of incomplete quiz passing */ + note_prevented: boolean; + /** set true for mail notification for each quiz passing */ + mail_notifications: boolean; + /** set true for save statistics only for unique quiz passing */ + unique_answers: boolean; + /** name of quiz. max 280 length */ + name: string; + /** description of quiz */ + description: string; + /** config of quiz. serialized json for rules of quiz flow */ + config: string; + /** status of quiz. allow only '', 'draft', 'template', 'stop', 'start' */ + status: "draft" | "template" | "stop" | "start"; + /** limit is count of max quiz passing */ + limit: number; + /** last time when quiz is valid. timestamp in seconds */ + due_to: number; + /** seconds to pass quiz */ + time_of_passing: number; + /** true if it is allowed for pause quiz */ + pausable: boolean; + /** count of questions */ + question_cnt?: number; + /** set true if squiz realize group functionality */ + super: boolean; + /** group of new quiz */ + group_id: number; } diff --git a/src/model/quiz/delete.ts b/src/model/quiz/delete.ts index 3cc0717a..d7d3a694 100644 --- a/src/model/quiz/delete.ts +++ b/src/model/quiz/delete.ts @@ -1,7 +1,7 @@ export interface DeleteQuizRequest { - id: number; + id: number; } export interface DeleteQuizResponse { - deactivated: number; + deactivated: number; } diff --git a/src/model/quiz/edit.ts b/src/model/quiz/edit.ts index a548a38c..90113d3c 100644 --- a/src/model/quiz/edit.ts +++ b/src/model/quiz/edit.ts @@ -1,66 +1,65 @@ import { Quiz } from "./quiz"; - export interface EditQuizRequest { - /** id of question for update */ - id: number; - /** set true for storing fingerprints */ - fp: boolean; - /** set true for allow to repeat quiz after passing */ - rep: boolean; - /** set true for store unfinished passing */ - note_prevented: boolean; - /** set true if we should send passing result on every passing */ - mailing: boolean; - /** set true if we allow only one user quiz passing */ - uniq: boolean; - /** new name of the quiz */ - name?: string; - /** new descriptions of the quiz */ - desc?: string; - /** new config of the quiz */ - conf?: string; - /** new status. only draft,template,stop,start allowed */ - status?: string; - /** max amount of quiz passing */ - limit: number; - /** max time of quiz passing */ - due_to: number; - /** max time to pass quiz */ - time_of_passing: number; - /** allow to pause quiz to user */ - pausable: boolean; - /** count of questions */ - question_cnt?: number; - /** set true if squiz realize group functionality */ - super?: boolean; - /** group of new quiz */ - group_id?: number; + /** id of question for update */ + id: number; + /** set true for storing fingerprints */ + fp: boolean; + /** set true for allow to repeat quiz after passing */ + rep: boolean; + /** set true for store unfinished passing */ + note_prevented: boolean; + /** set true if we should send passing result on every passing */ + mailing: boolean; + /** set true if we allow only one user quiz passing */ + uniq: boolean; + /** new name of the quiz */ + name?: string; + /** new descriptions of the quiz */ + desc?: string; + /** new config of the quiz */ + conf?: string; + /** new status. only draft,template,stop,start allowed */ + status?: string; + /** max amount of quiz passing */ + limit: number; + /** max time of quiz passing */ + due_to: number; + /** max time to pass quiz */ + time_of_passing: number; + /** allow to pause quiz to user */ + pausable: boolean; + /** count of questions */ + question_cnt?: number; + /** set true if squiz realize group functionality */ + super?: boolean; + /** group of new quiz */ + group_id?: number; } export interface EditQuizResponse { - /** id of new version of question */ - updated: number; + /** id of new version of question */ + updated: number; } export function quizToEditQuizRequest(quiz: Quiz): EditQuizRequest { - return { - id: quiz.backendId, - fp: quiz.fingerprinting, - rep: quiz.repeatable, - note_prevented: quiz.note_prevented, - mailing: quiz.mail_notifications, - uniq: quiz.unique_answers, - name: quiz.name, - desc: quiz.description, - conf: JSON.stringify(quiz.config), - status: quiz.status, - limit: quiz.limit, - due_to: quiz.due_to, - time_of_passing: quiz.time_of_passing, - pausable: quiz.pausable, - question_cnt: quiz.question_cnt, - super: quiz.super, - group_id: quiz.group_id, - }; + return { + id: quiz.backendId, + fp: quiz.fingerprinting, + rep: quiz.repeatable, + note_prevented: quiz.note_prevented, + mailing: quiz.mail_notifications, + uniq: quiz.unique_answers, + name: quiz.name, + desc: quiz.description, + conf: JSON.stringify(quiz.config), + status: quiz.status, + limit: quiz.limit, + due_to: quiz.due_to, + time_of_passing: quiz.time_of_passing, + pausable: quiz.pausable, + question_cnt: quiz.question_cnt, + super: quiz.super, + group_id: quiz.group_id, + }; } diff --git a/src/model/quiz/get.ts b/src/model/quiz/get.ts index 29988c75..e660f1a1 100644 --- a/src/model/quiz/get.ts +++ b/src/model/quiz/get.ts @@ -1,29 +1,29 @@ export interface GetQuizRequest { - quiz_id: string; - limit: number; - page: number; - need_config: boolean; + quiz_id: string; + limit: number; + page: number; + need_config: boolean; } export interface GetQuizResponse { - cnt: number; - settings: { - fp: boolean; - rep: boolean; - name: string; - cfg: string; - lim: number; - due: number; - delay: number; - pausable: boolean; - }; - items: { - id: number; - title: string; - desc: string; - typ: string; - req: boolean; - p: number; - c: string; - }[]; -} + cnt: number; + settings: { + fp: boolean; + rep: boolean; + name: string; + cfg: string; + lim: number; + due: number; + delay: number; + pausable: boolean; + }; + items: { + id: number; + title: string; + desc: string; + typ: string; + req: boolean; + p: number; + c: string; + }[]; +} diff --git a/src/model/quiz/getList.ts b/src/model/quiz/getList.ts index 3abed8ad..c0acc52a 100644 --- a/src/model/quiz/getList.ts +++ b/src/model/quiz/getList.ts @@ -1,29 +1,36 @@ import { RawQuiz } from "./quiz"; export interface GetQuizListRequest { - /** max items on page */ - limit?: number; - /** page number */ - offset?: number; - /** start time of time period. timestamp in seconds */ - from?: number; - /** end time of time period. timestamp in seconds */ - to?: number; - /** string for fulltext search in titles of quizes */ - search?: string; - /** allow only - draft, template, timeout, stop, start, offlimit */ - status?: "" | "draft" | "template" | "timeout" | "stop" | "start" | "offlimit"; - /** get deleted quizes */ - deleted?: boolean; - /** get archived quizes */ - archived?: boolean; - /** set true if squiz realize group functionality */ - super?: boolean; - /** group of new quiz */ - group_id?: number; + /** max items on page */ + limit?: number; + /** page number */ + offset?: number; + /** start time of time period. timestamp in seconds */ + from?: number; + /** end time of time period. timestamp in seconds */ + to?: number; + /** string for fulltext search in titles of quizes */ + search?: string; + /** allow only - draft, template, timeout, stop, start, offlimit */ + status?: + | "" + | "draft" + | "template" + | "timeout" + | "stop" + | "start" + | "offlimit"; + /** get deleted quizes */ + deleted?: boolean; + /** get archived quizes */ + archived?: boolean; + /** set true if squiz realize group functionality */ + super?: boolean; + /** group of new quiz */ + group_id?: number; } export interface GetQuizListResponse { - count: number; - items: RawQuiz[]; + count: number; + items: RawQuiz[]; } diff --git a/src/model/quiz/quiz.ts b/src/model/quiz/quiz.ts index 0de02cdc..d5e16d01 100644 --- a/src/model/quiz/quiz.ts +++ b/src/model/quiz/quiz.ts @@ -1,133 +1,137 @@ import { QuizConfig, defaultQuizConfig } from "@model/quizSettings"; import { nanoid } from "nanoid"; - export interface Quiz { - /** Stable id, generated on client */ - id: string; - /** Id of created quiz */ - backendId: number; - /** string id for customers */ - qid: string; - /** true if quiz deleted */ - deleted: boolean; - /** true if quiz archived */ - archived: boolean; - /** set true for save deviceId */ - fingerprinting: boolean; - /** set true for allow user to repeat quiz */ - repeatable: boolean; - /** set true for save statistic of incomplete quiz passing */ - note_prevented: boolean; - /** set true for mail notification for each quiz passing */ - mail_notifications: boolean; - /** set true for save statistics only for unique quiz passing */ - unique_answers: boolean; - /** name of quiz. max 280 length */ - name: string; - /** description of quiz */ - description: string; - /** quiz config*/ - config: QuizConfig; - /** status of quiz. allow only '', 'draft', 'template', 'stop', 'start' */ - status: string; - /** limit is count of max quiz passing */ - limit: number; - /** last time when quiz is valid. timestamp in seconds */ - due_to: number; - /** seconds to pass quiz */ - time_of_passing: number; - /** true if it is allowed for pause quiz */ - pausable: boolean; - /** version of quiz */ - version: number; - /** version comment to version of quiz */ - version_comment: string; - /** array of previous versions of quiz */ - parent_ids: number[]; - created_at: string; - updated_at: string; - /** count of questions */ - question_cnt: number; - /** count passings */ - passed_count: number; - /** average time of passing */ - average_time: number; - /** set true if squiz realize group functionality */ - super: boolean; - /** group of new quiz */ - group_id: number; + /** Stable id, generated on client */ + id: string; + /** Id of created quiz */ + backendId: number; + /** string id for customers */ + qid: string; + /** true if quiz deleted */ + deleted: boolean; + /** true if quiz archived */ + archived: boolean; + /** set true for save deviceId */ + fingerprinting: boolean; + /** set true for allow user to repeat quiz */ + repeatable: boolean; + /** set true for save statistic of incomplete quiz passing */ + note_prevented: boolean; + /** set true for mail notification for each quiz passing */ + mail_notifications: boolean; + /** set true for save statistics only for unique quiz passing */ + unique_answers: boolean; + /** name of quiz. max 280 length */ + name: string; + /** description of quiz */ + description: string; + /** quiz config*/ + config: QuizConfig; + /** status of quiz. allow only '', 'draft', 'template', 'stop', 'start' */ + status: string; + /** limit is count of max quiz passing */ + limit: number; + /** last time when quiz is valid. timestamp in seconds */ + due_to: number; + /** seconds to pass quiz */ + time_of_passing: number; + /** true if it is allowed for pause quiz */ + pausable: boolean; + /** version of quiz */ + version: number; + /** version comment to version of quiz */ + version_comment: string; + /** array of previous versions of quiz */ + parent_ids: number[]; + created_at: string; + updated_at: string; + /** count of questions */ + question_cnt: number; + /** count passings */ + passed_count: number; + /** average time of passing */ + average_time: number; + /** set true if squiz realize group functionality */ + super: boolean; + + questions_count: number; + /** group of new quiz */ + group_id: number; } /** Type that comes from server */ export interface RawQuiz { - /** Id of created quiz */ - id: number; - /** string id for customers */ - qid: string; - /** true if quiz deleted */ - deleted: boolean; - /** true if quiz archived */ - archived: boolean; - /** set true for save deviceId */ - fingerprinting: boolean; - /** set true for allow user to repeat quiz */ - repeatable: boolean; - /** set true for save statistic of incomplete quiz passing */ - note_prevented: boolean; - /** set true for mail notification for each quiz passing */ - mail_notifications: boolean; - /** set true for save statistics only for unique quiz passing */ - unique_answers: boolean; - /** name of quiz. max 280 length */ - name: string; - /** description of quiz */ - description: string; - /** config of quiz. serialized json for rules of quiz flow */ - config: string; - /** status of quiz. allow only '', 'draft', 'template', 'stop', 'start' */ - status: string; - /** limit is count of max quiz passing */ - limit: number; - /** last time when quiz is valid. timestamp in seconds */ - due_to: number; - /** seconds to pass quiz */ - time_of_passing: number; - /** true if it is allowed for pause quiz */ - pausable: boolean; - /** version of quiz */ - version: number; - /** version comment to version of quiz */ - version_comment: string; - /** array of previous versions of quiz */ - parent_ids: number[]; - created_at: string; - updated_at: string; - /** count of questions */ - question_cnt: number; - /** count passings */ - passed_count: number; - /** average time of passing */ - average_time: number; - /** set true if squiz realize group functionality */ - super: boolean; - /** group of new quiz */ - group_id: number; + /** Id of created quiz */ + id: number; + /** string id for customers */ + qid: string; + /** true if quiz deleted */ + deleted: boolean; + /** true if quiz archived */ + archived: boolean; + /** set true for save deviceId */ + fingerprinting: boolean; + /** set true for allow user to repeat quiz */ + repeatable: boolean; + /** set true for save statistic of incomplete quiz passing */ + note_prevented: boolean; + /** set true for mail notification for each quiz passing */ + mail_notifications: boolean; + /** set true for save statistics only for unique quiz passing */ + unique_answers: boolean; + /** name of quiz. max 280 length */ + name: string; + /** description of quiz */ + description: string; + /** config of quiz. serialized json for rules of quiz flow */ + config: string; + /** status of quiz. allow only '', 'draft', 'template', 'stop', 'start' */ + status: string; + /** limit is count of max quiz passing */ + limit: number; + /** last time when quiz is valid. timestamp in seconds */ + due_to: number; + /** seconds to pass quiz */ + time_of_passing: number; + /** true if it is allowed for pause quiz */ + pausable: boolean; + /** version of quiz */ + version: number; + /** version comment to version of quiz */ + version_comment: string; + /** array of previous versions of quiz */ + parent_ids: number[]; + created_at: string; + updated_at: string; + /** count of questions */ + question_cnt: number; + /** count passings */ + passed_count: number; + /** average time of passing */ + average_time: number; + /** set true if squiz realize group functionality */ + super: boolean; + /** group of new quiz */ + group_id: number; } export function rawQuizToQuiz(rawQuiz: RawQuiz): Quiz { - let config = defaultQuizConfig; + let config = defaultQuizConfig; - try { - config = JSON.parse(rawQuiz.config); - } catch (error) { - console.warn("Cannot parse quiz config from string, using default config", error); - } + try { + config = JSON.parse(rawQuiz.config); + } catch (error) { + console.warn( + "Cannot parse quiz config from string, using default config", + error, + ); + } - return { - ...rawQuiz, - config, - backendId: rawQuiz.id, - id: nanoid(), - }; + return { + ...rawQuiz, + config, + backendId: rawQuiz.id, + id: nanoid(), + }; } diff --git a/src/model/quizSettings.ts b/src/model/quizSettings.ts index 02b95274..cee0dbcc 100644 --- a/src/model/quizSettings.ts +++ b/src/model/quizSettings.ts @@ -6,15 +6,34 @@ import MegaphoneIcon from "@icons/MegaphoneIcon"; import QuestionIcon from "@icons/QuestionIcon"; import QuestionsMapIcon from "@icons/QuestionsMapIcon"; - export const quizSetupSteps = [ - { stepperText: "Настройка стартовой страницы", sidebarText: "Стартовая страница", sidebarIcon: LayoutIcon }, - { stepperText: "Задайте вопросы", sidebarText: "Вопросы", sidebarIcon: QuestionIcon }, - { stepperText: "Настройте авторезультаты", sidebarText: "Результаты", sidebarIcon: ChartPieIcon }, - // { stepperText: "Оценка графа карты вопросов", sidebarText: "Карта вопросов", sidebarIcon: QuestionsMapIcon }, - { stepperText: "Настройте форму контактов", sidebarText: "Форма контактов", sidebarIcon: ContactBookIcon }, - { stepperText: "Установите квиз", sidebarText: "Установка квиза", sidebarIcon: FlowArrowIcon }, - // { stepperText: "Запустите рекламу", sidebarText: "Запуск рекламы", sidebarIcon: MegaphoneIcon }, + { + stepperText: "Настройка стартовой страницы", + sidebarText: "Стартовая страница", + sidebarIcon: LayoutIcon, + }, + { + stepperText: "Задайте вопросы", + sidebarText: "Вопросы", + sidebarIcon: QuestionIcon, + }, + { + stepperText: "Настройте авторезультаты", + sidebarText: "Результаты", + sidebarIcon: ChartPieIcon, + }, + // { stepperText: "Оценка графа карты вопросов", sidebarText: "Карта вопросов", sidebarIcon: QuestionsMapIcon }, + { + stepperText: "Настройте форму контактов", + sidebarText: "Форма контактов", + sidebarIcon: ContactBookIcon, + }, + { + stepperText: "Установите quiz", + sidebarText: "Установка quiz", + sidebarIcon: FlowArrowIcon, + }, + // { stepperText: "Запустите рекламу", sidebarText: "Запуск рекламы", sidebarIcon: MegaphoneIcon }, ] as const; export const maxQuizSetupSteps = quizSetupSteps.length; @@ -28,148 +47,164 @@ export type QuizType = "quiz" | "form" | null; export type QuizResultsType = true | null; export interface QuizConfig { - type: QuizType; - noStartPage: boolean; - startpageType: QuizStartpageType; - results: QuizResultsType; - haveRoot: string | null; - theme: "StandardTheme" | "StandardDarkTheme" | "PinkTheme" | "PinkDarkTheme" | "BlackWhiteTheme" | "OliveTheme" | "YellowTheme" | "GoldDarkTheme" | "PurpleTheme" | "BlueTheme" | "BlueDarkTheme"; - resultInfo: { - when: 'before' | 'after' | 'email', - share: true | false, - replay: true | false, - theme: string, - reply: string, - replname: string, + type: QuizType; + noStartPage: boolean; + startpageType: QuizStartpageType; + results: QuizResultsType; + haveRoot: string | null; + theme: + | "StandardTheme" + | "StandardDarkTheme" + | "PinkTheme" + | "PinkDarkTheme" + | "BlackWhiteTheme" + | "OliveTheme" + | "YellowTheme" + | "GoldDarkTheme" + | "PurpleTheme" + | "BlueTheme" + | "BlueDarkTheme"; + resultInfo: { + when: "before" | "after" | "email"; + share: true | false; + replay: true | false; + theme: string; + reply: string; + replname: string; + }; + startpage: { + description: string; + button: string; + position: QuizStartpageAlignType; + favIcon: string | null; + logo: string | null; + originalLogo: string | null; + background: { + type: null | "image" | "video"; + desktop: string | null; + originalDesktop: string | null; + mobile: string | null; + originalMobile: string | null; + video: string | null; + cycle: boolean; }; - startpage: { - description: string; - button: string; - position: QuizStartpageAlignType; - favIcon: string | null; - logo: string | null; - originalLogo: string | null; - background: { - type: null | "image" | "video"; - desktop: string | null; - originalDesktop: string | null; - mobile: string | null; - originalMobile: string | null; - video: string | null; - cycle: boolean; - }; - }; - formContact: { - title: string; - desc: string; - fields: Record; - button: string; - }; - info: { - phonenumber: string; - clickable: boolean; - orgname: string; - site: string; - law?: string; - }; - meta: string; + }; + formContact: { + title: string; + desc: string; + fields: Record; + button: string; + }; + info: { + phonenumber: string; + clickable: boolean; + orgname: string; + site: string; + law?: string; + }; + meta: string; } -export type FormContactFieldName = "name" | "email" | "phone" | "text" | "address"; +export type FormContactFieldName = + | "name" + | "email" + | "phone" + | "text" + | "address"; type FormContactFieldData = { - text: string; - innerText: string; - key: string; - required: boolean; - used: boolean; + text: string; + innerText: string; + key: string; + required: boolean; + used: boolean; }; export type FieldSettingsDrawerState = { - field: FormContactFieldName | "all" | "", - isEdit: boolean; + field: FormContactFieldName | "all" | ""; + isEdit: boolean; }; export const defaultQuizConfig: QuizConfig = { - type: null, - noStartPage: false, - startpageType: null, - results: null, - haveRoot: null, - theme: "StandardTheme", - resultInfo: { - when: 'after', - share: false, - replay: false, - theme: "", - reply: "", - replname: "", + type: null, + noStartPage: false, + startpageType: null, + results: null, + haveRoot: null, + theme: "StandardTheme", + resultInfo: { + when: "after", + share: false, + replay: false, + theme: "", + reply: "", + replname: "", + }, + startpage: { + description: "", + button: "", + position: "left", + favIcon: null, + logo: null, + originalLogo: null, + background: { + type: null, + desktop: null, + originalDesktop: null, + mobile: null, + originalMobile: null, + video: null, + cycle: false, }, - startpage: { - description: "", - button: "", - position: "left", - favIcon: null, - logo: null, - originalLogo: null, - background: { - type: null, - desktop: null, - originalDesktop: null, - mobile: null, - originalMobile: null, - video: null, - cycle: false, - }, + }, + info: { + phonenumber: "", + clickable: false, + orgname: "", + site: "", + law: "", + }, + formContact: { + title: "", + desc: "", + fields: { + name: { + text: "", + innerText: "", + key: "", + required: false, + used: true, + }, + email: { + text: "", + innerText: "", + key: "", + required: false, + used: true, + }, + phone: { + text: "", + innerText: "", + key: "", + required: false, + used: true, + }, + text: { + text: "", + innerText: "", + key: "", + required: false, + used: false, + }, + address: { + text: "", + innerText: "", + key: "", + required: false, + used: false, + }, }, - info: { - phonenumber: "", - clickable: false, - orgname: "", - site: "", - law: "", - }, - formContact: { - title: "", - desc: "", - fields: { - name: { - text: "", - innerText: "", - key: "", - required: false, - used: true - }, - email: { - text: "", - innerText: "", - key: "", - required: false, - used: true - }, - phone: { - text: "", - innerText: "", - key: "", - required: false, - used: true - }, - text: { - text: "", - innerText: "", - key: "", - required: false, - used: false - }, - address: { - text: "", - innerText: "", - key: "", - required: false, - used: false - }, - }, - button: "", - }, - meta: "", + button: "", + }, + meta: "", }; diff --git a/src/mui.d.ts b/src/mui.d.ts index 446edc4a..22cbc91c 100755 --- a/src/mui.d.ts +++ b/src/mui.d.ts @@ -1,50 +1,50 @@ import "@material-ui/styles"; declare module "@mui/material/styles" { - interface Palette { - lightPurple: Palette["primary"], - darkPurple: Palette["primary"], - brightPurple: Palette["primary"], - fadePurple: Palette["primary"], - grey1: Palette["primary"], - grey2: Palette["primary"], - grey3: Palette["primary"], - grey4: Palette["primary"], - orange: Palette["primary"], - navbarbg: Palette["primary"], - } - interface PaletteOptions { - lightPurple?: PaletteOptions["primary"], - darkPurple?: PaletteOptions["primary"], - brightPurple?: PaletteOptions["primary"], - fadePurple?: PaletteOptions["primary"], - grey1?: PaletteOptions["primary"], - grey2?: PaletteOptions["primary"], - grey3?: PaletteOptions["primary"], - grey4?: PaletteOptions["primary"], - orange?: PaletteOptions["primary"], - navbarbg?: PaletteOptions["primary"], - } - interface TypographyVariants { - infographic: React.CSSProperties; - p1: React.CSSProperties; - } - interface TypographyVariantsOptions { - infographic?: React.CSSProperties; - p1?: React.CSSProperties; - } + interface Palette { + lightPurple: Palette["primary"]; + darkPurple: Palette["primary"]; + brightPurple: Palette["primary"]; + fadePurple: Palette["primary"]; + grey1: Palette["primary"]; + grey2: Palette["primary"]; + grey3: Palette["primary"]; + grey4: Palette["primary"]; + orange: Palette["primary"]; + navbarbg: Palette["primary"]; + } + interface PaletteOptions { + lightPurple?: PaletteOptions["primary"]; + darkPurple?: PaletteOptions["primary"]; + brightPurple?: PaletteOptions["primary"]; + fadePurple?: PaletteOptions["primary"]; + grey1?: PaletteOptions["primary"]; + grey2?: PaletteOptions["primary"]; + grey3?: PaletteOptions["primary"]; + grey4?: PaletteOptions["primary"]; + orange?: PaletteOptions["primary"]; + navbarbg?: PaletteOptions["primary"]; + } + interface TypographyVariants { + infographic: React.CSSProperties; + p1: React.CSSProperties; + } + interface TypographyVariantsOptions { + infographic?: React.CSSProperties; + p1?: React.CSSProperties; + } } declare module "@mui/material/Typography" { - interface TypographyPropsVariantOverrides { - infographic: true; - p1: true; - } + interface TypographyPropsVariantOverrides { + infographic: true; + p1: true; + } } type DataAttributeKey = `data-${string}`; -declare module 'react' { - interface HTMLAttributes extends AriaAttributes, DOMAttributes { - [dataAttribute: DataAttributeKey]: unknown; - } +declare module "react" { + interface HTMLAttributes extends AriaAttributes, DOMAttributes { + [dataAttribute: DataAttributeKey]: unknown; + } } diff --git a/src/pages/ContactFormPage/BranchingForm.tsx b/src/pages/ContactFormPage/BranchingForm.tsx index 5da2a71f..8186bbf8 100644 --- a/src/pages/ContactFormPage/BranchingForm.tsx +++ b/src/pages/ContactFormPage/BranchingForm.tsx @@ -1,140 +1,179 @@ import { - Box, - Button, - FormControl, FormControlLabel, Link, - Modal, Radio, RadioGroup, - SelectChangeEvent, - Typography, - useTheme + Box, + Button, + FormControl, + FormControlLabel, + Link, + Modal, + Radio, + RadioGroup, + SelectChangeEvent, + Typography, + useTheme, } from "@mui/material"; import * as React from "react"; import SelectableButton from "@ui_kit/SelectableButton"; -import {useState} from "react"; +import { useState } from "react"; import RadioCheck from "@ui_kit/RadioCheck"; import RadioIcon from "@ui_kit/RadioIcon"; type LogicForm = "conditions" | "results"; export default function BranchingForm() { - const theme = useTheme() - const [open, setOpen] = React.useState(false); - const handleOpen = () => setOpen(true); - const handleClose = () => setOpen(false); - const [logicForm, setLogicForm] = useState("conditions"); - const [display, setDisplay] = React.useState('1'); - const handleChange = (event: SelectChangeEvent) => { - setDisplay(event.target.value); - } + const theme = useTheme(); + const [open, setOpen] = React.useState(false); + const handleOpen = () => setOpen(true); + const handleClose = () => setOpen(false); + const [logicForm, setLogicForm] = useState("conditions"); + const [display, setDisplay] = React.useState("1"); + const handleChange = (event: SelectChangeEvent) => { + setDisplay(event.target.value); + }; - const [value, setValue] = React.useState('1'); + const [value, setValue] = React.useState("1"); - const handleChangeRadio = (event: React.ChangeEvent) => { - setValue((event.target as HTMLInputElement).value); - }; - return( - <> - - ) => { + setValue((event.target as HTMLInputElement).value); + }; + return ( + <> + + + + + Условия показа формы + + + - + Логика показа форм + + + + setLogicForm("conditions")} + > + От условий + + setLogicForm("results")} + > + С результатами + + + + {logicForm === "conditions" ? ( + <> + { + // }} + > + Добавить условие + - boxShadow: 24, - p: 0,}}> - + - Условия показа формы - - - - - Логика показа форм - - - setLogicForm("conditions")}> - От условий - - setLogicForm("results")}> - С результатами - - - - {logicForm === 'conditions' ? - - <> - { - // }} - > - Добавить условие - - - - - } icon={}/>} label="Все условия обязательны" /> - } icon={}/>} label="Обязательно хотя бы одно условие" /> - - - - : - <> - У вас пока что нет результатов. - - - } - - - - - - - - - - - ); -} \ No newline at end of file + } + icon={} + /> + } + label="Все условия обязательны" + /> + } + icon={} + /> + } + label="Обязательно хотя бы одно условие" + /> + + + + ) : ( + <> + У вас пока что нет результатов. + + + )} + + + + + + + + + + ); +} diff --git a/src/pages/ContactFormPage/ButtonSettingForms.tsx b/src/pages/ContactFormPage/ButtonSettingForms.tsx index d9570c56..023fbf5d 100644 --- a/src/pages/ContactFormPage/ButtonSettingForms.tsx +++ b/src/pages/ContactFormPage/ButtonSettingForms.tsx @@ -14,17 +14,35 @@ export default function ButtonSettingForms({ SSHC, switchState }: Props) { const theme = useTheme(); const buttonSetting: { icon: JSX.Element; title: string; value: string }[] = [ { - icon: , + icon: ( + + ), title: "Настройки", value: "setting", }, { - icon: , + icon: ( + + ), title: "Ветвление", value: "branching", }, { - icon: , + icon: ( + + ), title: "Добавить шаг формы", value: "supplement", }, @@ -53,8 +71,12 @@ export default function ButtonSettingForms({ SSHC, switchState }: Props) { SSHC(e.value); }} sx={{ - backgroundColor: switchState === e.value ? theme.palette.brightPurple.main : "transparent", - color: switchState === e.value ? "#ffffff" : theme.palette.grey3.main, + backgroundColor: + switchState === e.value + ? theme.palette.brightPurple.main + : "transparent", + color: + switchState === e.value ? "#ffffff" : theme.palette.grey3.main, }} > {e.icon} diff --git a/src/pages/ContactFormPage/ContactFormPage.tsx b/src/pages/ContactFormPage/ContactFormPage.tsx index c225fe0e..3cd0772b 100644 --- a/src/pages/ContactFormPage/ContactFormPage.tsx +++ b/src/pages/ContactFormPage/ContactFormPage.tsx @@ -1,5 +1,19 @@ import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; -import { Box, Button, IconButton, Link, Paper, SxProps, TextField, Theme, Typography, useTheme, Popover, useMediaQuery, Divider } from "@mui/material"; +import { + Box, + Button, + IconButton, + Link, + Paper, + SxProps, + TextField, + Theme, + Typography, + useTheme, + Popover, + useMediaQuery, + Divider, +} from "@mui/material"; import { incrementCurrentStep, updateQuiz } from "@root/quizes/actions"; import CustomTextField from "@ui_kit/CustomTextField"; import React, { ReactNode, useRef, useState } from "react"; @@ -17,261 +31,313 @@ import SwitchContactForm from "./switchContactForm"; import GearIcon from "@icons/GearIcon"; import { useQuestionsStore } from "@root/questions/store"; import { useCurrentQuiz } from "@root/quizes/hooks"; -import { FieldSettingsDrawerState, FormContactFieldName } from "@model/quizSettings"; +import { + FieldSettingsDrawerState, + FormContactFieldName, +} from "@model/quizSettings"; - -const buttons: { key: FormContactFieldName, name: string, desc: string; }[] = [ - { name: "Имя", desc: "Дмитрий", key: "name" }, - { name: "Email", desc: "mail@example.ru", key: "email" }, - { name: "Номер", desc: "+7 900 000 00 00", key: "phone" }, - { name: "Фамилия", desc: "Иванов", key: "text" }, - { name: "Адрес", desc: "Москва, Лаврушинский пер., 10", key: "address" }, +const buttons: { key: FormContactFieldName; name: string; desc: string }[] = [ + { name: "Имя", desc: "Дмитрий", key: "name" }, + { name: "Email", desc: "mail@example.ru", key: "email" }, + { name: "Номер", desc: "+7 900 000 00 00", key: "phone" }, + { name: "Фамилия", desc: "Иванов", key: "text" }, + { name: "Адрес", desc: "Москва, Лаврушинский пер., 10", key: "address" }, ]; export default function ContactFormPage() { - const theme = useTheme(); - const quiz = useCurrentQuiz(); - const isTablet = useMediaQuery(theme.breakpoints.down(1000)); - const [drawerNewField, setDrawerNewField] = useState({ field: "", isEdit: false }); - const [drawerMessenger, setDrawerMessenger] = useState(false); + const theme = useTheme(); + const quiz = useCurrentQuiz(); + const isTablet = useMediaQuery(theme.breakpoints.down(1000)); + const [drawerNewField, setDrawerNewField] = + useState({ field: "", isEdit: false }); + const [drawerMessenger, setDrawerMessenger] = useState(false); - const drawerMessengerHC = (bool: boolean) => { - setDrawerMessenger(bool); - }; + const drawerMessengerHC = (bool: boolean) => { + setDrawerMessenger(bool); + }; - return ( - - - - Как собрать данные посетителя - {" "} - {/* + return ( + + + + Как собрать данные посетителя + {" "} + {/* */} - - { - !quiz?.config.formContact.fields.name.used && - !quiz?.config.formContact.fields.email.used && - !quiz?.config.formContact.fields.phone.used && - !quiz?.config.formContact.fields.text.used && - !quiz?.config.formContact.fields.address.used ? - - - - : - - - - } - - - - - - - setDrawerNewField({ field: "", isEdit: false })}> - setDrawerNewField({ field: "", isEdit: false })} /> - + + {!quiz?.config.formContact.fields.name.used && + !quiz?.config.formContact.fields.email.used && + !quiz?.config.formContact.fields.phone.used && + !quiz?.config.formContact.fields.text.used && + !quiz?.config.formContact.fields.address.used ? ( + + + + ) : ( + + + + )} + + + + - ); + + setDrawerNewField({ field: "", isEdit: false })} + > + setDrawerNewField({ field: "", isEdit: false })} + /> + + + ); } interface Props { - outerContainerSx?: SxProps; - children?: ReactNode; + outerContainerSx?: SxProps; + children?: ReactNode; } function ContactFormParent({ outerContainerSx: sx, children }: Props) { - const theme = useTheme(); - const isTablet = useMediaQuery(theme.breakpoints.down(1000)); - const quiz = useCurrentQuiz(); + const theme = useTheme(); + const isTablet = useMediaQuery(theme.breakpoints.down(1000)); + const quiz = useCurrentQuiz(); - if (!quiz) return null; + if (!quiz) return null; - return ( - + + - - - { - updateQuiz(quiz.id, (quiz) => { - quiz.config.formContact.title = target.value; - }); - }} - value={quiz.config.formContact.title} - placeholder="Заголовок формы" text={""} /> - { + updateQuiz(quiz.id, (quiz) => { + quiz.config.formContact.title = target.value; + }); + }} + value={quiz.config.formContact.title} + placeholder="Заголовок формы" + text={""} + /> + { + updateQuiz(quiz.id, (quiz) => { + quiz.config.formContact.desc = target.value; + }); + }} + value={quiz.config.formContact.desc} + id="outlined-multiline-static" + multiline + rows={8} + placeholder="Дополнительный текст формы" + sx={{ + backgroundColor: theme.palette.background.default, - onChange={({ target }) => { - updateQuiz(quiz.id, (quiz) => { - quiz.config.formContact.desc = target.value; - }); - }} - value={quiz.config.formContact.desc} - id="outlined-multiline-static" - multiline - rows={8} - placeholder="Дополнительный текст формы" - sx={{ - backgroundColor: theme.palette.background.default, - - "& .MuiInputBase-root": { - borderRadius: "10px", - alignItems: "start", - color: theme.palette.grey2.main, - color: "black", - }, - }} - /> - - - {children} - - - ); + "& .MuiInputBase-root": { + borderRadius: "10px", + alignItems: "start", + color: theme.palette.grey2.main, + color: "black", + }, + }} + /> + + + {children} + + + ); } +const SettingField = ({ + name, + placeholder, + type, + drawerNewFieldHC, +}: { + name: string; + placeholder: string; + type: FormContactFieldName; + drawerNewFieldHC: (state: FieldSettingsDrawerState) => void; +}) => { + const theme = useTheme(); + const quiz = useCurrentQuiz(); -const SettingField = ({ name, placeholder, type, drawerNewFieldHC }: { name: string, placeholder: string, type: FormContactFieldName; drawerNewFieldHC: (state: FieldSettingsDrawerState) => void; }) => { - const theme = useTheme(); - const quiz = useCurrentQuiz(); + if (!quiz) return null; - if (!quiz) return null; - - return ( - <> - {quiz.config.formContact.fields[type].text || name} - - - {quiz.config.formContact.fields[type].innerText || placeholder} - drawerNewFieldHC({ field: type, isEdit: true })} - sx={{ - position: "absolute", - right: "0" - }}> - - - - updateQuiz(quiz?.id, (quiz) => { - quiz.config.formContact.fields[type].used = false; - })} - sx={{ - width: "48px", - ml: "5px" - }} - > - - - - - - ); + return ( + <> + + {quiz.config.formContact.fields[type].text || name} + + + + {quiz.config.formContact.fields[type].innerText || placeholder} + drawerNewFieldHC({ field: type, isEdit: true })} + sx={{ + position: "absolute", + right: "0", + }} + > + + + + + updateQuiz(quiz?.id, (quiz) => { + quiz.config.formContact.fields[type].used = false; + }) + } + sx={{ + width: "48px", + ml: "5px", + }} + > + + + + + ); }; -const ButtonsCard = ({ drawerNewFieldHC }: { drawerNewFieldHC: (state: FieldSettingsDrawerState) => void; }) => { - const theme = useTheme(); - const quiz = useCurrentQuiz(); +const ButtonsCard = ({ + drawerNewFieldHC, +}: { + drawerNewFieldHC: (state: FieldSettingsDrawerState) => void; +}) => { + const theme = useTheme(); + const quiz = useCurrentQuiz(); - if (!quiz) return null; + if (!quiz) return null; - return ( - - {buttons.flatMap((contentData) => { - const content = quiz.config.formContact.fields[contentData.key]; - return content.used ? ( - - ) : []; - })} - {( - quiz.config.formContact.fields.name.used && - quiz.config.formContact.fields.email.used && - quiz.config.formContact.fields.phone.used && - quiz.config.formContact.fields.text.used && - quiz.config.formContact.fields.address.used - ) ? - <> - : - - } - {/* + {buttons.flatMap((contentData) => { + const content = quiz.config.formContact.fields[contentData.key]; + return content.used ? ( + + ) : ( + [] + ); + })} + {quiz.config.formContact.fields.name.used && + quiz.config.formContact.fields.email.used && + quiz.config.formContact.fields.phone.used && + quiz.config.formContact.fields.text.used && + quiz.config.formContact.fields.address.used ? ( + <> + ) : ( + + )} + {/* drawerMessengerHC(true)} sx={{ @@ -285,51 +351,66 @@ const ButtonsCard = ({ drawerNewFieldHC }: { drawerNewFieldHC: (state: FieldSett Добавить мессенджеры */} - - - ); + + + ); }; -const EmptyCard = ({ drawerNewFieldHC }: { drawerNewFieldHC: (state: FieldSettingsDrawerState) => void; }) => { - const theme = useTheme(); - const [FC, setFC] = useState(false); - const openFC = () => setFC(true); - const closeFC = () => setFC(false); - const popover = useRef(null); +const EmptyCard = ({ + drawerNewFieldHC, +}: { + drawerNewFieldHC: (state: FieldSettingsDrawerState) => void; +}) => { + const theme = useTheme(); + const [FC, setFC] = useState(false); + const openFC = () => setFC(true); + const closeFC = () => setFC(false); + const popover = useRef(null); - return ( - - - - Будут показаны поля по умолчанию - - - + return ( + + + + + Будут показаны поля по умолчанию + + + + - - - Будут поля:

Имя, Email, Телефон - - - - - {/* + + Будут поля:

Имя, Email, Телефон +
+ + + {/* Добавить мессенджеры */} - - - ); + + + ); }; const PseudoButton = () => { - const quiz = useCurrentQuiz(); + const quiz = useCurrentQuiz(); - if (!quiz) return null; + if (!quiz) return null; - return ( - { - updateQuiz(quiz.id, (quiz) => { - quiz.config.formContact.button = target.value; - }); - }} - value={quiz.config.formContact.button} - sx={{ - heigth: "44px", - width: "190px", - "& .MuiInputBase-root": { - backgroundColor: "#7E2AEA", - borderRadius: "8px", - color: "white", - }, - "& .MuiInputBase-input": { - padding: "10px 20px", - textAlign: "center" - }, - "& .MuiInputBase-input::placeholder": { - color: "white", - opacity: "1" - } - }} - placeholder="Название кнопки" - > - {quiz.config.formContact.button || "Название кнопки"} - - - ); + return ( + { + updateQuiz(quiz.id, (quiz) => { + quiz.config.formContact.button = target.value; + }); + }} + value={quiz.config.formContact.button} + sx={{ + heigth: "44px", + width: "190px", + "& .MuiInputBase-root": { + backgroundColor: "#7E2AEA", + borderRadius: "8px", + color: "white", + }, + "& .MuiInputBase-input": { + padding: "10px 20px", + textAlign: "center", + }, + "& .MuiInputBase-input::placeholder": { + color: "white", + opacity: "1", + }, + }} + placeholder="Название кнопки" + > + {quiz.config.formContact.button || "Название кнопки"} + + ); }; diff --git a/src/pages/ContactFormPage/DrawerParent.tsx b/src/pages/ContactFormPage/DrawerParent.tsx index 539e330e..0d626a39 100644 --- a/src/pages/ContactFormPage/DrawerParent.tsx +++ b/src/pages/ContactFormPage/DrawerParent.tsx @@ -1,33 +1,33 @@ -import * as React from 'react'; -import Box from '@mui/material/Box'; -import Drawer from '@mui/material/Drawer'; -import Button from '@mui/material/Button'; -import {SxProps, Theme} from "@mui/material"; +import * as React from "react"; +import Box from "@mui/material/Box"; +import Drawer from "@mui/material/Drawer"; +import Button from "@mui/material/Button"; +import { SxProps, Theme } from "@mui/material"; interface Props { - outerContainerSx?: SxProps; - children?: React.ReactNode; - isOpenDrawer: string; - drawerNewFieldHC: (str: string) => void + outerContainerSx?: SxProps; + children?: React.ReactNode; + isOpenDrawer: string; + drawerNewFieldHC: (str: string) => void; } -export default function DrawerNewField({outerContainerSx: sx, children, isOpenDrawer: isOpen, drawerNewFieldHC }: Props) { - - return ( - <> - drawerNewFieldHC("")} - > - - - {children} - - - - ); -} \ No newline at end of file +export default function DrawerNewField({ + outerContainerSx: sx, + children, + isOpenDrawer: isOpen, + drawerNewFieldHC, +}: Props) { + return ( + <> + drawerNewFieldHC("")} + > + + {children} + + + + ); +} diff --git a/src/pages/ContactFormPage/Massengers/WindowMessengers.tsx b/src/pages/ContactFormPage/Massengers/WindowMessengers.tsx index 8309e804..0321bb5c 100644 --- a/src/pages/ContactFormPage/Massengers/WindowMessengers.tsx +++ b/src/pages/ContactFormPage/Massengers/WindowMessengers.tsx @@ -1,67 +1,100 @@ -import * as React from 'react'; -import Box from '@mui/material/Box'; -import Button from '@mui/material/Button'; -import {Typography, useTheme} from "@mui/material"; -import CloseIcon from '@mui/icons-material/Close'; +import * as React from "react"; +import Box from "@mui/material/Box"; +import Button from "@mui/material/Button"; +import { Typography, useTheme } from "@mui/material"; +import CloseIcon from "@mui/icons-material/Close"; import CustomTextField from "@ui_kit/CustomTextField"; import CustomCheckbox from "@ui_kit/CustomCheckbox"; import SelectableButton from "@ui_kit/SelectableButton"; -import {useState} from "react"; +import { useState } from "react"; import SelectMask from "../SelectMask"; -type SelectMessenger = 'contact'| 'bot'; +type SelectMessenger = "contact" | "bot"; export default function WindowMessengers() { - const theme = useTheme(); - const [selectMessenger, setSelectMessenger] = useState("contact"); - return( + const theme = useTheme(); + const [selectMessenger, setSelectMessenger] = + useState("contact"); + return ( + <> + + Настройки мессенджеров + + + + Заголовок страницы мессенджеров + + Текст на кнопке + + + + + setSelectMessenger("contact")} + > + Запрашивать контакт + + setSelectMessenger("bot")} + > + Чат-бот + + + {selectMessenger === "contact" ? ( <> - - Настройки мессенджеров - + + + + + - - Заголовок страницы мессенджеров - - Текст на кнопке - - - - - setSelectMessenger("contact")}> - Запрашивать контакт - - setSelectMessenger("bot")}> - Чат-бот - + + + + - {selectMessenger === 'contact' ? - <> - - - - - - - - - - - - - - - - - - - : - <> - } - + + + + - ) -} \ No newline at end of file + ) : ( + <> + )} + + + ); +} diff --git a/src/pages/ContactFormPage/NewField/NewFieldParent.tsx b/src/pages/ContactFormPage/NewField/NewFieldParent.tsx index 178bf7b4..d3a44318 100644 --- a/src/pages/ContactFormPage/NewField/NewFieldParent.tsx +++ b/src/pages/ContactFormPage/NewField/NewFieldParent.tsx @@ -1,5 +1,11 @@ import Box from "@mui/material/Box"; -import { FormControl, SxProps, TextField, Theme, Typography } from "@mui/material"; +import { + FormControl, + SxProps, + TextField, + Theme, + Typography, +} from "@mui/material"; import CustomTextField from "@ui_kit/CustomTextField"; import CustomCheckbox from "@ui_kit/CustomCheckbox"; import Button from "@mui/material/Button"; @@ -9,93 +15,112 @@ import { updateQuiz } from "@root/quizes/actions"; import { FormContactFieldName } from "@model/quizSettings"; interface Props { - outerContainerSx?: SxProps; - children?: React.ReactNode; - defaultValue: FormContactFieldName; - placeholderHelp: string; - placeholderField: string; - closeDrawer: () => void; + outerContainerSx?: SxProps; + children?: React.ReactNode; + defaultValue: FormContactFieldName; + placeholderHelp: string; + placeholderField: string; + closeDrawer: () => void; } -export default function NewFieldParent({ closeDrawer, defaultValue, placeholderHelp, placeholderField, outerContainerSx: sx, children }: Props) { - const quiz = useCurrentQuiz(); +export default function NewFieldParent({ + closeDrawer, + defaultValue, + placeholderHelp, + placeholderField, + outerContainerSx: sx, + children, +}: Props) { + const quiz = useCurrentQuiz(); - if (!quiz) return null; + if (!quiz) return null; - return ( - - - Подсказка - { - updateQuiz(quiz.id, (quiz) => { - quiz.config.formContact.fields[defaultValue].text = target.value; - }); - }} - value={quiz.config.formContact.fields[defaultValue].text} - - placeholder={placeholderHelp} text={''} /> - - - Подсказка внутри поля - { - updateQuiz(quiz.id, (quiz) => { - quiz.config.formContact.fields[defaultValue].innerText = target.value; - }); - }} - value={quiz.config.formContact.fields[defaultValue].innerText} - - placeholder={placeholderField} text={''} /> - - - - Ключ - { - updateQuiz(quiz.id, (quiz) => { - quiz.config.formContact.fields[defaultValue].key = target.value; - }); - }} - placeholder="text" - sx={{ - "& .css-1d3z3hw-MuiOutlinedInput-notchedOutline": { - border: 'none' - }, - "& .MuiInputBase-root": { - height: "48px", - borderRadius: "10px", - backgroundColor: '#EEE4FC', - }, - }} - /> - { - updateQuiz(quiz.id, (quiz) => { - quiz.config.formContact.fields[defaultValue].required = target.checked; - }); - }} - - label={"Обязательно к заполнению"} /> - - {/* + return ( + + + Подсказка + { + updateQuiz(quiz.id, (quiz) => { + quiz.config.formContact.fields[defaultValue].text = target.value; + }); + }} + value={quiz.config.formContact.fields[defaultValue].text} + placeholder={placeholderHelp} + text={""} + /> + + + Подсказка внутри поля + { + updateQuiz(quiz.id, (quiz) => { + quiz.config.formContact.fields[defaultValue].innerText = + target.value; + }); + }} + value={quiz.config.formContact.fields[defaultValue].innerText} + placeholder={placeholderField} + text={""} + /> + + + Ключ + { + updateQuiz(quiz.id, (quiz) => { + quiz.config.formContact.fields[defaultValue].key = target.value; + }); + }} + placeholder="text" + sx={{ + "& .css-1d3z3hw-MuiOutlinedInput-notchedOutline": { + border: "none", + }, + "& .MuiInputBase-root": { + height: "48px", + borderRadius: "10px", + backgroundColor: "#EEE4FC", + }, + }} + /> + { + updateQuiz(quiz.id, (quiz) => { + quiz.config.formContact.fields[defaultValue].required = + target.checked; + }); + }} + label={"Обязательно к заполнению"} + /> + + {/* Запрашивать на */} - {children} - - - ); + {children} + + + ); } diff --git a/src/pages/ContactFormPage/NewField/SwitchNewField.tsx b/src/pages/ContactFormPage/NewField/SwitchNewField.tsx index 30c62c32..0188a360 100644 --- a/src/pages/ContactFormPage/NewField/SwitchNewField.tsx +++ b/src/pages/ContactFormPage/NewField/SwitchNewField.tsx @@ -1,33 +1,51 @@ -import * as React from 'react'; +import * as React from "react"; import NewFieldParent from "./NewFieldParent"; import { FormControlLabel } from "@mui/material"; import SelectMask from "../SelectMask"; import CustomizedSwitch from "@ui_kit/CustomSwitch"; - - interface Props { - switchState: string, - closeDrawer: () => void; + switchState: string; + closeDrawer: () => void; } +export default function SwitchNewField({ + switchState = "name", + closeDrawer, +}: Props) { + const [SwitchMask, setSwitchMask] = React.useState(false); + const SwitchMaskHC = (bool: boolean) => { + setSwitchMask(bool); + }; -export default function SwitchNewField({ switchState = 'name', closeDrawer }: Props) { - const [SwitchMask, setSwitchMask] = React.useState(false); - const SwitchMaskHC = (bool: boolean) => { - setSwitchMask(bool); - }; - - switch (switchState) { - case 'name': - return (); - case 'email': - return (); - case 'phone': - - return ( - - {/* + ); + case "email": + return ( + + ); + case "phone": + return ( + + {/* } label="Маска для телефона" @@ -42,18 +60,28 @@ export default function SwitchNewField({ switchState = 'name', closeDrawer }: Pr /> */} - {SwitchMask ? - - : - <> - } - - ); - case 'text': - return (); - case 'address': - return (); - default: - return (<>); - } + {SwitchMask ? : <>} + + ); + case "text": + return ( + + ); + case "address": + return ( + + ); + default: + return <>; + } } diff --git a/src/pages/ContactFormPage/NewField/WindowNewField.tsx b/src/pages/ContactFormPage/NewField/WindowNewField.tsx index 24fd64d7..7ccdcdf6 100644 --- a/src/pages/ContactFormPage/NewField/WindowNewField.tsx +++ b/src/pages/ContactFormPage/NewField/WindowNewField.tsx @@ -3,85 +3,155 @@ import EmailIcon from "@icons/ContactFormIcon/EmailIcon"; import NameIcon from "@icons/ContactFormIcon/NameIcon"; import PhoneIcon from "@icons/ContactFormIcon/PhoneIcon"; import TextIcon from "@icons/ContactFormIcon/TextIcon"; -import { FieldSettingsDrawerState, FormContactFieldName } from "@model/quizSettings"; -import CloseIcon from '@mui/icons-material/Close'; +import { + FieldSettingsDrawerState, + FormContactFieldName, +} from "@model/quizSettings"; +import CloseIcon from "@mui/icons-material/Close"; import { Typography, useTheme } from "@mui/material"; -import Box from '@mui/material/Box'; -import Button from '@mui/material/Button'; -import { useCurrentQuiz } from '@root/quizes/hooks'; +import Box from "@mui/material/Box"; +import Button from "@mui/material/Button"; +import { useCurrentQuiz } from "@root/quizes/hooks"; import MiniButtonSetting from "@ui_kit/MiniButtonSetting"; -import { useEffect, useState } from 'react'; +import { useEffect, useState } from "react"; import SwitchNewField from "./SwitchNewField"; - interface Props { - drawerState: FieldSettingsDrawerState; - closeDrawer: () => void; + drawerState: FieldSettingsDrawerState; + closeDrawer: () => void; } export default function WindowNewField({ drawerState, closeDrawer }: Props) { - const quiz = useCurrentQuiz(); - const theme = useTheme(); - const [switchState, setSwitchState] = useState(""); + const quiz = useCurrentQuiz(); + const theme = useTheme(); + const [switchState, setSwitchState] = useState(""); - useEffect(() => { - if (!quiz) return; + useEffect(() => { + if (!quiz) return; - if (drawerState.isEdit) { - return setSwitchState(drawerState.field); - } + if (drawerState.isEdit) { + return setSwitchState(drawerState.field); + } - for (let val in quiz.config.formContact.fields) { - if (!quiz.config.formContact.fields[val as FormContactFieldName].used) { - setSwitchState(val); - return; - } - } - }, []); + for (let val in quiz.config.formContact.fields) { + if (!quiz.config.formContact.fields[val as FormContactFieldName].used) { + setSwitchState(val); + return; + } + } + }, []); - if (!quiz) return null; + if (!quiz) return null; - const SSHC = (data: string) => { - setSwitchState(data); - }; + const SSHC = (data: string) => { + setSwitchState(data); + }; - const buttonSetting: { icon: JSX.Element; title: string; value: FormContactFieldName; }[] = [ - { icon: , title: 'Имя', value: 'name' }, - { icon: , title: 'Email', value: 'email' }, - { icon: , title: 'Телефон', value: 'phone' }, - { icon: , title: 'Текст', value: 'text' }, - { icon: , title: 'Адрес', value: 'address' }, - ]; + const buttonSetting: { + icon: JSX.Element; + title: string; + value: FormContactFieldName; + }[] = [ + { + icon: ( + + ), + title: "Имя", + value: "name", + }, + { + icon: ( + + ), + title: "Email", + value: "email", + }, + { + icon: ( + + ), + title: "Телефон", + value: "phone", + }, + { + icon: ( + + ), + title: "Текст", + value: "text", + }, + { + icon: ( + + ), + title: "Адрес", + value: "address", + }, + ]; - return ( - <> - - Новое поле - - - - {buttonSetting.flatMap((e, i) => ( - drawerState.field === e.value || drawerState.field === "all" - ? { SSHC(e.value); }} - sx={{ - backgroundColor: switchState === e.value ? theme.palette.brightPurple.main : 'transparent', - color: switchState === e.value && drawerState.field === "all" ? '#ffffff' : theme.palette.grey3.main, - }} - > - {e.icon} - {e.title} - - : [] - ))} - - - - ); + return ( + <> + + Новое поле + + + + {buttonSetting.flatMap((e, i) => + drawerState.field === e.value || drawerState.field === "all" ? ( + { + SSHC(e.value); + }} + sx={{ + backgroundColor: + switchState === e.value + ? theme.palette.brightPurple.main + : "transparent", + color: + switchState === e.value && drawerState.field === "all" + ? "#ffffff" + : theme.palette.grey3.main, + }} + > + {e.icon} + {e.title} + + ) : ( + [] + ), + )} + + + + ); } diff --git a/src/pages/ContactFormPage/SelectMask.tsx b/src/pages/ContactFormPage/SelectMask.tsx index 5a76893a..0c61652a 100644 --- a/src/pages/ContactFormPage/SelectMask.tsx +++ b/src/pages/ContactFormPage/SelectMask.tsx @@ -1,84 +1,111 @@ -import {Box, Link, Typography, useTheme} from "@mui/material"; +import { Box, Link, Typography, useTheme } from "@mui/material"; import SelectableButton from "@ui_kit/SelectableButton"; import CustomTextField from "@ui_kit/CustomTextField"; import * as React from "react"; -import {useState} from "react"; +import { useState } from "react"; -type SelectMask = 'country'| 'mymask'; -export default function SelectMask () { +type SelectMask = "country" | "mymask"; +export default function SelectMask() { + const [State, setState] = React.useState(false); + const StateHC = (bool: boolean) => { + setState(bool); + }; - const [State, setState] = React.useState(false); - const StateHC = (bool:boolean) => { - setState(bool) - } - - const theme = useTheme() - const [selectMask, setSelectMask] = useState("country"); - return( + const theme = useTheme(); + const [selectMask, setSelectMask] = useState("country"); + return ( + <> + + setSelectMask("country")} + > + Выбор страны + + setSelectMask("mymask")} + > + Своя маска + + + {selectMask === "country" ? ( <> - - setSelectMask("country")}> - Выбор страны - - setSelectMask("mymask")}> - Своя маска - + + Посетителю нужно будет выбрать страну и ввести номер телефона. + Страна определяется автоматически в зависимости от настроек браузера + + { + StateHC(!State); + }} + > + Расширенные настройки + + {State ? ( + + + Страна по умолчанию + + + Если ничего не выбрано, страна будет выбрана автоматически + + + + Выделенные страны + + + Выбранные страны будут показываться вверху списка + + + + Показываемые страны + + + Будут показываться только выбранные страны + + + + Игнорируемые страны + + + Выбранные страны будут не будут показываться в списке + + - {selectMask === 'country' ? - <> - - Посетителю нужно будет выбрать страну - и ввести номер телефона. Страна определяется автоматически в зависимости от настроек браузера - - { - StateHC(!State) - }} - > - Расширенные настройки - - {State ? - - - Страна по умолчанию - - Если ничего не выбрано, страна - будет выбрана автоматически - - - Выделенные страны - - Выбранные страны будут - показываться вверху списка - - - Показываемые страны - - Будут показываться только - выбранные страны - - - Игнорируемые страны - - Выбранные страны будут не будут - показываться в списке - - - : - <> - } - - : - <> - - - } + ) : ( + <> + )} - ) + ) : ( + <> + + + )} + + ); } diff --git a/src/pages/ContactFormPage/Supplement.tsx b/src/pages/ContactFormPage/Supplement.tsx index 693da49f..cb0ff5c3 100644 --- a/src/pages/ContactFormPage/Supplement.tsx +++ b/src/pages/ContactFormPage/Supplement.tsx @@ -1 +1 @@ -export {} \ No newline at end of file +export {}; diff --git a/src/pages/ContactFormPage/settingForm.tsx b/src/pages/ContactFormPage/settingForm.tsx index c3812170..69eaef39 100644 --- a/src/pages/ContactFormPage/settingForm.tsx +++ b/src/pages/ContactFormPage/settingForm.tsx @@ -1,17 +1,17 @@ -import {Box, Typography} from "@mui/material"; +import { Box, Typography } from "@mui/material"; import CustomCheckbox from "@ui_kit/CustomCheckbox"; export default function SettingForm() { - return ( - - - Тип формы - - - - Настройки вопросов - - - - ); -}; \ No newline at end of file + return ( + + + Тип формы + + + + Настройки вопросов + + + + ); +} diff --git a/src/pages/ContactFormPage/switchContactForm.tsx b/src/pages/ContactFormPage/switchContactForm.tsx index ac7074bf..d8e3672d 100644 --- a/src/pages/ContactFormPage/switchContactForm.tsx +++ b/src/pages/ContactFormPage/switchContactForm.tsx @@ -1,26 +1,23 @@ -import * as React from 'react'; +import * as React from "react"; import SettingForm from "./settingForm"; import BranchingForm from "./BranchingForm"; - - interface Props { - switchState: string, + switchState: string; } -export default function SwitchContactForm({switchState = 'setting' }: Props) { - - switch (switchState) { - case 'setting': - return (); - break; - case 'branching': - return (); - break; - case 'supplement': - return (<>); - break; - default: - return (<>) - } -} \ No newline at end of file +export default function SwitchContactForm({ switchState = "setting" }: Props) { + switch (switchState) { + case "setting": + return ; + break; + case "branching": + return ; + break; + case "supplement": + return <>; + break; + default: + return <>; + } +} diff --git a/src/pages/DesignPage/ColorRingIcon.tsx b/src/pages/DesignPage/ColorRingIcon.tsx index 2aa926f4..aa4e944a 100644 --- a/src/pages/DesignPage/ColorRingIcon.tsx +++ b/src/pages/DesignPage/ColorRingIcon.tsx @@ -1,23 +1,36 @@ -import {Box} from "@mui/material"; +import { Box } from "@mui/material"; -interface Color{ - color?: string +interface Color { + color?: string; +} +export default function ColorRingIcon({ color = "#333647" }: Color) { + return ( + + + + + + ); } -export default function ColorRingIcon({color = "#333647"}: Color) { - - return ( - - - - - - ) -} \ No newline at end of file diff --git a/src/pages/DesignPage/DesignFilling.tsx b/src/pages/DesignPage/DesignFilling.tsx index 6715d3a8..4f1b300c 100644 --- a/src/pages/DesignPage/DesignFilling.tsx +++ b/src/pages/DesignPage/DesignFilling.tsx @@ -1,118 +1,155 @@ -import {Box, ButtonBase, IconButton, Paper, Typography, useMediaQuery, useTheme} from "@mui/material"; +import { + Box, + ButtonBase, + IconButton, + Paper, + Typography, + useMediaQuery, + useTheme, +} from "@mui/material"; import ColorRingIcon from "./ColorRingIcon"; -import {updateQuiz} from "@root/quizes/actions"; -import {useCurrentQuiz} from "@root/quizes/hooks"; -import {toggleQuizPreview} from "@root/quizPreview"; +import { updateQuiz } from "@root/quizes/actions"; +import { useCurrentQuiz } from "@root/quizes/hooks"; +import { toggleQuizPreview } from "@root/quizPreview"; import VisibilityIcon from "@mui/icons-material/Visibility"; import React from "react"; export const DesignFilling = () => { - const quiz = useCurrentQuiz(); - const theme = useTheme(); - const isMobile = useMediaQuery(theme.breakpoints.down(830)); - const ButtonsThemeLight = [ - ["Стандартный", "StandardTheme", "#7E2AEA", "#FFFFFF"], - ["Черно-белый", "BlackWhiteTheme", "#4E4D51", "#FFFFFF"], - ["Оливковый", "OliveTheme", "#758E4F", "#F9FBF1"], - ["Фиолетовый", "PurpleTheme", "#7E2AEA", "#FBF8FF"], - ["Желтый", "YellowTheme", "#F2B133", "#FFFCF6"], - ["Голубой", "BlueTheme", "#4964ED", "#F5F7FF"], - ["Розовый", "PinkTheme", "#D34085", "#FFF9FC"] - ] - const ButtonsThemeDark = [ - ["Стандартный", "StandardDarkTheme", "#7E2AEA", "#FFFFFF"], - ["Золотой", "GoldDarkTheme", "#E6AA37", "#FFFFFF"], - ["Розовый", "PinkDarkTheme", "#D34085", "#FFFFFF"], - ["Бирюзовый", "BlueDarkTheme", "#07A0C3", "#FFFFFF"], - ] - return ( - - Дизайн - + + Дизайн + + + Выберите цветовую схему для вашего опроса + + + + Со светлым фоном + + {ButtonsThemeLight.map((e, i) => ( + - - Со светлым фоном - - {ButtonsThemeLight.map((e, i) => ( - updateQuiz(quiz.id, (quiz) => { - quiz.config.theme = e[1]})} - > - {e[0]} - - - - - - - ))} - - - - С тёмным фоном - {ButtonsThemeDark.map((e, i) => ( - updateQuiz(quiz.id, (quiz) => { - quiz.config.theme = e[1]})} - > - {e[0]} - - - - - - - ))} - - - - - - - - + justifyContent: "space-between", + border: + quiz.config.theme == e[1] ? "1px solid #7E2AEA" : "none", + }} + key={i} + value={e[1]} + onClick={() => + updateQuiz(quiz.id, (quiz) => { + quiz.config.theme = e[1]; + }) + } + > + {e[0]} + + + + + + + ))} - ); -} \ No newline at end of file + + С тёмным фоном + {ButtonsThemeDark.map((e, i) => ( + + updateQuiz(quiz.id, (quiz) => { + quiz.config.theme = e[1]; + }) + } + > + {e[0]} + + + + + + + ))} + + + + + + + + + ); +}; diff --git a/src/pages/DesignPage/DesignPage.tsx b/src/pages/DesignPage/DesignPage.tsx index e983eade..d47f039d 100644 --- a/src/pages/DesignPage/DesignPage.tsx +++ b/src/pages/DesignPage/DesignPage.tsx @@ -1,5 +1,5 @@ import { quizApi } from "@api/quiz"; -import {Box, IconButton, useMediaQuery, useTheme} from "@mui/material"; +import { Box, IconButton, useMediaQuery, useTheme } from "@mui/material"; import { resetEditConfig, setQuizes, @@ -37,10 +37,10 @@ import { ModalInfoWhyCantCreate } from "../startPage/ModalInfoWhyCantCreate"; import { ConfirmLeaveModal } from "../startPage/ConfirmLeaveModal"; import { checkQuestionHint } from "@utils/checkQuestionHint"; import { Header } from "../startPage/Header"; -import {DesignFilling} from "./DesignFilling"; -import {toggleQuizPreview} from "@root/quizPreview"; +import { DesignFilling } from "./DesignFilling"; +import { toggleQuizPreview } from "@root/quizPreview"; import VisibilityIcon from "@mui/icons-material/Visibility"; -import {createPortal} from "react-dom"; +import { createPortal } from "react-dom"; import QuizPreview from "@ui_kit/QuizPreview/QuizPreview"; export const DesignPage = () => { @@ -52,10 +52,10 @@ export const DesignPage = () => { const getData = async () => { const quizes = await quizApi.getList(); setQuizes(quizes); - if (editQuizId) { - const questions = await questionApi.getList({ quiz_id: editQuizId }); - setQuestions(questions); - } + if (editQuizId) { + const questions = await questionApi.getList({ quiz_id: editQuizId }); + setQuestions(questions); + } }; getData(); }, []); @@ -74,12 +74,11 @@ export const DesignPage = () => { updateModalInfoWhyCantCreate(false); updateSomeWorkBackend(false); }, - [] + [], ); - + useEffect(() => { if (editQuizId === null) navigate("/list"); - }, [navigate, editQuizId]); const followNewPage = () => { @@ -87,7 +86,6 @@ export const DesignPage = () => { setCurrentStep(nextStep); }; - const changePage = (index: number) => { if (currentStep === 2) { setNextStep(index); @@ -99,7 +97,7 @@ export const DesignPage = () => { setCurrentStep(index); }; - console.log(quiz) + console.log(quiz); if (!quiz) return <>; return ( <> @@ -110,8 +108,8 @@ export const DesignPage = () => { ) : ( )} - - {createPortal(, document.body)} + + {createPortal(, document.body)} ) => { - setChecked([event.target.checked, checked[1]]); - }; + const handleChange1 = (event: React.ChangeEvent) => { + setChecked([event.target.checked, checked[1]]); + }; - const handleChange2 = (event: React.ChangeEvent) => { - setChecked([checked[0], event.target.checked, ]); - }; + const handleChange2 = (event: React.ChangeEvent) => { + setChecked([checked[0], event.target.checked]); + }; - return ( - - {/*левая часть*/} - - {/*бокс с кнопкой*/} - - - - - - Квиз будет открываться через указанное время - - - - - Если квиз уже установлен на - сайт, и вы что-то здесь изменили, - код на сайте нужно будет поменять. Настройки в этом конструкторе не сохраняются. - + return ( + + {/*левая часть*/} + + {/*бокс с кнопкой*/} + + + {" "} + + + + + + Quiz будет открываться через указанное время + - {/*правая часть*/} - - - - - - - - - - {checked[0] ? - - - Показывать через - - - - секунд - - - - - - - - : - <> - } - - {checked[1] ? - - - - - : - <> - } + + + + Если quiz уже установлен на сайт, и вы что-то здесь изменили, код на + сайте нужно будет поменять. Настройки в этом конструкторе не + сохраняются. + + + {/*правая часть*/} + + + + + + + + + + {checked[0] ? ( + + + + Показывать через + + + + + + секунд + - - ) + + + + + + ) : ( + <> + )} + + {checked[1] ? ( + + + + + ) : ( + <> + )} + + + ); } diff --git a/src/pages/InstallQuiz/BannerInstall.tsx b/src/pages/InstallQuiz/BannerInstall.tsx index 3e975651..f12a135a 100644 --- a/src/pages/InstallQuiz/BannerInstall.tsx +++ b/src/pages/InstallQuiz/BannerInstall.tsx @@ -1,199 +1,271 @@ import { - Box, - FormControl, - FormControlLabel, - Link, - Radio, - RadioGroup, - TextField, - Typography, - useTheme + Box, + FormControl, + FormControlLabel, + Link, + Radio, + RadioGroup, + TextField, + Typography, + useTheme, } from "@mui/material"; import InstallQzOnSiteParent from "./InstallQzOnSiteParent"; -import React, {useState} from "react"; -import BannerImg from "../../assets/BannerImg.png" +import React, { useState } from "react"; +import BannerImg from "../../assets/BannerImg.png"; import CustomTextField from "@ui_kit/CustomTextField"; import CustomCheckbox from "@ui_kit/CustomCheckbox"; import RadioCheck from "@ui_kit/RadioCheck"; import RadioIcon from "@ui_kit/RadioIcon"; import AccordMy from "@ui_kit/Accordion"; +type isExpanded = "panel1" | "panel2"; +export default function BannerInstall() { + const theme = useTheme(); -type isExpanded = "panel1" | "panel2" -export default function BannerInstall () { - const theme = useTheme(); + const [value, setValue] = React.useState("1"); - const [value, setValue] = React.useState("1"); + const handleChangeRadio = (event: React.ChangeEvent) => { + setValue((event.target as HTMLInputElement).value); + }; - const handleChangeRadio = (event: React.ChangeEvent) => { - setValue((event.target as HTMLInputElement).value); - }; + const [value2, setValue2] = React.useState("1"); - const [value2, setValue2] = React.useState("1"); + const handleChangeRadio2 = (event: React.ChangeEvent) => { + setValue2((event.target as HTMLInputElement).value); + }; - const handleChangeRadio2 = (event: React.ChangeEvent) => { - setValue2((event.target as HTMLInputElement).value); - }; + const [isExpanded, setIsExpanded] = useState("panel1"); - const [isExpanded, setIsExpanded] = useState("panel1"); - - return ( - - {/*левая часть*/} - - - - - Если квиз уже установлен на сайт, и вы что-то здесь изменили, код на сайте нужно будет поменять. - Настройки в этом конструкторе не сохраняются. - + return ( + + {/*левая часть*/} + + + + Если quiz уже установлен на сайт, и вы что-то здесь изменили, код на + сайте нужно будет поменять. Настройки в этом конструкторе не + сохраняются. + + + {/*правая часть*/} + + + + Текст-призыв + + + + Заголовок quiz + + + + + Показывать через + + + + + + секунд + + + + + Цвет кнопки + + + {" "} - {/*правая часть*/} - - - Текст-призыв - - Заголовок квиза - - - Показывать через - - - - секунд - - - Цвет кнопки - - Цвет текста кнопки - - - - - setIsExpanded("panel1")} sx={{display: "flex", flexDirection: 'column',}}> - Расположение - - - - - } icon={}/>} - label="Слева сверху" - /> - } icon={}/>} - label="Справа сверху" - /> - - - } icon={}/>} - label="Слева снизу" - /> - } icon={}/>} - label="Справа снизу" - /> - - - - - - Параметры - - - - - - - setIsExpanded("panel2")} sx={{display: "flex", flexDirection: 'column',}}> - Расположение - - - - } icon={}/>} - label="Сверху страницы" - /> - } icon={}/>} - label="Снизу страницы" - /> - - - - Параметры - - - - - - + Автооткрытие квиза + + Цвет текста кнопки + + + {" "} - - ) -} \ No newline at end of file + + + + setIsExpanded("panel1")} + sx={{ display: "flex", flexDirection: "column" }} + > + + Расположение + + + + + } icon={} /> + } + label="Слева сверху" + /> + } icon={} /> + } + label="Справа сверху" + /> + + + } icon={} /> + } + label="Слева снизу" + /> + } icon={} /> + } + label="Справа снизу" + /> + + + + + Параметры + + + + + + + + setIsExpanded("panel2")} + sx={{ display: "flex", flexDirection: "column" }} + > + + Расположение + + + + + } icon={} /> + } + label="Сверху страницы" + /> + } icon={} /> + } + label="Снизу страницы" + /> + + + + + Параметры + + + + + + + + + Автооткрытие quiz + + + + ); +} diff --git a/src/pages/InstallQuiz/ButtonSocial.tsx b/src/pages/InstallQuiz/ButtonSocial.tsx index 596efdd8..540bbcb3 100644 --- a/src/pages/InstallQuiz/ButtonSocial.tsx +++ b/src/pages/InstallQuiz/ButtonSocial.tsx @@ -1,13 +1,15 @@ import { - Box, - Button, FormControl, - IconButton, - InputAdornment, Link, - Modal, - OutlinedInput, - TextField, - Typography, - useTheme + Box, + Button, + FormControl, + IconButton, + InputAdornment, + Link, + Modal, + OutlinedInput, + TextField, + Typography, + useTheme, } from "@mui/material"; import BrowserIcon from "../../assets/icons/BrowserIcon"; import TiktokIcon from "../../assets/icons/tiktokIcon"; @@ -18,286 +20,345 @@ import CustomTextField from "@ui_kit/CustomTextField"; import UploadBox from "@ui_kit/UploadBox"; import UploadIcon from "../../assets/icons/UploadIcon"; import CopyIcon from "../../assets/icons/CopyIcon"; -import Qr from "../../assets/Qr.png" +import Qr from "../../assets/Qr.png"; +export default function ButtonSocial() { + const theme = useTheme(); -export default function ButtonSocial () { - const theme = useTheme(); + const [openGraph, setOpenGraph] = React.useState(false); + const handleOpenGraph = () => setOpenGraph(true); + const handleCloseGraph = () => setOpenGraph(false); - const [openGraph, setOpenGraph] = React.useState(false); - const handleOpenGraph = () => setOpenGraph(true); - const handleCloseGraph = () => setOpenGraph(false); + const [openTiktok, setOpenTiktok] = React.useState(false); + const handleOpenTiktok = () => setOpenTiktok(true); + const handleCloseTiktok = () => setOpenTiktok(false); - const [openTiktok, setOpenTiktok] = React.useState(false); - const handleOpenTiktok = () => setOpenTiktok(true); - const handleCloseTiktok = () => setOpenTiktok(false); + const [openQr, setOpenQr] = React.useState(false); + const handleOpenQr = () => setOpenQr(true); + const handleCloseQr = () => setOpenQr(false); - const [openQr, setOpenQr] = React.useState(false); - const handleOpenQr = () => setOpenQr(true); - const handleCloseQr = () => setOpenQr(false); + return ( + <> + + + + + + + + + + + + + + + {/*модалка Graph*/} + + - - - - - + boxShadow: 24, + p: 0, + }} + > + + + Open Graph + + + + + + Заголовок + + - {/*модалка Graph*/} - - - - Open Graph - - - - - Заголовок - - - - - - - Описание - - - - - - Изображение - - } text="5 MB максимум" /> - - - - - - - - - - {/*модалка тиктока*/} - + Описание + + + + - + Изображение + + } + text="5 MB максимум" + /> + + + + + + + + - boxShadow: 24, - p: 0,}}> - - Добавить квиз в Tiktok - - - - 1. Скопируйте ссылку на квиз + {/*модалка тиктока*/} + + - - - - - - } - label="Password" - /> - - - - - 2. Зайдите в аккаунт Tiktok - - Кликните по кнопке “Изменить профиль”. В поле Веб-сайт вставьте скопированную ссылку на квиз. - Готово! Квиз вставлен в аккаунт Tiktok. - - - Если всё ещё не понятно, более подробная инструкция тут - - - - - - - - - - - - {/*модалка QR*/} - + + + Добавить quiz в Tiktok + + + + - 1. Скопируйте ссылку на quiz - boxShadow: 24, - p: 0,}}> - - QR-код для перехода в квиз - - - - - Можно показывать в презентации на вебинарах или распечатать для офлайн мероприятий - - - + + + + + + + } + label="Password" + /> + + - - - - - - - + + 2. Зайдите в аккаунт Tiktok + + Кликните по кнопке “Изменить профиль”. В поле Веб-сайт вставьте + скопированную ссылку на quiz. Готово! Quiz вставлен в аккаунт + Tiktok. + + + Если всё ещё не понятно, более подробная инструкция тут + + - - ) -} \ No newline at end of file + + + + + + + + + {/*модалка QR*/} + + + + + QR-код для перехода в quiz + + + + + + Можно показывать в презентации на вебинарах или распечатать для + офлайн мероприятий + + + + + + + + + + + + + ); +} diff --git a/src/pages/InstallQuiz/InBodyInstall.tsx b/src/pages/InstallQuiz/InBodyInstall.tsx index 500eb178..d62505ac 100644 --- a/src/pages/InstallQuiz/InBodyInstall.tsx +++ b/src/pages/InstallQuiz/InBodyInstall.tsx @@ -1,125 +1,174 @@ -import {Box, Button, Link, Typography, useTheme} from "@mui/material"; +import { Box, Button, Link, Typography, useTheme } from "@mui/material"; import InstallQzOnSiteParent from "./InstallQzOnSiteParent"; import Dots from "../../assets/dots.png"; import React from "react"; import CustomTextField from "@ui_kit/CustomTextField"; import CustomCheckbox from "@ui_kit/CustomCheckbox"; - -export default function InBodyInstall () { - const theme = useTheme(); - return ( - - {/*левая часть*/} - - {/*бокс с кнопкой*/} - - - - - - - Квиз будет открыть прямо в том месте, где вы установите код на сайте - - - - В мобильной версии будет показана кнопка, открывающая квиз в модальном окне - - - Если квиз уже установлен на сайт, и вы что-то здесь изменили, - код на сайте нужно будет поменять. Настройки в этом конструкторе не сохраняются. - +export default function InBodyInstall() { + const theme = useTheme(); + return ( + + {/*левая часть*/} + + {/*бокс с кнопкой*/} + + + {" "} + + + + + + Quiz будет открыть прямо в том месте, где вы установите код на + сайте + - {/*правая часть*/} - - 1. Задайте размеры (опционально) - - - Ширина (px) - - Радиус (px) - - - - Высота (px) - - Отступ (px) - - - - - - 2. Настройте кнопку для мобильной версии - - - Цвет кнопки - - Цвет текста кнопки - - - - - - - - - Текст кнопки - - - + Автооткрытие квиза - - - + + В мобильной версии будет показана кнопка, открывающая quiz в + модальном окне + + + + + Если quiz уже установлен на сайт, и вы что-то здесь изменили, код на + сайте нужно будет поменять. Настройки в этом конструкторе не + сохраняются. + + - ) -} \ No newline at end of file + {/*правая часть*/} + + 1. Задайте размеры (опционально) + + + + Ширина (px) + + + + Радиус (px) + + + + + + Высота (px) + + + + Отступ (px) + + + + + + 2. Настройте кнопку для мобильной версии + + + Цвет кнопки + + + {" "} + + + Цвет текста кнопки + + + {" "} + + + + + + + + + Текст кнопки + + + + + Автооткрытие quiz + + + + + ); +} diff --git a/src/pages/InstallQuiz/InstallQuiz.tsx b/src/pages/InstallQuiz/InstallQuiz.tsx index e5ef774d..34614c5d 100644 --- a/src/pages/InstallQuiz/InstallQuiz.tsx +++ b/src/pages/InstallQuiz/InstallQuiz.tsx @@ -47,7 +47,7 @@ import { useCurrentQuiz } from "@root/quizes/hooks"; type BackgroundType = "text" | "video"; export default function InstallQuiz() { - const quiz = useCurrentQuiz() + const quiz = useCurrentQuiz(); const [display, setDisplay] = React.useState("1"); const handleChange = (event: SelectChangeEvent) => { @@ -66,14 +66,13 @@ export default function InstallQuiz() { const theme = useTheme(); - - const CopyLink = () => { - let one = document.getElementById("inputLinkone").value; - let text = document.getElementById("inputLink").value; - // text.select(); - navigator.clipboard.writeText(one+text) - // document.execCommand("copy"); - } + const CopyLink = () => { + let one = document.getElementById("inputLinkone").value; + let text = document.getElementById("inputLink").value; + // text.select(); + navigator.clipboard.writeText(one + text); + // document.execCommand("copy"); + }; return ( <> @@ -92,17 +91,20 @@ export default function InstallQuiz() { }} > - - Ссылка на квиз + + Ссылка на quiz - - - - - + {/**/} + {/* */} + {/* */} + {/* */} + {/**/} Стандартная - - На поддомене - + {/**/} + {/* На поддомене*/} + {/**/} @@ -229,34 +231,36 @@ export default function InstallQuiz() { }} /> - - - - + + + - + {/**/} - {quiz?.status === "start" ? "Опубликован" : "Не опубликован"} + + {quiz?.status === "start" ? "Опубликован" : "Не опубликован"} + - ) + ); } - - - // export default function InstallQuiz() { // const [display, setDisplay] = React.useState("1"); @@ -840,4 +844,4 @@ const buttonInstall: { icon: string; title: string; text: string }[] = [ title: "Виджет", text: "Сбоку страницы как консультант", }, -]; \ No newline at end of file +]; diff --git a/src/pages/InstallQuiz/InstallQzCode.tsx b/src/pages/InstallQuiz/InstallQzCode.tsx index 54b24425..69af42e2 100644 --- a/src/pages/InstallQuiz/InstallQzCode.tsx +++ b/src/pages/InstallQuiz/InstallQzCode.tsx @@ -1,129 +1,165 @@ import InstallQzOnSiteParent from "./InstallQzOnSiteParent"; import { - Box, Button, - FormControl, - IconButton, - InputAdornment, Link, - OutlinedInput, - TextField, - Typography, - useTheme + Box, + Button, + FormControl, + IconButton, + InputAdornment, + Link, + OutlinedInput, + TextField, + Typography, + useTheme, } from "@mui/material"; import CopyIcon from "@icons/CopyIcon"; import React from "react"; import InfoIcon from "@icons/InfoIcon"; - export default function InstallQzCode() { - const theme = useTheme(); - return( - - - - 1. Код инициализации - Вставьте блок head в начале страницы - + + + 1. Код инициализации + + Вставьте блок head в начале страницы + + - - - - - }} + sx={{ + "& .MuiInputBase-root": { + maxWidth: "520px", + width: "100%", + backgroundColor: theme.palette.background.default, + fontSize: "18px", + alignItems: "flex-start", + }, + }} + InputProps={{ + endAdornment: ( + + + - - - 2. Код кнопки - Установите код в то место, где должна быть кнопка открытия квиза - + 2. Код кнопки + + Установите код в то место, где должна быть кнопка открытия quiz + + - - - - - }} + sx={{ + "& .MuiInputBase-root": { + backgroundColor: theme.palette.background.default, + fontSize: "18px", + alignItems: "flex-start", + }, + }} + InputProps={{ + endAdornment: ( + + + - - - - { - // }} - > - Инструкция к платформам - - - - - + + + ), + }} + /> + + + + { + // }} + > + Инструкция к платформам + + + + + + + - - 3. Проверьте правильность установки - Введите полный адрес страницы, где вы установили квиз и нажмите "проверить" - - - - Код нужно вставить один раз. Изменения в самом квизе будут отображаться автоматически после сохранения. - - - Для добавления нескольких квизов на одну страницу, код инициализации достаточно добавить один раз с любого квиза, - а затем вставить кнопки открытия с нужных квизов - - - - ) -} \ No newline at end of file + + 3. Проверьте правильность установки + + Введите полный адрес страницы, где вы установили quiz и нажмите + "проверить" + + + + + Код нужно вставить один раз. Изменения в самом quiz будут отображаться + автоматически после сохранения. + + + Для добавления нескольких quiz на одну страницу, код инициализации + достаточно добавить один раз с любого quiz, а затем вставить кнопки + открытия с нужных quiz + + + + ); +} diff --git a/src/pages/InstallQuiz/InstallQzOnSiteParent.tsx b/src/pages/InstallQuiz/InstallQzOnSiteParent.tsx index b89c1cdc..c0e0df15 100644 --- a/src/pages/InstallQuiz/InstallQzOnSiteParent.tsx +++ b/src/pages/InstallQuiz/InstallQzOnSiteParent.tsx @@ -1,55 +1,69 @@ -import {Box, Button, SxProps, Theme, Typography, useTheme} from "@mui/material"; +import { + Box, + Button, + SxProps, + Theme, + Typography, + useTheme, +} from "@mui/material"; import OneIconBorder from "../../assets/icons/OneIconBorder"; import React from "react"; import NumberTwo from "@icons/NumberTwo"; import NumberThree from "@icons/NumberThree"; interface Props { - outerContainerSx?: SxProps; - children?: React.ReactNode; + outerContainerSx?: SxProps; + children?: React.ReactNode; } -export default function InstallQzOnSiteParent ({outerContainerSx: sx, children}: Props) { - const theme = useTheme(); - return ( - <> - - - Установка квизов на сайте - - Способ установки - - Настройка кнопки - - Вставить код на сайт - +export default function InstallQzOnSiteParent({ + outerContainerSx: sx, + children, +}: Props) { + const theme = useTheme(); + return ( + <> + + + + Установка quiz на сайте + + + + Способ установки + + + Настройка кнопки + + + Вставить код на сайт + + - - - {children} - - - - - - - - - - ) -} \ No newline at end of file + + {children} + + + + + + + ); +} diff --git a/src/pages/InstallQuiz/OnButtonInstall.tsx b/src/pages/InstallQuiz/OnButtonInstall.tsx index edfbdfad..25f2ee72 100644 --- a/src/pages/InstallQuiz/OnButtonInstall.tsx +++ b/src/pages/InstallQuiz/OnButtonInstall.tsx @@ -1,103 +1,165 @@ -import {Box, Button, Link, Typography, useTheme} from "@mui/material"; -import React, {useState} from "react"; +import { Box, Button, Link, Typography, useTheme } from "@mui/material"; +import React, { useState } from "react"; import CustomCheckbox from "@ui_kit/CustomCheckbox"; import CustomTextField from "@ui_kit/CustomTextField"; -import Dots from '../../assets/dots.png' +import Dots from "../../assets/dots.png"; import InstallQzOnSiteParent from "./InstallQzOnSiteParent"; import AccordMy from "@ui_kit/Accordion"; -type isExpanded = "panel1" | "panel2" +type isExpanded = "panel1" | "panel2"; -export default function OnButtonInstall () { - const theme = useTheme(); +export default function OnButtonInstall() { + const theme = useTheme(); - const [isExpanded, setIsExpanded] = useState("panel1"); - return ( - <> - - {/*левая часть*/} - - {/*бокс с кнопкой*/} - - - - - - - Если квиз уже установлен на сайт, и вы что-то здесь изменили, - код на сайте нужно будет поменять. Настройки в этом конструкторе не сохраняются. - - - {/*правая часть*/} - - setIsExpanded("panel1")} sx={{display: "flex", flexDirection: 'column',}}> - - Цвет кнопки - - Цвет текста кнопки - - - - - - - - Текст кнопки - - - setIsExpanded("panel2")} sx={{display: "flex", flexDirection: 'column', width: "100%"}}> - Ссылка для вашей кнопки - - Или событие - - + const [isExpanded, setIsExpanded] = useState("panel1"); + return ( + <> + + {/*левая часть*/} + + {/*бокс с кнопкой*/} + + + {" "} + + + + + + + + Если quiz уже установлен на сайт, и вы что-то здесь изменили, код на + сайте нужно будет поменять. Настройки в этом конструкторе не + сохраняются. + + + {/*правая часть*/} + + setIsExpanded("panel1")} + sx={{ display: "flex", flexDirection: "column" }} + > + + + Цвет кнопки + + + {" "} + + + Цвет текста кнопки + + + {" "} + + + + + + + + + Текст кнопки + + + + setIsExpanded("panel2")} + sx={{ display: "flex", flexDirection: "column", width: "100%" }} + > + + Ссылка для вашей кнопки + + + + Или событие + + + - + Автооткрытие квиза - - - - ) + + + Автооткрытие quiz + + + + + ); } diff --git a/src/pages/InstallQuiz/VidjetInstall.tsx b/src/pages/InstallQuiz/VidjetInstall.tsx index 356169f1..07caf8f1 100644 --- a/src/pages/InstallQuiz/VidjetInstall.tsx +++ b/src/pages/InstallQuiz/VidjetInstall.tsx @@ -1,206 +1,221 @@ import { - Box, - Button, - FormControl, - FormControlLabel, - Radio, - RadioGroup, - TextField, - Typography, - useTheme + Box, + Button, + FormControl, + FormControlLabel, + Radio, + RadioGroup, + TextField, + Typography, + useTheme, } from "@mui/material"; -import React, {useState} from "react"; +import React, { useState } from "react"; import InstallQzOnSiteParent from "./InstallQzOnSiteParent"; import CustomCheckbox from "@ui_kit/CustomCheckbox"; -import VidjetImg from "../../assets/VidjetImg.png" +import VidjetImg from "../../assets/VidjetImg.png"; import LDownButton from "@icons/InstallQuizIcon/LDownButton"; import RDownButton from "@icons/InstallQuizIcon/RDownButton"; import RadioCheck from "@ui_kit/RadioCheck"; import RadioIcon from "@ui_kit/RadioIcon"; +export default function VidjetInstall() { + const [value, setValue] = React.useState("1"); + const handleChangeRadio = (event: React.ChangeEvent) => { + setValue((event.target as HTMLInputElement).value); + }; + const [position, setPosition] = useState<"left" | "right">("left"); -export default function VidjetInstall () { - const [value, setValue] = React.useState("1"); + const theme = useTheme(); + return ( + + {/*левая часть*/} + + + + Если quiz уже установлен на сайт, и вы что-то здесь изменили, код на + сайте нужно будет поменять. Настройки в этом конструкторе не + сохраняются. + + + {/*правая часть*/} + + + Расположение + + + setPosition("left")} + isActive={position === "left"} + Icon={LDownButton} + /> + setPosition("right")} + isActive={position === "right"} + Icon={RDownButton} + /> + - const handleChangeRadio = (event: React.ChangeEvent) => { - setValue((event.target as HTMLInputElement).value); - }; - - const [position, setPosition] = useState<"left" | "right">("left"); - - const theme = useTheme(); - return ( - - {/*левая часть*/} - - - - Если квиз уже установлен на сайт, и вы что-то здесь изменили, код на сайте нужно будет поменять. - Настройки в этом конструкторе не сохраняются. - + + + Показывать виджет + + + + + + секунд + + + + Автооткрытие виджета при входе на сайт + + + + } icon={} /> + } + label="Да" + /> + } icon={} /> + } + label="Нет" + /> + + + {value === "1" ? ( + + + + Показывать через + + + + + + секунд + - {/*правая часть*/} - - - Расположение - - - setPosition("left")} - isActive={position === "left"} - Icon={LDownButton} - /> - setPosition("right")} - isActive={position === "right"} - Icon={RDownButton} - /> - + + Время, через которое quiz автоматически откроется + + + ) : ( + <> + )} - - - Показывать виджет - - - - секунд - - Автооткрытие виджета при входе на сайт - - - } - icon={} - /> - } - label="Да" - /> - } - icon={} - /> - } - label="Нет" - /> - - - {value === "1" ? - - - Показывать через - - - - секунд - - Время, через которое квиз автоматически откроется - - : - <> - } - - - - - - - ) + + + + + ); } interface Props { - Icon: React.ElementType; - isActive?: boolean; - onClick: () => void; + Icon: React.ElementType; + isActive?: boolean; + onClick: () => void; } function SelectButtonPosition({ Icon, isActive = false, onClick }: Props) { - const theme = useTheme(); - return ( - */} + {/* */} + {/* */} + {/* */} + {/* */} + {/* */} + {/* */} + {/* */} + {/* */} + {/* */} + {/* */} + {/* */} + {/**/} + + - {/**/} - {/* */} - {/* */} - {/* Как используют квиз*/} - {/* В крупном и малом бизнесе*/} - {/* */} - {/* */} - {/* */} - {/* */} - {/* */} - {/* */} - {/* */} - {/* */} - {/* */} - {/* */} - {/* */} - {/* */} - {/* */} - {/* */} - {/**/} - + Что еще можно делать с Опросником + + + Изящное решение исследовательских и бизнес-задач + + + {/**/} + {/* */} + {/* */} + {/* Исследования*/} + {/* */} + {/* */} + {/* */} + {/* Сегментация*/} + {/* */} + {/* */} + {/* */} + {/* Тестирование*/} + {/* */} + {/* */} + {/* */} + {/* E-commerce*/} + {/* */} + {/**/} + + + - - - Что еще можно делать - с Опросником - - - Изящное решение исследовательских и бизнес-задач - - - {/**/} - {/* */} - {/* */} - {/* Исследования*/} - {/* */} - {/* */} - {/* */} - {/* Сегментация*/} - {/* */} - {/* */} - {/* */} - {/* Тестирование*/} - {/* */} - {/* */} - {/* */} - {/* E-commerce*/} - {/* */} - {/**/} - - - - Исследуйте аудиторию и проверяйте гипотезы - - - - Опросник помогает проверять гипотезы - и принимать грамотные решения основанные - на данных. Создавайте опросы, собирайте обратную связь и анализируйте ответы - в удобной аналитике в личном кабинете. - - - - - - - + Исследуйте аудиторию и проверяйте гипотезы + + + + Опросник помогает проверять гипотезы и принимать грамотные + решения основанные на данных. Создавайте опросы, собирайте + обратную связь и анализируйте ответы в удобной аналитике в + личном кабинете. + - - ) -} \ No newline at end of file + + + + + + + + ); +} diff --git a/src/pages/Landing/Landing.tsx b/src/pages/Landing/Landing.tsx index e0109134..1e65ef9c 100644 --- a/src/pages/Landing/Landing.tsx +++ b/src/pages/Landing/Landing.tsx @@ -1,43 +1,40 @@ -import React from 'react'; -import {CssBaseline, useMediaQuery, useTheme} from "@mui/material"; -import Header from './HeaderLanding'; -import Footer from './FooterLanding'; -import Hero from './Hero'; -import Questions from './Questions'; -import Counter from './Counter'; -import Blog from './Blog'; -import HowItWorks from './HowItWorks'; -import BusinessPluses from './BusinessPluses'; -import HowToUse from './HowToUse'; +import React from "react"; +import { CssBaseline, useMediaQuery, useTheme } from "@mui/material"; +import Header from "./HeaderLanding"; +import Footer from "./FooterLanding"; +import Hero from "./Hero"; +import Questions from "./Questions"; +import Counter from "./Counter"; +import Blog from "./Blog"; +import HowItWorks from "./HowItWorks"; +import BusinessPluses from "./BusinessPluses"; +import HowToUse from "./HowToUse"; -import StartWithTemplates from './StartWithTemplates'; -import WhatTheFeatures from './WhatTheFeatures'; +import StartWithTemplates from "./StartWithTemplates"; +import WhatTheFeatures from "./WhatTheFeatures"; import FullScreenDialog from "./headerMobileLanding"; import Collaboration from "./Collaboration"; export default function Landing() { - const theme = useTheme(); - const isTablet = useMediaQuery(theme.breakpoints.down(1000)); + const theme = useTheme(); + const isTablet = useMediaQuery(theme.breakpoints.down(1000)); - return ( - <> - -
- - - {/* */} - - - - {/**/} - {/**/} - - {/**/} - {/**/} -