Skip to content

Commit 4d9bc41

Browse files
Various Bug Fixes, Students can add themselves to a course (#59)
* Removed phone number and potentially fixed error * Hide error if authentication not caught up * Students can join courses * Display course id in students tab * Fix lint errors
1 parent a9398d1 commit 4d9bc41

File tree

8 files changed

+541
-277
lines changed

8 files changed

+541
-277
lines changed

package-lock.json

Lines changed: 280 additions & 254 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
"@aws-amplify/interactions": "^3.3.29",
99
"@aws-amplify/storage": "^3.3.29",
1010
"@aws-amplify/ui": "^2.0.2",
11-
"@aws-amplify/ui-react": "^1.0.6",
11+
"@aws-amplify/ui-react": "^1.2.7",
1212
"@emotion/styled": "^11.3.0",
1313
"@fortawesome/fontawesome-svg-core": "^1.2.35",
1414
"@fortawesome/free-solid-svg-icons": "^5.15.3",
@@ -23,7 +23,7 @@
2323
"@types/react": "^17.0.3",
2424
"@types/react-dom": "^17.0.3",
2525
"@typescript-eslint/eslint-plugin": "^4.20.0",
26-
"aws-amplify": "^3.3.26",
26+
"aws-amplify": "^3.4.3",
2727
"aws-amplify-react": "^4.2.30",
2828
"bootstrap": "^4.6.0",
2929
"clsx": "^1.1.1",

src/App/App.tsx

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,47 @@
11
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
2-
import { Auth, Hub } from 'aws-amplify';
32
import { useState, useEffect } from 'react';
43
import { withAuthenticator } from 'aws-amplify-react';
4+
import Amplify, { Auth, Hub } from 'aws-amplify';
5+
import { ApolloError } from '@apollo/client/errors';
6+
57
import Sidebar from '../Components/Sidebar';
68
import Content from '../Components/Content';
79
import Navigation from '../Navigation/Navigation';
810

911
import './App.scss';
1012
import { useGetCoursesQuery } from '../__generated__/types';
13+
import { environment } from '../environment';
14+
15+
Amplify.configure({
16+
Auth: {
17+
identityPoolId: 'us-east-1:07057d76-612a-4045-8522-f38a759cf216',
18+
region: 'us-east-1',
19+
userPoolId: 'us-east-1_POfbbYTKF',
20+
userPoolWebClientId: '24sdf1brebo58s89ja0b63c51d',
21+
oauth: {
22+
domain: 'flipted-ios-test.auth.us-east-1.amazoncognito.com',
23+
scope: ['phone', 'email', 'profile', 'openid', 'aws.cognito.signin.user.admin'],
24+
redirectSignIn: environment.redirectSignIn,
25+
redirectSignOut: environment.redirectSignout,
26+
responseType: 'token',
27+
},
28+
},
29+
});
1130

1231
// Entry point of the Flitped App
1332
function App() {
1433
const [, setUser] = useState(null);
1534
const [fname, setFirstName] = useState('');
16-
const { loading, error, data: courseData, refetch } = useGetCoursesQuery();
35+
36+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
37+
const handleError = (_error: ApolloError) => {
38+
// eslint-disable-next-line
39+
void refetch();
40+
};
41+
42+
const { loading, error, data: courseData, refetch } = useGetCoursesQuery({
43+
onError: handleError,
44+
});
1745

1846
function storeToken(): void {
1947
Auth.currentSession()
@@ -35,6 +63,7 @@ function App() {
3563
Hub.listen('auth', ({ payload: { event, data } }) => {
3664
switch (event) {
3765
case 'signIn':
66+
case 'oauthSignIn':
3867
case 'cognitoHostedUI':
3968
storeToken();
4069
break;
@@ -54,7 +83,9 @@ function App() {
5483
}, []);
5584

5685
if (loading) return <div>Loading...</div>;
57-
if (error) return <div>`Error! ${error.message}`</div>;
86+
if (error) {
87+
return <></>;
88+
}
5889
if (!courseData) {
5990
return <></>;
6091
}
@@ -78,4 +109,6 @@ function App() {
78109
);
79110
}
80111

81-
export default withAuthenticator(App);
112+
export default withAuthenticator(App, undefined, undefined, undefined, undefined, {
113+
hiddenDefaults: ['phone_number'],
114+
});

src/Components/Dashboard/Dashboard.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { CourseInfoFieldsFragment, Role } from '../../__generated__/types';
22
import CourseCard from './CourseCard';
33
import CreateCourseDialog from '../CreateCourseDialog/CreateCourseDialog';
44
import './DashBoard.css';
5+
import { JoinCourseDialog } from '../MarketHome/Student/JoinCourseDialog';
56

67
type Props = {
78
courses: CourseInfoFieldsFragment[];
@@ -12,7 +13,11 @@ type Props = {
1213
function Dashboard({ courses, refetchCourses, role }: Props) {
1314
return (
1415
<div>
15-
{role === Role.Instructor ? <CreateCourseDialog refetch={refetchCourses} /> : <></>}
16+
{role === Role.Instructor ? (
17+
<CreateCourseDialog refetch={refetchCourses} />
18+
) : (
19+
<JoinCourseDialog refetch={refetchCourses} />
20+
)}
1621
{courses.map((courseInfo: CourseInfoFieldsFragment) => (
1722
<CourseCard key={courseInfo.courseId} courseInfo={courseInfo} />
1823
))}
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
/* eslint-disable @typescript-eslint/restrict-template-expressions */
2+
/* eslint-disable no-nested-ternary */
3+
/* eslint-disable @typescript-eslint/no-unused-vars */
4+
/* eslint-disable @typescript-eslint/no-unsafe-return */
5+
import {
6+
IconButton,
7+
Dialog,
8+
DialogTitle,
9+
DialogContent,
10+
CircularProgress,
11+
Container,
12+
Button,
13+
} from '@material-ui/core';
14+
import { useState } from 'react';
15+
import PersonAddIcon from '@material-ui/icons/PersonAdd';
16+
import { ApolloError } from '@apollo/client';
17+
import { AddStudentMutation, useAddStudentMutation } from '../../../__generated__/types';
18+
import { JoinCourseFormInput, joinCourseFormToInputType, JoinCourseForm } from './JoinCourseForm';
19+
20+
type Props = {
21+
refetch: any;
22+
};
23+
24+
export function JoinCourseDialog({ refetch }: Props) {
25+
const [error, setError] = useState(false);
26+
const [open, setOpen] = useState(false);
27+
28+
const handleClose = () => {
29+
setError(false);
30+
setOpen(false);
31+
};
32+
33+
const handleError = (_error: ApolloError) => {
34+
setError(true);
35+
};
36+
37+
const onMutationCompleted = (data: AddStudentMutation) => {
38+
console.log('Mutation Completed');
39+
handleClose();
40+
refetch();
41+
};
42+
43+
const [addStudent, { loading: mutationLoading, error: mutationError }] = useAddStudentMutation({
44+
onError: handleError,
45+
onCompleted: onMutationCompleted,
46+
});
47+
48+
const initialValues: JoinCourseFormInput = {
49+
firstName: '',
50+
lastName: '',
51+
instructorId: '',
52+
courseId: '',
53+
};
54+
55+
const handleClickOpen = () => {
56+
setError(false);
57+
setOpen(true);
58+
console.log('Opening and clearing error');
59+
};
60+
61+
const handleSubmit = (values: JoinCourseFormInput) => {
62+
addStudent({
63+
variables: {
64+
student: joinCourseFormToInputType(values),
65+
},
66+
}).catch((e) => {
67+
console.log(e);
68+
});
69+
};
70+
return (
71+
<Container>
72+
<div>
73+
<Button
74+
style={{
75+
width: 200,
76+
marginTop: 20,
77+
marginLeft: 0,
78+
backgroundColor: '#4274F3',
79+
color: 'white',
80+
}}
81+
onClick={handleClickOpen}
82+
data-testid="create-btn"
83+
>
84+
Join Course
85+
</Button>
86+
<Dialog
87+
open={open}
88+
fullWidth
89+
onClose={handleClose}
90+
aria-labelledby="form-dialog-title"
91+
maxWidth="sm"
92+
data-testid="create-dialog"
93+
>
94+
<DialogTitle
95+
style={{ backgroundColor: '#4274F3', color: 'white' }}
96+
id="form-dialog-title"
97+
>
98+
Join Course
99+
</DialogTitle>
100+
<DialogContent>
101+
<JoinCourseForm initialValues={initialValues} onSubmit={handleSubmit} />
102+
</DialogContent>
103+
<div style={{ marginLeft: '4%' }}>
104+
{mutationLoading ? (
105+
<CircularProgress size={25} />
106+
) : error ? (
107+
<span style={{ color: 'red' }}>ERROR: Could not find ID combination. </span>
108+
) : (
109+
<></>
110+
)}
111+
</div>
112+
</Dialog>
113+
</div>
114+
</Container>
115+
);
116+
}
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
import { DialogActions } from '@material-ui/core';
2+
import { Button } from 'aws-amplify-react';
3+
import { Formik, Form } from 'formik';
4+
import { StudentInput } from '../../../__generated__/types';
5+
import { SmallTextField } from '../FieldStyles';
6+
7+
type Props = {
8+
initialValues: JoinCourseFormInput;
9+
onSubmit: (values: JoinCourseFormInput) => void;
10+
};
11+
12+
export type JoinCourseFormInput = {
13+
firstName: string;
14+
lastName: string;
15+
courseId: string;
16+
instructorId: string;
17+
};
18+
19+
export function joinCourseFormToInputType(input: JoinCourseFormInput): StudentInput {
20+
return {
21+
firstName: input.firstName,
22+
lastName: input.lastName,
23+
studentId: '',
24+
instructorId: input.instructorId,
25+
courseId: input.courseId,
26+
};
27+
}
28+
29+
export function JoinCourseForm({ initialValues, onSubmit }: Props) {
30+
return (
31+
<Formik
32+
initialValues={initialValues}
33+
onSubmit={(values, { setSubmitting }) => {
34+
setSubmitting(false);
35+
onSubmit(values);
36+
}}
37+
>
38+
{({ values, handleChange, handleBlur, handleSubmit, isSubmitting }) => (
39+
<Form onSubmit={handleSubmit}>
40+
<SmallTextField
41+
required
42+
id="courseId"
43+
label="Course ID"
44+
type="text"
45+
fullWidth
46+
variant="outlined"
47+
margin="dense"
48+
value={values.courseId}
49+
onChange={handleChange}
50+
onBlur={handleBlur}
51+
/>
52+
<SmallTextField
53+
required
54+
id="instructorId"
55+
label="Instructor ID"
56+
type="text"
57+
fullWidth
58+
variant="outlined"
59+
margin="dense"
60+
value={values.instructorId}
61+
onChange={handleChange}
62+
onBlur={handleBlur}
63+
/>
64+
65+
<SmallTextField
66+
required
67+
id="firstName"
68+
label="First Name"
69+
type="text"
70+
fullWidth
71+
variant="outlined"
72+
margin="dense"
73+
value={values.firstName}
74+
onChange={handleChange}
75+
onBlur={handleBlur}
76+
/>
77+
<SmallTextField
78+
required
79+
id="lastName"
80+
label="Last Name"
81+
type="text"
82+
fullWidth
83+
variant="outlined"
84+
margin="dense"
85+
value={values.lastName}
86+
onChange={handleChange}
87+
onBlur={handleBlur}
88+
/>
89+
<DialogActions>
90+
<Button type="submit" disabled={isSubmitting} color="primary">
91+
Add
92+
</Button>
93+
</DialogActions>
94+
</Form>
95+
)}
96+
</Formik>
97+
);
98+
}

src/Components/MarketHome/StudentsTab.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,8 @@ export function StudentsTab() {
106106
<div className="table">
107107
<TableComponent columns={columns} data={rowData} rowClickFunction={rowClicked} />
108108
</div>
109+
<p>Course ID: {classId}</p>
110+
109111
<AddStudentDialog course={classId} refetch={refetch} />
110112
</div>
111113
);

src/index.tsx

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,29 +3,13 @@ import ReactDOM from 'react-dom';
33
import './index.css';
44
import { BrowserRouter as Router } from 'react-router-dom';
55
import { ApolloProvider } from '@apollo/client';
6-
import Amplify from 'aws-amplify';
76
import App from './App';
87
import reportWebVitals from './reportWebVitals';
98
import apolloClient from './clients/apollo-client';
109
import '@aws-amplify/ui/dist/style.css';
1110
import { environment } from './environment';
1211

1312
console.log(environment);
14-
Amplify.configure({
15-
Auth: {
16-
identityPoolId: 'us-east-1:07057d76-612a-4045-8522-f38a759cf216',
17-
region: 'us-east-1',
18-
userPoolId: 'us-east-1_POfbbYTKF',
19-
userPoolWebClientId: '24sdf1brebo58s89ja0b63c51d',
20-
oauth: {
21-
domain: 'flipted-ios-test.auth.us-east-1.amazoncognito.com',
22-
scope: ['phone', 'email', 'profile', 'openid', 'aws.cognito.signin.user.admin'],
23-
redirectSignIn: environment.redirectSignIn,
24-
redirectSignOut: environment.redirectSignout,
25-
responseType: 'token',
26-
},
27-
},
28-
});
2913

3014
ReactDOM.render(
3115
<React.StrictMode>

0 commit comments

Comments
 (0)