diff options
-rw-r--r-- | package-lock.json | 107 | ||||
-rw-r--r-- | package.json | 2 | ||||
-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 |
15 files changed, 239 insertions, 154 deletions
diff --git a/package-lock.json b/package-lock.json index 59b1f75..e4183d1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1626,6 +1626,11 @@ "@types/node": "*" } }, + "@types/history": { + "version": "4.7.7", + "resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.7.tgz", + "integrity": "sha512-2xtoL22/3Mv6a70i4+4RB7VgbDDORoWwjcqeNysojZA0R7NK17RbY5Gof/2QiFfJgX+KkWghbwJ+d/2SB8Ndzg==" + }, "@types/istanbul-lib-coverage": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.2.tgz", @@ -1702,6 +1707,25 @@ "@types/react": "*" } }, + "@types/react-router": { + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.8.tgz", + "integrity": "sha512-HzOyJb+wFmyEhyfp4D4NYrumi+LQgQL/68HvJO+q6XtuHSDvw6Aqov7sCAhjbNq3bUPgPqbdvjXC5HeB2oEAPg==", + "requires": { + "@types/history": "*", + "@types/react": "*" + } + }, + "@types/react-router-dom": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@types/react-router-dom/-/react-router-dom-5.1.5.tgz", + "integrity": "sha512-ArBM4B1g3BWLGbaGvwBGO75GNFbLDUthrDojV2vHLih/Tq8M+tgvY1DSwkuNrPSwdp/GUL93WSEpTZs8nVyJLw==", + "requires": { + "@types/history": "*", + "@types/react": "*", + "@types/react-router": "*" + } + }, "@types/react-transition-group": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.0.tgz", @@ -6307,6 +6331,19 @@ "resolved": "https://registry.npmjs.org/hex-color-regex/-/hex-color-regex-1.1.0.tgz", "integrity": "sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ==" }, + "history": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/history/-/history-4.10.1.tgz", + "integrity": "sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==", + "requires": { + "@babel/runtime": "^7.1.2", + "loose-envify": "^1.2.0", + "resolve-pathname": "^3.0.0", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0", + "value-equal": "^1.0.1" + } + }, "hmac-drbg": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", @@ -8316,6 +8353,15 @@ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" }, + "mini-create-react-context": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/mini-create-react-context/-/mini-create-react-context-0.4.0.tgz", + "integrity": "sha512-b0TytUgFSbgFJGzJqXPKCFCBWigAjpjo+Fl7Vf7ZbKRDptszpppKxXH6DRXEABZ/gcEQczeb0iZ7JvL8e8jjCA==", + "requires": { + "@babel/runtime": "^7.5.5", + "tiny-warning": "^1.0.3" + } + }, "mini-css-extract-plugin": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.9.0.tgz", @@ -10832,6 +10878,52 @@ "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" }, + "react-router": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.2.0.tgz", + "integrity": "sha512-smz1DUuFHRKdcJC0jobGo8cVbhO3x50tCL4icacOlcwDOEQPq4TMqwx3sY1TP+DvtTgz4nm3thuo7A+BK2U0Dw==", + "requires": { + "@babel/runtime": "^7.1.2", + "history": "^4.9.0", + "hoist-non-react-statics": "^3.1.0", + "loose-envify": "^1.3.1", + "mini-create-react-context": "^0.4.0", + "path-to-regexp": "^1.7.0", + "prop-types": "^15.6.2", + "react-is": "^16.6.0", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "path-to-regexp": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", + "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "requires": { + "isarray": "0.0.1" + } + } + } + }, + "react-router-dom": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.2.0.tgz", + "integrity": "sha512-gxAmfylo2QUjcwxI63RhQ5G85Qqt4voZpUXSEqCwykV0baaOTQDR1f0PmY8AELqIyVc0NEZUj0Gov5lNGcXgsA==", + "requires": { + "@babel/runtime": "^7.1.2", + "history": "^4.9.0", + "loose-envify": "^1.3.1", + "prop-types": "^15.6.2", + "react-router": "5.2.0", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0" + } + }, "react-scripts": { "version": "3.4.1", "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-3.4.1.tgz", @@ -11549,6 +11641,11 @@ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=" }, + "resolve-pathname": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-3.0.0.tgz", + "integrity": "sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng==" + }, "resolve-url": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", @@ -13023,6 +13120,11 @@ "resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz", "integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=" }, + "tiny-invariant": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.1.0.tgz", + "integrity": "sha512-ytxQvrb1cPc9WBEI/HSeYYoGD0kWnGEOR8RY6KomWLBVhqz0RgTwVO9dLrGz7dC+nN9llyI7OKAgRq8Vq4ZBSw==" + }, "tiny-warning": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", @@ -13419,6 +13521,11 @@ "spdx-expression-parse": "^3.0.0" } }, + "value-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz", + "integrity": "sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw==" + }, "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", diff --git a/package.json b/package.json index 676e20a..2690f3a 100644 --- a/package.json +++ b/package.json @@ -6,12 +6,14 @@ "@material-ui/core": "^4.10.1", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "^4.0.0-alpha.56", + "@types/react-router-dom": "^5.1.5", "axios": "^0.19.2", "lodash": "^4.17.15", "notistack": "^0.9.17", "react": "^16.13.1", "react-dom": "^16.13.1", "react-icons": "^3.10.0", + "react-router-dom": "^5.2.0", "react-scripts": "3.4.1", "react-virtualized": "^9.21.2", "typeface-roboto": "0.0.75", 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; |