diff --git a/package-lock.json b/package-lock.json
index f41f558..d1c3347 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -984,17 +984,36 @@
"integrity": "sha512-igX9a37DR2ZPGYtV6suZ6whr8pTFtyHL3K/oLUotxpSVO2ASaprmAe2Dkq7tBo7CRY7MMDrAa9nuQP9/YG8FxQ=="
},
"@emotion/react": {
- "version": "11.4.1",
- "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.4.1.tgz",
- "integrity": "sha512-pRegcsuGYj4FCdZN6j5vqCALkNytdrKw3TZMekTzNXixRg4wkLsU5QEaBG5LC6l01Vppxlp7FE3aTHpIG5phLg==",
+ "version": "11.5.0",
+ "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.5.0.tgz",
+ "integrity": "sha512-MYq/bzp3rYbee4EMBORCn4duPQfgpiEB5XzrZEBnUZAL80Qdfr7CEv/T80jwaTl/dnZmt9SnTa8NkTrwFNpLlw==",
"requires": {
"@babel/runtime": "^7.13.10",
- "@emotion/cache": "^11.4.0",
+ "@emotion/cache": "^11.5.0",
"@emotion/serialize": "^1.0.2",
- "@emotion/sheet": "^1.0.2",
+ "@emotion/sheet": "^1.0.3",
"@emotion/utils": "^1.0.0",
"@emotion/weak-memoize": "^0.2.5",
"hoist-non-react-statics": "^3.3.1"
+ },
+ "dependencies": {
+ "@emotion/cache": {
+ "version": "11.5.0",
+ "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.5.0.tgz",
+ "integrity": "sha512-mAZ5QRpLriBtaj/k2qyrXwck6yeoz1V5lMt/jfj6igWU35yYlNKs2LziXVgvH81gnJZ+9QQNGelSsnuoAy6uIw==",
+ "requires": {
+ "@emotion/memoize": "^0.7.4",
+ "@emotion/sheet": "^1.0.3",
+ "@emotion/utils": "^1.0.0",
+ "@emotion/weak-memoize": "^0.2.5",
+ "stylis": "^4.0.10"
+ }
+ },
+ "@emotion/sheet": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.0.3.tgz",
+ "integrity": "sha512-YoX5GyQ4db7LpbmXHMuc8kebtBGP6nZfRC5Z13OKJMixBEwdZrJ914D6yJv/P+ZH/YY3F5s89NYX2hlZAf3SRQ=="
+ }
}
},
"@emotion/serialize": {
diff --git a/package.json b/package.json
index 8e7bbe6..55cb9ad 100644
--- a/package.json
+++ b/package.json
@@ -9,10 +9,10 @@
"lint": "prettier --check \"src/**/*.{js,jsx,ts,tsx}\""
},
"dependencies": {
- "@chakra-ui/icons": "^1.0.15",
- "@chakra-ui/react": "^1.0.0",
- "@emotion/react": "^11.0.0",
- "@emotion/styled": "^11.0.0",
+ "@chakra-ui/icons": "^1.0.16",
+ "@chakra-ui/react": "^1.6.10",
+ "@emotion/react": "^11.5.0",
+ "@emotion/styled": "^11.3.0",
"@hookform/resolvers": "^2.8.0",
"axios": "^0.21.1",
"framer-motion": "^4.0.0",
diff --git a/src/App.tsx b/src/App.tsx
index 237cb83..ec5e270 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -1,10 +1,6 @@
import React from 'react';
import { Router, Switch } from 'react-router-dom';
-
-/**
- * Types
- */
-import { UserRoleEnum } from '@educt/enums';
+import { routes } from './routes.config';
/**
* Hooks
@@ -17,20 +13,6 @@ import { useRootStore } from '@educt/hooks/useRootStore';
import PrivateRoute from '@educt/components/PrivateRoute';
import PublicRoute from '@educt/components/PublicRoute';
-/**
- * Pages
- */
-import AuthPage from '@educt/pages/auth/auth';
-import NotFoundPage from '@educt/pages/404/404';
-import CreateCoursePage from '@educt/pages/courses/create/create';
-import ChangePasswordPage from '@educt/pages/profile/change-password/change-password';
-import ChangeEmailPage from '@educt/pages/profile/change-email/change-email';
-const CoursesPage = React.lazy(() => import('@educt/pages/courses/courses'));
-const MainPage = React.lazy(() => import('@educt/pages/main/main'));
-const MessagesPage = React.lazy(() => import('@educt/pages/messages/messages'));
-const ProfilePage = React.lazy(() => import('@educt/pages/profile/profile'));
-const UsersPage = React.lazy(() => import('@educt/pages/users/users'));
-
const App = () => {
const {
uiStore: { history },
@@ -39,26 +21,10 @@ const App = () => {
return (
-
-
-
-
-
-
-
-
-
-
+ {routes.map((routeProps, i) => {
+ const { isPrivate, ...props } = routeProps;
+ return isPrivate ? : ;
+ })}
);
diff --git a/src/components/Nav/Desktop/index.tsx b/src/components/Nav/Desktop/index.tsx
index 02a9e5c..ec33bb5 100644
--- a/src/components/Nav/Desktop/index.tsx
+++ b/src/components/Nav/Desktop/index.tsx
@@ -50,8 +50,8 @@ const Nav: React.FC = () => {
-
- Learning Management System
Made by Sergey Yarkov
+
+ Learning Management System
Made by Sergey Yarkov
v{config.metaData.appVersion}
diff --git a/src/components/PrivateRoute/PrivateRoute.tsx b/src/components/PrivateRoute/PrivateRoute.tsx
index b65482e..10b4e67 100644
--- a/src/components/PrivateRoute/PrivateRoute.tsx
+++ b/src/components/PrivateRoute/PrivateRoute.tsx
@@ -3,16 +3,13 @@ import React from 'react';
import Helmet from 'react-helmet';
import { ErrorBoundary } from 'react-error-boundary';
import { Route, Redirect } from 'react-router-dom';
-import { RouteProps } from 'react-router';
-import { IPageProps } from '@educt/interfaces';
import { UserRoleEnum } from '@educt/enums';
import { useRootStore } from '@educt/hooks/useRootStore';
import Layout from '@educt/components/Layout';
import ErrorFallback from '@educt/components/ErrorFallback';
+import { IPublicRouteProps } from '../PublicRoute/PublicRoute';
-export interface IPrivateRouteProps extends RouteProps {
- component: React.FC;
- title?: string;
+export interface IPrivateRouteProps extends IPublicRouteProps {
/**
* This field means who can access the page
*/
diff --git a/src/components/PublicRoute/PublicRoute.tsx b/src/components/PublicRoute/PublicRoute.tsx
index fd2b719..d107f61 100644
--- a/src/components/PublicRoute/PublicRoute.tsx
+++ b/src/components/PublicRoute/PublicRoute.tsx
@@ -7,7 +7,7 @@ import ErrorFallback from '@educt/components/ErrorFallback';
export interface IPublicRouteProps extends RouteProps {
component: React.FC;
- title?: string;
+ title: string;
}
/**
diff --git a/src/config.ts b/src/config.ts
index e64023c..a0a6f0f 100644
--- a/src/config.ts
+++ b/src/config.ts
@@ -1,6 +1,7 @@
import { UserRoleEnum } from '@educt/enums';
import { MdAccountCircle, MdCollectionsBookmark, MdGroup, MdHome, MdMessage } from 'react-icons/md';
import { IAppConfig } from './interfaces';
+import packageJson from '../package.json';
const config: IAppConfig = {
/**
@@ -8,7 +9,8 @@ const config: IAppConfig = {
*/
metaData: {
appName: 'Educt',
- appDescription: 'Learn management system',
+ appDescription: 'Learning management system',
+ appVersion: packageJson.version,
},
/**
* Links that are rendered in the navigation
diff --git a/src/interfaces/index.ts b/src/interfaces/index.ts
index 4757bd3..f431b2f 100644
--- a/src/interfaces/index.ts
+++ b/src/interfaces/index.ts
@@ -6,6 +6,7 @@ export interface IAppConfig {
metaData: {
appName: string;
appDescription: string;
+ appVersion: string;
};
links: LinkType[];
}
@@ -127,10 +128,5 @@ export interface IApiRespose {
}
export interface IPageProps extends RouteComponentProps {
- title?: string;
-}
-
-export interface IWindowDimensions {
- width: number;
- height: number;
+ title: string;
}
diff --git a/src/pages/404/404.tsx b/src/pages/404/404.tsx
index 18d5174..32b1a4c 100644
--- a/src/pages/404/404.tsx
+++ b/src/pages/404/404.tsx
@@ -1,10 +1,15 @@
import React from 'react';
import Helmet from 'react-helmet';
-import { MdError } from 'react-icons/md';
-import { Flex, Box, Heading, Text, useToast, Link } from '@chakra-ui/react';
import { Link as ReactRouterLink } from 'react-router-dom';
+import { Flex, Box, Heading, Text, useToast, Link } from '@chakra-ui/react';
+import { MdError } from 'react-icons/md';
-const NotFoundPage: React.FC = () => {
+/**
+ * Types
+ */
+import { IPageProps } from '@educt/interfaces';
+
+const NotFoundPage: React.FC = ({ title }) => {
const toast = useToast();
React.useEffect(() => {
@@ -14,7 +19,7 @@ const NotFoundPage: React.FC = () => {
return (
<>
- Error 404
+ {title}
diff --git a/src/pages/auth/auth.tsx b/src/pages/auth/auth.tsx
index e402a3d..1eb1977 100644
--- a/src/pages/auth/auth.tsx
+++ b/src/pages/auth/auth.tsx
@@ -11,7 +11,7 @@ import AuthForm from './components/AuthForm';
/**
* Auth page
*/
-const AuthPage: React.FC = () => {
+const AuthPage: React.FC = ({ title }) => {
const { authStore } = useRootStore();
/**
@@ -24,7 +24,7 @@ const AuthPage: React.FC = () => {
return (
<>
- Auth
+ {title}
diff --git a/src/pages/courses/components/CourseList/CourseList.tsx b/src/pages/courses/components/CourseList/CourseList.tsx
index 5fad702..6dd15d3 100644
--- a/src/pages/courses/components/CourseList/CourseList.tsx
+++ b/src/pages/courses/components/CourseList/CourseList.tsx
@@ -44,7 +44,7 @@ const CourseList: React.FC = ({ courses, isLoading }) => {
const toast = useToast();
/**
- * Fetch handler
+ * Fetch courses handler
*/
useEffect(() => {
if (me !== null) {
@@ -53,7 +53,7 @@ const CourseList: React.FC = ({ courses, isLoading }) => {
status: me.isAdmin || me.isTeacher ? courseStatus : CourseStatusEnum.PUBLISHED,
});
}
- }, [courseStore, selectedCategory, courseStatus, me]);
+ }, [courseStore, selectedCategory, courseStatus]);
/**
* Handle delete course
diff --git a/src/pages/courses/courses.tsx b/src/pages/courses/courses.tsx
index 8a0066a..24e8c74 100644
--- a/src/pages/courses/courses.tsx
+++ b/src/pages/courses/courses.tsx
@@ -30,7 +30,7 @@ import { useHistory } from 'react-router';
/**
* Courses page
*/
-const CoursesPage: React.FC = ({ title }) => {
+const CoursesPage: React.FC = () => {
const {
userStore: { me },
categoryStore,
@@ -46,7 +46,7 @@ const CoursesPage: React.FC = ({ title }) => {
Courses
- List of all available courses.
+ List of all courses.
{(me.isAdmin || me.isTeacher) && (
+
+
Telegram
= ({ con
{errors.telegram_id?.message}
+
VKontakte
= () => {
-
- }>
-
-
-
- First Name
-
-
- {me.first_name}
-
-
-
-
-
-
- Last Name
-
-
- {me.last_name}
-
-
-
-
-
-
- Email
-
-
- {me.email}
-
-
-
-
-
-
-
- Password
-
-
- **********
-
-
-
-
-
-
+
diff --git a/src/routes.config.ts b/src/routes.config.ts
new file mode 100644
index 0000000..35ff0bd
--- /dev/null
+++ b/src/routes.config.ts
@@ -0,0 +1,87 @@
+import { lazy } from 'react';
+import { IPrivateRouteProps } from './components/PrivateRoute/PrivateRoute';
+
+/**
+ * Pages
+ */
+import AuthPage from '@educt/pages/auth/auth';
+import NotFoundPage from '@educt/pages/404/404';
+import CreateCoursePage from '@educt/pages/courses/create/create';
+import ChangePasswordPage from '@educt/pages/profile/change-password/change-password';
+import ChangeEmailPage from '@educt/pages/profile/change-email/change-email';
+import { UserRoleEnum } from './enums';
+const CoursesPage = lazy(() => import('@educt/pages/courses/courses'));
+const MainPage = lazy(() => import('@educt/pages/main/main'));
+const MessagesPage = lazy(() => import('@educt/pages/messages/messages'));
+const ProfilePage = lazy(() => import('@educt/pages/profile/profile'));
+const UsersPage = lazy(() => import('@educt/pages/users/users'));
+
+interface IRouteOption extends IPrivateRouteProps {
+ isPrivate: boolean;
+}
+
+export const routes: IRouteOption[] = [
+ {
+ path: '/',
+ title: 'Main',
+ component: MainPage,
+ exact: true,
+ isPrivate: true,
+ },
+ {
+ path: '/courses',
+ title: 'Courses',
+ component: CoursesPage,
+ exact: true,
+ isPrivate: true,
+ },
+ {
+ path: '/courses/create',
+ title: 'Create new course',
+ component: CreateCoursePage,
+ isPrivate: true,
+ },
+ {
+ path: '/messages',
+ title: 'Messages',
+ component: MessagesPage,
+ isPrivate: true,
+ },
+ {
+ path: '/profile',
+ title: 'Profile',
+ component: ProfilePage,
+ isPrivate: true,
+ exact: true,
+ },
+ {
+ path: '/profile/change-password',
+ title: 'Change password',
+ component: ChangePasswordPage,
+ isPrivate: true,
+ },
+ {
+ path: '/profile/change-email',
+ title: 'Change email',
+ component: ChangeEmailPage,
+ isPrivate: true,
+ },
+ {
+ path: '/users',
+ title: 'Users management',
+ component: UsersPage,
+ isPrivate: true,
+ roles: [UserRoleEnum.ADMIN, UserRoleEnum.TEACHER],
+ },
+ {
+ path: '/auth',
+ title: 'Auth',
+ component: AuthPage,
+ isPrivate: false,
+ },
+ {
+ title: 'Page not found',
+ component: NotFoundPage,
+ isPrivate: false,
+ },
+];
diff --git a/src/stores/UIStore.ts b/src/stores/UIStore.ts
index 154fb68..9605cdf 100644
--- a/src/stores/UIStore.ts
+++ b/src/stores/UIStore.ts
@@ -1,11 +1,6 @@
-import { makeAutoObservable, observable, runInAction } from 'mobx';
+import { makeAutoObservable } from 'mobx';
import { createBrowserHistory } from 'history';
-/**
- * Types
- */
-import { IWindowDimensions } from '@educt/interfaces';
-
/**
* Stores
*/
@@ -18,15 +13,11 @@ export default class UIStore {
public history: ReturnType;
- public windowDimensions: IWindowDimensions = { width: window.innerWidth, height: window.innerHeight };
-
constructor(root: RootStore) {
this.root = root;
this.history = createBrowserHistory();
- makeAutoObservable(this, {
- windowDimensions: observable.struct,
- });
+ makeAutoObservable(this);
this.setupListeners();
}
@@ -41,31 +32,10 @@ export default class UIStore {
this.history.listen(({ pathname }) => {
this.setLocation(pathname);
});
-
- /**
- * Window dimensions updated
- */
- window.onresize = () => this.updateWindowDimensions();
}
public setLocation(location: string): void {
console.log(`[history]: location changed to "${location}"`);
this.location = location;
}
-
- private updateWindowDimensions(): void {
- this.windowDimensions = { width: window.innerWidth, height: window.innerHeight };
- }
-
- get isDesktop() {
- return this.windowDimensions.width > 991;
- }
-
- get isTablet() {
- return this.windowDimensions.width < 991;
- }
-
- get isMobile() {
- return this.windowDimensions.width < 568;
- }
}