Skip to content

Commit 1d9b596

Browse files
authored
Merge pull request #182 from wlmac/develop
Develop
2 parents ff51fde + 3433c98 commit 1d9b596

File tree

26 files changed

+223
-121
lines changed

26 files changed

+223
-121
lines changed

src/components/account/left-nav/index.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ export const ProfileNav = (): JSX.Element => {
3636
<div className="secondary-nav-wrapper">
3737
<ul className="secondary-nav">
3838
<li>
39-
<Link className={`link${location.pathname.startsWith('/user/') ? ' current' : ''}`} to="/accounts/profile">Profile</Link>
39+
<Link className={`link${location.pathname.startsWith('/user/') ? ' current' : ''}`} to="/account/profile">Profile</Link>
4040
</li>
4141
<li>
4242
<Link className={`link${location.pathname.startsWith('/timetable') ? ' current' : ''}`} to="/timetable">Timetable</Link>
@@ -46,14 +46,14 @@ export const ProfileNav = (): JSX.Element => {
4646
notFound ?
4747
console.log("Why you looing for ghosts huh?")
4848
:
49-
"username" in user ?
50-
user.organizations_leading.length > 0 ?
49+
"username" in current_user ?
50+
current_user.organizations_leading.length > 0 ?
5151
<div>
5252
<li>
53-
<Link className="link" to="/admin/core/announcement/add/">Announcements</Link>
53+
<a className="link" href={`${Routes.BASEURL}/admin/core/announcement/add/`}>Announcements</a>
5454
</li>
5555
<li>
56-
<Link className="link" to="/admin/core/event/add/">Events</Link>
56+
<a className="link" href={`${Routes.BASEURL}/admin/core/event/add/`}>Events</a>
5757
</li>
5858
<hr />
5959
</div>
@@ -66,7 +66,7 @@ export const ProfileNav = (): JSX.Element => {
6666
</div>
6767
}
6868
<li>
69-
<Link className="link" to="/accounts/logout/">Logout</Link>
69+
<Link className="link" to="/account/logout/">Logout</Link>
7070
</li>
7171
</ul>
7272
</div>

src/components/account/profile/index.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ export const Profile = (props: { children?: JSX.Element }): JSX.Element => {
1717
<div className="container">
1818
<ul className="sidenav secondnav" id="secondary-out">
1919
<li>
20-
<Link className="sidenav-close" to="/accounts/profile">Profile</Link>
20+
<Link className="sidenav-close" to="/account/profile">Profile</Link>
2121
</li>
2222
<li>
2323
<Link className="sidenav-close" to="/timetable">Timetable</Link>
@@ -31,7 +31,7 @@ export const Profile = (props: { children?: JSX.Element }): JSX.Element => {
3131
</li>
3232
<li className="divider"></li>
3333
<li>
34-
<Link to="/accounts/logout/" className="sidenav-close">Logout</Link>
34+
<Link to="/account/logout/" className="sidenav-close">Logout</Link>
3535
</li>
3636
</ul>
3737

src/components/account/profile/view/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ export const ProfileView = (): JSX.Element => {
7373
session.user.id === user.id &&
7474
<div className="edit-button">
7575
<i className="zmdi zmdi-fw-3x zmdi-edit"></i>
76-
<Link to="/accounts/profile/update">Edit</Link>
76+
<Link to="/account/profile/update">Edit</Link>
7777
</div>
7878
}
7979
</div>

src/components/account/timetable/edit/index.tsx

Lines changed: 76 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -2,48 +2,79 @@ import { Autocomplete, TextField } from "@mui/material";
22
import * as React from "react";
33
import { Session, SessionContext } from "../../../../util/core/session";
44
import { Link, useNavigate, useParams } from "react-router-dom";
5-
import { Course, Timetable } from "../../../../util/core/interfaces/timetable";
5+
import { Course, Timetable, Term } from "../../../../util/core/interfaces/timetable";
66
import Routes from "../../../../util/core/misc/routes";
7+
import "../../../../../public/resources/static/css/timetable/main.css";
78

89
export const TimetableEdit = (): JSX.Element => {
910
const session: Session = React.useContext(SessionContext);
1011
const nav = useNavigate();
1112

12-
const { ID } = useParams();
13-
14-
const [allCourses, setAllCourses] = React.useState<Array<Course>>([]);
15-
const [selectedCourses, setSelectedCourses] = React.useState<Array<Course>>([]);
16-
17-
const [timetable, setTimetable] = React.useState({} as Timetable);
13+
const [timetable, setTimetable] = React.useState<Timetable | undefined>(undefined);
14+
const [term, setTerm] = React.useState<Term | undefined>(undefined);
1815

1916
const fetchTimetable = (): void => {
2017
session.request('get', Routes.PERSONAL_TIMETABLE).then((res) => {
2118
setTimetable(res.data);
22-
// console.log(res.data[1]);
19+
session.request('get', `${Routes.OBJECT}/term?id=${res.data.term.id}`).then((res) => {
20+
setTerm(res.data.results[0]);
21+
})
2322
});
2423
}
2524

2625
React.useEffect(() => {
2726
fetchTimetable();
2827
}, []);
2928

29+
const submitForm = (selectedCourses: Array<Course>): void => {
30+
if(timetable){
31+
session.request('put', `${Routes.TIMETABLE}/single/${timetable.id}`, {
32+
term: timetable.term.id,
33+
courses: selectedCourses.map((course: Course): number => {
34+
return course.id
35+
}),
36+
owner: session.user.id
37+
}).then(() => {
38+
session.notify("Successfully updated courses!", "success");
39+
nav(`/timetable`)
40+
});
41+
}
42+
}
43+
44+
return timetable && term ? <TimetableEditor term={term} submitForm={submitForm} defaultCourses={timetable.courses} /> : <></>
45+
}
46+
47+
export const TimetableAdd = (): JSX.Element => {
48+
const session: Session = React.useContext(SessionContext);
49+
const { ID } = useParams();
50+
const [term, setTerm] = React.useState<Term | undefined>(undefined);
51+
3052
React.useEffect(() => {
31-
session.request('get', `${Routes.COURSE}?term=${ID}`).then((res) => {
32-
setAllCourses(res.data.results);
33-
});
34-
}, []);
53+
session.request('get', `${Routes.OBJECT}/term?id=${ID}`).then((res) => {
54+
if(res.status === 200){
55+
if(res.data.results?.length > 0){
56+
setTerm(res.data.results[0])
57+
}
58+
}
59+
})
60+
}, [])
3561

36-
const submitForm = (): void => {
37-
session.request('put', `${Routes.TIMETABLE}/single/${timetable.id}`, {
38-
term: timetable.term.id,
39-
courses: selectedCourses.map((course: Course): number => {
40-
return course.id
41-
})
42-
}).then(() => {
43-
session.notify("Successfully updated courses!", "success");
44-
nav(`/timetable`)
45-
});
46-
}
62+
return term ? <TimetableEditor term={term} submitForm={(courses: Array<Course>) => {
63+
session.request('post', `${Routes.OBJECT}/timetable/new`, {
64+
term: term.id,
65+
courses: courses.map(i => i.id),
66+
owner: session.user.id
67+
})
68+
}} defaultCourses={[]}></TimetableEditor> : <></>
69+
}
70+
71+
const TimetableEditor = (params: {
72+
term: Term, submitForm: (course: Array<Course>) => void, defaultCourses: Array<Course>
73+
}): JSX.Element => {
74+
const term = params.term;
75+
76+
const allCourses = term.courses;
77+
const [selectedCourses, setSelectedCourses] = React.useState<Array<Course>>(params.defaultCourses);
4778

4879
return (
4980
<>
@@ -52,39 +83,35 @@ export const TimetableEdit = (): JSX.Element => {
5283
<div className="card-body" data-select2-id="select2-data-21-vyjo">
5384
<form onSubmit={(ev) => {
5485
ev.preventDefault();
55-
submitForm();
86+
params.submitForm(selectedCourses);
5687
}} data-select2-id="select2-data-20-cr8n">
57-
<h5 className="card-title"><strong>Edit timetable for Test term</strong></h5>
88+
<h5 className="card-title"><strong>Edit timetable for {term.name}</strong></h5>
5889
<input type="hidden" name="csrfmiddlewaretoken" value="dUBPiwcYI3sSDgC52qu3o8cutarEiO1xML4iteigRLs9eEEA26us3LXlBdxidNAh" />
5990

6091
{/* <label htmlFor="id_courses">Courses:</label> */}
6192

62-
{
63-
timetable.courses ?
64-
<Autocomplete
65-
multiple
66-
onChange={(event, value) => {
67-
setSelectedCourses(value);
68-
}}
69-
id="tags-outlined"
70-
options={allCourses}
71-
getOptionLabel={(option: Course) => option.code}
72-
defaultValue={timetable.courses}
73-
filterSelectedOptions
74-
renderInput={(params) => (
75-
<TextField
76-
{...params}
77-
label="Courses"
78-
placeholder="Start typing course code..."
79-
/>
80-
)}
81-
sx={{ marginTop: "1.25em", marginBottom: "1.25em" }}
93+
<Autocomplete
94+
multiple
95+
onChange={(event, value) => {
96+
setSelectedCourses(value);
97+
}}
98+
id="tags-outlined"
99+
options={allCourses}
100+
getOptionLabel={(option: Course) => option.code}
101+
value={selectedCourses}
102+
filterSelectedOptions
103+
isOptionEqualToValue={(option, value) => option.id === value.id}
104+
renderInput={(params) => (
105+
<TextField
106+
{...params}
107+
label="Courses"
108+
placeholder="Start typing course code..."
82109
/>
83-
:
84-
<>Loading courses...</>
85-
}
110+
)}
111+
sx={{ marginTop: "1.25em", marginBottom: "1.25em" }}
112+
/>
86113

87-
<Link to={`/course/add/term/${timetable.term}?next=${encodeURIComponent(window.location.pathname)}`}>Add a missing course</Link><br />
114+
<Link to={`/course/add/term/${term.id}?next=${encodeURIComponent(window.location.pathname)}`}>Add a missing course</Link><br />
88115

89116
<div style={{ display: "flex", alignItems: "center", "gap": "3px", marginTop: "1.5em" }}>
90117
<button type="submit" className="btn btn-primary mr-2">Save</button>

src/components/account/timetable/edit/new-course/index.tsx

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,29 @@ import * as React from "react";
33
import { Link, NavigateFunction, useNavigate, useParams } from "react-router-dom";
44
import { Session, SessionContext } from "../../../../../util/core/session";
55
import Routes from "../../../../../util/core/misc/routes";
6+
import { Term } from "../../../../../util/core/interfaces/timetable";
67

78
export const NewCourse = (): JSX.Element => {
89
const session: Session = React.useContext(SessionContext);
910
const nav: NavigateFunction = useNavigate();
1011
const { ID } = useParams();
1112

1213
const [code, setCode] = React.useState("");
14+
const [term, setTerm] = React.useState<Term | undefined>(undefined);
1315
const [position, setPosition] = React.useState<number>(-1);
1416

17+
React.useEffect(() => {
18+
session.request('get', `${Routes.OBJECT}/term?id=${ID}`).then((res) => {
19+
if(res.status === 200){
20+
if(res.data.count === 1){
21+
setTerm(res.data.results[0]);
22+
} else {
23+
setTerm(undefined);
24+
}
25+
}
26+
})
27+
}, [])
28+
1529
const submitNewCourse = (): void => {
1630
session.request('post', `${Routes.COURSE}/new`, {
1731
code: code,
@@ -23,7 +37,7 @@ export const NewCourse = (): JSX.Element => {
2337
});
2438
}
2539

26-
return (
40+
return term ? (
2741
<>
2842
<link rel="stylesheet" href="/resources/static/css/secondary.css" />
2943
<link rel="stylesheet" href="/resources/static/css/timetable/main.css" />
@@ -32,7 +46,7 @@ export const NewCourse = (): JSX.Element => {
3246
ev.preventDefault();
3347
submitNewCourse();
3448
}}>
35-
<h6 className="card-subtitle mb-2 text-muted card-top">Add a course for Test term</h6>
49+
<h6 className="card-subtitle mb-2 text-muted card-top">Add a course for {term.name}</h6>
3650

3751
<label htmlFor="id_code" className="active">Code:</label>
3852

@@ -103,5 +117,5 @@ export const NewCourse = (): JSX.Element => {
103117
</div>
104118
</form>
105119
</>
106-
);
120+
) : <></>;
107121
}

src/components/account/timetable/index.tsx

Lines changed: 47 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { Box, FormControl, InputLabel, MenuItem, Select } from "@mui/material";
22
import * as React from "react";
33
import { Link, NavigateFunction, useNavigate } from "react-router-dom";
44
import { loggedIn } from "../../../util/core/AuthService";
5-
import { Course, Timetable } from "../../../util/core/interfaces/timetable";
5+
import { Course, Timetable, Term } from "../../../util/core/interfaces/timetable";
66
import Routes from "../../../util/core/misc/routes";
77
import { Session, SessionContext } from "../../../util/core/session";
88
import { ProfileNav } from "../left-nav";
@@ -66,27 +66,60 @@ const TimetableElement = (props: { timetable: Timetable }): JSX.Element => {
6666
export const TimetablePage = (): JSX.Element => {
6767
const nav: NavigateFunction = useNavigate();
6868
const [timetable, setTimetable] = React.useState({} as Timetable);
69+
const [noTimetable, setNoTimetable] = React.useState(false);
70+
const [term, setTerm] = React.useState({} as Term);
6971
const session: Session = React.useContext(SessionContext);
7072

7173
const fetchTimetable = (): void => {
7274
if (loggedIn()) {
7375
session.request('get', Routes.PERSONAL_TIMETABLE).then((res) => {
7476
setTimetable(res.data);
75-
// console.log(res.data[1]);
77+
setNoTimetable(false);
7678
}).catch((err) => {
77-
if (err.response.status === 404) {
79+
setNoTimetable(true);
80+
});
81+
}
82+
}
83+
84+
const dateInBetween = (start: string, current: Date, end: string): boolean => {
85+
return new Date(start) <= current && current <= new Date(end) ? true : false;
86+
}
87+
88+
const fetchTerm = (): void => {
89+
if(loggedIn()) {
90+
session.request('get', `${Routes.OBJECT}/term`).then((res) => {
91+
if(res.status === 200){
92+
if(res.data.results?.length > 0){
93+
const curTerm: Term = res.data.results[0];
94+
if(dateInBetween(curTerm.start_date, new Date(), curTerm.end_date)){
95+
setTerm(curTerm);
96+
}
97+
}
98+
}
99+
}).catch((err) => {
100+
if(err.status === 404){
78101
return;
79102
}
80103
session.refreshAuth();
81104
fetchTimetable();
82-
});
105+
})
83106
}
84107
}
85108

86109
React.useEffect(() => {
87110
fetchTimetable();
88111
}, []);
89112

113+
React.useEffect(() => {
114+
fetchTerm();
115+
}, [])
116+
117+
const createTimetable = (): void => {
118+
nav(`/timetable/add/${term.id}`);
119+
}
120+
121+
// console.log(term)
122+
// console.log(noTimetable)
90123
return (
91124
<>
92125
<link rel="stylesheet" href="/resources/static/css/timetable/list.css" />
@@ -105,23 +138,30 @@ export const TimetablePage = (): JSX.Element => {
105138
:
106139
<div className="timetable-add-container">
107140
<div className="card-body">
108-
<form onSubmit={(ev) => { ev.preventDefault(); console.log("Submitted"); }}>
141+
<form onSubmit={(ev) => { ev.preventDefault(); createTimetable(); }}>
109142
<h5 className="card-title">Add timetable</h5>
110143
<hr />
111144
<input type="hidden" name="csrfmiddlewaretoken" value="M5IY2bEzx9c5zEI25e3yzsF7XGycqazLGhT6fs8hrUw5fUunY4kgQZETZDpblGVm" />
112145

113146
<Box sx={{ minWidth: 120 }}>
114147
<FormControl fullWidth>
115148
<InputLabel id="demo-simple-select-label">Term</InputLabel>
149+
{term && noTimetable ? <Select
150+
labelId={term.name}
151+
id={"" + term.id}
152+
value={term.id}
153+
label="Term"
154+
>
155+
<MenuItem value={term.id}>{term.name}</MenuItem>
156+
</Select> :
116157
<Select
117158
labelId="demo-simple-select-label"
118159
id="demo-simple-select"
119160
value={0}
120161
label="Term"
121-
onChange={() => { }}
122162
>
123163
<MenuItem value={0}>---------</MenuItem>
124-
</Select>
164+
</Select>}
125165
</FormControl>
126166
</Box>
127167

0 commit comments

Comments
 (0)