Skip to content
This repository was archived by the owner on Jun 1, 2022. It is now read-only.

Commit 0f41431

Browse files
mojo9492gorhack
authored andcommitted
Add UserContext
Fix EventDetails formatting
1 parent c964133 commit 0f41431

10 files changed

Lines changed: 123 additions & 78 deletions

File tree

client/src/App.tsx

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -10,28 +10,31 @@ import { PrimaryNavigation } from "./Navigation/PrimaryNavigation";
1010
import { Footer } from "./Navigation/Footer";
1111
import { About } from "./About";
1212
import { UserSettings } from "./Users/UserSettings";
13+
import { UserContextProvider } from "./Users/UserContext";
1314

1415
const App: React.FC = () => {
1516
return (
1617
<StompSocketProvider>
17-
<BrowserRouter>
18-
<div className="App">
19-
<div className="App-Container">
20-
<PrimaryNavigation />
21-
<main className="App-Content">
22-
<Switch>
23-
<Route path="/createEvent" component={CreateEvent} />
24-
<Route path="/editEvent/:eventId" component={CreateEvent} />
25-
<Route path="/event/:eventId" component={EventPage} />
26-
<Route path="/about" component={About} />
27-
<Route path="/settings" component={UserSettings} />
28-
<Route path="/" component={Home} />
29-
</Switch>
30-
</main>
31-
<Footer />
18+
<UserContextProvider>
19+
<BrowserRouter>
20+
<div className="App">
21+
<div className="App-Container">
22+
<PrimaryNavigation />
23+
<main className="App-Content">
24+
<Switch>
25+
<Route path="/createEvent" component={CreateEvent} />
26+
<Route path="/editEvent/:eventId" component={CreateEvent} />
27+
<Route path="/event/:eventId" component={EventPage} />
28+
<Route path="/about" component={About} />
29+
<Route path="/settings" component={UserSettings} />
30+
<Route path="/" component={Home} />
31+
</Switch>
32+
</main>
33+
<Footer />
34+
</div>
3235
</div>
33-
</div>
34-
</BrowserRouter>
36+
</BrowserRouter>
37+
</UserContextProvider>
3538
</StompSocketProvider>
3639
);
3740
};

client/src/Home.tsx

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useEffect, useState } from "react";
1+
import React, { useContext, useEffect } from "react";
22
import { useHistory } from "react-router-dom";
33
import { EventsSection } from "./Event/EventsSection";
44
import { useStompSocketContext } from "./StompSocketContext";
@@ -7,29 +7,28 @@ import { IMessage } from "@stomp/stompjs";
77
import { SocketSubscriptionTopics, TsrEvent } from "./Event/EventApi";
88
import { PrimaryButton } from "./Buttons/Buttons";
99
import "./Home.css";
10-
import { emptyTsrUser, getUserInfo, TsrUser } from "./Users/UserApi";
10+
import UserContext from "./Users/UserContext";
1111

1212
export const Home: React.FC = () => {
1313
const { socketService } = useStompSocketContext();
14-
const [tsrUser, setTsrUser] = useState<TsrUser>(emptyTsrUser);
14+
const tsrUser = useContext(UserContext);
1515
const history = useHistory();
1616

1717
useEffect(() => {
18-
(async () => {
19-
await getUserInfo()
20-
.then((result) => {
21-
setTsrUser(result);
22-
})
23-
.catch((error) => {
24-
console.error(`unable to get current user ${error.message}`);
25-
});
26-
})();
27-
}, [setTsrUser]);
18+
if (tsrUser === undefined) {
19+
return;
20+
}
21+
}, [tsrUser]);
2822

2923
useEffect(() => {
24+
if (tsrUser === undefined) {
25+
return;
26+
}
27+
3028
if (socketService.status !== SocketStatus.CONNECTED || tsrUser.userId.length === 0) {
3129
return;
3230
}
31+
3332
tsrUser.settings.organizations.forEach((org) => {
3433
socketService.subscribe({
3534
topic: `${SocketSubscriptionTopics.EVENT_CREATED}${org.organizationId}`,
@@ -59,6 +58,10 @@ export const Home: React.FC = () => {
5958
};
6059
}, [socketService, tsrUser]);
6160

61+
if (tsrUser === undefined) {
62+
return <></>;
63+
}
64+
6265
return (
6366
<>
6467
<div className="Home-Header flex-row-wrap">

client/src/Navigation/PrimaryNavigation.tsx

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import React, { ReactElement, ReactFragment, useEffect, useState } from "react";
2-
import { emptyTsrUser, getUserInfo, TsrUser } from "../Users/UserApi";
1+
import React, { ReactElement, ReactFragment, useContext, useEffect } from "react";
32
import "./PrimaryNavigation.css";
43
import { DrawerMenu } from "./DrawerMenu";
54
import TrackedName from "../Icons/TrackedName.svg";
5+
import UserContext from "../Users/UserContext";
66

77
interface PrimaryNavigationProps {
88
children?: ReactFragment;
@@ -11,19 +11,17 @@ interface PrimaryNavigationProps {
1111
export const PrimaryNavigation: React.FC<PrimaryNavigationProps> = ({
1212
children,
1313
}: PrimaryNavigationProps): ReactElement => {
14-
const [tsrUser, setTsrUser] = useState<TsrUser>(emptyTsrUser);
14+
const tsrUser = useContext(UserContext);
1515

1616
useEffect(() => {
17-
(async () => {
18-
await getUserInfo()
19-
.then((result) => {
20-
setTsrUser(result);
21-
})
22-
.catch((error) => {
23-
console.error(`unable to get user info ${error.message}`);
24-
});
25-
})();
26-
}, [setTsrUser]);
17+
if (tsrUser === undefined) {
18+
return;
19+
}
20+
}, [tsrUser]);
21+
22+
if (tsrUser === undefined) {
23+
return <></>;
24+
}
2725

2826
return (
2927
<nav className="PrimaryNavigation">

client/src/Users/UserApi.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ export interface TsrUserSettings {
3232
}
3333

3434
export type UserRole = "ADMIN" | "USER";
35-
3635
export interface TsrUser {
3736
userId: string;
3837
username: string;

client/src/Users/UserContext.tsx

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import React, { useEffect, useState } from "react";
2+
import { getUserInfo, TsrUser } from "./UserApi";
3+
4+
const UserContext = React.createContext<TsrUser | undefined>(undefined);
5+
6+
export const UserContextProvider: React.FC = (props) => {
7+
const [user, setUser] = useState<TsrUser | undefined>(undefined);
8+
9+
useEffect(() => {
10+
(async () => {
11+
await getUserInfo()
12+
.then((result) => {
13+
setUser(result);
14+
})
15+
.catch((error) => {
16+
console.error(`unable to get current user ${error.message}`);
17+
});
18+
})();
19+
}, [setUser]);
20+
21+
return <UserContext.Provider value={user}>{props.children}</UserContext.Provider>;
22+
};
23+
24+
export default UserContext;

client/src/Users/UserSettings.tsx

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
1-
import React, { ReactElement, useCallback, useEffect, useReducer, useState } from "react";
2-
import { emptyTsrUser, getUserInfo, setUserSettings, TsrUser, TsrUserSettings } from "./UserApi";
1+
import React, {
2+
ReactElement,
3+
useCallback,
4+
useContext,
5+
useEffect,
6+
useReducer,
7+
useState,
8+
} from "react";
9+
import { setUserSettings, TsrUserSettings } from "./UserApi";
310
import { Option } from "../api";
411
import { FieldValues, SubmitHandler, useForm } from "react-hook-form";
512
import {
@@ -14,6 +21,7 @@ import "./UserSettings.css";
1421
import { LabeledInput } from "../Inputs/LabeledInput";
1522
import sortedUniqBy from "lodash/sortedUniqBy";
1623
import { useHistory } from "react-router-dom";
24+
import UserContext from "./UserContext";
1725

1826
interface FormData extends FieldValues {
1927
email: string;
@@ -23,6 +31,7 @@ interface FormData extends FieldValues {
2331

2432
export const UserSettings: React.FC = (): ReactElement => {
2533
const history = useHistory();
34+
const tsrUser = useContext(UserContext);
2635

2736
const orgCacheReducer = (state: Organization[], action: OrgCacheReducerAction) => {
2837
if (action.type === OrganizationActionTypes.LOAD) {
@@ -36,7 +45,6 @@ export const UserSettings: React.FC = (): ReactElement => {
3645
};
3746
const [organizationsCache, organizationCacheDispatch] = useReducer(orgCacheReducer, []);
3847

39-
const [user, setUser] = useState<TsrUser>(emptyTsrUser);
4048
const [orgValues, setOrgValues] = useState<Option[]>([]);
4149
const {
4250
control,
@@ -70,21 +78,19 @@ export const UserSettings: React.FC = (): ReactElement => {
7078
);
7179

7280
useEffect((): void => {
73-
(async () => {
74-
await getUserInfo()
75-
.then((result) => {
76-
setUser(result);
77-
organizationCacheDispatch({
78-
type: OrganizationActionTypes.LOAD,
79-
organizations: result.settings.organizations,
80-
});
81-
setFormValues(result.settings);
82-
})
83-
.catch((error) => {
84-
console.error(`unable to get current user ${error.message}`);
85-
});
86-
})();
87-
}, [setUser, setFormValues]);
81+
if (tsrUser === undefined) {
82+
return;
83+
}
84+
organizationCacheDispatch({
85+
type: OrganizationActionTypes.LOAD,
86+
organizations: tsrUser.settings.organizations,
87+
});
88+
setFormValues(tsrUser.settings);
89+
}, [tsrUser, setFormValues]);
90+
91+
if (tsrUser === undefined) {
92+
return <></>;
93+
}
8894

8995
const onSubmit: SubmitHandler<FormData> = async (data): Promise<void> => {
9096
const { phone, email } = data;
@@ -116,13 +122,13 @@ export const UserSettings: React.FC = (): ReactElement => {
116122
};
117123
const onCancel = (e: React.MouseEvent<HTMLButtonElement>): void => {
118124
e.preventDefault();
119-
setFormValues(user.settings);
125+
setFormValues(tsrUser.settings);
120126
};
121127

122128
return (
123129
<>
124130
<LinkButton onClick={() => history.push("/")}>{"< back to events"}</LinkButton>
125-
<h1 className="UserSettings-Header">{`${user.username} settings`}</h1>
131+
<h1 className="UserSettings-Header">{`${tsrUser.username} settings`}</h1>
126132
<div className="UserSettings-Content">
127133
<form
128134
className="Form-Content"

client/src/__tests__/Home.test.tsx

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import { TsrUser } from "../Users/UserApi";
1818
import { PageDTO } from "../api";
1919
import { StompSocketProvider } from "../StompSocketContext";
2020
import { SocketService } from "../SocketService";
21+
import { UserContextProvider } from "../Users/UserContext";
2122

2223
describe("home page of the application", () => {
2324
let mockGetActiveEventsByUserId: typeof EventApi.getActiveEventsByUserId;
@@ -152,11 +153,13 @@ describe("home page of the application", () => {
152153

153154
const result = render(
154155
<StompSocketProvider {...socketProps}>
155-
<Router history={history}>
156-
<Route path="/">
157-
<Home />
158-
</Route>
159-
</Router>
156+
<UserContextProvider>
157+
<Router history={history}>
158+
<Route path="/">
159+
<Home />
160+
</Route>
161+
</Router>
162+
</UserContextProvider>
160163
</StompSocketProvider>,
161164
);
162165
await act(async () => {

client/src/__tests__/Navigation/DrawerMenu.test.tsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { DrawerMenu } from "../../Navigation/DrawerMenu";
55
import { findByAriaLabel } from "../TestHelpers";
66
import { createMemoryHistory, MemoryHistory } from "history";
77
import { Router } from "react-router";
8+
import { UserContextProvider } from "../../Users/UserContext";
89

910
describe("Drawer menu", () => {
1011
const CLOSE_MENU_BUTTON_NAME = "open menu";
@@ -79,9 +80,11 @@ describe("Drawer menu", () => {
7980
history.push("/somewhere");
8081

8182
return render(
82-
<Router history={history}>
83-
<DrawerMenu />
84-
</Router>,
83+
<UserContextProvider>
84+
<Router history={history}>
85+
<DrawerMenu />
86+
</Router>
87+
</UserContextProvider>,
8588
);
8689
};
8790
});

client/src/__tests__/Navigation/PrimaryNavigation.test.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import * as UserApi from "../../Users/UserApi";
44
import { act, render, RenderResult, screen } from "@testing-library/react";
55
import { MemoryRouter } from "react-router";
66
import { PrimaryNavigation } from "../../Navigation/PrimaryNavigation";
7+
import { UserContextProvider } from "../../Users/UserContext";
78

89
describe("Primary nav", () => {
910
let mockGetUserInfo: typeof UserApi.getUserInfo;
@@ -29,7 +30,9 @@ describe("Primary nav", () => {
2930
const renderPrimaryNavigation = async (): Promise<RenderResult> => {
3031
return render(
3132
<MemoryRouter>
32-
<PrimaryNavigation />
33+
<UserContextProvider>
34+
<PrimaryNavigation />
35+
</UserContextProvider>
3336
</MemoryRouter>,
3437
);
3538
};

client/src/__tests__/Users/UserSettings.test.tsx

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import selectEvent from "react-select-event";
1919
import { fireEvent } from "@testing-library/dom";
2020
import { createMemoryHistory, MemoryHistory } from "history";
2121
import { Route, Router } from "react-router";
22+
import { UserContextProvider } from "../../Users/UserContext";
2223

2324
const EMAIL_ADDRESS = "test@example.com";
2425
const PHONE_NUMBER_LABEL = "phone number";
@@ -273,11 +274,13 @@ describe("User settings", () => {
273274
td.when(mockGetUserInfo()).thenDo(() => Promise.resolve(userPromise));
274275
td.when(mockGetOrganizationContains("")).thenDo(() => Promise.resolve(organizationPromise));
275276
const result = render(
276-
<Router history={history}>
277-
<Route path={"/settings"}>
278-
<UserSettings />
279-
</Route>
280-
</Router>,
277+
<UserContextProvider>
278+
<Router history={history}>
279+
<Route path={"/settings"}>
280+
<UserSettings />
281+
</Route>
282+
</Router>
283+
</UserContextProvider>,
281284
);
282285

283286
await act(async () => {

0 commit comments

Comments
 (0)