diff --git a/.dockerignore b/.dockerignore index b0542ba..36d88eb 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,4 +1,5 @@ /dist +/dist-package /widget Makefile README.md diff --git a/.eslintrc.cjs b/.eslintrc.cjs index df269ee..1684a63 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -26,8 +26,10 @@ module.exports = { "@typescript-eslint/no-unsafe-assignment": "off", "@typescript-eslint/no-unsafe-call": "off", "@typescript-eslint/no-unsafe-member-access": "off", - "@typescript-eslint/no-unused-vars": "warn", - "@typescript-eslint/require-await": "warn", + "@typescript-eslint/no-unused-vars": [ + "warn", + { "vars": "all", "args": "none" } + ], "@typescript-eslint/restrict-template-expressions": "off", "no-debugger": "off", "no-empty-function": "off", diff --git a/.gitignore b/.gitignore index a302ba2..5d68f75 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ lerna-debug.log* node_modules dist +dist-package dist-ssr widget *.local @@ -22,4 +23,4 @@ widget *.ntvs* *.njsproj *.sln -*.sw? \ No newline at end of file +*.sw? diff --git a/README.md b/README.md new file mode 100644 index 0000000..f6f7e1b --- /dev/null +++ b/README.md @@ -0,0 +1,52 @@ +## Виджет +### Сборка +```bash +yarn build:widget +``` +### Использование +```html + +``` +## Npm-пакет +### Перед использованием и публикацией +```bash +npm config set //penahub.gitlab.yandexcloud.net/api/v4/packages/npm/:_authToken=INSTANCE_TOKEN +npm config set //penahub.gitlab.yandexcloud.net/api/v4/projects/43/packages/npm/:_authToken=PROJECT_TOKEN +``` +### Публикация +1. Инкрементировать версию в package.json +2. +```bash +yarn publish +``` +3. Нажать enter при запросе версии +### Установка +Добавить в корень проекта файл .yarnrc с содержимым +``` +"@frontend:registry" "https://penahub.gitlab.yandexcloud.net/api/v4/packages/npm/" +``` +```bash +yarn add @frontend/squzanswerer +``` +Peer dependencies: +```bash +yarn add @emoji-mart/data @emoji-mart/react @emotion/react @emotion/styled @mui/icons-material @mui/material @mui/x-date-pickers axios emoji-mart immer moment nanoid notistack react-dom react-error-boundary react-router-dom react swr use-debounce zustand +``` +### Использование +```ts +import { QuizView } from "@frontend/squzanswerer"; + +export default function Component() { + // ... + return ( + + } +} +``` diff --git a/lib/api/quizRelase.ts b/lib/api/quizRelase.ts new file mode 100644 index 0000000..9d64cbd --- /dev/null +++ b/lib/api/quizRelase.ts @@ -0,0 +1,152 @@ +import { GetQuizDataResponse, parseQuizData } from "@model/api/getQuizData"; +import axios from "axios"; + +import type { AxiosError } from "axios"; +import { replaceSpacesToEmptyLines } from "../components/ViewPublicationPage/tools/replaceSpacesToEmptyLines"; +import { QuizSettings } from "@model/settingsData"; + +let SESSIONS = ""; + +const domain = location.hostname ==="localhost" ? "https://s.hbpn.link" : "" + +export const publicationMakeRequest = ({ url, body }: any) => { + return axios(url, { + data: body, + headers: { + "X-Sessionkey": SESSIONS, + "Content-Type": "multipart/form-data", + }, + method: "POST", + }); +}; + +export async function getData(quizId: string): Promise<{ + data: GetQuizDataResponse | null; + isRecentlyCompleted: boolean; + error?: string; +}> { + try { + const { data, headers } = await axios( + domain + `/answer/settings`, + { + method: "POST", + headers: { + "X-Sessionkey": SESSIONS, + "Content-Type": "application/json", + }, + data: { + quiz_id: quizId, + limit: 100, + page: 0, + need_config: true, + }, + } + ); + const sessions = JSON.parse(localStorage.getItem("sessions") || "{}"); + + if (typeof sessions[quizId] === "number") { + // unix время. Если меньше суток прошло - выводить ошибку, иначе пустить дальше + if (Date.now() - sessions[quizId] < 86400000) { + return { data, isRecentlyCompleted: true }; + } + } + + SESSIONS = headers["x-sessionkey"] ? headers["x-sessionkey"] : SESSIONS; + + return { data, isRecentlyCompleted: false }; + } catch (nativeError) { + const error = nativeError as AxiosError; + + return { data: null, isRecentlyCompleted: false, error: error.message }; + } +} + +export async function getQuizData(quizId: string) { + const response = await getData(quizId); + const quizDataResponse = response.data; + + if (response.error) { + throw new Error(response.error); + } + if (!quizDataResponse) { + throw new Error("Quiz not found"); + } + + const quizSettings = replaceSpacesToEmptyLines(parseQuizData(quizDataResponse)); + + const res = JSON.parse(JSON.stringify({ data: quizSettings }).replaceAll(/\\" \\"/g, '""').replaceAll(/" "/g, '""')).data as QuizSettings; + res.recentlyCompleted = response.isRecentlyCompleted; + return res; +} + +export function sendAnswer({ questionId, body, qid }: any) { + const formData = new FormData(); + + const answers = [ + { + question_id: questionId, + content: body, //тут массив с ответом + }, + ]; + formData.append("answers", JSON.stringify(answers)); + console.log("QID", qid) + formData.append("qid", qid); + + return publicationMakeRequest({ + url: domain + `/answer/answer`, + body: formData, + method: "POST", + }); +} + +//body ={file, filename} +export function sendFile({ questionId, body, qid }: any) { + const formData = new FormData(); + + const answers: any = [ + { + question_id: questionId, + content: "file:" + body.name, + }, + ]; + + formData.append("answers", JSON.stringify(answers)); + formData.append(body.name, body.file); + console.log("QID", qid) + formData.append("qid", qid); + + return publicationMakeRequest({ + url: domain + `/answer/answer`, + body: formData, + method: "POST", + }); +} + +//форма контактов +export function sendFC({ questionId, body, qid }: any) { + const formData = new FormData(); + + // const keysBody = Object.keys(body) + // const content:any = {} + // fields.forEach((key) => { + // if (keysBody.includes(key)) content[key] = body.key + // }) + + const answers = [ + { + question_id: questionId, + content: JSON.stringify(body), + result: true, + qid, + }, + ]; + + formData.append("answers", JSON.stringify(answers)); + formData.append("qid", qid); + + return publicationMakeRequest({ + url: domain + `/answer/answer`, + body: formData, + method: "POST", + }); +} diff --git a/src/assets/icons/ArrowDownIcon.tsx b/lib/assets/icons/ArrowDownIcon.tsx old mode 100755 new mode 100644 similarity index 100% rename from src/assets/icons/ArrowDownIcon.tsx rename to lib/assets/icons/ArrowDownIcon.tsx diff --git a/lib/assets/icons/BlankImage.tsx b/lib/assets/icons/BlankImage.tsx new file mode 100644 index 0000000..6e976bc --- /dev/null +++ b/lib/assets/icons/BlankImage.tsx @@ -0,0 +1,10 @@ +export default function BlankImage() { + + return ( + + + + + + ); +} diff --git a/src/assets/icons/CalendarIcon.tsx b/lib/assets/icons/CalendarIcon.tsx similarity index 100% rename from src/assets/icons/CalendarIcon.tsx rename to lib/assets/icons/CalendarIcon.tsx diff --git a/src/assets/icons/Checkbox.tsx b/lib/assets/icons/Checkbox.tsx similarity index 100% rename from src/assets/icons/Checkbox.tsx rename to lib/assets/icons/Checkbox.tsx diff --git a/src/assets/icons/CloseBold.tsx b/lib/assets/icons/CloseBold.tsx similarity index 100% rename from src/assets/icons/CloseBold.tsx rename to lib/assets/icons/CloseBold.tsx diff --git a/src/assets/icons/ContactFormIcon/AddressIcon.tsx b/lib/assets/icons/ContactFormIcon/AddressIcon.tsx similarity index 100% rename from src/assets/icons/ContactFormIcon/AddressIcon.tsx rename to lib/assets/icons/ContactFormIcon/AddressIcon.tsx diff --git a/src/assets/icons/ContactFormIcon/EmailIcon.tsx b/lib/assets/icons/ContactFormIcon/EmailIcon.tsx similarity index 100% rename from src/assets/icons/ContactFormIcon/EmailIcon.tsx rename to lib/assets/icons/ContactFormIcon/EmailIcon.tsx diff --git a/src/assets/icons/ContactFormIcon/NameIcon.tsx b/lib/assets/icons/ContactFormIcon/NameIcon.tsx similarity index 100% rename from src/assets/icons/ContactFormIcon/NameIcon.tsx rename to lib/assets/icons/ContactFormIcon/NameIcon.tsx diff --git a/src/assets/icons/ContactFormIcon/PhoneIcon.tsx b/lib/assets/icons/ContactFormIcon/PhoneIcon.tsx similarity index 100% rename from src/assets/icons/ContactFormIcon/PhoneIcon.tsx rename to lib/assets/icons/ContactFormIcon/PhoneIcon.tsx diff --git a/src/assets/icons/ContactFormIcon/TextIcon.tsx b/lib/assets/icons/ContactFormIcon/TextIcon.tsx similarity index 100% rename from src/assets/icons/ContactFormIcon/TextIcon.tsx rename to lib/assets/icons/ContactFormIcon/TextIcon.tsx diff --git a/src/assets/icons/Info.tsx b/lib/assets/icons/Info.tsx similarity index 100% rename from src/assets/icons/Info.tsx rename to lib/assets/icons/Info.tsx diff --git a/src/assets/icons/NameplateLogo.tsx b/lib/assets/icons/NameplateLogo.tsx similarity index 100% rename from src/assets/icons/NameplateLogo.tsx rename to lib/assets/icons/NameplateLogo.tsx diff --git a/src/assets/icons/NameplateLogoFQ.tsx b/lib/assets/icons/NameplateLogoFQ.tsx similarity index 100% rename from src/assets/icons/NameplateLogoFQ.tsx rename to lib/assets/icons/NameplateLogoFQ.tsx diff --git a/src/assets/icons/NameplateLogoFQDark.tsx b/lib/assets/icons/NameplateLogoFQDark.tsx similarity index 99% rename from src/assets/icons/NameplateLogoFQDark.tsx rename to lib/assets/icons/NameplateLogoFQDark.tsx index 154e056..9916f39 100644 --- a/src/assets/icons/NameplateLogoFQDark.tsx +++ b/lib/assets/icons/NameplateLogoFQDark.tsx @@ -21,4 +21,4 @@ export const NameplateLogoFQDark: FC> = (props) => ( -); \ No newline at end of file +); diff --git a/src/assets/icons/UploadIcon.tsx b/lib/assets/icons/UploadIcon.tsx old mode 100755 new mode 100644 similarity index 100% rename from src/assets/icons/UploadIcon.tsx rename to lib/assets/icons/UploadIcon.tsx diff --git a/src/assets/icons/questionsPage/FlagIcon.tsx b/lib/assets/icons/questionsPage/FlagIcon.tsx similarity index 100% rename from src/assets/icons/questionsPage/FlagIcon.tsx rename to lib/assets/icons/questionsPage/FlagIcon.tsx diff --git a/src/assets/icons/questionsPage/StarIconMini.tsx b/lib/assets/icons/questionsPage/StarIconMini.tsx similarity index 100% rename from src/assets/icons/questionsPage/StarIconMini.tsx rename to lib/assets/icons/questionsPage/StarIconMini.tsx diff --git a/src/assets/icons/questionsPage/hashtagIcon.tsx b/lib/assets/icons/questionsPage/hashtagIcon.tsx similarity index 100% rename from src/assets/icons/questionsPage/hashtagIcon.tsx rename to lib/assets/icons/questionsPage/hashtagIcon.tsx diff --git a/src/assets/icons/questionsPage/heartIcon.tsx b/lib/assets/icons/questionsPage/heartIcon.tsx similarity index 100% rename from src/assets/icons/questionsPage/heartIcon.tsx rename to lib/assets/icons/questionsPage/heartIcon.tsx diff --git a/src/assets/icons/questionsPage/lightbulbIcon.tsx b/lib/assets/icons/questionsPage/lightbulbIcon.tsx similarity index 100% rename from src/assets/icons/questionsPage/lightbulbIcon.tsx rename to lib/assets/icons/questionsPage/lightbulbIcon.tsx diff --git a/src/assets/icons/questionsPage/likeIcon.tsx b/lib/assets/icons/questionsPage/likeIcon.tsx similarity index 100% rename from src/assets/icons/questionsPage/likeIcon.tsx rename to lib/assets/icons/questionsPage/likeIcon.tsx diff --git a/src/assets/icons/questionsPage/tropfyIcon.tsx b/lib/assets/icons/questionsPage/tropfyIcon.tsx similarity index 100% rename from src/assets/icons/questionsPage/tropfyIcon.tsx rename to lib/assets/icons/questionsPage/tropfyIcon.tsx diff --git a/lib/components/QuizAnswerer.tsx b/lib/components/QuizAnswerer.tsx new file mode 100644 index 0000000..376c87d --- /dev/null +++ b/lib/components/QuizAnswerer.tsx @@ -0,0 +1,78 @@ +import { QuizDataContext } from "@contexts/QuizDataContext"; +import { QuizSettings } from "@model/settingsData"; +import { Box, CssBaseline, ThemeProvider } from "@mui/material"; +import { LocalizationProvider } from "@mui/x-date-pickers"; +import { AdapterMoment } from "@mui/x-date-pickers/AdapterMoment"; +import { ruRU } from '@mui/x-date-pickers/locales'; +import { handleComponentError } from "@utils/handleComponentError"; +import lightTheme from "@utils/themes/light"; +import moment from "moment"; +import { SnackbarProvider } from 'notistack'; +import { ErrorBoundary } from "react-error-boundary"; +import { ApologyPage } from "./ViewPublicationPage/ApologyPage"; +import ViewPublicationPage from "./ViewPublicationPage/ViewPublicationPage"; +import { RootContainerWidthContext } from "@contexts/RootContainerWidthContext"; +import { startTransition, useEffect, useLayoutEffect, useRef, useState } from "react"; + + +moment.locale("ru"); +const localeText = ruRU.components.MuiLocalizationProvider.defaultProps.localeText; + +type Props = { + quizSettings: QuizSettings; + quizId: string; + preview?: boolean; +}; + +export default function QuizAnswerer({ quizSettings, quizId, preview = false }: Props) { + const [rootContainerWidth, setRootContainerWidth] = useState(() => window.innerWidth); + const rootContainerRef = useRef(null); + + useLayoutEffect(() => { + if (rootContainerRef.current) setRootContainerWidth(rootContainerRef.current.clientWidth); + }, []); + + useEffect(() => { + const handleWindowResize = () => { + startTransition(() => { + if (rootContainerRef.current) setRootContainerWidth(rootContainerRef.current.clientWidth); + }); + }; + window.addEventListener("resize", handleWindowResize); + + return () => { + window.removeEventListener("resize", handleWindowResize); + }; + }, []); + + return ( + + + + + + + + + + + + + + + + + ); +} diff --git a/lib/components/ViewPublicationPage/ApologyPage.tsx b/lib/components/ViewPublicationPage/ApologyPage.tsx new file mode 100644 index 0000000..634cda0 --- /dev/null +++ b/lib/components/ViewPublicationPage/ApologyPage.tsx @@ -0,0 +1,28 @@ +import { Box, Typography } from "@mui/material"; +import { FallbackProps } from "react-error-boundary"; + +type Props = Partial; + +export const ApologyPage = ({ error }: Props) => { + let message = "Что-то пошло не так"; + + if (error.message === "No questions found") message = "Нет созданных вопросов"; + if (error.message === "Quiz already completed") message = "Вы уже прошли этот опрос"; + + return ( + + {message} + + ); +}; diff --git a/lib/components/ViewPublicationPage/ContactForm.tsx b/lib/components/ViewPublicationPage/ContactForm.tsx new file mode 100644 index 0000000..37ad04a --- /dev/null +++ b/lib/components/ViewPublicationPage/ContactForm.tsx @@ -0,0 +1,436 @@ +import AddressIcon from "@icons/ContactFormIcon/AddressIcon"; +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 { Box, Button, InputAdornment, Link, TextField as MuiTextField, TextFieldProps, Typography, useTheme } from "@mui/material"; + +import CustomCheckbox from "@ui_kit/CustomCheckbox"; +import { FC, useRef, useState } from "react"; + +import { sendFC } from "@api/quizRelase"; +import { NameplateLogo } from "@icons/NameplateLogo"; +import { QuizQuestionResult } from "@model/questionTypes/result"; +import { AnyTypedQuizQuestion } from "@model/questionTypes/shared"; +import { quizThemes } from "@utils/themes/Publication/themePublication"; +import { enqueueSnackbar } from "notistack"; +import { useRootContainerSize } from "../../contexts/RootContainerWidthContext"; +import { useQuizData } from "@contexts/QuizDataContext"; + + +const TextField = MuiTextField as unknown as FC; // temporary fix ts(2590) +const EMAIL_REGEXP = /^(([^<>()[\].,:\s@"]+(\.[^<>()[\].,:\s@"]+)*)|(".+"))@(([^<>()[\].,:\s@"]+\.)+[^<>()[\].,:\s@"]{2,})$/iu; + +type Props = { + currentQuestion: AnyTypedQuizQuestion; + onShowResult: () => void; +}; + +export const ContactForm = ({ currentQuestion, onShowResult }: Props) => { + const theme = useTheme(); + const { settings, questions, quizId } = useQuizData(); + + const [ready, setReady] = useState(false); + const [name, setName] = useState(""); + const [email, setEmail] = useState(""); + const [phone, setPhone] = useState(""); + const [text, setText] = useState(""); + const [adress, setAdress] = useState(""); + + const fireOnce = useRef(true); + const [fire, setFire] = useState(false); + const isMobile = useRootContainerSize() < 850; + + const resultQuestion = currentQuestion.type === "result" + ? currentQuestion + : questions.find((question): question is QuizQuestionResult => { + if (settings?.cfg.haveRoot) { + return ( + question.type === "result" && + question.content.rule.parentId === currentQuestion.content.id + ); + } else { + return ( + question.type === "result" && question.content.rule.parentId === "line" + ); + } + }); + + if (!resultQuestion) throw new Error("Result question not found"); + + const inputHC = async () => { + const FC = settings.cfg.formContact.fields || settings.cfg.formContact; + const body = {} as any; + if (name.length > 0) body.name = name; + if (email.length > 0) body.email = email; + if (phone.length > 0) body.phone = phone; + if (adress.length > 0) body.address = adress; + if (text.length > 0) body.customs = { [FC.text.text || "Фамилия"]: text }; + + if (Object.keys(body).length > 0) { + try { + await sendFC({ + questionId: currentQuestion.id, + body: body, + qid: quizId, + }); + + const sessions = JSON.parse(localStorage.getItem("sessions") || "{}"); + localStorage.setItem( + "sessions", + JSON.stringify({ ...sessions, [quizId]: new Date().getTime() }) + ); + } catch (e) { + enqueueSnackbar("ответ не был засчитан"); + } + } + }; + + const FCcopy: any = settings.cfg.formContact.fields || settings.cfg.formContact; + + const filteredFC: any = {}; + for (const i in FCcopy) { + const field = FCcopy[i]; + if (field.used) { + filteredFC[i] = field; + } + } + const isWide = Object.keys(filteredFC).length > 2; + + async function handleShowResultsClick() { + //@ts-ignore + const FC: any = settings.cfg.formContact.fields || settings.cfg.formContact; + if (FC["email"].used !== EMAIL_REGEXP.test(email)) { + return enqueueSnackbar("введена некорректная почта"); + } + + + if (fireOnce.current) { + if ( + name.length === 0 + && email.length === 0 + && phone.length === 0 + && text.length === 0 + && adress.length === 0 + ) return enqueueSnackbar("Пожалуйста, заполните поля"); + + //почта валидна, хоть одно поле заполнено + setFire(true); + try { + await inputHC(); + fireOnce.current = false; + const sessions: any = JSON.parse( + localStorage.getItem("sessions") || "{}" + ); + sessions[quizId] = Date.now(); + localStorage.setItem( + "sessions", + JSON.stringify(sessions) + ); + enqueueSnackbar("Данные успешно отправлены"); + } catch (e) { + enqueueSnackbar("повторите попытку позже"); + } + + onShowResult(); + } + + setFire(false); + } + + return ( + + + + + {settings.cfg.formContact.title || + "Заполните форму, чтобы получить результаты теста"} + + {settings.cfg.formContact.desc && ( + + {settings.cfg.formContact.desc} + + )} + + + + + + + + { + // resultQuestion && + // settings.cfg.resultInfo.when === "after" && + + } + + + { + setReady(target.checked); + }} + checked={ready} + colorIcon={theme.palette.primary.main} + /> + + С  + + Положением об обработке персональных данных{" "} + +  и  + + {" "} + Политикой конфиденциальности{" "} + +  ознакомлен + + + + + + Сделано на PenaQuiz + + + + + + ); +}; + +const Inputs = ({ + name, + setName, + email, + setEmail, + phone, + setPhone, + text, + setText, + adress, + setAdress, +}: any) => { + const { settings } = useQuizData(); + + // @ts-ignore + const FC = settings.cfg.formContact.fields || settings.cfg.formContact; + + if (!FC) return null; + + //@ts-ignore + const Name = ( + setName(target.value)} + id={name} + title={FC["name"].innerText || "Введите имя"} + desc={FC["name"].text || "имя"} + Icon={NameIcon} + /> + ); + //@ts-ignore + const Email = ( + setEmail(target.value)} + id={email} + title={FC["email"].innerText || "Введите Email"} + desc={FC["email"].text || "Email"} + Icon={EmailIcon} + /> + ); + const Phone = ( + setPhone(target.value)} + id={phone} + title={FC["phone"].innerText || "Введите номер телефона"} + desc={FC["phone"].text || "номер телефона"} + Icon={PhoneIcon} + /> + ); + //@ts-ignore + const Text = ( + setText(target.value)} + id={text} + title={FC["text"].text || "Введите фамилию"} + desc={FC["text"].innerText || "фамилию"} + Icon={TextIcon} + /> + ); + //@ts-ignore + const Adress = ( + setAdress(target.value)} + id={adress} + title={FC["address"].innerText || "Введите адрес"} + desc={FC["address"].text || "адрес"} + Icon={AddressIcon} + /> + ); + + //@ts-ignore + if (Object.values(FC).some((data) => data.used)) { + return ( + <> + {FC["name"].used ? Name : <>} + {FC["email"].used ? Email : <>} + {FC["phone"].used ? Phone : <>} + {FC["text"].used ? Text : <>} + {FC["address"].used ? Adress : <>} + + ); + } else { + return ( + <> + {Name} + {Email} + {Phone} + + ); + } +}; + +const CustomInput = ({ title, desc, Icon, onChange }: any) => { + const theme = useTheme(); + const isMobile = useRootContainerSize() < 600; + //@ts-ignore + return ( + + + {title} + + + + + + ), + }} + /> + + ); +}; diff --git a/lib/components/ViewPublicationPage/Footer.tsx b/lib/components/ViewPublicationPage/Footer.tsx new file mode 100644 index 0000000..7debe23 --- /dev/null +++ b/lib/components/ViewPublicationPage/Footer.tsx @@ -0,0 +1,111 @@ +import { useQuizData } from "@contexts/QuizDataContext"; +import { Box, Typography, useTheme } from "@mui/material"; +import { ReactNode } from "react"; + + +type FooterProps = { + stepNumber: number | null; + nextButton: ReactNode; + prevButton: ReactNode; +}; + +export const Footer = ({ stepNumber, nextButton, prevButton }: FooterProps) => { + const theme = useTheme(); + const { questions } = useQuizData(); + console.log(questions) + + return ( + + + {/*{mode[settings.cfg.theme] ? (*/} + {/* */} + {/*):(*/} + {/* */} + {/*)}*/} + {stepNumber !== null && + + Шаг + + {stepNumber} + + Из + + {questions.filter(q => q.type !== "result").length} + + + } + + + {/* Шаг + + {stepNumber} */} + {/* */} + {/* Из + + {questions.length} + */} + + {prevButton} + {nextButton} + + + ); +}; diff --git a/lib/components/ViewPublicationPage/Question.tsx b/lib/components/ViewPublicationPage/Question.tsx new file mode 100644 index 0000000..440138b --- /dev/null +++ b/lib/components/ViewPublicationPage/Question.tsx @@ -0,0 +1,97 @@ +import {Box, Link, useTheme} from "@mui/material"; + +import { Footer } from "./Footer"; +import { Date } from "./questions/Date"; +import { Emoji } from "./questions/Emoji"; +import { File } from "./questions/File"; +import { Images } from "./questions/Images"; +import { Number } from "./questions/Number"; +import { Page } from "./questions/Page"; +import { Rating } from "./questions/Rating"; +import { Select } from "./questions/Select"; +import { Text } from "./questions/Text"; +import { Variant } from "./questions/Variant"; +import { Varimg } from "./questions/Varimg"; + +import type { RealTypedQuizQuestion } from "../../model/questionTypes/shared"; + +import { NameplateLogoFQ } from "@icons/NameplateLogoFQ"; +import { NameplateLogoFQDark } from "@icons/NameplateLogoFQDark"; +import { useQuizData } from "@contexts/QuizDataContext"; +import { notReachable } from "@utils/notReachable"; +import { quizThemes } from "@utils/themes/Publication/themePublication"; +import { ReactNode } from "react"; +import { useRootContainerSize } from "../../contexts/RootContainerWidthContext"; + +type Props = { + currentQuestion: RealTypedQuizQuestion; + currentQuestionStepNumber: number | null; + nextButton: ReactNode; + prevButton: ReactNode; +}; + +export const Question = ({ + currentQuestion, + currentQuestionStepNumber, + nextButton, + prevButton, +}: Props) => { + const theme = useTheme(); + const { settings } = useQuizData(); + const isMobile = useRootContainerSize() < 650; +console.log(settings) + return ( + + + + {quizThemes[settings.cfg.theme].isLight ? ( + + + + ) : ( + + + + + )} + +