Skip to content

Commit 0ba1632

Browse files
committed
refactor
1 parent 86589e7 commit 0ba1632

2 files changed

Lines changed: 93 additions & 178 deletions

File tree

Lines changed: 85 additions & 164 deletions
Original file line numberDiff line numberDiff line change
@@ -1,191 +1,112 @@
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";
2119
import 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);

hwproj.front/src/components/Courses/Course.tsx

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import * as React from "react";
22
import {Link as RouterLink} from "react-router-dom";
3-
import {RouteComponentProps} from 'react-router';
43
import {AccountDataDto, CourseViewModel, HomeworkViewModel, StatisticsCourseMatesModel} from "../../api";
54
import CourseHomework from "../Homeworks/CourseHomework";
65
import AddHomework from "../Homeworks/AddHomework";
@@ -40,18 +39,14 @@ interface IPageState {
4039
tabValue: TabValue
4140
}
4241

43-
interface ICourseProps {
44-
id: string;
45-
}
46-
4742
const styles = makeStyles(() => ({
4843
info: {
4944
display: "flex",
5045
justifyContent: "space-between",
5146
},
5247
}))
5348

54-
const Course: React.FC<RouteComponentProps<ICourseProps>> = (props) => {
49+
const Course: React.FC = () => {
5550
const getLastViewedCourseId = () =>
5651
{
5752
const sessionStorageCourseId = sessionStorage.getItem("courseId")
@@ -63,10 +58,9 @@ const Course: React.FC<RouteComponentProps<ICourseProps>> = (props) => {
6358
sessionStorage.setItem("courseId", courseId)
6459
}
6560

66-
const courseIdFromProps = props.match.params.id
67-
const isFromYandex = courseIdFromProps === undefined
68-
const courseId = isFromYandex ? getLastViewedCourseId() : courseIdFromProps
69-
const {tab} = useParams()
61+
let {courseId, tab} = useParams()
62+
const isFromYandex = courseId === undefined
63+
courseId = isFromYandex ? getLastViewedCourseId() : courseId
7064
const navigate = useNavigate()
7165
const classes = styles()
7266

@@ -132,7 +126,7 @@ const Course: React.FC<RouteComponentProps<ICourseProps>> = (props) => {
132126
}
133127

134128
const setCurrentState = async () => {
135-
updatedLastViewedCourseId(courseId)
129+
updatedLastViewedCourseId(courseId!)
136130
const course = await ApiSingleton.coursesApi.apiCoursesByCourseIdGet(+courseId!)
137131
const solutions = await ApiSingleton.statisticsApi.apiStatisticsByCourseIdGet(+courseId!)
138132

@@ -162,11 +156,11 @@ const Course: React.FC<RouteComponentProps<ICourseProps>> = (props) => {
162156

163157
const getUserYandexCode = (url: string) =>
164158
{
165-
const queryParameters = new URLSearchParams(window.location.search)
159+
const queryParameters = new URLSearchParams(url)
166160
return queryParameters.get("code")
167161
}
168162

169-
const id = getUserYandexCode(props.location.search)
163+
const yandexCode = getUserYandexCode(window.location.search)
170164

171165
const joinCourse = async () => {
172166
await ApiSingleton.coursesApi
@@ -361,7 +355,7 @@ const Course: React.FC<RouteComponentProps<ICourseProps>> = (props) => {
361355
isMentor={isMentor}
362356
course={courseState.course}
363357
solutions={studentSolutions}
364-
yandexCode={id}
358+
yandexCode={yandexCode}
365359
/>
366360
</Grid>
367361
</Grid>}

0 commit comments

Comments
 (0)