diff options
Diffstat (limited to 'src/containers/Feed')
| -rw-r--r-- | src/containers/Feed/Feed.tsx | 27 | ||||
| -rw-r--r-- | src/containers/Feed/PollSubmission.tsx | 92 | ||||
| -rw-r--r-- | src/containers/Feed/PollSubmissionImage.tsx | 87 | ||||
| -rw-r--r-- | src/containers/Feed/types.ts | 7 | 
4 files changed, 213 insertions, 0 deletions
| diff --git a/src/containers/Feed/Feed.tsx b/src/containers/Feed/Feed.tsx new file mode 100644 index 0000000..e923bdd --- /dev/null +++ b/src/containers/Feed/Feed.tsx @@ -0,0 +1,27 @@ +import React from 'react'; +import { Poll } from 'which-types'; +import { Container } from '@material-ui/core/'; + +import PollsList from '../../components/PollsList/PollsList'; +import PollSubmission from './PollSubmission'; +import { useAuth } from '../../hooks/useAuth'; +import { useFeed } from '../../hooks/APIClient'; + +const Feed: React.FC = () => { +  const { data: polls, mutate } = useFeed(); +  const { isAuthenticated } = useAuth(); + +  const addPoll = (poll: Poll): void => { +    mutate([poll, ...polls], true); +  }; + +  return ( +    <Container maxWidth="sm" disableGutters> +      {isAuthenticated && <PollSubmission addPoll={addPoll} />} +      <PollsList polls={polls} mutate={mutate} /> +    </Container> +  ); +}; + +export default Feed; + diff --git a/src/containers/Feed/PollSubmission.tsx b/src/containers/Feed/PollSubmission.tsx new file mode 100644 index 0000000..347eecc --- /dev/null +++ b/src/containers/Feed/PollSubmission.tsx @@ -0,0 +1,92 @@ +import React, { useState } from 'react'; +import { makeStyles } from '@material-ui/core/styles'; +import Collapse from '@material-ui/core/Collapse'; +import { +  Button, +  Card, +  ClickAwayListener, +  Divider +} from '@material-ui/core'; +import { Poll, Which } from 'which-types'; +import { useSnackbar } from 'notistack'; +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{ +  addPoll: (poll: Poll) => void; +} + +const useStyles = makeStyles(theme => ({ +  root: { +    marginBottom: theme.spacing(4) +  }, +  images: { +    height: theme.spacing(50), +    display: 'flex' +  } +})); + +const emptyContents: Contents = { +  left: { url: '' }, +  right: { url: '' } +}; + +const PollSubmission: React.FC<PropTypes> = ({ addPoll }) => { +  const classes = useStyles(); +  const [expanded, setExpanded] = useState(false); +  const [contents, setContents] = useState<Contents>(emptyContents); +  const { enqueueSnackbar } = useSnackbar(); +  const { user } = useAuth(); + +  const readyToSubmit = contents.left.url && contents.right.url; + +  const setUrl = (which: Which) => (url: string): void => { +    setContents({ ...contents, [which]: { url } }); +  }; + +  const handleClickAway = () => { +    setExpanded(false); +  }; + +  const handleClick = () => { +    if (expanded && readyToSubmit) { +      post('/polls/', { contents }).then(response => { +        addPoll(response.data); +        enqueueSnackbar('Your poll has been successfully created!', { +          variant: 'success' +        }); +      }); +      setContents({ ...emptyContents }); +    } +    setExpanded(!expanded); +  }; + +  return ( +    <ClickAwayListener onClickAway={handleClickAway}> +      <Card className={classes.root}> +        <Collapse in={expanded} timeout="auto" unmountOnExit> +          {user && <UserStrip user={user} info="" />} +          <Divider /> +          <div className={classes.images}> +            <PollSubmissionImage url={contents.left.url} setUrl={setUrl('left')} /> +            <PollSubmissionImage url={contents.right.url} setUrl={setUrl('right')} /> +          </div> +        </Collapse> +        <Button +          color="primary" +          disabled={expanded && !readyToSubmit} +          variant={expanded ? 'contained' : 'outlined'} +          onClick={handleClick} +          fullWidth +        > +          {expanded ? 'Submit' : 'Create a Poll'} +        </Button> +      </Card> +    </ClickAwayListener> +  ); +}; + +export default PollSubmission; diff --git a/src/containers/Feed/PollSubmissionImage.tsx b/src/containers/Feed/PollSubmissionImage.tsx new file mode 100644 index 0000000..8835989 --- /dev/null +++ b/src/containers/Feed/PollSubmissionImage.tsx @@ -0,0 +1,87 @@ +import React, { useState } from 'react'; +import { makeStyles } from '@material-ui/core/styles'; +import CloudUploadIcon from '@material-ui/icons/CloudUpload'; +import { CardActionArea, CardMedia, Typography } from '@material-ui/core'; +import CancelOutlinedIcon from '@material-ui/icons/CancelOutlined'; + +import UploadImage from '../../components/UploadImage/UploadImage'; + +interface PropTypes { +  url: string; +  setUrl: (url: string) => void; +} + +const useStyles = makeStyles({ +  root: { +    display: 'flex', +    justifyContent: 'center', +    flexDirection: 'column', +    alignItems: 'center' +  }, +  clearIcon: { +    opacity: '.5', +    fontSize: 50 +  }, +  media: { +    height: '100%', +    width: '100%', +    display: 'flex', +    justifyContent: 'center', +    alignItems: 'center' +  }, +  text: { +    textAlign: 'center' +  } +}); + + +const PollSubmissionImage: React.FC<PropTypes> = ({ url, setUrl }) => { +  const classes = useStyles(); +  const [isModalOpen, setIsModalOpen] = useState(false); +  const [isMediaHover, setIsMediaHover] = useState(false); + +  const handleClick = (): void => { +    if (!isModalOpen) { +      if (url) setUrl(''); +      else setIsModalOpen(!isModalOpen); +    } +  }; + +  const handleMouseEnter = (): void => { +    setIsMediaHover(true); +  }; + +  const handleMouseLeave = (): void => { +    setIsMediaHover(false); +  }; + + +  const Upload = ( +    <> +      <CloudUploadIcon fontSize="large" color="primary" /> +      <Typography variant="h5" className={classes.text}> Upload an image </Typography> +    </> +  ); + +  const Media = ( +    <CardMedia +      image={url} +      className={classes.media} +      onMouseEnter={handleMouseEnter} +      onMouseLeave={handleMouseLeave} +    > +      {isMediaHover && <CancelOutlinedIcon className={classes.clearIcon} />} +    </CardMedia> +  ); + +  return ( +    <> +      <CardActionArea onClick={handleClick} className={classes.root}> +        {url ? Media : Upload} +      </CardActionArea> +      <UploadImage isOpen={isModalOpen} setIsOpen={setIsModalOpen} callback={setUrl} /> +    </> +  ); +}; + +export default PollSubmissionImage; diff --git a/src/containers/Feed/types.ts b/src/containers/Feed/types.ts new file mode 100644 index 0000000..24ace4e --- /dev/null +++ b/src/containers/Feed/types.ts @@ -0,0 +1,7 @@ +export interface ImageData { +  url: string; +} +export interface Contents { +  left: ImageData; +  right: ImageData; +} | 
