diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/components/Header/Header.tsx | 18 | ||||
-rw-r--r-- | src/components/Header/SearchBar.tsx | 9 | ||||
-rw-r--r-- | src/components/UserStrip/UserStrip.tsx | 6 | ||||
-rw-r--r-- | src/hooks/useNavigate.tsx | 42 | ||||
-rw-r--r-- | src/index.tsx | 7 | ||||
-rw-r--r-- | src/pages/AuthPage/AuthPage.tsx | 50 | ||||
-rw-r--r-- | src/pages/HomePage/HomePage.tsx | 8 | ||||
-rw-r--r-- | src/pages/HomePage/ReviewForm.tsx | 6 | ||||
-rw-r--r-- | src/pages/LoginPage/LoginPage.tsx (renamed from src/pages/AuthPage/SignInForm.tsx) | 35 | ||||
-rw-r--r-- | src/pages/Page.tsx | 20 | ||||
-rw-r--r-- | src/pages/ProfilePage/MoreMenu.tsx | 6 | ||||
-rw-r--r-- | src/pages/ProfilePage/ProfilePage.tsx | 38 | ||||
-rw-r--r-- | src/pages/RegistrationPage/RegistrationPage.tsx (renamed from src/pages/AuthPage/SignUpForm.tsx) | 39 |
13 files changed, 130 insertions, 154 deletions
diff --git a/src/components/Header/Header.tsx b/src/components/Header/Header.tsx index 41aeec7..5aa66ba 100644 --- a/src/components/Header/Header.tsx +++ b/src/components/Header/Header.tsx @@ -1,4 +1,5 @@ import React from 'react'; +import { useHistory } from 'react-router-dom'; import { AppBar, Toolbar, @@ -11,11 +12,11 @@ import { makeStyles, useTheme } 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 { useAuth } from '../../hooks/useAuth'; import SearchBar from './SearchBar'; + const useStyles = makeStyles(theme => ({ mobile: { top: 'auto', @@ -40,28 +41,29 @@ const useStyles = makeStyles(theme => ({ } })); + const Header: React.FC = () => { const classes = useStyles(); const { user } = useAuth(); - const { navigate } = useNavigate(); const theme = useTheme(); + const history = useHistory(); const isMobile = useMediaQuery(theme.breakpoints.down('sm')); const handleHome = (): void => { - navigate('home'); + history.push('/'); }; const handleFeed = (): void => { - navigate('feed'); + history.push('/feed'); }; const handleProfile = (): void => { - if (user) navigate('profile'); - else navigate('auth'); + if (user) history.push(`/profile/${user.username}`); + else history.push('/login'); }; const handleNotifications = (): void => { - navigate('notifications'); + history.push('/notifications'); }; const FeedButton = ( diff --git a/src/components/Header/SearchBar.tsx b/src/components/Header/SearchBar.tsx index ba0943b..f541589 100644 --- a/src/components/Header/SearchBar.tsx +++ b/src/components/Header/SearchBar.tsx @@ -1,4 +1,5 @@ import React, { useState, useEffect } from 'react'; +import { useHistory } from 'react-router-dom'; import SearchIcon from '@material-ui/icons/Search'; import { InputBase, @@ -10,10 +11,9 @@ import { } from '@material-ui/core'; 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'; - const INTERVAL = 300; const LIMIT = 7; @@ -41,7 +41,7 @@ const SearchBar: React.FC = () => { const [results, setResults] = useState<User[]>([]); const [query, setQuery] = useState<string>(''); const [debouncedQuery, setDebouncedQuery] = useState<string>(query); - const { navigate } = useNavigate(); + const history = useHistory(); const classes = useStyles(); useEffect(() => { @@ -69,7 +69,8 @@ const SearchBar: React.FC = () => { }; const handleNavigate = (index: number) => () => { - navigate('profile', results[index]._id); + const { username } = results[index]; + history.push(`/profile/${username}`); handleClose(); }; diff --git a/src/components/UserStrip/UserStrip.tsx b/src/components/UserStrip/UserStrip.tsx index 3ac47b3..73d9363 100644 --- a/src/components/UserStrip/UserStrip.tsx +++ b/src/components/UserStrip/UserStrip.tsx @@ -1,9 +1,9 @@ import React from 'react'; +import { useHistory } from 'react-router-dom'; import { makeStyles } from '@material-ui/core/styles'; import VerifiedIcon from '@material-ui/icons/CheckCircleOutline'; import { Avatar, CardHeader } from '@material-ui/core/'; import { User } from 'which-types'; -import { useNavigate } from '../../hooks/useNavigate'; interface PropTypes { @@ -30,11 +30,11 @@ const useStyles = makeStyles(theme => ({ const UserStrip: React.FC<PropTypes> = ({ user, info }) => { const classes = useStyles(); - const { navigate } = useNavigate(); + const history = useHistory(); const { username, avatarUrl, verified } = user; const handleNavigate = () => { - navigate('profile', user._id); + history.push(`/profile/${username}`); }; const avatar = ( diff --git a/src/hooks/useNavigate.tsx b/src/hooks/useNavigate.tsx deleted file mode 100644 index d1a433d..0000000 --- a/src/hooks/useNavigate.tsx +++ /dev/null @@ -1,42 +0,0 @@ -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: 'home' }; - -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 }); - window.scrollTo(0, 0); - }; - - 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 e8fbce1..64b1760 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -2,6 +2,7 @@ import React from 'react'; import ReactDOM from 'react-dom'; import { createMuiTheme, ThemeProvider } from '@material-ui/core/styles'; import { CssBaseline } from '@material-ui/core'; +import { BrowserRouter } from 'react-router-dom'; import teal from '@material-ui/core/colors/teal'; import 'typeface-roboto'; @@ -9,7 +10,7 @@ import Header from './components/Header/Header'; import ScrollTopArrow from './components/ScrollTopArrow/ScrollTopArrow'; import Page from './pages/Page'; import { AuthProvider } from './hooks/useAuth'; -import { NavigationProvider } from './hooks/useNavigate'; + const theme = createMuiTheme({ palette: { @@ -23,7 +24,7 @@ const theme = createMuiTheme({ const App: React.FC = () => { return ( - <NavigationProvider> + <BrowserRouter> <AuthProvider> <ThemeProvider theme={theme}> <CssBaseline /> @@ -32,7 +33,7 @@ const App: React.FC = () => { <ScrollTopArrow /> </ThemeProvider> </AuthProvider> - </NavigationProvider> + </BrowserRouter> ); }; diff --git a/src/pages/AuthPage/AuthPage.tsx b/src/pages/AuthPage/AuthPage.tsx deleted file mode 100644 index ad93463..0000000 --- a/src/pages/AuthPage/AuthPage.tsx +++ /dev/null @@ -1,50 +0,0 @@ -import React, { useState } from 'react'; -import { makeStyles } from '@material-ui/core/styles'; -import SignInForm from './SignInForm'; -import SignUpForm from './SignUpForm'; - -const useStyles = makeStyles({ - formTransfer: { - display: 'flex', - justifyContent: 'center' - }, - transferButton: { - marginLeft: 10, - color: 'green', - cursor: 'pointer' - } -}); - -const AuthPage: React.FC = () => { - const [auth, setAuth] = useState<'signIn' | 'signUp'>('signIn'); - const classes = useStyles(); - - const handleRedirect = () => { - setAuth(auth === 'signIn' ? 'signUp' : 'signIn'); - }; - - const footerInfo = { - signIn: ['Don\'t have an account?', 'Sign up'], - signUp: ['Already have an account?', 'Sign in'] - }; - - return ( - <> - {auth === 'signIn' && <SignInForm />} - {auth === 'signUp' && <SignUpForm />} - <div className={classes.formTransfer}> - <div>{footerInfo[auth][0]}</div> - <span - onClick={handleRedirect} - className={classes.transferButton} - role="presentation" - > - {footerInfo[auth][1]} - </span> - </div> - </> - ); -}; - -export default AuthPage; - diff --git a/src/pages/HomePage/HomePage.tsx b/src/pages/HomePage/HomePage.tsx index a6c54b0..17e377a 100644 --- a/src/pages/HomePage/HomePage.tsx +++ b/src/pages/HomePage/HomePage.tsx @@ -1,4 +1,5 @@ import React, { useState, useEffect } from 'react'; +import { useHistory } from 'react-router-dom'; import { Typography, Divider, @@ -12,7 +13,6 @@ import TrendingUpIcon from '@material-ui/icons/TrendingUp'; import { Rating } from '@material-ui/lab'; import { Feedback } from 'which-types'; -import { useNavigate } from '../../hooks/useNavigate'; import { useAuth } from '../../hooks/useAuth'; import { get } from '../../requests'; import ReviewCard from '../../components/ReviewCard/ReviewCard'; @@ -43,7 +43,7 @@ const useStyles = makeStyles(theme => ({ const HomePage: React.FC = () => { const [feedbacks, setFeedbacks] = useState<Feedback[]>([]); const classes = useStyles(); - const { navigate } = useNavigate(); + const history = useHistory(); const { isAuthenticated, user } = useAuth(); const theme = useTheme(); const isMobile = useMediaQuery(theme.breakpoints.down('sm')); @@ -60,11 +60,11 @@ const HomePage: React.FC = () => { }, []); const handleLetsGo = () => { - navigate('feed'); + history.push('/feed'); }; const handleSignUp = () => { - navigate('auth'); + history.push('/registration'); }; const GithubLink = <Link href="https://github.com/which-ecosystem">GitHub</Link>; diff --git a/src/pages/HomePage/ReviewForm.tsx b/src/pages/HomePage/ReviewForm.tsx index 248e36e..b626ce2 100644 --- a/src/pages/HomePage/ReviewForm.tsx +++ b/src/pages/HomePage/ReviewForm.tsx @@ -1,11 +1,11 @@ import React, { useState } from 'react'; +import { useHistory } from 'react-router-dom'; import { makeStyles } from '@material-ui/core/styles'; import { TextField, Button } from '@material-ui/core'; import { Rating } from '@material-ui/lab'; import { useSnackbar } from 'notistack'; import { post } from '../../requests'; -import { useNavigate } from '../../hooks/useNavigate'; const version = 'v1.0.0'; @@ -23,7 +23,7 @@ const ReviewForm: React.FC = () => { const [contents, setContents] = useState<string>(''); const [score, setScore] = useState<number>(0); const classes = useStyles(); - const { navigate } = useNavigate(); + const history = useHistory(); const { enqueueSnackbar } = useSnackbar(); const handleSubmit = (): void => { @@ -32,7 +32,7 @@ const ReviewForm: React.FC = () => { enqueueSnackbar('Your feedback has been submitted!', { variant: 'success' }); - navigate('feed'); + history.push('/feed'); }); } }; diff --git a/src/pages/AuthPage/SignInForm.tsx b/src/pages/LoginPage/LoginPage.tsx index e68483b..335cbb1 100644 --- a/src/pages/AuthPage/SignInForm.tsx +++ b/src/pages/LoginPage/LoginPage.tsx @@ -1,4 +1,5 @@ import React, { useState, useRef } from 'react'; +import { useHistory } from 'react-router-dom'; import { makeStyles } from '@material-ui/core/styles'; import { TextField, @@ -7,7 +8,6 @@ import { Switch } from '@material-ui/core'; import { useAuth } from '../../hooks/useAuth'; -import { useNavigate } from '../../hooks/useNavigate'; const useStyles = makeStyles(theme => ({ root: { @@ -23,33 +23,46 @@ const useStyles = makeStyles(theme => ({ formHeader: { textAlign: 'center', fontSize: 25 + }, + formTransfer: { + display: 'flex', + justifyContent: 'center' + }, + transferButton: { + marginLeft: 10, + color: 'green', + cursor: 'pointer' } })); -const SignInForm: React.FC = () => { +const LoginPage: 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 history = useHistory(); const handleCheck = () => { setRemember(!remember); }; const handleSubmit = async () => { - const name = nameRef.current?.value; + const name = nameRef.current?.value?.toLowerCase(); const password = passwordRef.current?.value; if (name && password) { login(name, password, remember).then(success => { - if (success) navigate('profile'); + if (success) history.push(`/profile/${name}`); else setError(true); }); } }; + const handleRegistration = () => { + history.push('/registration'); + }; + return ( <> <div className={classes.formHeader}>Sign In</div> @@ -72,9 +85,19 @@ const SignInForm: React.FC = () => { /> <Button variant="contained" onClick={handleSubmit}>submit</Button> </form> + <div className={classes.formTransfer}> + <div>{'Don\'t have an account?'}</div> + <span + onClick={handleRegistration} + className={classes.transferButton} + role="presentation" + > + Sign up + </span> + </div> </> ); }; -export default SignInForm; +export default LoginPage; diff --git a/src/pages/Page.tsx b/src/pages/Page.tsx index 56d7372..668b171 100644 --- a/src/pages/Page.tsx +++ b/src/pages/Page.tsx @@ -2,13 +2,14 @@ import React from 'react'; import { makeStyles, useTheme } from '@material-ui/core/styles'; import { useMediaQuery } from '@material-ui/core'; import { SnackbarProvider } from 'notistack'; +import { Switch, Route } from 'react-router-dom'; import ProfilePage from './ProfilePage/ProfilePage'; import FeedPage from './FeedPage/FeedPage'; -import AuthPage from './AuthPage/AuthPage'; +import LoginPage from './LoginPage/LoginPage'; +import RegistrationPage from './RegistrationPage/RegistrationPage'; import HomePage from './HomePage/HomePage'; import NotificationsPage from './NotificationsPage/NotificationsPage'; -import { useNavigate } from '../hooks/useNavigate'; const useStyles = makeStyles(theme => ({ @@ -22,8 +23,8 @@ const useStyles = makeStyles(theme => ({ } })); + const Page: React.FC = () => { - const { page } = useNavigate(); const classes = useStyles(); const theme = useTheme(); const isMobile = useMediaQuery(theme.breakpoints.down('sm')); @@ -37,11 +38,14 @@ const Page: React.FC = () => { }} > <div className={classes.root}> - { page.prefix === 'home' && <HomePage />} - { page.prefix === 'profile' && <ProfilePage />} - { page.prefix === 'feed' && <FeedPage /> } - { page.prefix === 'auth' && <AuthPage /> } - { page.prefix === 'notifications' && <NotificationsPage /> } + <Switch> + <Route exact path="/" component={HomePage} /> + <Route exact path="/login" component={LoginPage} /> + <Route exact path="/registration" component={RegistrationPage} /> + <Route exact path="/feed" component={FeedPage} /> + <Route exact path="/notifications" component={NotificationsPage} /> + <Route path="/profile/:username" component={ProfilePage} /> + </Switch> </div> </SnackbarProvider> ); diff --git a/src/pages/ProfilePage/MoreMenu.tsx b/src/pages/ProfilePage/MoreMenu.tsx index 4e681f5..1f41879 100644 --- a/src/pages/ProfilePage/MoreMenu.tsx +++ b/src/pages/ProfilePage/MoreMenu.tsx @@ -1,11 +1,11 @@ import React from 'react'; +import { useHistory } from 'react-router-dom'; import IconButton from '@material-ui/core/IconButton'; 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'; import { useAuth } from '../../hooks/useAuth'; -import { useNavigate } from '../../hooks/useNavigate'; const ITEM_HEIGHT = 48; @@ -21,7 +21,7 @@ const MoreMenu: React.FC = () => { const classes = useStyles(); const [anchorEl, setAnchorEl] = React.useState<HTMLButtonElement | null>(null); const { logout } = useAuth(); - const { navigate } = useNavigate(); + const history = useHistory(); const open = Boolean(anchorEl); @@ -31,7 +31,7 @@ const MoreMenu: React.FC = () => { const handleLogout = () => { logout(); - navigate('auth'); + history.push('/login'); }; const handleClose = () => { diff --git a/src/pages/ProfilePage/ProfilePage.tsx b/src/pages/ProfilePage/ProfilePage.tsx index 34c9efa..ae94b9f 100644 --- a/src/pages/ProfilePage/ProfilePage.tsx +++ b/src/pages/ProfilePage/ProfilePage.tsx @@ -1,4 +1,5 @@ import React, { useState, useEffect } from 'react'; +import { useHistory, useParams } from 'react-router-dom'; import { User, Poll } from 'which-types'; import { Container } from '@material-ui/core'; @@ -6,28 +7,41 @@ import ProfileInfo from './ProfileInfo'; import Feed from '../../components/Feed/Feed'; import { get } from '../../requests'; import { useAuth } from '../../hooks/useAuth'; -import { useNavigate } from '../../hooks/useNavigate'; 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(); const [isInfoLoading, setIsInfoLoading] = useState(false); const [isPollsLoading, setIsPollsLoading] = useState(false); + const history = useHistory(); + const { username } = useParams(); + const { user } = useAuth(); useEffect(() => { - const id = page?.id || user?._id; setIsInfoLoading(true); - setIsPollsLoading(true); - if (id) { - get(`/users/${id}`).then(response => { - setUserInfo(response.data); + + const redirect = () => { + if (user) history.push(`/profile/${user.username}`); + else history.push('/login'); + }; + + if (username) { + get(`/users?username=${username}`).then(response => { + if (!response.data.length) redirect(); // TODO: handle this case + setUserInfo(response.data[0]); setIsInfoLoading(false); - }); - get(`/profiles/${id}`).then(response => { + }).catch(() => redirect()); + } else redirect(); + }, [username, user, history]); + + + useEffect(() => { + if (userInfo?._id) { + setIsPollsLoading(true); + + get(`/profiles/${userInfo._id}`).then(response => { setIsPollsLoading(false); setPolls([]); setPolls(response.data); @@ -38,8 +52,8 @@ const ProfilePage: React.FC = () => { }, 0 )); }); - } else navigate('auth'); - }, [navigate, page, user]); + } + }, [userInfo]); return ( <Container maxWidth="sm" disableGutters> diff --git a/src/pages/AuthPage/SignUpForm.tsx b/src/pages/RegistrationPage/RegistrationPage.tsx index 1dacd45..18a9379 100644 --- a/src/pages/AuthPage/SignUpForm.tsx +++ b/src/pages/RegistrationPage/RegistrationPage.tsx @@ -1,10 +1,10 @@ import React, { useState, useRef } from 'react'; +import { useHistory } from 'react-router-dom'; 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'; const useStyles = makeStyles(theme => ({ @@ -21,29 +21,42 @@ const useStyles = makeStyles(theme => ({ formHeader: { textAlign: 'center', fontSize: 25 + }, + formTransfer: { + display: 'flex', + justifyContent: 'center' + }, + transferButton: { + marginLeft: 10, + color: 'green', + cursor: 'pointer' } })); -const SignUpForm: React.FC = () => { +const RegistrationPage: 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 history = useHistory(); - const onClick = () => { - const username = usernameRef.current?.value; + const handleSubmit = () => { + const username = usernameRef.current?.value?.toLowerCase(); const password = passwordRef.current?.value; const email = emailRef.current?.value; if (username && password) { post('/users', { username, password, email }) .then(() => login(username, password)) - .then(() => navigate('profile')); + .then(() => history.push(`/profile/${username}`)); } else setError(true); }; + const handleLogin = () => { + history.push('/login'); + }; + return ( <> <div className={classes.formHeader}>Sign Up</div> @@ -64,10 +77,20 @@ const SignUpForm: React.FC = () => { error={error} helperText={error && 'This field is required!'} /> - <Button variant="contained" onClick={onClick}>submit</Button> + <Button variant="contained" onClick={handleSubmit}>submit</Button> </form> + <div className={classes.formTransfer}> + <div>Already have an account?</div> + <span + onClick={handleLogin} + className={classes.transferButton} + role="presentation" + > + Log in + </span> + </div> </> ); }; -export default SignUpForm; +export default RegistrationPage; |