diff --git a/offline_node_modules/cross-fetch-npm-4.0.0-9c67668db4-386727dc4c.zip b/offline_node_modules/cross-fetch-npm-4.0.0-9c67668db4-386727dc4c.zip new file mode 100644 index 0000000..ce69d2d Binary files /dev/null and b/offline_node_modules/cross-fetch-npm-4.0.0-9c67668db4-386727dc4c.zip differ diff --git a/offline_node_modules/html-parse-stringify-npm-3.0.1-5762cd4b01-159292753d.zip b/offline_node_modules/html-parse-stringify-npm-3.0.1-5762cd4b01-159292753d.zip new file mode 100644 index 0000000..8209aea Binary files /dev/null and b/offline_node_modules/html-parse-stringify-npm-3.0.1-5762cd4b01-159292753d.zip differ diff --git a/offline_node_modules/i18next-browser-languagedetector-npm-8.0.0-fcff5207d7-08a7c747ec.zip b/offline_node_modules/i18next-browser-languagedetector-npm-8.0.0-fcff5207d7-08a7c747ec.zip new file mode 100644 index 0000000..1fc7616 Binary files /dev/null and b/offline_node_modules/i18next-browser-languagedetector-npm-8.0.0-fcff5207d7-08a7c747ec.zip differ diff --git a/offline_node_modules/i18next-http-backend-npm-2.5.2-6cbbe5e7c3-57cfbeeea4.zip b/offline_node_modules/i18next-http-backend-npm-2.5.2-6cbbe5e7c3-57cfbeeea4.zip new file mode 100644 index 0000000..1d004dd Binary files /dev/null and b/offline_node_modules/i18next-http-backend-npm-2.5.2-6cbbe5e7c3-57cfbeeea4.zip differ diff --git a/offline_node_modules/i18next-npm-23.11.5-27df1f473c-b0bec64250.zip b/offline_node_modules/i18next-npm-23.11.5-27df1f473c-b0bec64250.zip new file mode 100644 index 0000000..b6e08f2 Binary files /dev/null and b/offline_node_modules/i18next-npm-23.11.5-27df1f473c-b0bec64250.zip differ diff --git a/offline_node_modules/node-fetch-npm-2.7.0-587d57004e-b55786b602.zip b/offline_node_modules/node-fetch-npm-2.7.0-587d57004e-b55786b602.zip new file mode 100644 index 0000000..43a929c Binary files /dev/null and b/offline_node_modules/node-fetch-npm-2.7.0-587d57004e-b55786b602.zip differ diff --git a/offline_node_modules/react-i18next-npm-14.1.2-9873475bd7-cb8a83b369.zip b/offline_node_modules/react-i18next-npm-14.1.2-9873475bd7-cb8a83b369.zip new file mode 100644 index 0000000..a21ea6f Binary files /dev/null and b/offline_node_modules/react-i18next-npm-14.1.2-9873475bd7-cb8a83b369.zip differ diff --git a/offline_node_modules/tr46-npm-0.0.3-de53018915-047cb209a6.zip b/offline_node_modules/tr46-npm-0.0.3-de53018915-047cb209a6.zip new file mode 100644 index 0000000..6928ef0 Binary files /dev/null and b/offline_node_modules/tr46-npm-0.0.3-de53018915-047cb209a6.zip differ diff --git a/offline_node_modules/void-elements-npm-3.1.0-4f43780839-0b8686f9f9.zip b/offline_node_modules/void-elements-npm-3.1.0-4f43780839-0b8686f9f9.zip new file mode 100644 index 0000000..b05b8d8 Binary files /dev/null and b/offline_node_modules/void-elements-npm-3.1.0-4f43780839-0b8686f9f9.zip differ diff --git a/offline_node_modules/webidl-conversions-npm-3.0.1-60310f6a2b-5612d5f3e5.zip b/offline_node_modules/webidl-conversions-npm-3.0.1-60310f6a2b-5612d5f3e5.zip new file mode 100644 index 0000000..dda75f1 Binary files /dev/null and b/offline_node_modules/webidl-conversions-npm-3.0.1-60310f6a2b-5612d5f3e5.zip differ diff --git a/offline_node_modules/whatwg-url-npm-5.0.0-374fb45e60-1588bed84d.zip b/offline_node_modules/whatwg-url-npm-5.0.0-374fb45e60-1588bed84d.zip new file mode 100644 index 0000000..7c03e0b Binary files /dev/null and b/offline_node_modules/whatwg-url-npm-5.0.0-374fb45e60-1588bed84d.zip differ diff --git a/package.json b/package.json index a55b35e..4eb8def 100644 --- a/package.json +++ b/package.json @@ -38,12 +38,16 @@ "@mui/material": "5.15.19", "@react-spring/web": "9.7.3", "classnames": "2.5.1", + "i18next": "23.11.5", + "i18next-browser-languagedetector": "8.0.0", + "i18next-http-backend": "2.5.2", "notistack": "3.0.1", "prop-types": "15.8.1", "react": "18.3.1", "react-dnd": "16.0.1", "react-dnd-html5-backend": "16.0.1", "react-dom": "18.3.1", + "react-i18next": "14.1.2", "react-router-dom": "6.23.1", "workbox-core": "7.1.0", "workbox-precaching": "7.1.0", diff --git a/public/locales/en/analyze-page.json b/public/locales/en/analyze-page.json new file mode 100644 index 0000000..56146e7 --- /dev/null +++ b/public/locales/en/analyze-page.json @@ -0,0 +1,4 @@ +{ + "title": "Analyze Page", + "toolbar": "Analyze Page Toolbar" +} diff --git a/public/locales/en/error-page.json b/public/locales/en/error-page.json new file mode 100644 index 0000000..152f171 --- /dev/null +++ b/public/locales/en/error-page.json @@ -0,0 +1,5 @@ +{ + "title": "Something goes wrong", + "toolbar": "Unhandled error", + "404-toolbar": "Page does not exist" +} diff --git a/public/locales/en/payments-page.json b/public/locales/en/payments-page.json new file mode 100644 index 0000000..660f4e4 --- /dev/null +++ b/public/locales/en/payments-page.json @@ -0,0 +1,4 @@ +{ + "title": "Payments Page", + "toolbar": "Payments Page Toolbar" +} diff --git a/public/locales/en/schedule-page.json b/public/locales/en/schedule-page.json new file mode 100644 index 0000000..725796b --- /dev/null +++ b/public/locales/en/schedule-page.json @@ -0,0 +1,4 @@ +{ + "title": "Schedule Page", + "toolbar": "Schedule Page Toolbar" +} diff --git a/public/locales/en/sidebar.json b/public/locales/en/sidebar.json new file mode 100644 index 0000000..ef6d9f5 --- /dev/null +++ b/public/locales/en/sidebar.json @@ -0,0 +1,5 @@ +{ + "analyze-page-link": "Analyze", + "payments-page-link": "Payments list", + "schedule-page-link": "Schedule" +} diff --git a/public/locales/en/translation.json b/public/locales/en/translation.json new file mode 100644 index 0000000..0e2341f --- /dev/null +++ b/public/locales/en/translation.json @@ -0,0 +1,3 @@ +{ + "language": "English" +} diff --git a/public/locales/ru/analyze-page.json b/public/locales/ru/analyze-page.json new file mode 100644 index 0000000..9f9b429 --- /dev/null +++ b/public/locales/ru/analyze-page.json @@ -0,0 +1,4 @@ +{ + "title": "Аналитика", + "toolbar": "Доска аналитики" +} diff --git a/public/locales/ru/error-page.json b/public/locales/ru/error-page.json new file mode 100644 index 0000000..1b5a8cd --- /dev/null +++ b/public/locales/ru/error-page.json @@ -0,0 +1,5 @@ +{ + "title": "Что-то пошло не так", + "toolbar": "Произошла непредвиденная ошибка", + "404-toolbar": "Такой страницы не существует" +} diff --git a/public/locales/ru/payments-page.json b/public/locales/ru/payments-page.json new file mode 100644 index 0000000..f5a3a68 --- /dev/null +++ b/public/locales/ru/payments-page.json @@ -0,0 +1,4 @@ +{ + "title": "Платежи", + "toolbar": "Доска платежей" +} diff --git a/public/locales/ru/schedule-page.json b/public/locales/ru/schedule-page.json new file mode 100644 index 0000000..3246bc4 --- /dev/null +++ b/public/locales/ru/schedule-page.json @@ -0,0 +1,4 @@ +{ + "title": "График платежей", + "toolbar": "Доска графика платежей" +} diff --git a/public/locales/ru/sidebar.json b/public/locales/ru/sidebar.json new file mode 100644 index 0000000..37b2a7f --- /dev/null +++ b/public/locales/ru/sidebar.json @@ -0,0 +1,5 @@ +{ + "analyze-page-link": "Аналитика", + "payments-page-link": "Список платежей", + "schedule-page-link": "График платежей" +} diff --git a/public/locales/ru/translation.json b/public/locales/ru/translation.json new file mode 100644 index 0000000..0bb9424 --- /dev/null +++ b/public/locales/ru/translation.json @@ -0,0 +1,3 @@ +{ + "language": "Русский" +} diff --git a/src/apps/MoneyControllApp/model/providers/RouterProvider/index.tsx b/src/apps/MoneyControllApp/model/providers/RouterProvider/index.tsx index 5798b35..7407b88 100644 --- a/src/apps/MoneyControllApp/model/providers/RouterProvider/index.tsx +++ b/src/apps/MoneyControllApp/model/providers/RouterProvider/index.tsx @@ -1,8 +1,8 @@ import CalendarMonthIcon from '@mui/icons-material/CalendarMonth'; import FormatListBulletedIcon from '@mui/icons-material/FormatListBulleted'; import PieChartIcon from '@mui/icons-material/PieChart'; -import CircularProgress from '@mui/material/CircularProgress'; import { Suspense } from 'react'; +import { useTranslation } from 'react-i18next'; import { createBrowserRouter, Navigate, RouterProvider as RRDRouterProvider } from 'react-router-dom'; import { AnalyzePage, AnalyzePageToolbar } from 'pages/AnalyzePage'; @@ -11,6 +11,7 @@ import { PaymentsPage, PaymentsPageToolbar } from 'pages/PaymentsPage'; import { SchedulePage, SchedulePageToolbar } from 'pages/SchedulePage'; import { AsideMenuLayout } from 'widgets/AsideMenuLayout'; +import { PageLoader } from 'widgets/PageLoader'; import type { ReactNode } from 'react'; import type { RouteObject } from 'react-router-dom'; @@ -23,76 +24,78 @@ type PageListItem = { Toolbar?: ReactNode; }; -const pages: PageListItem[] = [ - { - icon: , - title: 'Аналитика', - path: '/analyze', - Content: ( - }> - - - ), - Toolbar: , - }, - { - icon: , - title: 'График платежей', - path: '/schedule', - Content: ( - }> - - - ), - Toolbar: , - }, - { - icon: , - title: 'Список платежей', - path: '/payments', - Content: ( - }> - - - ), - Toolbar: , - }, -]; +const RouterProvider = () => { + const { t } = useTranslation('sidebar'); -const routes: RouteObject[] = pages.map((page) => ({ - path: page.path, - element: ( + const pages: PageListItem[] = [ + { + icon: , + title: t('analyze-page-link'), + path: '/analyze', + Content: , + Toolbar: , + }, + { + icon: , + title: t('schedule-page-link'), + path: '/schedule', + Content: , + Toolbar: , + }, + { + icon: , + title: t('payments-page-link'), + path: '/payments', + Content: , + Toolbar: , + }, + ]; + const Fallback = ( } pages={pages} - Toolbar={page.Toolbar} /> - ), - errorElement: ( - } - pages={pages} - Toolbar={} - /> - ), -})); -const router = createBrowserRouter([ - ...routes, - { - path: '/', - element: , + ); + const routes: RouteObject[] = pages.map((page) => ({ + path: page.path, + element: ( + + + + ), errorElement: ( - } - pages={pages} - Toolbar={} - /> + + } + pages={pages} + Toolbar={} + /> + ), - }, -]); + })); -const RouterProvider = () => ( - -); + const router = createBrowserRouter([ + ...routes, + { + path: '/', + element: , + errorElement: ( + } + pages={pages} + Toolbar={} + /> + ), + }, + ]); + + return ( + + ); +}; export default RouterProvider; diff --git a/src/features/LangSwitcher/index.ts b/src/features/LangSwitcher/index.ts new file mode 100644 index 0000000..57ad91e --- /dev/null +++ b/src/features/LangSwitcher/index.ts @@ -0,0 +1 @@ +export { default as LangSwitcher } from './ui/LangSwitcher.ui'; diff --git a/src/features/LangSwitcher/ui/LangSwitcher.ui.tsx b/src/features/LangSwitcher/ui/LangSwitcher.ui.tsx new file mode 100644 index 0000000..9bea81a --- /dev/null +++ b/src/features/LangSwitcher/ui/LangSwitcher.ui.tsx @@ -0,0 +1,30 @@ +import { useCallback } from 'react'; +import { useTranslation } from 'react-i18next'; + +import i18next from 'i18n'; + +import { LANGUAGE } from 'shared/constants'; + +import type { FC, ChangeEventHandler } from 'react'; + +const LangSwitcher: FC = () => { + const { i18n } = useTranslation(); + + const onChangedHandler = useCallback>(async (e) => { + await i18next.changeLanguage(e.target.value); + }, []); + + return ( + + ); +}; + +export default LangSwitcher; diff --git a/src/i18n.ts b/src/i18n.ts new file mode 100644 index 0000000..46125c8 --- /dev/null +++ b/src/i18n.ts @@ -0,0 +1,22 @@ +import i18n from 'i18next'; +import LanguageDetector from 'i18next-browser-languagedetector'; +import Backend from 'i18next-http-backend'; +import { initReactI18next } from 'react-i18next'; + +import type { HttpBackendOptions } from 'i18next-http-backend'; + +// eslint-disable-next-line @typescript-eslint/no-floating-promises +i18n + .use(Backend) + .use(LanguageDetector) + .use(initReactI18next) + .init({ + fallbackLng: 'en', + debug: process.env.NODE_ENV === 'development', + load: 'currentOnly', + backend: { + loadPath: 'locales/{{lng}}/{{ns}}.json', + }, + }); + +export default i18n; diff --git a/src/index.tsx b/src/index.tsx index 0c08c2e..a12cf2f 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,3 +1,4 @@ +import './i18n'; import 'shared/styles/fonts/fonts.css'; import React from 'react'; import { createRoot } from 'react-dom/client'; diff --git a/src/pages/AnalyzePage/ui/AnalyzePage.ui.tsx b/src/pages/AnalyzePage/ui/AnalyzePage.ui.tsx index 410145c..8d5b83d 100644 --- a/src/pages/AnalyzePage/ui/AnalyzePage.ui.tsx +++ b/src/pages/AnalyzePage/ui/AnalyzePage.ui.tsx @@ -1,10 +1,16 @@ +import { useTranslation } from 'react-i18next'; + import type { DetailedHTMLProps, FC, HTMLAttributes } from 'react'; type AnalyzePageProps = DetailedHTMLProps, HTMLDivElement>; -const AnalyzePage: FC = (props) => ( -
- Analyze page -
-); +const AnalyzePage: FC = (props) => { + const { t } = useTranslation('analyze-page'); + + return ( +
+ {t('title')} +
+ ); +}; export default AnalyzePage; diff --git a/src/pages/AnalyzePage/ui/AnalyzePageToolbar.ui.tsx b/src/pages/AnalyzePage/ui/AnalyzePageToolbar.ui.tsx index 8fbac9c..c219ea6 100644 --- a/src/pages/AnalyzePage/ui/AnalyzePageToolbar.ui.tsx +++ b/src/pages/AnalyzePage/ui/AnalyzePageToolbar.ui.tsx @@ -1,15 +1,20 @@ import Toolbar from '@mui/material/Toolbar'; import Typography from '@mui/material/Typography'; +import { useTranslation } from 'react-i18next'; import type { ToolbarProps } from '@mui/material/Toolbar/Toolbar'; import type { FC } from 'react'; type AnalyzePageToolbarProps = ToolbarProps; -const AnalyzePageToolbar: FC = (props) => ( - - - Analyze Page Toolbar - - -); +const AnalyzePageToolbar: FC = (props) => { + const { t } = useTranslation('analyze-page'); + + return ( + + + {t('toolbar')} + + + ); +}; export default AnalyzePageToolbar; diff --git a/src/pages/ErrorPage/ui/ErrorPage.ui.tsx b/src/pages/ErrorPage/ui/ErrorPage.ui.tsx index 398fe9e..8fc1cdf 100644 --- a/src/pages/ErrorPage/ui/ErrorPage.ui.tsx +++ b/src/pages/ErrorPage/ui/ErrorPage.ui.tsx @@ -1,5 +1,6 @@ import { Grid } from '@mui/material'; import Typography from '@mui/material/Typography'; +import { useTranslation } from 'react-i18next'; import _404Image from 'public/assets/images/404.png'; import OopsImage from 'public/assets/images/oops.png'; @@ -16,6 +17,8 @@ const ErrorPage: FC = (props) => { ...restProps } = props; + const { t } = useTranslation('error-page'); + if (type === 'ErrorBoundary') { return ( = (props) => { > - Что-то пошло не так + {t('title')} diff --git a/src/pages/ErrorPage/ui/ErrorPageToolbar.ui.tsx b/src/pages/ErrorPage/ui/ErrorPageToolbar.ui.tsx index a92fca7..17c42c1 100644 --- a/src/pages/ErrorPage/ui/ErrorPageToolbar.ui.tsx +++ b/src/pages/ErrorPage/ui/ErrorPageToolbar.ui.tsx @@ -1,5 +1,6 @@ import Toolbar from '@mui/material/Toolbar'; import Typography from '@mui/material/Typography'; +import { useTranslation } from 'react-i18next'; import type { ToolbarProps } from '@mui/material/Toolbar/Toolbar'; import type { FC } from 'react'; @@ -8,17 +9,19 @@ export type ErrorPageToolbarProps = ToolbarProps & { type?: '404' | 'ErrorBoundary'; }; -const TITLE: Record, string> = { - 404: 'Страницы не существует', - ErrorBoundary: 'Непредвиденная ошибка', -}; - const ErrorPageToolbar: FC = (props) => { const { type = 'ErrorBoundary', ...restProps } = props; + const { t } = useTranslation('error-page'); + + const TITLE: Record, string> = { + 404: t('404-toolbar'), + ErrorBoundary: t('toolbar'), + }; + return ( diff --git a/src/pages/PaymentsPage/ui/PaymentsPage.ui.tsx b/src/pages/PaymentsPage/ui/PaymentsPage.ui.tsx index d15c64b..4661b2b 100644 --- a/src/pages/PaymentsPage/ui/PaymentsPage.ui.tsx +++ b/src/pages/PaymentsPage/ui/PaymentsPage.ui.tsx @@ -1,10 +1,16 @@ +import { useTranslation } from 'react-i18next'; + import type { DetailedHTMLProps, FC, HTMLAttributes } from 'react'; export type PaymentsPageProps = DetailedHTMLProps, HTMLDivElement>; -const PaymentsPage: FC = (props) => ( -
- Payments Page -
-); +const PaymentsPage: FC = (props) => { + const { t } = useTranslation('payments-page'); + + return ( +
+ {t('title')} +
+ ); +}; export default PaymentsPage; diff --git a/src/pages/PaymentsPage/ui/PaymentsPageToolbar.ui.tsx b/src/pages/PaymentsPage/ui/PaymentsPageToolbar.ui.tsx index 472229f..6e93b5f 100644 --- a/src/pages/PaymentsPage/ui/PaymentsPageToolbar.ui.tsx +++ b/src/pages/PaymentsPage/ui/PaymentsPageToolbar.ui.tsx @@ -1,16 +1,21 @@ import Toolbar from '@mui/material/Toolbar'; import Typography from '@mui/material/Typography'; +import { useTranslation } from 'react-i18next'; import type { ToolbarProps } from '@mui/material/Toolbar/Toolbar'; import type { FC } from 'react'; export type PaymentsPageToolbarProps = ToolbarProps; -const PaymentsPageToolbar: FC = (props) => ( - - - Payments Page Toolbar - - -); +const PaymentsPageToolbar: FC = (props) => { + const { t } = useTranslation('payments-page'); + + return ( + + + {t('toolbar')} + + + ); +}; export default PaymentsPageToolbar; diff --git a/src/pages/SchedulePage/ui/SchedulePage.ui.tsx b/src/pages/SchedulePage/ui/SchedulePage.ui.tsx index 31a5d2f..ebd3dd8 100644 --- a/src/pages/SchedulePage/ui/SchedulePage.ui.tsx +++ b/src/pages/SchedulePage/ui/SchedulePage.ui.tsx @@ -1,10 +1,16 @@ +import { useTranslation } from 'react-i18next'; + import type { DetailedHTMLProps, FC, HTMLAttributes } from 'react'; export type SchedulePageProps = DetailedHTMLProps, HTMLDivElement>; -const SchedulePage: FC = (props) => ( -
- Schedule Page -
-); +const SchedulePage: FC = (props) => { + const { t } = useTranslation('schedule-page'); + + return ( +
+ {t('title')} +
+ ); +}; export default SchedulePage; diff --git a/src/pages/SchedulePage/ui/SchedulePageToolbar.ui.tsx b/src/pages/SchedulePage/ui/SchedulePageToolbar.ui.tsx index 38f5013..36b7d18 100644 --- a/src/pages/SchedulePage/ui/SchedulePageToolbar.ui.tsx +++ b/src/pages/SchedulePage/ui/SchedulePageToolbar.ui.tsx @@ -1,16 +1,21 @@ import Toolbar from '@mui/material/Toolbar'; import Typography from '@mui/material/Typography'; +import { useTranslation } from 'react-i18next'; import type { ToolbarProps } from '@mui/material/Toolbar/Toolbar'; import type { FC } from 'react'; type SchedulePageToolbarProps = ToolbarProps; -const SchedulePageToolbar: FC = (props) => ( - - - Schedule Page Toolbar - - -); +const SchedulePageToolbar: FC = (props) => { + const { t } = useTranslation('schedule-page'); + + return ( + + + {t('toolbar')} + + + ); +}; export default SchedulePageToolbar; diff --git a/src/shared/constants/index.ts b/src/shared/constants/index.ts index 44822ee..591e37f 100644 --- a/src/shared/constants/index.ts +++ b/src/shared/constants/index.ts @@ -1,5 +1,5 @@ export { DAYS_IN_WEEK, MONTHS, WEEK_DAYS } from './date'; -export { MONTHS_LABEL, WEEK_DAYS_LABEL } from './locale'; +export { MONTHS_LABEL, WEEK_DAYS_LABEL, LANGUAGE } from './locale'; export type { MonthsKeys, MonthsValues, diff --git a/src/shared/constants/locale.ts b/src/shared/constants/locale.ts index 5c799e9..f4a1ed4 100644 --- a/src/shared/constants/locale.ts +++ b/src/shared/constants/locale.ts @@ -136,3 +136,14 @@ export const WEEK_DAYS_LABEL: Record = { }, }, }; + +export const LANGUAGE = { + ru: { + name: 'Русский', + emoji: '🇷🇺', + }, + en: { + name: 'English', + emoji: '🇬🇧', + }, +}; diff --git a/src/widgets/AsideMenuLayout/ui/AsideMenuLayout.ui.tsx b/src/widgets/AsideMenuLayout/ui/AsideMenuLayout.ui.tsx index f2fdb6a..92674d7 100644 --- a/src/widgets/AsideMenuLayout/ui/AsideMenuLayout.ui.tsx +++ b/src/widgets/AsideMenuLayout/ui/AsideMenuLayout.ui.tsx @@ -7,6 +7,8 @@ import { animated, useTransition } from '@react-spring/web'; import { useContext } from 'react'; import { useLocation } from 'react-router-dom'; +import { LangSwitcher } from 'features/LangSwitcher'; + import { DesktopAppBar, MobileAppBar } from './components/AppBar'; import { AsideMenuContext, AsideMenuProvider } from './components/AsideMenuProvider'; import { DesktopDrawer } from './components/DesktopDrawer'; @@ -15,6 +17,7 @@ import { MobileDrawer } from './components/MobileDrawer'; import type { MenuItemProps } from './components/MenuItem/ui/MenuItem.ui'; import type { BoxProps } from '@mui/material/Box/Box'; +// eslint-disable-next-line import/max-dependencies import type { FC, ReactNode } from 'react'; export const DESKTOP_DRAWER_WIDTH = 250; @@ -32,7 +35,6 @@ const AsideMenuLayout: FC = (props) => { Toolbar, ...restProps } = props; - const { desktopDrawerOpen, setMobileDrawerOpen } = useContext(AsideMenuContext); const theme = useTheme(); const isMobileView = useMediaQuery(theme.breakpoints.down('sm')); @@ -49,7 +51,7 @@ const AsideMenuLayout: FC = (props) => { const AnimatedContent = ( <> {transitions((styles) => ( - + {Content} ))} @@ -85,6 +87,8 @@ const AsideMenuLayout: FC = (props) => { {AnimatedToolBar} + + ) } @@ -113,14 +117,16 @@ const AsideMenuLayout: FC = (props) => { - + { Boolean(Toolbar) && ( {AnimatedToolBar} + + )} - + {AnimatedContent} diff --git a/src/widgets/PageLoader/index.ts b/src/widgets/PageLoader/index.ts new file mode 100644 index 0000000..d658126 --- /dev/null +++ b/src/widgets/PageLoader/index.ts @@ -0,0 +1 @@ +export { default as PageLoader } from './ui/PageLoader.ui'; diff --git a/src/widgets/PageLoader/ui/PageLoader.ui.tsx b/src/widgets/PageLoader/ui/PageLoader.ui.tsx new file mode 100644 index 0000000..bc3a384 --- /dev/null +++ b/src/widgets/PageLoader/ui/PageLoader.ui.tsx @@ -0,0 +1,20 @@ +import CircularProgress from '@mui/material/CircularProgress'; +import { styled } from '@mui/material/styles'; + +const CenteredDiv = styled('div')( + () => ({ + width: '100%', + height: '100%', + display: 'flex', + justifyContent: 'center', + alignItems: 'center', + }), +); + +const PageLoader = () => ( + + + +); + +export default PageLoader; diff --git a/yarn.lock b/yarn.lock index d0789be..0a9ebbf 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2671,7 +2671,7 @@ __metadata: languageName: node linkType: hard -"@babel/runtime@npm:^7.11.2": +"@babel/runtime@npm:^7.11.2, @babel/runtime@npm:^7.23.2": version: 7.24.7 resolution: "@babel/runtime@npm:7.24.7" dependencies: @@ -7769,6 +7769,15 @@ __metadata: languageName: node linkType: hard +"cross-fetch@npm:4.0.0": + version: 4.0.0 + resolution: "cross-fetch@npm:4.0.0" + dependencies: + node-fetch: "npm:^2.6.12" + checksum: 10c0/386727dc4c6b044746086aced959ff21101abb85c43df5e1d151547ccb6f338f86dec3f28b9dbddfa8ff5b9ec8662ed2263ad4607a93b2dc354fb7fe3bbb898a + languageName: node + linkType: hard + "cross-spawn@npm:7.0.3, cross-spawn@npm:^7.0.0, cross-spawn@npm:^7.0.2, cross-spawn@npm:^7.0.3": version: 7.0.3 resolution: "cross-spawn@npm:7.0.3" @@ -10579,6 +10588,15 @@ __metadata: languageName: node linkType: hard +"html-parse-stringify@npm:^3.0.1": + version: 3.0.1 + resolution: "html-parse-stringify@npm:3.0.1" + dependencies: + void-elements: "npm:3.1.0" + checksum: 10c0/159292753d48b84d216d61121054ae5a33466b3db5b446e2ffc093ac077a411a99ce6cbe0d18e55b87cf25fa3c5a86c4d8b130b9719ec9b66623259000c72c15 + languageName: node + linkType: hard + "html-webpack-plugin@npm:5.6.0": version: 5.6.0 resolution: "html-webpack-plugin@npm:5.6.0" @@ -10751,6 +10769,33 @@ __metadata: languageName: node linkType: hard +"i18next-browser-languagedetector@npm:8.0.0": + version: 8.0.0 + resolution: "i18next-browser-languagedetector@npm:8.0.0" + dependencies: + "@babel/runtime": "npm:^7.23.2" + checksum: 10c0/08a7c747ec18a0743b54390a0b42836d814b15fb49c92b90c259298e6a6e7e001ff9df99d0fd308283a34fceea53b4d9053aa1695a37f696bc04160017bbb524 + languageName: node + linkType: hard + +"i18next-http-backend@npm:2.5.2": + version: 2.5.2 + resolution: "i18next-http-backend@npm:2.5.2" + dependencies: + cross-fetch: "npm:4.0.0" + checksum: 10c0/57cfbeeea40a751134e1521fac89b14b780c9ad87b74a4f7d7168a88a8b603efed9f5df455dddbb408f7e268eae5aa0a6888e47b9f10cb9482d812d4d6997ffa + languageName: node + linkType: hard + +"i18next@npm:23.11.5": + version: 23.11.5 + resolution: "i18next@npm:23.11.5" + dependencies: + "@babel/runtime": "npm:^7.23.2" + checksum: 10c0/b0bec64250a3e529d4c51e2fc511406a85c5dde3d005d3aabe919551ca31dfc0a8f5490bf6e44649822e895a1fa91a58092d112367669cd11b2eb89e6ba90d1a + languageName: node + linkType: hard + "iconv-lite@npm:0.4.24": version: 0.4.24 resolution: "iconv-lite@npm:0.4.24" @@ -13039,6 +13084,9 @@ __metadata: eslint-config-ksv741: "npm:0.0.3" eslint-import-resolver-webpack: "npm:0.13.8" husky: "npm:9.0.11" + i18next: "npm:23.11.5" + i18next-browser-languagedetector: "npm:8.0.0" + i18next-http-backend: "npm:2.5.2" identity-obj-proxy: "npm:3.0.0" jest: "npm:29.7.0" jest-environment-jsdom: "npm:29.7.0" @@ -13050,6 +13098,7 @@ __metadata: react-dnd: "npm:16.0.1" react-dnd-html5-backend: "npm:16.0.1" react-dom: "npm:18.3.1" + react-i18next: "npm:14.1.2" react-router-dom: "npm:6.23.1" standard-version: "npm:9.5.0" ts-jest: "npm:29.1.4" @@ -13156,6 +13205,20 @@ __metadata: languageName: node linkType: hard +"node-fetch@npm:^2.6.12": + version: 2.7.0 + resolution: "node-fetch@npm:2.7.0" + dependencies: + whatwg-url: "npm:^5.0.0" + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + checksum: 10c0/b55786b6028208e6fbe594ccccc213cab67a72899c9234eb59dba51062a299ea853210fcf526998eaa2867b0963ad72338824450905679ff0fa304b8c5093ae8 + languageName: node + linkType: hard + "node-forge@npm:^1": version: 1.3.1 resolution: "node-forge@npm:1.3.1" @@ -14857,6 +14920,24 @@ __metadata: languageName: node linkType: hard +"react-i18next@npm:14.1.2": + version: 14.1.2 + resolution: "react-i18next@npm:14.1.2" + dependencies: + "@babel/runtime": "npm:^7.23.9" + html-parse-stringify: "npm:^3.0.1" + peerDependencies: + i18next: ">= 23.2.3" + react: ">= 16.8.0" + peerDependenciesMeta: + react-dom: + optional: true + react-native: + optional: true + checksum: 10c0/cb8a83b3696639f083dc9f770d9d9e0681c0fe56f6b5fe24cd6facce08d363c37bd3440078e9d63abacabd7037b783e6b4e4d0c935de9c8dda7820bd4ef7e329 + languageName: node + linkType: hard + "react-is@npm:^16.13.1, react-is@npm:^16.7.0": version: 16.13.1 resolution: "react-is@npm:16.13.1" @@ -16587,6 +16668,13 @@ __metadata: languageName: node linkType: hard +"tr46@npm:~0.0.3": + version: 0.0.3 + resolution: "tr46@npm:0.0.3" + checksum: 10c0/047cb209a6b60c742f05c9d3ace8fa510bff609995c129a37ace03476a9b12db4dbf975e74600830ef0796e18882b2381fb5fb1f6b4f96b832c374de3ab91a11 + languageName: node + linkType: hard + "trim-newlines@npm:^3.0.0": version: 3.0.1 resolution: "trim-newlines@npm:3.0.1" @@ -17134,6 +17222,13 @@ __metadata: languageName: node linkType: hard +"void-elements@npm:3.1.0": + version: 3.1.0 + resolution: "void-elements@npm:3.1.0" + checksum: 10c0/0b8686f9f9aa44012e9bd5eabf287ae0cde409b9a2854c5a2335cb83920c957668ac5876e3f0d158dd424744ac411a7270e64128556b451ed3bec875ef18534d + languageName: node + linkType: hard + "w3c-xmlserializer@npm:^4.0.0": version: 4.0.0 resolution: "w3c-xmlserializer@npm:4.0.0" @@ -17171,6 +17266,13 @@ __metadata: languageName: node linkType: hard +"webidl-conversions@npm:^3.0.0": + version: 3.0.1 + resolution: "webidl-conversions@npm:3.0.1" + checksum: 10c0/5612d5f3e54760a797052eb4927f0ddc01383550f542ccd33d5238cfd65aeed392a45ad38364970d0a0f4fea32e1f4d231b3d8dac4a3bdd385e5cf802ae097db + languageName: node + linkType: hard + "webidl-conversions@npm:^4.0.2": version: 4.0.2 resolution: "webidl-conversions@npm:4.0.2" @@ -17415,6 +17517,16 @@ __metadata: languageName: node linkType: hard +"whatwg-url@npm:^5.0.0": + version: 5.0.0 + resolution: "whatwg-url@npm:5.0.0" + dependencies: + tr46: "npm:~0.0.3" + webidl-conversions: "npm:^3.0.0" + checksum: 10c0/1588bed84d10b72d5eec1d0faa0722ba1962f1821e7539c535558fb5398d223b0c50d8acab950b8c488b4ba69043fd833cc2697056b167d8ad46fac3995a55d5 + languageName: node + linkType: hard + "whatwg-url@npm:^7.0.0": version: 7.1.0 resolution: "whatwg-url@npm:7.1.0"