1- import React , { Component } from "react" ;
2- import {
3- Switch ,
4- Route ,
5- Redirect ,
6- RouteComponentProps ,
7- withRouter ,
8- } from "react-router-dom" ;
9- import decode from "jwt-decode" ;
10- import { Button } from "@skbkontur/react-ui" ;
11-
12- import { IUser , Role } from "types" ;
13- import { API_ROOT } from "config" ;
14-
15- import Profile from "pages/Profile" ;
16- import Login from "pages/Login" ;
17- import Register from "pages/Register" ;
18-
19- import ModalRoot from "./ModalRoot" ;
20- import Footer from "parts/Footer" ;
1+ import React , { Component } from "react" ;
2+ import { Route , Routes , useNavigate } from "react-router-dom" ;
3+ import "./App.css" ;
4+ import "./components/Courses/Course" ;
5+ import Course from "./components/Courses/Course" ;
6+ import Courses from "./components/Courses/Courses" ;
7+ import CreateCourse from "./components/Courses/CreateCourse" ;
8+ import Notifications from "./components/Notifications" ;
9+ import Workspace from "./components/Workspace" ;
10+ import TaskSolutionsPage from "./components/Solutions/TaskSolutionsPage" ;
11+ import { Header } from "./components/AppBar" ;
12+ import Login from "./components/Auth/Login" ;
13+ import EditCourse from "./components/Courses/EditCourse" ;
14+ import EditTask from "./components/Tasks/EditTask" ;
15+ import EditHomework from "./components/Homeworks/EditHomework" ;
16+ import Register from "./components/Auth/Register" ;
17+ import StudentSolutionsPage from "./components/Solutions/StudentSolutionsPage" ;
18+ import EditProfile from "./components/EditProfile" ;
2119import ApiSingleton from "./api/ApiSingleton" ;
20+ import SystemInfoComponent from "./components/System/SystemInfoComponent" ;
21+ import WrongPath from "./components/WrongPath" ;
2222
23- type Props = RouteComponentProps ;
23+ // TODO: add flux
2424
25- interface ModalState {
26- type : "INVITE_LECTURER" | "COURSE_WORK_CREATE" | "" ;
27- props : any ;
25+ interface AppState {
26+ loggedIn : boolean ;
27+ isLecturer : boolean ;
28+ newNotificationsCount : number ;
2829}
2930
30- interface State {
31- user : IUser ;
32- logged ?: boolean ;
33- token : string ;
34- modal : ModalState ;
35- }
31+ const withRouter = ( Component : any ) => {
32+ return ( props : any ) => {
33+ const navigate = useNavigate ( ) ;
3634
37- interface IModalContext {
38- state : ModalState ;
39- openModal : ( type : ModalState [ "type" ] , props ?: ModalState [ "props" ] ) => void ;
40- closeModal : ( ) => void ;
41- }
42-
43- export const ModalContext = React . createContext < IModalContext > (
44- { } as IModalContext
45- ) ;
35+ return (
36+ < Component
37+ navigate = { navigate }
38+ { ...props }
39+ />
40+ ) ;
41+ } ;
42+ } ;
4643
47- class App extends Component < Props , State > {
48- constructor ( props : Props ) {
44+ class App extends Component < { navigate : any } , AppState > {
45+ constructor ( props : { navigate : any } ) {
4946 super ( props ) ;
5047 this . state = {
51- user : { } as IUser ,
52- logged : false ,
53- token : localStorage . getItem ( "id_token" ) ?? "" ,
54- modal : { type : "" , props : { } } ,
48+ loggedIn : ApiSingleton . authService . isLoggedIn ( ) ,
49+ isLecturer : ApiSingleton . authService . isLecturer ( ) ,
50+ newNotificationsCount : 0
5551 } ;
56-
57- this . login = this . login . bind ( this ) ;
58- this . logout = this . logout . bind ( this ) ;
59- this . decodeUserFromToken = this . decodeUserFromToken . bind ( this ) ;
60- this . fetchUserData = this . fetchUserData . bind ( this ) ;
6152 }
6253
63- decodeUserFromToken ( token : string ) {
64- const user : IUser = decode ( token ) ;
65- return {
66- userId : ( user as any ) . _id as number ,
67- role : ( user as any ) . _role as Role ,
68- firstName : "" ,
69- lastName : "" ,
70- isCritic : false ,
71- } ;
54+ componentDidMount = async ( ) => {
55+ await this . updatedNewNotificationsCount ( )
7256 }
7357
74- login ( token : string ) {
75- this . setState ( {
76- user : this . decodeUserFromToken ( token ) ,
77- logged : true ,
78- token : token ,
79- } ) ;
80- }
81-
82- logout ( ) {
83- this . setState ( { user : { } as IUser , logged : false , token : "" } ) ;
84- localStorage . removeItem ( "id_token" ) ;
85- this . props . history . push ( "/login" ) ;
86- }
87-
88- componentDidMount ( ) {
89- if ( this . state . token ) {
90- if ( ApiSingleton . authService . isTokenExpired ( this . state . token ) ) {
91- this . logout ( ) ;
92- } else {
93- this . login ( this . state . token ) ;
94- this . props . history . push ( "/profile" ) ;
95- }
58+ updatedNewNotificationsCount = async ( ) => {
59+ if ( ApiSingleton . authService . isLoggedIn ( ) ) {
60+ const data = await ApiSingleton . notificationsApi . apiNotificationsGetNewNotificationsCountGet ( )
61+ this . setState ( { newNotificationsCount : data } )
9662 }
9763 }
9864
99- componentDidUpdate ( prevProps : Props , prevState : State ) {
100- if ( prevState . logged !== this . state . logged ) {
101- if ( this . state . logged ) {
102- this . fetchUserData ( ) ;
103- }
104- }
65+ login = ( ) => {
66+ this . setState ( {
67+ loggedIn : true ,
68+ isLecturer : ApiSingleton . authService . isLecturer ( )
69+ } )
70+ this . props . navigate ( "/" ) ;
10571 }
10672
107- async fetchUserData ( ) {
108- try {
109- /*const res = await axios.get(
110- `${API_ROOT}/account/getUserData/${this.state.user.userId}`
111- );*/
112-
113- const res = await ApiSingleton . accountApi . apiAccountGetUserDataByUserIdGet ( this . state . user . userId . toString ( ) ) ;
114- /*if (res. status === 200) {
115- this.setState({
116- user: {
117- ...this.state.user,
118- firstName: res.data.name,
119- lastName: res.data.surname,
120- middleName: res.data.middleName,
121- },
122- });
123- }*/
124- } catch ( err ) {
125- console . error ( err . response ) ;
126- // if token has expired:
127- // show 'expired message'
128- // redirect to login page.
129- }
73+ logout = ( ) => {
74+ ApiSingleton . authService . logout ( ) ;
75+ this . setState ( { loggedIn : false } ) ;
76+ this . setState ( { isLecturer : false } ) ;
77+ this . props . navigate ( "/login" ) ;
13078 }
13179
132- handleInviteLecturer = ( email : string ) => {
133- return ApiSingleton . accountApi . apiAccountInvitenewlecturerPost ( { email} )
134- } ;
135-
13680 render ( ) {
137- const modalContextValue : IModalContext = {
138- state : this . state . modal ,
139- openModal : ( type , props = { } ) =>
140- this . setState ( { modal : { type, props } } ) ,
141- closeModal : ( ) => this . setState ( { modal : { type : "" , props : { } } } ) ,
142- } ;
143-
144- if ( this . state . token && ! this . state . logged ) {
145- return null ;
146- }
147-
14881 return (
149- < div className = "page" >
150- < ModalContext . Provider value = { modalContextValue } >
151- < Switch >
152- < Route path = "/register" component = { Register } />
153- < Route
154- path = "/login"
155- render = { ( props ) => < Login { ...props } auth = { this . login } /> }
156- />
157- < Route
158- path = "/profile"
159- render = { ( props ) => (
160- < Profile
161- { ...props }
162- user = { this . state . user }
163- token = { this . state . token }
164- logout = { this . logout }
165- />
166- ) }
167- />
168- < Redirect to = "/login" />
169- </ Switch >
170- < ModalRoot />
171- </ ModalContext . Provider >
172- < Footer >
173- { this . state . logged && this . state . user . role !== Role . Student && (
174- < Button
175- use = "primary"
176- onClick = { ( ) =>
177- modalContextValue . openModal ( "INVITE_LECTURER" , {
178- onSubmit : this . handleInviteLecturer ,
179- } )
180- }
181- >
182- Пригласить
183- </ Button >
184- ) }
185- </ Footer >
186- </ div >
82+ < >
83+ < Header loggedIn = { this . state . loggedIn }
84+ newNotificationsCount = { this . state . newNotificationsCount }
85+ isLecturer = { this . state . isLecturer }
86+ onLogout = { this . logout } />
87+ < Routes >
88+ < Route path = "system" element = { < SystemInfoComponent /> } />
89+ < Route path = "user/edit" element = { < EditProfile /> } />
90+ < Route path = "/" element = { < Workspace /> } />
91+ < Route path = "notifications" element = { < Notifications onMarkAsSeen = { this . updatedNewNotificationsCount } /> } />
92+ < Route path = "courses" element = { < Courses navigate = { this . props . navigate } /> } />
93+ < Route path = "profile/:id" element = { < Workspace /> } />
94+ < Route path = "create_course" element = { < CreateCourse /> } />
95+ < Route path = "courses/:courseId" element = { < Course /> } />
96+ < Route path = "courses/:courseId/:tab" element = { < Course /> } />
97+ < Route path = "courses/:courseId/edit" element = { < EditCourse /> } />
98+ < Route path = "homework/:homeworkId/edit" element = { < EditHomework /> } />
99+ < Route path = "task/:taskId/edit" element = { < EditTask /> } />
100+ < Route path = "task/:taskId/:studentId" element = { < StudentSolutionsPage /> } />
101+ < Route path = "task/:taskId/" element = { < TaskSolutionsPage /> } />
102+ < Route path = "login" element = { < Login onLogin = { this . login } /> } />
103+ < Route path = "register" element = { < Register onLogin = { this . login } /> } />
104+ < Route path = "/yandex" element = { < Course /> } />
105+ < Route path = { "*" } element = { < WrongPath /> } />
106+ </ Routes >
107+ </ >
187108 ) ;
188109 }
189110}
190111
191- export default withRouter ( App ) ;
112+ export default withRouter ( App ) ;
0 commit comments