split widget and default App components
use router in default App for retrieving quizId from url add QuizIdContext
This commit is contained in:
parent
db541d97ef
commit
fb3d46110f
@ -27,6 +27,7 @@
|
||||
"notistack": "^3.0.1",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-router-dom": "^6.21.3",
|
||||
"swr": "^2.2.4",
|
||||
"typescript": "^5.2.2",
|
||||
"use-debounce": "^9.0.4",
|
||||
|
62
src/App.tsx
62
src/App.tsx
@ -1,56 +1,24 @@
|
||||
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 moment from "moment";
|
||||
import { SnackbarProvider } from 'notistack';
|
||||
import { SWRConfig } from "swr";
|
||||
import { Box } from "@mui/material";
|
||||
import ContextProviders from "ContextProviders";
|
||||
import { QuizIdContext } from "contexts/QuizIdContext";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { ViewPage } from "./pages/ViewPublicationPage/ViewPublicationPage";
|
||||
import lightTheme from "./utils/themes/light";
|
||||
|
||||
|
||||
const defaultQuizId = "ef836ff8-35b1-4031-9acf-af5766bac2b2";
|
||||
|
||||
moment.locale("ru");
|
||||
const localeText = ruRU.components.MuiLocalizationProvider.defaultProps.localeText;
|
||||
|
||||
interface Props {
|
||||
widget?: boolean;
|
||||
quizId?: string;
|
||||
}
|
||||
|
||||
export default function App({ widget = false, quizId }: Props) {
|
||||
quizId ??= defaultQuizId;
|
||||
export default function App() {
|
||||
const quizId = useParams().quizId ?? defaultQuizId;
|
||||
|
||||
return (
|
||||
<SWRConfig value={{
|
||||
revalidateOnFocus: false,
|
||||
shouldRetryOnError: false,
|
||||
}}>
|
||||
<LocalizationProvider dateAdapter={AdapterMoment} adapterLocale="ru" localeText={localeText}>
|
||||
<ThemeProvider theme={lightTheme}>
|
||||
<SnackbarProvider
|
||||
preventDuplicate={true}
|
||||
style={{ backgroundColor: lightTheme.palette.brightPurple.main }}
|
||||
>
|
||||
<CssBaseline />
|
||||
{widget ? (
|
||||
<Box sx={{
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
}}>
|
||||
<ViewPage quizId={quizId} />
|
||||
</Box>
|
||||
) : (
|
||||
<Box sx={{
|
||||
height: "100dvh",
|
||||
}}>
|
||||
<ViewPage quizId={quizId} />
|
||||
</Box>
|
||||
)}
|
||||
</SnackbarProvider>
|
||||
</ThemeProvider>
|
||||
</LocalizationProvider>
|
||||
</SWRConfig>
|
||||
<QuizIdContext.Provider value={quizId}>
|
||||
<ContextProviders>
|
||||
<Box sx={{
|
||||
height: "100dvh",
|
||||
}}>
|
||||
<ViewPage />
|
||||
</Box>
|
||||
</ContextProviders>
|
||||
</QuizIdContext.Provider>
|
||||
);
|
||||
}
|
||||
|
38
src/ContextProviders.tsx
Normal file
38
src/ContextProviders.tsx
Normal file
@ -0,0 +1,38 @@
|
||||
import { 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 moment from "moment";
|
||||
import { SnackbarProvider } from 'notistack';
|
||||
import { SWRConfig } from "swr";
|
||||
import lightTheme from "./utils/themes/light";
|
||||
|
||||
|
||||
moment.locale("ru");
|
||||
const localeText = ruRU.components.MuiLocalizationProvider.defaultProps.localeText;
|
||||
|
||||
interface Props {
|
||||
children: JSX.Element;
|
||||
}
|
||||
|
||||
export default function ContextProviders({ children }: Props) {
|
||||
|
||||
return (
|
||||
<SWRConfig value={{
|
||||
revalidateOnFocus: false,
|
||||
shouldRetryOnError: false,
|
||||
}}>
|
||||
<LocalizationProvider dateAdapter={AdapterMoment} adapterLocale="ru" localeText={localeText}>
|
||||
<ThemeProvider theme={lightTheme}>
|
||||
<SnackbarProvider
|
||||
preventDuplicate={true}
|
||||
style={{ backgroundColor: lightTheme.palette.brightPurple.main }}
|
||||
>
|
||||
<CssBaseline />
|
||||
{children}
|
||||
</SnackbarProvider>
|
||||
</ThemeProvider>
|
||||
</LocalizationProvider>
|
||||
</SWRConfig>
|
||||
);
|
||||
}
|
25
src/WidgetApp.tsx
Normal file
25
src/WidgetApp.tsx
Normal file
@ -0,0 +1,25 @@
|
||||
import { Box } from "@mui/material";
|
||||
import ContextProviders from "ContextProviders";
|
||||
import { QuizIdContext } from "contexts/QuizIdContext";
|
||||
import { ViewPage } from "./pages/ViewPublicationPage/ViewPublicationPage";
|
||||
|
||||
|
||||
interface Props {
|
||||
quizId: string;
|
||||
}
|
||||
|
||||
export default function WidgetApp({ quizId }: Props) {
|
||||
|
||||
return (
|
||||
<QuizIdContext.Provider value={quizId}>
|
||||
<ContextProviders>
|
||||
<Box sx={{
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
}}>
|
||||
<ViewPage />
|
||||
</Box>
|
||||
</ContextProviders>
|
||||
</QuizIdContext.Provider>
|
||||
);
|
||||
}
|
11
src/contexts/QuizIdContext.ts
Normal file
11
src/contexts/QuizIdContext.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import { createContext, useContext } from "react";
|
||||
|
||||
|
||||
export const QuizIdContext = createContext<string | null>(null);
|
||||
|
||||
export const useQuizId = () => {
|
||||
const quizId = useContext(QuizIdContext);
|
||||
if (quizId === null) throw new Error("quizId context is null");
|
||||
|
||||
return quizId;
|
||||
};
|
19
src/main.tsx
19
src/main.tsx
@ -1,7 +1,24 @@
|
||||
import { createRoot } from "react-dom/client";
|
||||
import { RouterProvider, createBrowserRouter } from "react-router-dom";
|
||||
import App from "./App";
|
||||
|
||||
|
||||
const router = createBrowserRouter([
|
||||
{
|
||||
path: "/",
|
||||
children: [
|
||||
{
|
||||
index: true,
|
||||
element: <App />,
|
||||
},
|
||||
{
|
||||
path: ":quizId",
|
||||
element: <App />,
|
||||
},
|
||||
]
|
||||
}
|
||||
]);
|
||||
|
||||
const root = createRoot(document.getElementById("root")!);
|
||||
|
||||
root.render(<App />);
|
||||
root.render(<RouterProvider router={router} />);
|
||||
|
@ -13,13 +13,12 @@ import { Question } from "./Question";
|
||||
import { StartPageViewPublication } from "./StartPageViewPublication";
|
||||
|
||||
import { parseQuizData } from "@model/api/getQuizData";
|
||||
import { useQuizId } from "contexts/QuizIdContext";
|
||||
import { replaceSpacesToEmptyLines } from "./tools/replaceSpacesToEmptyLines";
|
||||
|
||||
type Props = {
|
||||
quizId: string;
|
||||
};
|
||||
|
||||
export const ViewPage = ({ quizId }: Props) => {
|
||||
export const ViewPage = () => {
|
||||
const quizId = useQuizId();
|
||||
const { isLoading, error } = useSWR(["quizData", quizId], params => getQuizData(params[1]), {
|
||||
onSuccess: setQuizData,
|
||||
});
|
||||
|
@ -1,5 +1,5 @@
|
||||
import WidgetApp from "./WidgetApp";
|
||||
import { Root, createRoot } from "react-dom/client";
|
||||
import App from "./App";
|
||||
|
||||
|
||||
let root: Root | undefined = undefined;
|
||||
@ -14,7 +14,7 @@ const widget = {
|
||||
|
||||
root = createRoot(element);
|
||||
|
||||
root.render(<App widget quizId={quizId} />);
|
||||
root.render(<WidgetApp quizId={quizId} />);
|
||||
},
|
||||
unmount() {
|
||||
if (root) root.unmount();
|
||||
|
20
yarn.lock
20
yarn.lock
@ -737,6 +737,11 @@
|
||||
resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.8.tgz#6b79032e760a0899cd4204710beede972a3a185f"
|
||||
integrity sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==
|
||||
|
||||
"@remix-run/router@1.14.2":
|
||||
version "1.14.2"
|
||||
resolved "https://registry.yarnpkg.com/@remix-run/router/-/router-1.14.2.tgz#4d58f59908d9197ba3179310077f25c88e49ed17"
|
||||
integrity sha512-ACXpdMM9hmKZww21yEqWwiLws/UPLhNKvimN8RrYSqPSvB3ov7sLvAcfvaxePeLvccTQKGdkDIhLYApZVDFuKg==
|
||||
|
||||
"@rollup/rollup-android-arm-eabi@4.9.5":
|
||||
version "4.9.5"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.9.5.tgz#b752b6c88a14ccfcbdf3f48c577ccc3a7f0e66b9"
|
||||
@ -2724,6 +2729,21 @@ react-refresh@^0.14.0:
|
||||
resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.14.0.tgz#4e02825378a5f227079554d4284889354e5f553e"
|
||||
integrity sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ==
|
||||
|
||||
react-router-dom@^6.21.3:
|
||||
version "6.21.3"
|
||||
resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-6.21.3.tgz#ef3a7956a3699c7b82c21fcb3dbc63c313ed8c5d"
|
||||
integrity sha512-kNzubk7n4YHSrErzjLK72j0B5i969GsuCGazRl3G6j1zqZBLjuSlYBdVdkDOgzGdPIffUOc9nmgiadTEVoq91g==
|
||||
dependencies:
|
||||
"@remix-run/router" "1.14.2"
|
||||
react-router "6.21.3"
|
||||
|
||||
react-router@6.21.3:
|
||||
version "6.21.3"
|
||||
resolved "https://registry.yarnpkg.com/react-router/-/react-router-6.21.3.tgz#8086cea922c2bfebbb49c6594967418f1f167d70"
|
||||
integrity sha512-a0H638ZXULv1OdkmiK6s6itNhoy33ywxmUFT/xtSoVyf9VnC7n7+VT4LjVzdIHSaF5TIh9ylUgxMXksHTgGrKg==
|
||||
dependencies:
|
||||
"@remix-run/router" "1.14.2"
|
||||
|
||||
react-transition-group@^4.4.5:
|
||||
version "4.4.5"
|
||||
resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.4.5.tgz#e53d4e3f3344da8521489fbef8f2581d42becdd1"
|
||||
|
Loading…
Reference in New Issue
Block a user