aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEugene Sokolov <eug-vs@keemail.me>2020-06-30 01:47:27 +0300
committerGitHub <noreply@github.com>2020-06-30 01:47:27 +0300
commit720a32c4cb1697f3a8f90973f28c334551ab87ff (patch)
treec9028ea3ff850774d33cbc510eb19dd0e9f7aade /src
parentb301bf24c5037403a1e5fc32fc8c10794941b528 (diff)
parente170d04d5d2c8c86d2683f3accb4feb2d94c881a (diff)
downloadwhich-ui-720a32c4cb1697f3a8f90973f28c334551ab87ff.tar.gz
Merge pull request #54 from which-ecosystem/hooks
Use hooks logic
Diffstat (limited to 'src')
-rw-r--r--src/components/Feed/Feed.tsx5
-rw-r--r--src/components/Header/Header.tsx20
-rw-r--r--src/components/Header/SearchBar.tsx9
-rw-r--r--src/components/PollCard/PollCard.tsx5
-rw-r--r--src/components/UserStrip/UserStrip.tsx16
-rw-r--r--src/hooks/useAuth.tsx77
-rw-r--r--src/hooks/useNavigate.tsx41
-rw-r--r--src/index.tsx106
-rw-r--r--src/pages/AuthPage/AuthPage.tsx11
-rw-r--r--src/pages/AuthPage/SignInForm.tsx15
-rw-r--r--src/pages/AuthPage/SignUpForm.tsx15
-rw-r--r--src/pages/FeedPage/FeedPage.tsx15
-rw-r--r--src/pages/FeedPage/PollSubmission.tsx11
-rw-r--r--src/pages/FeedPage/PollSubmissionImage.tsx2
-rw-r--r--src/pages/Page.tsx31
-rw-r--r--src/pages/ProfilePage/MoreMenu.tsx18
-rw-r--r--src/pages/ProfilePage/ProfileInfo.tsx24
-rw-r--r--src/pages/ProfilePage/ProfilePage.tsx52
-rw-r--r--src/types.d.ts4
19 files changed, 266 insertions, 211 deletions
diff --git a/src/components/Feed/Feed.tsx b/src/components/Feed/Feed.tsx
index 0c4d84f..7636573 100644
--- a/src/components/Feed/Feed.tsx
+++ b/src/components/Feed/Feed.tsx
@@ -5,7 +5,6 @@ import PollCard from '../PollCard/PollCard';
interface PropTypes {
polls: Poll[];
- navigate: (prefix: string, id: string) => void;
}
const useStyles = makeStyles(theme => ({
@@ -16,11 +15,11 @@ const useStyles = makeStyles(theme => ({
}
}));
-const Feed: React.FC<PropTypes> = ({ polls, navigate }) => {
+const Feed: React.FC<PropTypes> = ({ polls }) => {
const classes = useStyles();
return (
<div className={classes.root}>
- {polls.map(poll => <PollCard initialPoll={poll} key={poll._id} navigate={navigate} />)}
+ {polls.map(poll => <PollCard initialPoll={poll} key={poll._id} />)}
</div>
);
};
diff --git a/src/components/Header/Header.tsx b/src/components/Header/Header.tsx
index d0d9081..72e40f8 100644
--- a/src/components/Header/Header.tsx
+++ b/src/components/Header/Header.tsx
@@ -9,14 +9,11 @@ import { makeStyles } from '@material-ui/core/styles';
import AccountCircle from '@material-ui/icons/AccountCircle';
import NotificationsIcon from '@material-ui/icons/Notifications';
import HomeIcon from '@material-ui/icons/Home';
+import { useAuth } from '../../hooks/useAuth';
+import { useNavigate } from '../../hooks/useNavigate';
import SearchBar from './SearchBar';
-interface PropTypes {
- userImage: string | undefined;
- navigate: (prefix: string) => void;
-}
-
const useStyles = makeStyles({
root: {
display: 'flex',
@@ -33,15 +30,18 @@ const useStyles = makeStyles({
}
});
-const Header: React.FC<PropTypes> = ({ navigate, userImage }) => {
+const Header: React.FC = () => {
const classes = useStyles();
+ const { user } = useAuth();
+ const { navigate } = useNavigate();
const handleHome = (): void => {
navigate('feed');
};
const handleProfile = (): void => {
- navigate('profile');
+ if (user) navigate('profile');
+ else navigate('auth');
};
const handleNotifications = (): void => {};
@@ -52,7 +52,7 @@ const Header: React.FC<PropTypes> = ({ navigate, userImage }) => {
<Typography variant="h5" className={classes.logo}>
Which
</Typography>
- <SearchBar navigate={navigate} />
+ <SearchBar />
<div>
<IconButton onClick={handleHome}>
<HomeIcon />
@@ -62,8 +62,8 @@ const Header: React.FC<PropTypes> = ({ navigate, userImage }) => {
</IconButton>
<IconButton onClick={handleProfile}>
{
- userImage?.match(/\.(jpeg|jpg|gif|png)$/)
- ? <Avatar className={classes.avatar} src={userImage} />
+ user?.avatarUrl?.match(/\.(jpeg|jpg|gif|png)$/)
+ ? <Avatar className={classes.avatar} src={user?.avatarUrl} />
: <AccountCircle />
}
</IconButton>
diff --git a/src/components/Header/SearchBar.tsx b/src/components/Header/SearchBar.tsx
index bff16a0..253e77f 100644
--- a/src/components/Header/SearchBar.tsx
+++ b/src/components/Header/SearchBar.tsx
@@ -12,10 +12,8 @@ import { makeStyles } from '@material-ui/core/styles';
import { User } from 'which-types';
import { get } from '../../requests';
import UserStrip from '../UserStrip/UserStrip';
+import { useNavigate } from '../../hooks/useNavigate';
-interface PropTypes {
- navigate: (prefix: string, id: string) => void;
-}
const INTERVAL = 300;
const LIMIT = 7;
@@ -36,10 +34,11 @@ const useStyles = makeStyles(theme => ({
}
}));
-const SearchBar: React.FC<PropTypes> = ({ navigate }) => {
+const SearchBar: React.FC = () => {
const [results, setResults] = useState<User[]>([]);
const [query, setQuery] = useState<string>('');
const [debouncedQuery, setDebouncedQuery] = useState<string>(query);
+ const { navigate } = useNavigate();
const classes = useStyles();
useEffect(() => {
@@ -79,7 +78,7 @@ const SearchBar: React.FC<PropTypes> = ({ navigate }) => {
results.map((result, index) => (
<div key={result._id}>
<ListItem button onClick={handleNavigate(index)}>
- <UserStrip user={result} navigate={navigate} />
+ <UserStrip user={result} />
</ListItem>
{(index < results.length - 1) && <Divider />}
</div>
diff --git a/src/components/PollCard/PollCard.tsx b/src/components/PollCard/PollCard.tsx
index 156315a..2a23522 100644
--- a/src/components/PollCard/PollCard.tsx
+++ b/src/components/PollCard/PollCard.tsx
@@ -13,7 +13,6 @@ import { post } from '../../requests';
interface PropTypes {
initialPoll: Poll;
- navigate: (prefix: string, id: string) => void;
}
const DATE_FORMAT = {
@@ -54,7 +53,7 @@ const useStyles = makeStyles(theme => ({
}
}));
-const PollCard: React.FC<PropTypes> = ({ initialPoll, navigate }) => {
+const PollCard: React.FC<PropTypes> = ({ initialPoll }) => {
const [poll, setPoll] = useState<Poll>(initialPoll);
const classes = useStyles();
const { author, contents: { left, right }, vote } = poll;
@@ -87,7 +86,7 @@ const PollCard: React.FC<PropTypes> = ({ initialPoll, navigate }) => {
return (
<Card className={classes.root}>
- <UserStrip user={author} info={date} navigate={navigate} />
+ <UserStrip user={author} info={date} />
<div className={classes.imagesBlock}>
<CardActionArea onDoubleClick={handleLeft}>
<CardMedia
diff --git a/src/components/UserStrip/UserStrip.tsx b/src/components/UserStrip/UserStrip.tsx
index f02adc3..3ac47b3 100644
--- a/src/components/UserStrip/UserStrip.tsx
+++ b/src/components/UserStrip/UserStrip.tsx
@@ -1,16 +1,13 @@
import React from 'react';
import { makeStyles } from '@material-ui/core/styles';
import VerifiedIcon from '@material-ui/icons/CheckCircleOutline';
-import {
- Avatar,
- CardHeader
-} from '@material-ui/core/';
+import { Avatar, CardHeader } from '@material-ui/core/';
import { User } from 'which-types';
+import { useNavigate } from '../../hooks/useNavigate';
interface PropTypes {
user: User;
- navigate: (prefix: string, id: string) => void;
info?: string | JSX.Element
}
@@ -31,13 +28,10 @@ const useStyles = makeStyles(theme => ({
}));
-const UserStrip: React.FC<PropTypes> = ({ user, info, navigate }) => {
+const UserStrip: React.FC<PropTypes> = ({ user, info }) => {
const classes = useStyles();
- const {
- username,
- avatarUrl,
- verified
- } = user;
+ const { navigate } = useNavigate();
+ const { username, avatarUrl, verified } = user;
const handleNavigate = () => {
navigate('profile', user._id);
diff --git a/src/hooks/useAuth.tsx b/src/hooks/useAuth.tsx
new file mode 100644
index 0000000..55e142c
--- /dev/null
+++ b/src/hooks/useAuth.tsx
@@ -0,0 +1,77 @@
+import React, {
+ useState, useEffect, useContext, createContext
+} from 'react';
+import { User } from 'which-types';
+import { post, get } from '../requests';
+
+
+interface ContextType {
+ user: User | null,
+ setUser: (user: User) => void;
+ login: (username: string, password: string, remember?: boolean) => Promise<boolean>;
+ logout: () => void;
+ isAuthenticated: () => boolean;
+}
+
+const authContext = createContext<ContextType>({
+ user: null,
+ setUser: () => {},
+ login: async () => false,
+ logout: () => {},
+ isAuthenticated: () => false
+});
+
+const useProvideAuth = () => {
+ const [user, setUser] = useState<User | null>(null);
+
+ const login: ContextType['login'] = (username, password, remember = true) => {
+ return post('/authentication', {
+ strategy: 'local',
+ username,
+ password
+ }).then(response => {
+ const me = response.data.user;
+ const token = response.data.accessToken;
+ setUser(me);
+ localStorage.setItem('userId', me._id);
+ localStorage.setItem('token', token);
+ if (!remember) localStorage.setItem('shouldClear', 'true');
+ return true;
+ }).catch(() => false);
+ };
+
+ const logout = () => {
+ setUser(null);
+ localStorage.removeItem('userId');
+ localStorage.removeItem('token');
+ };
+
+ const isAuthenticated = () => Boolean(user);
+
+ useEffect(() => {
+ if (localStorage.getItem('shouldClear')) {
+ localStorage.clear();
+ }
+ const userId = localStorage.getItem('userId');
+ if (userId) {
+ get(`/users/${userId}`).then(response => {
+ setUser(response.data);
+ });
+ }
+ }, []);
+
+ return {
+ user, setUser, login, logout, isAuthenticated
+ };
+};
+
+export const AuthProvider: React.FC = ({ children }) => {
+ const auth = useProvideAuth();
+ const { Provider } = authContext;
+ return <Provider value={auth}>{children}</Provider>;
+};
+
+export const useAuth = (): ContextType => {
+ return useContext(authContext);
+};
+
diff --git a/src/hooks/useNavigate.tsx b/src/hooks/useNavigate.tsx
new file mode 100644
index 0000000..befc529
--- /dev/null
+++ b/src/hooks/useNavigate.tsx
@@ -0,0 +1,41 @@
+import React, { useState, useContext, createContext } from 'react';
+
+export interface Page {
+ prefix: string;
+ id?: string;
+}
+
+interface ContextType {
+ page: Page;
+ setPage: (page: Page) => void;
+ navigate: (prefix: string, id?: string) => void;
+}
+
+const landingPage = { prefix: 'feed' };
+
+const context = createContext<ContextType>({
+ page: landingPage,
+ setPage: () => {},
+ navigate: () => {}
+});
+
+const useProvideNavigation = () => {
+ const [page, setPage] = useState<Page>(landingPage);
+
+ const navigate: ContextType['navigate'] = (prefix, id?) => {
+ setPage({ prefix, id });
+ };
+
+ return { page, setPage, navigate };
+};
+
+export const NavigationProvider: React.FC = ({ children }) => {
+ const navigation = useProvideNavigation();
+ const { Provider } = context;
+ return <Provider value={navigation}>{children}</Provider>;
+};
+
+export const useNavigate = (): ContextType => {
+ return useContext(context);
+};
+
diff --git a/src/index.tsx b/src/index.tsx
index 02f7969..180f80c 100644
--- a/src/index.tsx
+++ b/src/index.tsx
@@ -1,22 +1,15 @@
-import React, { useState, useEffect } from 'react';
+import React from 'react';
import ReactDOM from 'react-dom';
-import {
- createMuiTheme,
- ThemeProvider,
- makeStyles
-} from '@material-ui/core/styles';
+import { createMuiTheme, ThemeProvider } from '@material-ui/core/styles';
import { CssBaseline } from '@material-ui/core';
import teal from '@material-ui/core/colors/teal';
import 'typeface-roboto';
-import { User } from 'which-types';
import Header from './components/Header/Header';
-import ProfilePage from './pages/ProfilePage/ProfilePage';
-import FeedPage from './pages/FeedPage/FeedPage';
-import AuthPage from './pages/AuthPage/AuthPage';
-import { Page } from './types';
-import { get, post } from './requests';
import ScrollTopArrow from './components/ScrollTopArrow/ScrollTopArrow';
+import Page from './pages/Page';
+import { AuthProvider } from './hooks/useAuth';
+import { NavigationProvider } from './hooks/useNavigate';
const theme = createMuiTheme({
@@ -28,88 +21,19 @@ const theme = createMuiTheme({
}
});
-const useStyles = makeStyles({
- root: {
- width: theme.spacing(75),
- marginTop: theme.spacing(15),
- margin: '0 auto'
- }
-});
const App: React.FC = () => {
- const [user, setUser] = React.useState<User | undefined>();
- const [page, setPage] = useState<Page>({ prefix: 'feed', id: '' });
- const classes = useStyles();
-
- const navigate = (prefix: string, id?: string): void => {
- if (prefix === 'profile' && !id && !user) {
- setPage({
- prefix: 'auth',
- id: ''
- });
- } else {
- setPage({
- prefix,
- id: (id || user?._id || '')
- });
- }
- };
-
- const logIn = (username: string, password: string, remember = true): Promise<boolean> => {
- return post('/authentication', {
- strategy: 'local',
- username,
- password
- }).then(response => {
- const me = response.data.user;
- const token = response.data.accessToken;
- setUser(me);
- navigate('profile', me._id);
- localStorage.setItem('userId', me._id);
- localStorage.setItem('token', token);
- if (!remember) localStorage.setItem('shouldClear', 'true');
- return true;
- }).catch(() => false);
- };
-
- const logOut = () => {
- setUser(undefined);
- localStorage.removeItem('userId');
- localStorage.removeItem('token');
- navigate('auth');
- };
-
- useEffect(() => {
- if (localStorage.getItem('shouldClear')) {
- localStorage.clear();
- }
- const userId = localStorage.getItem('userId');
- if (userId) {
- get(`/users/${userId}`).then(response => {
- setUser(response.data);
- });
- }
- }, []);
-
return (
- <ThemeProvider theme={theme}>
- <CssBaseline />
- <Header navigate={navigate} userImage={user?.avatarUrl} />
- <div className={classes.root}>
- { page.prefix === 'profile' && (
- <ProfilePage
- logOut={logOut}
- id={page.id}
- navigate={navigate}
- setUser={setUser}
- />
- ) }
- { page.prefix === 'feed' && <FeedPage navigate={navigate} user={user} /> }
- { page.prefix === 'auth' && <AuthPage logIn={logIn} /> }
- </div>
- <ScrollTopArrow />
- </ThemeProvider>
-
+ <NavigationProvider>
+ <AuthProvider>
+ <ThemeProvider theme={theme}>
+ <CssBaseline />
+ <Header />
+ <Page />
+ <ScrollTopArrow />
+ </ThemeProvider>
+ </AuthProvider>
+ </NavigationProvider>
);
};
diff --git a/src/pages/AuthPage/AuthPage.tsx b/src/pages/AuthPage/AuthPage.tsx
index d2c2eec..ad93463 100644
--- a/src/pages/AuthPage/AuthPage.tsx
+++ b/src/pages/AuthPage/AuthPage.tsx
@@ -3,11 +3,6 @@ import { makeStyles } from '@material-ui/core/styles';
import SignInForm from './SignInForm';
import SignUpForm from './SignUpForm';
-
-interface PropTypes {
- logIn: (name: string, password: string, remember?: boolean) => Promise<boolean>;
-}
-
const useStyles = makeStyles({
formTransfer: {
display: 'flex',
@@ -20,7 +15,7 @@ const useStyles = makeStyles({
}
});
-const AuthPage: React.FC<PropTypes> = ({ logIn }) => {
+const AuthPage: React.FC = () => {
const [auth, setAuth] = useState<'signIn' | 'signUp'>('signIn');
const classes = useStyles();
@@ -35,8 +30,8 @@ const AuthPage: React.FC<PropTypes> = ({ logIn }) => {
return (
<>
- {auth === 'signIn' && <SignInForm logIn={logIn} />}
- {auth === 'signUp' && <SignUpForm logIn={logIn} />}
+ {auth === 'signIn' && <SignInForm />}
+ {auth === 'signUp' && <SignUpForm />}
<div className={classes.formTransfer}>
<div>{footerInfo[auth][0]}</div>
<span
diff --git a/src/pages/AuthPage/SignInForm.tsx b/src/pages/AuthPage/SignInForm.tsx
index 1dad153..e68483b 100644
--- a/src/pages/AuthPage/SignInForm.tsx
+++ b/src/pages/AuthPage/SignInForm.tsx
@@ -6,10 +6,8 @@ import {
FormControlLabel,
Switch
} from '@material-ui/core';
-
-interface PropTypes {
- logIn: (name: string, password: string, remember?: boolean) => Promise<boolean>;
-}
+import { useAuth } from '../../hooks/useAuth';
+import { useNavigate } from '../../hooks/useNavigate';
const useStyles = makeStyles(theme => ({
root: {
@@ -28,12 +26,14 @@ const useStyles = makeStyles(theme => ({
}
}));
-const SignInForm: React.FC<PropTypes> = ({ logIn }) => {
+const SignInForm: React.FC = () => {
const [error, setError] = useState<boolean>(false);
const [remember, setRemember] = useState<boolean>(true);
const classes = useStyles();
const nameRef = useRef<HTMLInputElement>();
const passwordRef = useRef<HTMLInputElement>();
+ const { login } = useAuth();
+ const { navigate } = useNavigate();
const handleCheck = () => {
setRemember(!remember);
@@ -43,8 +43,9 @@ const SignInForm: React.FC<PropTypes> = ({ logIn }) => {
const name = nameRef.current?.value;
const password = passwordRef.current?.value;
if (name && password) {
- logIn(name, password, remember).then(success => {
- if (!success) setError(true);
+ login(name, password, remember).then(success => {
+ if (success) navigate('profile');
+ else setError(true);
});
}
};
diff --git a/src/pages/AuthPage/SignUpForm.tsx b/src/pages/AuthPage/SignUpForm.tsx
index 25b79ff..1dacd45 100644
--- a/src/pages/AuthPage/SignUpForm.tsx
+++ b/src/pages/AuthPage/SignUpForm.tsx
@@ -3,10 +3,9 @@ import { makeStyles } from '@material-ui/core/styles';
import TextField from '@material-ui/core/TextField';
import Button from '@material-ui/core/Button';
import { post } from '../../requests';
+import { useAuth } from '../../hooks/useAuth';
+import { useNavigate } from '../../hooks/useNavigate';
-interface PropTypes {
- logIn: (name: string, password: string) => Promise<boolean>;
-}
const useStyles = makeStyles(theme => ({
root: {
@@ -25,21 +24,23 @@ const useStyles = makeStyles(theme => ({
}
}));
-const SignUpForm: React.FC<PropTypes> = ({ logIn }) => {
+const SignUpForm: React.FC = () => {
const [error, setError] = useState<boolean>(false);
const classes = useStyles();
const usernameRef = useRef<HTMLInputElement>();
const emailRef = useRef<HTMLInputElement>();
const passwordRef = useRef<HTMLInputElement>();
+ const { login } = useAuth();
+ const { navigate } = useNavigate();
const onClick = () => {
const username = usernameRef.current?.value;
const password = passwordRef.current?.value;
const email = emailRef.current?.value;
if (username && password) {
- post('/users', { username, password, email }).then(() => {
- logIn(username, password);
- });
+ post('/users', { username, password, email })
+ .then(() => login(username, password))
+ .then(() => navigate('profile'));
} else setError(true);
};
diff --git a/src/pages/FeedPage/FeedPage.tsx b/src/pages/FeedPage/FeedPage.tsx
index 0017275..d29103a 100644
--- a/src/pages/FeedPage/FeedPage.tsx
+++ b/src/pages/FeedPage/FeedPage.tsx
@@ -1,18 +1,15 @@
import React, { useState, useEffect } from 'react';
-import { Poll, User } from 'which-types';
+import { Poll } from 'which-types';
import Feed from '../../components/Feed/Feed';
import { get } from '../../requests';
import PollSubmission from './PollSubmission';
+import { useAuth } from '../../hooks/useAuth';
-interface PropTypes {
- navigate: (prefix: string, id: string) => void;
- user: User | undefined;
-}
-
-const FeedPage: React.FC<PropTypes> = ({ navigate, user }) => {
+const FeedPage: React.FC = () => {
const [polls, setPolls] = useState<Poll[]>([]);
+ const { isAuthenticated } = useAuth();
useEffect(() => {
get('/feed').then(response => {
@@ -28,8 +25,8 @@ const FeedPage: React.FC<PropTypes> = ({ navigate, user }) => {
return (
<>
- {user && <PollSubmission user={user} addPoll={addPoll} />}
- <Feed polls={polls} navigate={navigate} />
+ {isAuthenticated() && <PollSubmission addPoll={addPoll} />}
+ <Feed polls={polls} />
</>
);
};
diff --git a/src/pages/FeedPage/PollSubmission.tsx b/src/pages/FeedPage/PollSubmission.tsx
index 16c8350..18f029c 100644
--- a/src/pages/FeedPage/PollSubmission.tsx
+++ b/src/pages/FeedPage/PollSubmission.tsx
@@ -7,14 +7,14 @@ import {
ClickAwayListener,
Divider
} from '@material-ui/core';
-import { User, Poll, Which } from 'which-types';
+import { Poll, Which } from 'which-types';
import PollSubmissionImage from './PollSubmissionImage';
import UserStrip from '../../components/UserStrip/UserStrip';
import { post } from '../../requests';
import { Contents } from './types';
+import { useAuth } from '../../hooks/useAuth';
interface PropTypes{
- user: User;
addPoll: (poll: Poll) => void;
}
@@ -30,10 +30,11 @@ const emptyContents: Contents = {
right: { url: '' }
};
-const PollSubmission: React.FC<PropTypes> = ({ user, addPoll }) => {
+const PollSubmission: React.FC<PropTypes> = ({ addPoll }) => {
const classes = useStyles();
const [expanded, setExpanded] = useState(false);
const [contents, setContents] = useState<Contents>(emptyContents);
+ const { user } = useAuth();
const readyToSubmit = contents.left.url && contents.right.url;
@@ -47,7 +48,7 @@ const PollSubmission: React.FC<PropTypes> = ({ user, addPoll }) => {
const handleClick = () => {
if (expanded && readyToSubmit) {
- post('/polls/', { authorId: user._id, contents }).then(response => {
+ post('/polls/', { contents }).then(response => {
addPoll(response.data);
});
setContents({ ...emptyContents });
@@ -59,7 +60,7 @@ const PollSubmission: React.FC<PropTypes> = ({ user, addPoll }) => {
<ClickAwayListener onClickAway={handleClickAway}>
<Card>
<Collapse in={expanded} timeout="auto" unmountOnExit>
- <UserStrip user={user} info="" navigate={() => {}} />
+ {user && <UserStrip user={user} info="" />}
<Divider />
<div className={classes.root}>
<PollSubmissionImage url={contents.left.url} setUrl={setUrl('left')} />
diff --git a/src/pages/FeedPage/PollSubmissionImage.tsx b/src/pages/FeedPage/PollSubmissionImage.tsx
index 8d82d45..e2ffad3 100644
--- a/src/pages/FeedPage/PollSubmissionImage.tsx
+++ b/src/pages/FeedPage/PollSubmissionImage.tsx
@@ -41,7 +41,7 @@ const PollSubmissionImage: React.FC<PropTypes> = ({ url, setUrl }) => {
if (!isModalOpen) {
if (url) setUrl('');
else setIsModalOpen(!isModalOpen);
- };
+ }
};
const handleMouseEnter = (): void => {
diff --git a/src/pages/Page.tsx b/src/pages/Page.tsx
new file mode 100644
index 0000000..6d4315e
--- /dev/null
+++ b/src/pages/Page.tsx
@@ -0,0 +1,31 @@
+import React from 'react';
+import { makeStyles } from '@material-ui/core/styles';
+import ProfilePage from './ProfilePage/ProfilePage';
+import FeedPage from './FeedPage/FeedPage';
+import AuthPage from './AuthPage/AuthPage';
+import { useNavigate } from '../hooks/useNavigate';
+
+const useStyles = makeStyles(theme => ({
+ root: {
+ width: theme.spacing(75),
+ marginTop: theme.spacing(15),
+ margin: '0 auto'
+ }
+}));
+
+const Page: React.FC = () => {
+ const { page } = useNavigate();
+ const classes = useStyles();
+
+ return (
+ <div className={classes.root}>
+ { page.prefix === 'profile' && <ProfilePage />}
+ { page.prefix === 'feed' && <FeedPage /> }
+ { page.prefix === 'auth' && <AuthPage /> }
+ </div>
+ );
+};
+
+
+export default Page;
+
diff --git a/src/pages/ProfilePage/MoreMenu.tsx b/src/pages/ProfilePage/MoreMenu.tsx
index bf3347b..4e681f5 100644
--- a/src/pages/ProfilePage/MoreMenu.tsx
+++ b/src/pages/ProfilePage/MoreMenu.tsx
@@ -4,10 +4,8 @@ import Menu from '@material-ui/core/Menu';
import MenuItem from '@material-ui/core/MenuItem';
import MoreHorizIcon from '@material-ui/icons/MoreHoriz';
import { makeStyles } from '@material-ui/core';
-
-interface PropTypes {
- logOut: () => void;
-}
+import { useAuth } from '../../hooks/useAuth';
+import { useNavigate } from '../../hooks/useNavigate';
const ITEM_HEIGHT = 48;
@@ -19,15 +17,23 @@ const useStyles = makeStyles({
}
});
-const MoreMenu: React.FC<PropTypes> = ({ logOut }) => {
+const MoreMenu: React.FC = () => {
const classes = useStyles();
const [anchorEl, setAnchorEl] = React.useState<HTMLButtonElement | null>(null);
+ const { logout } = useAuth();
+ const { navigate } = useNavigate();
+
const open = Boolean(anchorEl);
const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
setAnchorEl(event.currentTarget);
};
+ const handleLogout = () => {
+ logout();
+ navigate('auth');
+ };
+
const handleClose = () => {
setAnchorEl(null);
};
@@ -56,7 +62,7 @@ const MoreMenu: React.FC<PropTypes> = ({ logOut }) => {
}
}}
>
- <MenuItem onClick={logOut}>Log out</MenuItem>
+ <MenuItem onClick={handleLogout}>Log out</MenuItem>
</Menu>
</div>
</div>
diff --git a/src/pages/ProfilePage/ProfileInfo.tsx b/src/pages/ProfilePage/ProfileInfo.tsx
index 9fe5912..9557a5e 100644
--- a/src/pages/ProfilePage/ProfileInfo.tsx
+++ b/src/pages/ProfilePage/ProfileInfo.tsx
@@ -8,15 +8,14 @@ import MoreMenu from './MoreMenu';
import Highlight from './Highlight';
import UploadImage from '../../components/UploadImage/UploadImage';
import { patch } from '../../requests';
+import { useAuth } from '../../hooks/useAuth';
interface PropTypes {
- user: User | undefined;
- logOut: () => void;
savedPolls: number;
totalVotes: number;
- setUserInfo: (a: User) => void;
- setUser: (a:User) => void;
+ userInfo: User | undefined;
+ setUserInfo: (userInfo: User) => void;
}
const useStyles = makeStyles(theme => ({
@@ -78,13 +77,14 @@ const useStyles = makeStyles(theme => ({
const ProfileInfo: React.FC<PropTypes> = ({
- user, logOut, savedPolls, totalVotes, setUserInfo, setUser
+ savedPolls, totalVotes, setUserInfo, userInfo
}) => {
const classes = useStyles();
const [input, setInput] = useState(false);
+ const { setUser } = useAuth();
- const dateSince = new Date(user?.createdAt || '').toLocaleDateString();
+ const dateSince = new Date(userInfo?.createdAt || '').toLocaleDateString();
const handleClick = () => {
setInput(!input);
@@ -101,10 +101,10 @@ const ProfileInfo: React.FC<PropTypes> = ({
return (
<div className={classes.root}>
{
- user?._id === localStorage.getItem('userId')
+ userInfo?._id === localStorage.getItem('userId')
? (
<div>
- <MoreMenu logOut={logOut} />
+ <MoreMenu />
<div className={classes.avatarContainer}>
<Badge
overlap="circle"
@@ -118,17 +118,17 @@ const ProfileInfo: React.FC<PropTypes> = ({
</div>
)}
>
- <Avatar className={classes.avatar} src={user?.avatarUrl} />
+ <Avatar className={classes.avatar} src={userInfo?.avatarUrl} />
</Badge>
</div>
<UploadImage isOpen={input} setIsOpen={setInput} callback={patchAvatar} />
</div>
)
- : <Avatar className={classes.avatar} src={user?.avatarUrl} />
+ : <Avatar className={classes.avatar} src={userInfo?.avatarUrl} />
}
<Typography variant="h5" className={classes.name}>
- {user?.username}
- {user?.verified && <VerifiedIcon className={classes.verified} color="primary" />}
+ {userInfo?.username}
+ {userInfo?.verified && <VerifiedIcon className={classes.verified} color="primary" />}
</Typography>
<div className={classes.profileMenu}>
<Highlight text="Polls" value={savedPolls} />
diff --git a/src/pages/ProfilePage/ProfilePage.tsx b/src/pages/ProfilePage/ProfilePage.tsx
index b0ac103..2c18466 100644
--- a/src/pages/ProfilePage/ProfilePage.tsx
+++ b/src/pages/ProfilePage/ProfilePage.tsx
@@ -4,50 +4,44 @@ import { User, Poll } from 'which-types';
import ProfileInfo from './ProfileInfo';
import Feed from '../../components/Feed/Feed';
import { get } from '../../requests';
+import { useAuth } from '../../hooks/useAuth';
+import { useNavigate } from '../../hooks/useNavigate';
-interface PropTypes {
- logOut: () => void;
- navigate: (prefix: string, id: string) => void;
- id: string;
- setUser:(a:User)=>void;
-}
-const ProfilePage: React.FC<PropTypes> = ({
- logOut, id, navigate, setUser
-}) => {
+const ProfilePage: React.FC = () => {
const [userInfo, setUserInfo] = useState<User>();
const [polls, setPolls] = useState<Poll[]>([]);
const [totalVotes, setTotalVotes] = useState<number>(0);
+ const { page, navigate } = useNavigate();
+ const { user } = useAuth();
useEffect(() => {
- get(`/users/${id}`).then(response => {
- setUserInfo(response.data);
- });
- }, [id]);
-
- useEffect(() => {
- get(`/profiles/${id}`).then(response => {
- setPolls(response.data);
- setTotalVotes(response.data.reduce(
- (total: number, current: Poll) => {
- const { left, right } = current.contents;
- return total + left.votes + right.votes;
- }, 0
- ));
- });
- }, [id, userInfo]);
+ const id = page?.id || user?._id;
+ if (id) {
+ get(`/users/${id}`).then(response => {
+ setUserInfo(response.data);
+ });
+ get(`/profiles/${id}`).then(response => {
+ setPolls(response.data);
+ setTotalVotes(response.data.reduce(
+ (total: number, current: Poll) => {
+ const { left, right } = current.contents;
+ return total + left.votes + right.votes;
+ }, 0
+ ));
+ });
+ } else navigate('auth');
+ }, [navigate, page, user]);
return (
<>
<ProfileInfo
- user={userInfo}
+ userInfo={userInfo}
setUserInfo={setUserInfo}
- setUser={setUser}
- logOut={logOut}
savedPolls={polls.length}
totalVotes={totalVotes}
/>
- <Feed polls={[...polls]} navigate={navigate} />
+ <Feed polls={[...polls]} />
</>
);
};
diff --git a/src/types.d.ts b/src/types.d.ts
index 4b1ffd6..e69de29 100644
--- a/src/types.d.ts
+++ b/src/types.d.ts
@@ -1,4 +0,0 @@
-export interface Page {
- prefix: string;
- id: string;
-}