diff options
-rw-r--r-- | src/components/Feed/Feed.tsx | 5 | ||||
-rw-r--r-- | src/components/Header/Header.tsx | 10 | ||||
-rw-r--r-- | src/components/Header/SearchBar.tsx | 9 | ||||
-rw-r--r-- | src/components/PollCard/PollCard.tsx | 5 | ||||
-rw-r--r-- | src/components/UserStrip/UserStrip.tsx | 16 | ||||
-rw-r--r-- | src/hooks/useNavigate.tsx | 42 | ||||
-rw-r--r-- | src/index.tsx | 71 | ||||
-rw-r--r-- | src/pages/FeedPage/FeedPage.tsx | 8 | ||||
-rw-r--r-- | src/pages/FeedPage/PollSubmission.tsx | 2 | ||||
-rw-r--r-- | src/pages/Page.tsx | 31 | ||||
-rw-r--r-- | src/pages/ProfilePage/ProfilePage.tsx | 14 | ||||
-rw-r--r-- | src/types.d.ts | 4 |
12 files changed, 117 insertions, 100 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 49f427f..546ecc3 100644 --- a/src/components/Header/Header.tsx +++ b/src/components/Header/Header.tsx @@ -10,13 +10,10 @@ 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 { - navigate: (prefix: string) => void; -} - const useStyles = makeStyles({ root: { display: 'flex', @@ -33,9 +30,10 @@ const useStyles = makeStyles({ } }); -const Header: React.FC<PropTypes> = ({ navigate }) => { +const Header: React.FC = () => { const classes = useStyles(); const { user } = useAuth(); + const { navigate } = useNavigate(); const handleHome = (): void => { navigate('feed'); @@ -53,7 +51,7 @@ const Header: React.FC<PropTypes> = ({ navigate }) => { <Typography variant="h5" className={classes.logo}> Which </Typography> - <SearchBar navigate={navigate} /> + <SearchBar /> <div> <IconButton onClick={handleHome}> <HomeIcon /> 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..bbd595e 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/useNavigate.tsx b/src/hooks/useNavigate.tsx new file mode 100644 index 0000000..0650f55 --- /dev/null +++ b/src/hooks/useNavigate.tsx @@ -0,0 +1,42 @@ +import React, { useState, useContext, createContext } from 'react'; +import { User } from 'which-types'; + +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 = (prefix: string, id?: string): void => { + 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 = () => { + return useContext(context); +} + diff --git a/src/index.tsx b/src/index.tsx index a82a28b..180f80c 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,23 +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 { useAuth, AuthProvider } from './hooks/useAuth'; +import Page from './pages/Page'; +import { AuthProvider } from './hooks/useAuth'; +import { NavigationProvider } from './hooks/useNavigate'; const theme = createMuiTheme({ @@ -29,52 +21,21 @@ const theme = createMuiTheme({ } }); -const useStyles = makeStyles({ - root: { - width: theme.spacing(75), - marginTop: theme.spacing(15), - margin: '0 auto' - } -}); const App: React.FC = () => { - const [page, setPage] = useState<Page>({ prefix: 'feed', id: '' }); - const classes = useStyles(); - const { user } = useAuth(); - - const navigate = (prefix: string, id?: string): void => { - if (prefix === 'profile' && !id && !user) { - setPage({ - prefix: 'auth', - id: '' - }); - } else { - setPage({ - prefix, - id: (id || user?._id || '') - }); - } - }; - return ( - <ThemeProvider theme={theme}> - <CssBaseline /> - <Header navigate={navigate} /> - <div className={classes.root}> - { page.prefix === 'profile' && ( - <ProfilePage - id={page.id} - navigate={navigate} - /> - ) } - { page.prefix === 'feed' && <FeedPage navigate={navigate} /> } - { page.prefix === 'auth' && <AuthPage /> } - </div> - <ScrollTopArrow /> - </ThemeProvider> - + <NavigationProvider> + <AuthProvider> + <ThemeProvider theme={theme}> + <CssBaseline /> + <Header /> + <Page /> + <ScrollTopArrow /> + </ThemeProvider> + </AuthProvider> + </NavigationProvider> ); }; -ReactDOM.render(<AuthProvider> <App /> </AuthProvider>, document.getElementById('root')); +ReactDOM.render(<App />, document.getElementById('root')); diff --git a/src/pages/FeedPage/FeedPage.tsx b/src/pages/FeedPage/FeedPage.tsx index 6561991..87a56ec 100644 --- a/src/pages/FeedPage/FeedPage.tsx +++ b/src/pages/FeedPage/FeedPage.tsx @@ -7,11 +7,7 @@ import PollSubmission from './PollSubmission'; import { useAuth } from '../../hooks/useAuth'; -interface PropTypes { - navigate: (prefix: string, id: string) => void; -} - -const FeedPage: React.FC<PropTypes> = ({ navigate }) => { +const FeedPage: React.FC = () => { const [polls, setPolls] = useState<Poll[]>([]); const { isAuthenticated } = useAuth(); @@ -30,7 +26,7 @@ const FeedPage: React.FC<PropTypes> = ({ navigate }) => { return ( <> {isAuthenticated() && <PollSubmission addPoll={addPoll} />} - <Feed polls={polls} navigate={navigate} /> + <Feed polls={polls} /> </> ); }; diff --git a/src/pages/FeedPage/PollSubmission.tsx b/src/pages/FeedPage/PollSubmission.tsx index 4e06254..42612f0 100644 --- a/src/pages/FeedPage/PollSubmission.tsx +++ b/src/pages/FeedPage/PollSubmission.tsx @@ -60,7 +60,7 @@ const PollSubmission: React.FC<PropTypes> = ({ addPoll }) => { <ClickAwayListener onClickAway={handleClickAway}> <Card> <Collapse in={expanded} timeout="auto" unmountOnExit> - {user && <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/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/ProfilePage.tsx b/src/pages/ProfilePage/ProfilePage.tsx index ad2da46..808d43a 100644 --- a/src/pages/ProfilePage/ProfilePage.tsx +++ b/src/pages/ProfilePage/ProfilePage.tsx @@ -4,16 +4,18 @@ 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 { - navigate: (prefix: string, id: string) => void; - id: string; -} -const ProfilePage: React.FC<PropTypes> = ({ id, navigate }) => { +const ProfilePage: React.FC = () => { const [userInfo, setUserInfo] = useState<User>(); const [polls, setPolls] = useState<Poll[]>([]); const [totalVotes, setTotalVotes] = useState<number>(0); + const { page } = useNavigate(); + const { user } = useAuth(); + + const id = page?.id || user?._id; useEffect(() => { get(`/users/${id}`).then(response => { @@ -41,7 +43,7 @@ const ProfilePage: React.FC<PropTypes> = ({ id, navigate }) => { 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; -} |