@material-ui/core#CardActionArea JavaScript Examples

The following examples show how to use @material-ui/core#CardActionArea. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: Gravatars.jsx    From Gameplayer with MIT License 6 votes vote down vote up
Gravatar = ({ classes, id, displayName, imageUrl, owner }) => (
  <Grid item>
    <Card>
      <CardActionArea className={classes.actionArea}>
        {imageUrl && (
          <CardMedia className={classes.image} image={imageUrl} title={displayName} />
        )}
        <CardContent>
          <Typography variant="h6" component="h3" className={classes.displayName}>
            {displayName || '—'}
          </Typography>
          <Typography color="textSecondary">ID</Typography>
          <Typography component="p" className={classes.id}>
            {id}
          </Typography>
          <Typography color="textSecondary">Owner</Typography>
          <Typography component="p" className={classes.owner}>
            {owner}
          </Typography>
        </CardContent>
      </CardActionArea>
    </Card>
  </Grid>
)
Example #2
Source File: ChallengeCard.js    From dscbppimt-official-website with MIT License 6 votes vote down vote up
ChallengeCard = (props) => {
    const classes = useStyles();

    return (
        <Card className={classes.root}>
        <CardActionArea>
          <CardMedia
            className={classes.media}
            image="/static/images/cards/contemplative-reptile.jpg"
            title="Contemplative Reptile"
          />
          <CardContent>
            <Typography gutterBottom variant="h5" component="h2">
              Lizard
            </Typography>
            <Typography variant="body2" color="textSecondary" component="p">
              Lizards are a widespread group of squamate reptiles, with over 6,000 species, ranging
              across all continents except Antarctica
            </Typography>
          </CardContent>
        </CardActionArea>
        <CardActions>
          <Button size="small" color="primary">
            Share
          </Button>
          <Button size="small" color="primary">
            Learn More
          </Button>
        </CardActions>
      </Card>
    )
}
Example #3
Source File: JoinUsOnDiscord.js    From qasong with ISC License 6 votes vote down vote up
function Playlist() {
  const classes = useStyles();

  return (
    <Grid key={"discord"} item>
      <CardActionArea href="https://discord.gg/VnpcrtYnrS" className={classes.playlist}>
        <Grid
          container
          alignContent="center"
          justify="center"
          alignItems="center"
          align="center"
        >
          <Grid item xs={12} sm={3}>
            <img className={classes.svg} src="./static/img/discord.svg"></img>
          </Grid>
          <Grid item xs={12} sm={6}>
            <Typography align="center" color="secondary">
              Join Us On Discord
            </Typography>
            <Typography align="center" variant="body2" color="textSecondary">
              contact the Qasong Team
            </Typography>
          </Grid>
          <Grid item xs={12} sm={3}>
            <img width="80px" src="./static/img/qasong.svg"></img>
          </Grid>
        </Grid>
      </CardActionArea>
    </Grid>
  );
}
Example #4
Source File: RouteRow.js    From hk-independent-bus-eta with GNU General Public License v3.0 6 votes vote down vote up
RouteRow = React.memo(( {data, index, style} ) => {
  const { t, i18n } = useTranslation()
  const { routeList } = data
  const route = routeList[index]
  const [routeNo, service_type] = route[0].split('+').slice(0,2)
  const classes = useStyles()
  const history = useHistory()
  const handleClick = () => {
    vibrate(1)
    setTimeout(() => {
      history.push('/'+i18n.language+'/route/'+route[0])
    }, 0)
  }

  return (
    <div onClick={handleClick} >
      <Card variant="outlined" key={route[0]} style={style} square>
        <CardActionArea>
          <CardContent className={classes.cardContent}>
            <Typography variant="h5" display="inline">{routeNo}</Typography>
            <Typography variant="caption"> - {route[1].co.map(co => t(co)).join('+')}</Typography>
            <br/>
            <RouteInfo route={route[1]} />
            <Typography variant="caption">{service_type >= 2 ? t('特別班次') : ' '}</Typography>
          </CardContent>
        </CardActionArea>
      </Card>
    </div>
  )
}, areEqual)
Example #5
Source File: About.jsx    From Design-Initiative-Dashboard-frontend with GNU General Public License v3.0 6 votes vote down vote up
export default function AboutCard() {
  const classes = useStyles();

  return (
    <Card className={classes.root}>
    <React.Fragment>
      {about.map((data)=> (
      <CardActionArea>
        <CardContent>
          <Typography
            variant="body2"
            color="textPrimary"
            component="p"
            align="left"
            className={classes.pos2}
          >
            {data.desc}
          </Typography>
          
          {data.features.map((f) => (
            <Button variant="contained" color="primary" size="small" className={classes.cap} >
              {f.name}
            </Button>
        ))}

        </CardContent>
        </CardActionArea>
        
      ))}
        
       </React.Fragment>
    </Card>
  );
}
Example #6
Source File: team-member.js    From turinghut-website with BSD Zero Clause License 6 votes vote down vote up
export default function TeamMember() {
  const classes = teamMemberStyles();
  return (
    <div>
      <Typography variant="h3" className={classes.heading}>our team</Typography>
      <div className={classes.root}>
        <Grid container spacing={4} className={classes.gridContainer}>
          {team.map((member, i) => (
            <Grid item xs={12} md={4} key={i}>
              <Card className={classes.card}>
                <CardActionArea >
                  <CardMedia className={classes.media} image={member.imageUrl} title={member.name} />
                  <DialogDisplay person={member} />
                </CardActionArea>
              </Card>
            </Grid>
          ))}
        </Grid>
      </div>
    </div>
  );
}
Example #7
Source File: Categories.jsx    From scholar-front-end with MIT License 6 votes vote down vote up
categoriesCard = data.map(item => (
    <Grid item sm={3}>
    <Card className="cardActions">
        <CardActionArea >
            <CardMedia className="card"
                image={require(`../../data/Images/${item.name}`).default}
                style={{ height: 300 }} />
            <CardContent>
                <Typography variant="h5"><span className="categoryName">{item.category}</span></Typography>
            </CardContent>
        </CardActionArea>
    </Card>
</Grid>
))
Example #8
Source File: Sliders.jsx    From scholar-front-end with MIT License 6 votes vote down vote up
function CourseCard({data}){
  var image = require("./CourseLogo.jpg").default;

  const classes = useStyles();
  return (
<Card className={classes.root}>
  <CardActionArea>
  <CardMedia alt="course" component="img" height="140" title={data} image={image}/>
  <CardContent>
    <Typography gutterBottom variant="h5" component="h2">
      Course Title
    </Typography>
    <Typography variant="body2" color="textSecondary" component="p">
      Course Number {data}
    </Typography>
  </CardContent>
  </CardActionArea>
  <CardActions>
    <Button size="small" color="primary">Open</Button>
  </CardActions>
</Card>
  )

}
Example #9
Source File: AccountDialogThanks.js    From crypto-red.github.io with MIT License 6 votes vote down vote up
render() {

        const { classes, open } = this.state;

        return (
            <Dialog className={classes.thanksCard} open={open} onClick={this.props.accept} onClose={(event) => {this.props.onClose(event)}}>
                <CardActionArea className={classes.thanksCardArea}>
                    <CardHeader className={classes.thanksCardHeader}>
                        Thanks !
                    </CardHeader>
                    <CardContent className={classes.thanksCardContent}>
                        <div className={classes.thanksCardImage} />
                        Thanks for your engagement, we appreciate it a lot,
                        We have a new friend or user, do you want to join with a new person?
                    </CardContent>
                    <KindlyHappyEmojiIcon className={classes.thanksEmoji} />
                    <div className={classes.thanksButtonContainer}>
                        <Button color="primary" variant={"contained"} className={classes.thanksButton}>Invite a friend</Button>
                    </div>
                </CardActionArea>
            </Dialog>
        );
    }
Example #10
Source File: ProjectCard.js    From eSim-Cloud with GNU General Public License v3.0 6 votes vote down vote up
export default function ProjectCard ({ pub, is_review }) {
  const classes = useStyles()
  return (
    <>
      <Card>
        <ButtonBase
          target="_blank"
          component={RouterLink}
          to={'/project?save_id=' + pub.save_id + '&version=' + pub.active_version + '&branch=' + pub.active_branch + '&project_id=' + pub.project_id}
          style={{ width: '100%' }}>
          <CardActionArea>
            <CardHeader title={pub.title} />
            <CardMedia
              className={classes.media}
              image={pub.active_save.base64_image} />
            <CardContent>
              <Typography variant="body2" component="p" noWrap={true}>
                {pub.description}
              </Typography>
              <br/>
              <Typography variant='body2' color='textSecondary' component='p'>
              Status: {pub.status_name}
              </Typography>
              {/* <Typography variant='body2' component='p' color='textSecondary' style={{ margin: '5px 0px 0px 0px' }}>
              Updated at {timeSince(pub.save_time)} ago...
            </Typography> */}
            </CardContent>
          </CardActionArea>
        </ButtonBase>
      </Card>
    </>
  )
}
Example #11
Source File: LinkContent.js    From covid19ph.net with MIT License 5 votes vote down vote up
LinkContent = ({
  image,
  title,
  url,
}) => {
  const classes = useStyles()

  return (
    <CardActionArea
      component="a"
      href={url}
      rel="noreferrer noopener"
      target="_blank"
    >
      <CardMedia
        component="img"
        height="256"
        image={image}
        alt={title}
        title={title}
        className={classes.linkImage}
      />
      <CardContent>
        <Typography
          gutterBottom
          variant="h5"
          component="h2"
          className={classes.linkTitle}
        >
          {title}
        </Typography>
        <Typography
          variant="body2"
          color="textSecondary"
          component="p"
          className={classes.linkUrl}
        >
          {url}
        </Typography>
      </CardContent>
    </CardActionArea>
  )
}
Example #12
Source File: ResultCard.js    From qasong with ISC License 5 votes vote down vote up
export default function ResultCard({
  video,
  setNowPlaying,
  nowPlaying,
  queue,
  setQueue,
}) {
  const classes = useStyles();
  const [playing, setPlaying] = useState(false);

  useEffect(() => {
    if (nowPlaying && nowPlaying.videoId === video.videoId) {
      setPlaying(true);
    } else {
      setPlaying(false);
    }
  }, [nowPlaying]);

  function handlePlayButton(event) {
    event.stopPropagation();

    if (!playing) {
      setNowPlaying(video);
      setPlaying(true);
    } else {
      setNowPlaying({});
      setPlaying(false);
    }
  }

  function handleAddQueue(event) {
    event.stopPropagation();
    setQueue(
      queue.concat({
        ...video,
        qid: uuid(),
      })
    );
  }

  return (
    <Card
      className={classes.card}
      style={{ backgroundColor: playing && qasongOrange }}
      onClick={handlePlayButton}
    >
      <CardActionArea>
        <CardMedia className={classes.media} image={video.image} />
        <Box p={1}>
          <Grid container direction="column">
            <Grid item>
              <Typography className={classes.truncate} variant="caption">
                {video.title}
              </Typography>
            </Grid>
            <Grid item container justify="space-between">
              <Grid item>
                <Typography className={classes.truncate} variant="caption">
                  {video.author.name}
                </Typography>
              </Grid>
              <Grid item>
                <Typography className={classes.truncate} variant="caption">
                  {video.timestamp}
                </Typography>
              </Grid>
            </Grid>
          </Grid>
        </Box>
      </CardActionArea>

      <Box className={classes.overlay}>
        <AddToQueueButton {...{ handleAddQueue }} />
      </Box>
    </Card>
  );
}
Example #13
Source File: EventCard.js    From AdaptivApps-fe with MIT License 5 votes vote down vote up
export default function EventCard({ event }) {
  const classes = useStyles();
  const [updateEvent] = useMutation(REGISTER_EVENT);

  const { user } = useAuth0();
  const navigate = useNavigate();

  const registerEvent = async () => {
    await updateEvent({
      variables: { id: event.id, email: user.email },
    });
    await navigate(`/calendar/${event.id}`);
  };

  return (
    <Card className={classes.root}>
      <CardActionArea className={classes.card}>
        <Box>
          <div className={classes.banner}>{event.type}</div>
          <CardMedia
            className={classes.cardImg}
            component="img"
            alt="Event"
            width="15rem"
            image={event?.imgUrl}
            title="Angel City Event"
          />
        </Box>
        <CardContent className={classes.content}>
          <Typography
            className={classes.cardDate}
            variant="body2"
            color="textSecondary"
            component="p"
          >
            {event.startDate} - {event.endDate}
          </Typography>
          <Typography
            className={classes.cardTitle}
            gutterBottom
            variant="h5"
            component="h2"
          >
            {event.title}
          </Typography>
          <Typography
            className={classes.cardLoc}
            variant="body2"
            color="textSecondary"
            component="p"
          >
            {event.location}
          </Typography>
        </CardContent>
      </CardActionArea>
      <CardActions className={classes.btnContainer}>
        <SimpleModal event={event} registerEvent={registerEvent} />
      </CardActions>
    </Card>
  );
}
Example #14
Source File: Rules.js    From gitlab-lint-react with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
Rules = () => {
  const classes = useStyles();
  const [rows, setData] = useState({});
  const fetchData = () => {
    GitlabLintHttpClient("GET_ALL", { entity: "rules" })
      .then((data) => {
        setData(data.data);
      })
      .catch((err) => console.error(err));
  };

  useEffect(() => {
    fetchData();
  }, []);

  if (Object.keys(rows).length === 0 && rows.constructor === Object) {
    return <Loading />;
  }

  return (
    <React.Fragment>
      <Typography variant="h4" paragraph>
        Rules
      </Typography>

      <Grid container spacing={4}>
        {rows.map((row) => {
          return (
            <Grid item key={row.ruleId} xs={12} sm={6} md={4}>
              <Card className={classes.root}>
                <CardActionArea component={Link} to={`rules/${row.ruleId}`}>
                  <CardHeader
                    className={classes[row.level]}
                    classes={{ title: classes["title"] }}
                    title={row.level}
                  />
                  <CardContent>
                    <Typography gutterBottom variant="h5" component="h2">
                      {row.name}
                    </Typography>
                    {row.description && (
                      <Typography
                        variant="body2"
                        color="textSecondary"
                        component="p"
                      >
                        {row.description}
                      </Typography>
                    )}
                  </CardContent>
                </CardActionArea>
                <CardActions>
                  <Button
                    component={Link}
                    size="small"
                    color="secondary"
                    to={`/rules/${row.ruleId}`}
                  >
                    Show projects
                  </Button>
                </CardActions>
              </Card>
            </Grid>
          );
        })}
      </Grid>
    </React.Fragment>
  );
}
Example #15
Source File: ProjectCard.jsx    From Design-Initiative-Dashboard-frontend with GNU General Public License v3.0 5 votes vote down vote up
export default function ProjectCard() {
  const classes = useStyles();
  const history = useHistory();

  function handleChange(){
    history.push('./ProjectDetails');
  }
  

  return (
    <React.Fragment>
      {cardData.map((data) => (
        <Card className={classes.root}>
          <CardActionArea>
            <div className={classes.details}>
              <CardMedia
                className={classes.im}
                component="img"
                alt="org-logo"
                height="140"
                src={data.image}
                title="Organisation card"
              />
              <CardContent className={classes.content}>
                <Typography
                  variant="h5"
                  component="h2"
                  align="left"
                  className={classes.pos1}
                >
                  {data.title}

                  {data.features.map((f) => (
                    <Button
                      variant="contained"
                      color="primary"
                      size="small"
                      className={classes.cap}
                    >
                      {f.name}
                    </Button>
                  ))}
                </Typography>

                <Typography
                  variant="body2"
                  color="textSecondary"
                  component="p"
                  align="left"
                  className={classes.pos2}
                >
                  {data.desc}
                </Typography>
              </CardContent>
            </div>
          </CardActionArea>
          <div>
            <CardActions>
              <Button size="small" color="primary" className={classes.btn} onClick={handleChange}>
                View more
              </Button>
            </CardActions>
          </div>
        </Card>
      ))}
    </React.Fragment>
  );
}
Example #16
Source File: Gallery.js    From eSim-Cloud with GNU General Public License v3.0 5 votes vote down vote up
// Card displaying overview of gallery sample schematics.
function SchematicCard ({ sch }) {
  const classes = useStyles()
  const auth = useSelector(state => state.authReducer)
  const dispatch = useDispatch()
  const [snacOpen, setSnacOpen] = React.useState(false)

  const handleSnacClick = () => {
    setSnacOpen(true)
  }
  const handleSnacClose = (event, reason) => {
    if (reason === 'clickaway') {
      return
    }
    setSnacOpen(false)
  }
  useEffect(() => {
    dispatch(fetchRole())
  }, [dispatch])

  return (
    <>
      <Card>
        <ButtonBase
          target="_blank"
          component={RouterLink}
          to={'/editor?id=' + sch.save_id}
          style={{ width: '100%' }}
        >
          <CardActionArea>
            <CardMedia
              className={classes.media}
              image={sch.media}
              title={sch.name}
            />
            <CardContent>
              <Typography gutterBottom variant="h5" component="h2">
                {sch.name}
              </Typography>
              <Typography variant="body2" component="p">
                {sch.description}
              </Typography>
            </CardContent>
          </CardActionArea>
        </ButtonBase>

        <CardActions>
          <Button
            target="_blank"
            component={RouterLink}
            to={'/editor?id=' + sch.save_id}
            size="small"
            color="primary"
          >
            Launch in Editor
          </Button>
          {console.log(auth.roles)}
          {auth.roles && auth.roles.is_type_staff &&
            <Button onClick={() => { handleSnacClick() }}>
              <Tooltip title="Delete" placement="bottom" arrow>
                <DeleteIcon
                  color="secondary"
                  fontSize="small"
                />
              </Tooltip>
            </Button>}
          <SimpleSnackbar open={snacOpen} close={handleSnacClose} sch={sch} confirmation={deleteGallerySch} />
        </CardActions>
      </Card>
    </>
  )
}
Example #17
Source File: Project.jsx    From zubhub with GNU Affero General Public License v3.0 4 votes vote down vote up
/**
 * @function Project Component
 * @author Raymond Ndibe <[email protected]>
 *
 * @todo - describe function's signature
 */
function Project(props) {
  const classes = useStyles();
  const common_classes = useCommonStyles();

  const { project, t } = props;
  return (
    <Link to={`/projects/${project.id}`} className={classes.textDecorationNone}>
      <Card className={classes.root}>
        <CardMedia className={classes.mediaBoxStyle} title={project.title}>
          <Tooltip
            title={getPublishTypeLabel(project.publish.type)}
            placement="right-start"
            arrow
          >
            <Box className={classes.publishStyle}>
              {project.publish.type === publish_type.Draft
                ? t('project.publish.draft')
                : ''}
              {project.publish.type === publish_type.Preview
                ? t('project.publish.preview')
                : ''}
              {project.publish.type ===
              publish_type['Authenticated Creators'] ? (
                <LockIcon />
              ) : (
                ''
              )}
              {project.publish.type === publish_type.Public ? (
                <PublicIcon />
              ) : (
                ''
              )}
            </Box>
          </Tooltip>
          {project.video ? (
            <>
              <img
                className={classes.mediaImageStyle}
                src={buildVideoThumbnailURL(project.video)}
                alt={project.title}
              />
              <img className={classes.playIconStyle} src={playIcon} alt="" />
            </>
          ) : project.images.length > 0 ? (
            <img
              className={classes.mediaImageStyle}
              src={project.images[0].image_url}
              alt={project.title}
            />
          ) : null}
        </CardMedia>
        <CardActionArea className={classes.actionAreaStyle}>
          <CardContent
            className={clsx(classes.contentStyle, classes.positionRelative)}
          >
            <Fab
              className={classes.fabButtonStyle}
              size="small"
              aria-label="save button"
              onClick={(e, id = project.id) => toggleSave(e, id, props)}
            >
              {project.saved_by.includes(props.auth.id) ? (
                <BookmarkIcon aria-label="unsave" />
              ) : (
                <BookmarkBorderIcon aria-label="save" />
              )}
            </Fab>
            <Fab
              className={clsx(classes.fabButtonStyle, classes.likeButtonStyle)}
              size="small"
              aria-label="like button"
              variant="extended"
              onClick={(e, id = project.id) => toggleLike(e, id, props)}
            >
              {project.likes.includes(props.auth.id) ? (
                <ClapIcon arial-label="unlike" />
              ) : (
                <ClapBorderIcon arial-label="like" />
              )}
              {nFormatter(project.likes.length)}
            </Fab>
            <Typography
              className={classes.titleStyle}
              variant="h5"
              component="h2"
            >
              {project.title}
            </Typography>
            <Box className={classes.descriptionStyle}>
              <Typography
                variant="subtitle2"
                color="textSecondary"
                component="p"
              >
                {formatProjectDescription(project.description)}
              </Typography>
            </Box>
            <Link
              to={`/creators/${project.creator.username}`}
              className={classes.textDecorationNone}
            >
              <Box className={classes.creatorBoxStyle}>
                <Avatar
                  className={classes.creatorAvatarStyle}
                  src={project.creator.avatar}
                  alt={project.creator.username}
                />
                <Typography
                  color="textSecondary"
                  variant="caption"
                  component="p"
                >
                  {project.creator.username}
                </Typography>
                <Link
                  className={common_classes.textDecorationNone}
                  to={`/search/?q=${project.creator.tags[0]}&tab=creators`}
                >
                  <Typography
                    className={clsx(common_classes.baseTagStyle, {
                      [common_classes.extendedTagStyle]: !isBaseTag(
                        project.creator.tags[0],
                      ),
                    })}
                    component="h2"
                  >
                    {project.creator.tags[0]}
                  </Typography>
                </Link>
              </Box>
            </Link>
            <Box className={classes.captionStyle}>
              <Box className={classes.captionStyle}>
                <Typography
                  className={clsx(
                    classes.captionIconStyle,
                    classes.VisibilityIconStyle,
                  )}
                  color="textSecondary"
                  variant="caption"
                  component="span"
                >
                  <VisibilityIcon /> {project.views_count}
                </Typography>
                <Typography
                  className={classes.captionIconStyle}
                  color="textSecondary"
                  variant="caption"
                  component="span"
                >
                  <CommentIcon /> {project.comments_count}
                </Typography>
              </Box>
              <Typography
                color="textSecondary"
                variant="caption"
                component="span"
              >
                {`${dFormatter(project.created_on).value} ${t(
                  `date.${dFormatter(project.created_on).key}`,
                )} ${t('date.ago')}`}
              </Typography>
            </Box>
          </CardContent>
        </CardActionArea>
      </Card>
    </Link>
  );
}
Example #18
Source File: MyEventCard.js    From AdaptivApps-fe with MIT License 4 votes vote down vote up
export default function MyEventCard({ event, refetch }) {
  const classes = useStyles();
  const navigate = useNavigate();
  // Retrieves current user info from Auth0
  const { user } = useAuth0();
  const { data } = useQuery(GET_PARTICIPANT_IDS, {
    variables: { email: user.email, id: event.id },
    fetchPolicy: "no-cache",
  });
  const [unregisterFromAll] = useMutation(UNREGISTER_FROM_ALL);
  const [unregisterFromEventActivity] = useMutation(
    UNREGISTER_FROM_EVENT_ACTIVITY
  );
  // Unregisters user from specified event and all it's activities
  const unregisterFromEvent = async () => {
    const participantIds = data?.participants?.map(participant => {
      return participant.id;
    });

    const participantIdValue = data?.participants?.map(participant => {
      return participant.id;
    });

    const participantId = JSON.stringify(participantIdValue).replace(
      /[\[\]"]+/g,
      ""
    );

    data && data?.participants?.length === 1
      ? await unregisterFromEventActivity({
          variables: {
            id: event.id,
            email: user.email,
            participantId: participantId,
          },
        })
      : data && data?.participants === null
      ? await unregisterFromEvent({
          variables: {
            id: event.id,
            email: user.email,
          },
        })
      : await unregisterFromAll({
          variables: {
            id: event.id,
            email: user.email,
            participantIds: participantIds,
          },
        });
    await refetch();
  };
  const viewEventDetails = async () => {
    await navigate(`/myevents/${event?.id}`);
  };

  return (
    <Card className={classes.root}>
      <CardActionArea className={classes.card}>
        <Box>
          <div className={classes.banner}>{event.type}</div>
          <CardMedia
            className={classes.cardImg}
            component="img"
            alt="Event"
            width="15rem"
            image={event?.imgUrl}
            title="Angel City Event"
          />
        </Box>
        <CardContent className={classes.content}>
          <Typography
            className={classes.cardDate}
            variant="body2"
            color="textSecondary"
            component="p"
          >
            {event.startDate} - {event.endDate}
          </Typography>
          <Typography
            className={classes.cardTitle}
            gutterBottom
            variant="h5"
            component="h2"
          >
            {event.title}
          </Typography>
          <Typography
            className={classes.cardLoc}
            variant="body2"
            color="textSecondary"
            component="p"
          >
            {event.location}
          </Typography>
        </CardContent>
      </CardActionArea>
      <CardActions className={classes.btnContainer}>
        <Button onClick={viewEventDetails} className={classes.btn}>
          View Details
        </Button>
        <Button className={classes.btn} onClick={unregisterFromEvent}>
          Unregister
        </Button>
      </CardActions>
    </Card>
  );
}
Example #19
Source File: Signup.jsx    From zubhub with GNU Affero General Public License v3.0 4 votes vote down vote up
/**
 * @function Signup View
 * @author Raymond Ndibe <[email protected]>
 *
 * @todo - describe function's signature
 */
function Signup(props) {
  const classes = useStyles();

  const refs = {
    phone_el: React.useRef(null),
    location_el: React.useRef(null),
    date_of_birth_el: React.useRef(null),
  };

  const [state, setState] = React.useState({
    locations: [],
    show_password1: false,
    show_password2: false,
    tool_tip_open: false,
    subscribe_box_checked: false,
  });

  React.useEffect(() => {
    handleSetState(getLocations(props));
  }, []);

  React.useEffect(() => {
    initIntlTelInput(props, refs);
  }, [refs.phone_el]);

  React.useEffect(() => {
    setLabelWidthOfStaticFields(refs, document, props);
  }, [props.i18n.language]);

  React.useEffect(() => {
    if (props.touched['email']) {
      vars.email_field_touched = true;
    } else {
      vars.email_field_touched = false;
    }

    if (props.touched['phone']) {
      vars.phone_field_touched = true;
    } else {
      vars.phone_field_touched = false;
    }
  }, [props.touched['email'], props.touched['phone']]);

  const handleSetState = obj => {
    if (obj) {
      Promise.resolve(obj).then(obj => {
        setState(state => ({ ...state, ...obj }));
      });
    }
  };

  const {
    locations,
    tool_tip_open,
    show_password1,
    show_password2,
    subscribe_box_checked,
  } = state;
  const { t } = props;

  return (
    <Box className={classes.root}>
      <Container className={classes.containerStyle}>
        <Card className={classes.cardStyle}>
          <CardActionArea>
            <CardContent>
              <form
                className="auth-form"
                name="signup"
                noValidate="noValidate"
                onSubmit={e => signup(e, props)}
              >
                <Typography
                  gutterBottom
                  variant="h5"
                  component="h2"
                  color="textPrimary"
                  className={classes.titleStyle}
                >
                  {t('signup.welcomeMsg.primary')}
                </Typography>
                <Typography
                  className={classes.descStyle}
                  variant="body2"
                  color="textSecondary"
                  component="p"
                >
                  {t('signup.welcomeMsg.secondary')}
                </Typography>
                <Grid container spacing={3}>
                  <Grid item xs={12}>
                    <Box
                      component="p"
                      className={
                        props.status &&
                        props.status['non_field_errors'] &&
                        classes.errorBox
                      }
                    >
                      {props.status && props.status['non_field_errors'] && (
                        <Box component="span" className={classes.error}>
                          {props.status['non_field_errors']}
                        </Box>
                      )}
                    </Box>
                  </Grid>
                  <Grid item xs={12}>
                    <FormControl
                      className={clsx(classes.margin, classes.textField)}
                      variant="outlined"
                      size="small"
                      fullWidth
                      margin="normal"
                      error={
                        (props.status && props.status['username']) ||
                        (props.touched['username'] && props.errors['username'])
                      }
                    >
                      <InputLabel
                        className={classes.customLabelStyle}
                        htmlFor="username"
                      >
                        {t('signup.inputs.username.label')}
                      </InputLabel>
                      <ClickAwayListener
                        onClickAway={() => handleSetState(handleTooltipClose())}
                      >
                        <Tooltip
                          title={t('signup.tooltips.noRealName')}
                          placement="top-start"
                          arrow
                          onClose={() => handleSetState(handleTooltipClose())}
                          PopperProps={{
                            disablePortal: true,
                          }}
                          open={tool_tip_open}
                          disableFocusListener
                          disableHoverListener
                          disableTouchListener
                        >
                          <OutlinedInput
                            className={classes.customInputStyle}
                            id="username"
                            name="username"
                            type="text"
                            onClick={() => handleSetState(handleTooltipOpen())}
                            onChange={props.handleChange}
                            onBlur={props.handleBlur}
                            labelWidth={calculateLabelWidth(
                              t('signup.inputs.username.label'),
                              document,
                            )}
                          />
                        </Tooltip>
                      </ClickAwayListener>
                      <FormHelperText
                        className={classes.fieldHelperTextStyle}
                        error
                      >
                        {(props.status && props.status['username']) ||
                          (props.touched['username'] &&
                            props.errors['username'] &&
                            t(
                              `signup.inputs.username.errors.${props.errors['username']}`,
                            ))}
                      </FormHelperText>
                    </FormControl>
                  </Grid>

                  <Grid item xs={12} sm={6} md={6}>
                    <FormControl
                      className={clsx(classes.margin, classes.textField)}
                      variant="outlined"
                      size="small"
                      fullWidth
                      margin="normal"
                      error={
                        (props.status && props.status['user_location']) ||
                        (props.touched['user_location'] &&
                          props.errors['user_location'])
                      }
                    >
                      <InputLabel
                        className={classes.customLabelStyle}
                        id="user_location"
                      >
                        {t('signup.inputs.location.label')}
                      </InputLabel>
                      <Select
                        ref={refs.location_el}
                        labelId="user_location"
                        id="user_location"
                        name="user_location"
                        className={classes.customInputStyle}
                        value={
                          props.values.user_location
                            ? props.values.user_location
                            : ''
                        }
                        onChange={e => handleLocationChange(e, props)}
                        onBlur={props.handleBlur}
                        // label="Location"
                        labelWidth={calculateLabelWidth(
                          t('signup.inputs.location.label'),
                          document,
                        )}
                      >
                        <MenuItem value="">
                          <em>None</em>
                        </MenuItem>
                        {Array.isArray(locations) &&
                          locations.map(location => (
                            <MenuItem key={location.name} value={location.name}>
                              {location.name}
                            </MenuItem>
                          ))}
                      </Select>
                      <FormHelperText
                        className={classes.fieldHelperTextStyle}
                        error
                      >
                        {(props.status && props.status['user_location']) ||
                          (props.touched['user_location'] &&
                            props.errors['user_location'] &&
                            t(
                              `signup.inputs.location.errors.${props.errors['user_location']}`,
                            ))}
                      </FormHelperText>
                    </FormControl>
                  </Grid>

                  <Grid item xs={12} sm={6} md={6}>
                    <FormControl
                      className={clsx(classes.margin, classes.textField)}
                      variant="outlined"
                      size="small"
                      fullWidth
                      margin="normal"
                      error={
                        (props.status && props.status['dateOfBirth']) ||
                        (props.touched['dateOfBirth'] &&
                          props.errors['dateOfBirth'])
                      }
                    >
                      <InputLabel
                        className={classes.customLabelStyle}
                        htmlFor="dateOfBirth"
                        shrink
                      >
                        {t('signup.inputs.dateOfBirth.label')}
                      </InputLabel>
                      <OutlinedInput
                        ref={refs.date_of_birth_el}
                        className={clsx(classes.customInputStyle)}
                        id="dateOfBirth"
                        name="dateOfBirth"
                        type="date"
                        onChange={props.handleChange}
                        onBlur={props.handleBlur}
                      />
                      <FormHelperText
                        className={classes.fieldHelperTextStyle}
                        error
                      >
                        {(props.status && props.status['dateOfBirth']) ||
                          (props.touched['dateOfBirth'] &&
                            props.errors['dateOfBirth'] &&
                            t(
                              `signup.inputs.dateOfBirth.errors.${props.errors['dateOfBirth']}`,
                            ))}
                      </FormHelperText>
                    </FormControl>
                  </Grid>

                  <Grid item xs={12} sm={6} md={6}>
                    <FormControl
                      className={clsx(classes.margin, classes.textField)}
                      variant="outlined"
                      size="small"
                      fullWidth
                      margin="normal"
                      error={
                        (props.status && props.status['phone']) ||
                        (props.touched['phone'] && props.errors['phone'])
                      }
                    >
                      <InputLabel
                        className={classes.customLabelStyle}
                        shrink
                        htmlFor="phone"
                      >
                        {t('signup.inputs.phone.label')}
                      </InputLabel>
                      <OutlinedInput
                        ref={refs.phone_el}
                        className={clsx(
                          classes.customInputStyle,
                          classes.locationInputStyle,
                        )}
                        id="phone"
                        name="phone"
                        type="phone"
                        onChange={props.handleChange}
                        onBlur={props.handleBlur}
                      />
                      <FormHelperText
                        className={classes.fieldHelperTextStyle}
                        error
                      >
                        {(props.status && props.status['phone']) ||
                          (props.touched['phone'] &&
                            props.errors['phone'] &&
                            t(
                              `signup.inputs.phone.errors.${props.errors['phone']}`,
                            ))}
                      </FormHelperText>
                    </FormControl>
                  </Grid>

                  <Grid item xs={12} sm={6} md={6}>
                    <FormControl
                      className={clsx(classes.margin, classes.textField)}
                      variant="outlined"
                      size="small"
                      fullWidth
                      margin="normal"
                      error={
                        (props.status && props.status['email']) ||
                        (props.touched['email'] && props.errors['email'])
                      }
                    >
                      <InputLabel
                        className={classes.customLabelStyle}
                        htmlFor="email"
                      >
                        {t('signup.inputs.email.label')}
                      </InputLabel>
                      <OutlinedInput
                        className={classes.customInputStyle}
                        id="email"
                        name="email"
                        type="text"
                        onChange={props.handleChange}
                        onBlur={props.handleBlur}
                        labelWidth={calculateLabelWidth(
                          t('signup.inputs.email.label'),
                          document,
                        )}
                      />
                      <FormHelperText
                        className={classes.fieldHelperTextStyle}
                        error
                      >
                        {(props.status && props.status['email']) ||
                          (props.touched['email'] &&
                            props.errors['email'] &&
                            t(
                              `signup.inputs.email.errors.${props.errors['email']}`,
                            ))}
                      </FormHelperText>
                    </FormControl>
                  </Grid>

                  <Grid item xs={12} sm={6} md={6}>
                    <FormControl
                      className={clsx(classes.margin, classes.textField)}
                      variant="outlined"
                      size="small"
                      fullWidth
                      margin="normal"
                      error={
                        (props.status && props.status['password1']) ||
                        (props.touched['password1'] &&
                          props.errors['password1'])
                      }
                    >
                      <InputLabel
                        className={classes.customLabelStyle}
                        htmlFor="password1"
                      >
                        {t('signup.inputs.password1.label')}
                      </InputLabel>
                      <OutlinedInput
                        className={classes.customInputStyle}
                        id="password1"
                        name="password1"
                        type={show_password1 ? 'text' : 'password'}
                        onChange={props.handleChange}
                        onBlur={props.handleBlur}
                        endAdornment={
                          <InputAdornment position="end">
                            <IconButton
                              aria-label={t(
                                'signup.ariaLabel.togglePasswordVisibility',
                              )}
                              onClick={() =>
                                setState({
                                  ...state,
                                  show_password1: !show_password1,
                                })
                              }
                              onMouseDown={handleMouseDownPassword}
                              edge="end"
                            >
                              {show_password1 ? (
                                <Visibility />
                              ) : (
                                <VisibilityOff />
                              )}
                            </IconButton>
                          </InputAdornment>
                        }
                        labelWidth={calculateLabelWidth(
                          t('signup.inputs.password1.label'),
                          document,
                        )}
                      />
                      <FormHelperText
                        className={classes.fieldHelperTextStyle}
                        error
                      >
                        {(props.status && props.status['password1']) ||
                          (props.touched['password1'] &&
                            props.errors['password1'] &&
                            t(
                              `signup.inputs.password1.errors.${props.errors['password1']}`,
                            ))}
                      </FormHelperText>
                    </FormControl>
                  </Grid>

                  <Grid item xs={12} sm={6} md={6}>
                    <FormControl
                      className={clsx(classes.margin, classes.textField)}
                      variant="outlined"
                      size="small"
                      fullWidth
                      margin="normal"
                      error={
                        (props.status && props.status['password2']) ||
                        (props.touched['password2'] &&
                          props.errors['password2'])
                      }
                    >
                      <InputLabel
                        className={classes.customLabelStyle}
                        htmlFor="password2"
                      >
                        {t('signup.inputs.password2.label')}
                      </InputLabel>
                      <OutlinedInput
                        className={classes.customInputStyle}
                        id="password2"
                        name="password2"
                        type={show_password2 ? 'text' : 'password'}
                        onChange={props.handleChange}
                        onBlur={props.handleBlur}
                        endAdornment={
                          <InputAdornment position="end">
                            <IconButton
                              aria-label={t(
                                'signup.ariaLabel.togglePasswordVisibility',
                              )}
                              onClick={() =>
                                setState({
                                  ...state,
                                  show_password2: !show_password2,
                                })
                              }
                              onMouseDown={handleMouseDownPassword}
                              edge="end"
                            >
                              {show_password2 ? (
                                <Visibility />
                              ) : (
                                <VisibilityOff />
                              )}
                            </IconButton>
                          </InputAdornment>
                        }
                        labelWidth={calculateLabelWidth(
                          t('signup.inputs.password2.label'),
                          document,
                        )}
                      />
                      <FormHelperText
                        className={classes.fieldHelperTextStyle}
                        error
                      >
                        {(props.status && props.status['password2']) ||
                          (props.touched['password2'] &&
                            props.errors['password2'] &&
                            t(
                              `signup.inputs.password2.errors.${props.errors['password2']}`,
                            ))}
                      </FormHelperText>
                    </FormControl>
                  </Grid>

                  <Grid item xs={12}>
                    <FormControl
                      className={clsx(classes.margin, classes.textField)}
                      variant="outlined"
                      size="small"
                      fullWidth
                      margin="small"
                      error={
                        (props.status && props.status['bio']) ||
                        (props.touched['bio'] && props.errors['bio'])
                      }
                    >
                      <InputLabel
                        className={classes.customLabelStyle}
                        htmlFor="bio"
                      >
                        {t('signup.inputs.bio.label')}
                      </InputLabel>
                      <OutlinedInput
                        className={classes.customInputStyle}
                        id="bio"
                        name="bio"
                        type="text"
                        multiline
                        rows={6}
                        rowsMax={6}
                        onChange={props.handleChange}
                        onBlur={props.handleBlur}
                        labelWidth={calculateLabelWidth(
                          t('signup.inputs.bio.label'),
                          document,
                        )}
                      />
                      <FormHelperText
                        className={classes.fieldHelperTextStyle}
                        error
                      >
                        <Typography
                          color="textSecondary"
                          variant="caption"
                          component="span"
                          className={classes.fieldHelperTextStyle}
                        >
                          {t('signup.inputs.bio.helpText')}
                        </Typography>
                        <br />
                        {(props.status && props.status['bio']) ||
                          (props.touched['bio'] &&
                            props.errors['bio'] &&
                            t(
                              `signup.inputs.bio.errors.${props.errors['bio']}`,
                            ))}
                      </FormHelperText>
                    </FormControl>
                  </Grid>
                  <Grid item xs={12}>
                    <FormControlLabel
                      value={subscribe_box_checked}
                      onChange={e =>
                        handleSetState(
                          handleToggleSubscribeBox(e, props, state),
                        )
                      }
                      control={
                        <Checkbox
                          name="subscribe"
                          id="subscribe"
                          color="primary"
                        />
                      }
                      label={
                        <Typography
                          color="textSecondary"
                          variant="caption"
                          component="span"
                          className={classes.fieldHelperTextStyle}
                        >
                          {t('signup.unsubscribe')}
                        </Typography>
                      }
                      labelPlacement="end"
                    />
                  </Grid>

                  <Grid item xs={12}>
                    <CustomButton
                      variant="contained"
                      size="large"
                      primaryButtonStyle
                      type="submit"
                      fullWidth
                      customButtonStyle
                    >
                      {t('signup.inputs.submit')}
                    </CustomButton>
                  </Grid>
                </Grid>
              </form>
              <Grid container spacing={3}>
                <Grid item xs={12}>
                  <Box className={classes.center}>
                    <Divider className={classes.divider} />
                    <Typography
                      variant="body2"
                      color="textSecondary"
                      component="p"
                    >
                      {t('signup.alreadyAMember')}
                    </Typography>
                    <Divider className={classes.divider} />
                  </Box>
                </Grid>
                <Grid item xs={12}>
                  <Link to="/login" className={classes.textDecorationNone}>
                    <CustomButton
                      variant="outlined"
                      size="large"
                      secondaryButtonStyle
                      customButtonStyle
                      fullWidth
                    >
                      {t('signup.login')}
                    </CustomButton>
                  </Link>
                </Grid>
              </Grid>
            </CardContent>
          </CardActionArea>
        </Card>
      </Container>
    </Box>
  );
}
Example #20
Source File: PhoneConfirm.jsx    From zubhub with GNU Affero General Public License v3.0 4 votes vote down vote up
/**
 * @function PhoneConfirm View
 * @author Raymond Ndibe <[email protected]>
 *
 * @todo - describe function's signature
 */
function PhoneConfirm(props) {
  const classes = useStyles();

  let { username, key } = getUsernameAndKey(props.location.search);

  const [state, setState] = React.useState({
    username: username ?? null,
    key: key ?? null,
    errors: null,
  });

  const handleSetState = obj => {
    if (obj) {
      Promise.resolve(obj).then(obj => {
        setState(state => ({ ...state, ...obj }));
      });
    }
  };

  username = state.username;
  let errors = state.errors;
  const { t } = props;

  return (
    <Box className={classes.root}>
      <Container className={classes.containerStyle}>
        <Card className={classes.cardStyle}>
          <CardActionArea>
            <CardContent>
              <form
                className="auth-form"
                name="phone_confirm"
                noValidate="noValidate"
                onSubmit={e => handleSetState(confirmPhone(e, props, state))}
              >
                <Typography
                  gutterBottom
                  variant="h5"
                  component="h2"
                  color="textPrimary"
                  className={classes.titleStyle}
                >
                  {t('phoneConfirm.welcomeMsg.primary')}
                </Typography>
                <Typography
                  className={classes.descStyle}
                  variant="body2"
                  color="textSecondary"
                  component="p"
                >
                  {t('phoneConfirm.welcomeMsg.secondary').replace(
                    '<>',
                    username,
                  )}
                </Typography>

                <Grid container spacing={3}>
                  <Grid item xs={12}>
                    <Box component="p" className={errors && classes.errorBox}>
                      {errors && (
                        <Box component="span" className={classes.error}>
                          {errors}
                        </Box>
                      )}
                    </Box>
                  </Grid>
                  <Grid item xs={12}>
                    <CustomButton
                      variant="contained"
                      size="large"
                      type="submit"
                      fullWidth
                      primaryButtonStyle
                      customButtonStyle
                    >
                      {t('phoneConfirm.inputs.submit')}
                    </CustomButton>
                  </Grid>
                </Grid>
              </form>
            </CardContent>
          </CardActionArea>
        </Card>
      </Container>
    </Box>
  );
}
Example #21
Source File: PasswordResetConfirm.jsx    From zubhub with GNU Affero General Public License v3.0 4 votes vote down vote up
/**
 * @function PasswordResetConfirm View
 * @author Raymond Ndibe <[email protected]>
 *
 * @todo - describe function's signature
 */
function PasswordResetConfirm(props) {
  const classes = useStyles();

  const [state, setState] = React.useState({
    show_password1: false,
    show_password2: false,
  });

  const handleSetState = obj => {
    if (obj) {
      Promise.resolve(obj).then(obj => {
        setState(state => ({ ...state, ...obj }));
      });
    }
  };

  const { show_password1, show_password2 } = state;
  const { t } = props;

  return (
    <Box className={classes.root}>
      <Container className={classes.containerStyle}>
        <Card className={classes.cardStyle}>
          <CardActionArea>
            <CardContent>
              <form
                className="auth-form"
                name="password_reset_confirm"
                noValidate="noValidate"
                onSubmit={e => resetPassword(e, props)}
              >
                <Typography
                  gutterBottom
                  variant="h5"
                  component="h2"
                  color="textPrimary"
                  className={classes.titleStyle}
                >
                  {t('passwordResetConfirm.welcomeMsg.primary')}
                </Typography>
                <Grid container spacing={3}>
                  <Grid item xs={12}>
                    <Box
                      component="p"
                      className={
                        props.status &&
                        props.status['non_field_errors'] &&
                        classes.errorBox
                      }
                    >
                      {props.status && props.status['non_field_errors'] && (
                        <Box component="span" className={classes.error}>
                          {props.status['non_field_errors']}
                        </Box>
                      )}
                    </Box>
                  </Grid>

                  <Grid item xs={12} sm={6} md={6}>
                    <FormControl
                      className={clsx(classes.margin, classes.textField)}
                      variant="outlined"
                      size="small"
                      fullWidth
                      margin="normal"
                      error={
                        (props.status && props.status['new_password1']) ||
                        (props.touched['new_password1'] &&
                          props.errors['new_password1'])
                      }
                    >
                      <InputLabel
                        className={classes.customLabelStyle}
                        htmlFor="new_password1"
                      >
                        {t('passwordResetConfirm.inputs.newPassword1.label')}
                      </InputLabel>
                      <OutlinedInput
                        className={classes.customInputStyle}
                        id="new_password1"
                        name="new_password1"
                        type={show_password1 ? 'text' : 'password'}
                        onChange={props.handleChange}
                        onBlur={props.handleBlur}
                        endAdornment={
                          <InputAdornment position="end">
                            <IconButton
                              aria-label="toggle password visibility"
                              onClick={(_, field = 1) =>
                                handleSetState(
                                  handleClickShowPassword(field, state),
                                )
                              }
                              onMouseDown={handleMouseDownPassword}
                              edge="end"
                            >
                              {show_password1 ? (
                                <Visibility />
                              ) : (
                                <VisibilityOff />
                              )}
                            </IconButton>
                          </InputAdornment>
                        }
                        labelWidth={calculateLabelWidth(
                          t('passwordResetConfirm.inputs.newPassword1.label'),
                          document,
                        )}
                      />
                      <FormHelperText
                        className={classes.fieldHelperTextStyle}
                        error
                      >
                        {(props.status && props.status['new_password1']) ||
                          (props.touched['new_password1'] &&
                            props.errors['new_password1'] &&
                            t(
                              `passwordResetConfirm.inputs.newPassword1.errors.${props.errors['new_password1']}`,
                            ))}
                      </FormHelperText>
                    </FormControl>
                  </Grid>

                  <Grid item xs={12} sm={6} md={6}>
                    <FormControl
                      className={clsx(classes.margin, classes.textField)}
                      variant="outlined"
                      size="small"
                      fullWidth
                      margin="normal"
                      error={
                        (props.status && props.status['new_password2']) ||
                        (props.touched['new_password2'] &&
                          props.errors['new_password2'])
                      }
                    >
                      <InputLabel
                        className={classes.customLabelStyle}
                        htmlFor="new_password2"
                      >
                        {t('passwordResetConfirm.inputs.newPassword2.label')}
                      </InputLabel>
                      <OutlinedInput
                        className={classes.customInputStyle}
                        id="new_password2"
                        name="new_password2"
                        type={show_password2 ? 'text' : 'password'}
                        onChange={props.handleChange}
                        onBlur={props.handleBlur}
                        endAdornment={
                          <InputAdornment position="end">
                            <IconButton
                              aria-label="toggle password visibility"
                              onClick={(_, field = 2) =>
                                handleSetState(
                                  handleClickShowPassword(field, state),
                                )
                              }
                              onMouseDown={handleMouseDownPassword}
                              edge="end"
                            >
                              {show_password2 ? (
                                <Visibility />
                              ) : (
                                <VisibilityOff />
                              )}
                            </IconButton>
                          </InputAdornment>
                        }
                        labelWidth={calculateLabelWidth(
                          t('passwordResetConfirm.inputs.newPassword2.label'),
                          document,
                        )}
                      />
                      <FormHelperText
                        className={classes.fieldHelperTextStyle}
                        error
                      >
                        {(props.status && props.status['new_password2']) ||
                          (props.touched['new_password2'] &&
                            props.errors['new_password2'] &&
                            t(
                              `passwordResetConfirm.inputs.newPassword2.errors.${props.errors['new_password2']}`,
                            ))}
                      </FormHelperText>
                    </FormControl>
                  </Grid>
                  <Grid item xs={12}>
                    <CustomButton
                      variant="contained"
                      size="large"
                      type="submit"
                      primaryButtonStyle
                      customButtonStyle
                      fullWidth
                    >
                      {t('passwordResetConfirm.inputs.submit')}
                    </CustomButton>
                  </Grid>
                </Grid>
              </form>
            </CardContent>
          </CardActionArea>
        </Card>
      </Container>
    </Box>
  );
}
Example #22
Source File: PasswordReset.jsx    From zubhub with GNU Affero General Public License v3.0 4 votes vote down vote up
/**
 * @function PasswordReset View
 * @author Raymond Ndibe <[email protected]>
 *
 * @todo - describe function's signature
 */
function PasswordReset(props) {
  const classes = useStyles();
  const { t } = props;

  return (
    <Box className={classes.root}>
      <Container className={classes.containerStyle}>
        <Card className={classes.cardStyle}>
          <CardActionArea>
            <CardContent>
              <form
                className="auth-form"
                name="password_reset"
                noValidate="noValidate"
                onSubmit={e => sendPasswordResetLink(e, props)}
              >
                <Typography
                  gutterBottom
                  variant="h5"
                  component="h2"
                  color="textPrimary"
                  className={classes.titleStyle}
                >
                  {t('passwordReset.welcomeMsg.primary')}
                </Typography>
                <Typography
                  className={classes.descStyle}
                  variant="body2"
                  color="textSecondary"
                  component="p"
                >
                  {t('passwordReset.welcomeMsg.secondary')}
                </Typography>
                <Grid container spacing={3}>
                  <Grid item xs={12}>
                    <Box
                      component="p"
                      className={
                        props.status &&
                        props.status['non_field_errors'] &&
                        classes.errorBox
                      }
                    >
                      {props.status && props.status['non_field_errors'] && (
                        <Box component="span" className={classes.error}>
                          {props.status['non_field_errors']}
                        </Box>
                      )}
                    </Box>
                  </Grid>
                  <Grid item xs={12}>
                    <FormControl
                      className={clsx(classes.margin, classes.textField)}
                      variant="outlined"
                      size="small"
                      fullWidth
                      margin="normal"
                      error={
                        (props.status && props.status['email']) ||
                        (props.touched['email'] && props.errors['email'])
                      }
                    >
                      <InputLabel
                        className={classes.customLabelStyle}
                        htmlFor="email"
                      >
                        {t('passwordReset.inputs.email.label')}
                      </InputLabel>
                      <OutlinedInput
                        className={classes.customInputStyle}
                        id="email"
                        name="email"
                        type="text"
                        onChange={props.handleChange}
                        onBlur={props.handleBlur}
                        labelWidth={calculateLabelWidth(
                          t('passwordReset.inputs.email.label'),
                          document,
                        )}
                      />
                      <FormHelperText
                        className={classes.fieldHelperTextStyle}
                        error
                      >
                        {(props.status && props.status['email']) ||
                          (props.touched['email'] &&
                            props.errors['email'] &&
                            t(
                              `passwordReset.inputs.email.errors.${props.errors['email']}`,
                            ))}
                      </FormHelperText>
                    </FormControl>
                  </Grid>
                  <Grid item xs={12}>
                    <CustomButton
                      variant="contained"
                      size="large"
                      primaryButtonStyle
                      customButtonStyle
                      type="submit"
                      fullWidth
                    >
                      {t('passwordReset.inputs.submit')}
                    </CustomButton>
                  </Grid>
                </Grid>
              </form>
            </CardContent>
          </CardActionArea>
        </Card>
      </Container>
    </Box>
  );
}
Example #23
Source File: Login.jsx    From zubhub with GNU Affero General Public License v3.0 4 votes vote down vote up
/**
 * @function Login View
 * @author Raymond Ndibe <[email protected]>
 *
 * @todo - describe function's signature
 */
function Login(props) {
  const classes = useStyles();

  const [state, setState] = React.useState({
    show_password: false,
  });

  const handleSetState = obj => {
    if (obj) {
      Promise.resolve(obj).then(obj => {
        setState(state => ({ ...state, ...obj }));
      });
    }
  };

  const { show_password } = state;
  const { t } = props;

  return (
    <Box className={classes.root}>
      <Container className={classes.containerStyle}>
        <Card className={classes.cardStyle}>
          <CardActionArea>
            <CardContent>
              <form
                className="auth-form"
                name="login"
                noValidate="noValidate"
                onSubmit={e => handleSetState(login(e, props))}
              >
                <Typography
                  gutterBottom
                  variant="h5"
                  component="h2"
                  color="textPrimary"
                  className={classes.titleStyle}
                >
                  {t('login.welcomeMsg.primary')}
                </Typography>
                <Typography
                  className={classes.descStyle}
                  variant="body2"
                  color="textSecondary"
                  component="p"
                >
                  {t('login.welcomeMsg.secondary')}
                </Typography>
                <Grid container spacing={3}>
                  <Grid item xs={12}>
                    <Box
                      component="p"
                      className={
                        props.status &&
                        props.status['non_field_errors'] &&
                        classes.errorBox
                      }
                    >
                      {props.status && props.status['non_field_errors'] && (
                        <Box component="span" className={classes.error}>
                          {props.status['non_field_errors']}
                        </Box>
                      )}
                    </Box>
                  </Grid>
                  <Grid item xs={12} sm={6} md={6}>
                    <FormControl
                      className={clsx(classes.margin, classes.textField)}
                      variant="outlined"
                      size="small"
                      fullWidth
                      margin="normal"
                      error={
                        (props.status && props.status['username']) ||
                        (props.touched['username'] && props.errors['username'])
                      }
                    >
                      <InputLabel
                        className={classes.customLabelStyle}
                        htmlFor="username"
                      >
                        {t('login.inputs.username.label')}
                      </InputLabel>
                      <OutlinedInput
                        className={classes.customInputStyle}
                        id="username"
                        name="username"
                        type="text"
                        onChange={props.handleChange}
                        onBlur={props.handleBlur}
                        labelWidth={calculateLabelWidth(
                          t('login.inputs.username.label'),
                          document,
                        )}
                      />
                      <FormHelperText
                        className={classes.fieldHelperTextStyle}
                        error
                      >
                        {(props.status && props.status['username']) ||
                          (props.touched['username'] &&
                            props.errors['username'] &&
                            t(
                              `login.inputs.username.errors.${props.errors['username']}`,
                            ))}
                      </FormHelperText>
                    </FormControl>
                  </Grid>

                  <Grid item xs={12} sm={6} md={6}>
                    <FormControl
                      className={clsx(classes.margin, classes.textField)}
                      variant="outlined"
                      size="small"
                      fullWidth
                      margin="normal"
                      error={
                        (props.status && props.status['password']) ||
                        (props.touched['password'] && props.errors['password'])
                      }
                    >
                      <InputLabel
                        className={classes.customLabelStyle}
                        htmlFor="password"
                      >
                        {t('login.inputs.password.label')}
                      </InputLabel>
                      <OutlinedInput
                        className={classes.customInputStyle}
                        id="password"
                        name="password"
                        type={show_password ? 'text' : 'password'}
                        onChange={props.handleChange}
                        onBlur={props.handleBlur}
                        endAdornment={
                          <InputAdornment position="end">
                            <IconButton
                              aria-label="toggle password visibility"
                              onClick={() =>
                                handleSetState(handleClickShowPassword(state))
                              }
                              onMouseDown={handleMouseDownPassword}
                              edge="end"
                            >
                              {show_password ? (
                                <Visibility />
                              ) : (
                                <VisibilityOff />
                              )}
                            </IconButton>
                          </InputAdornment>
                        }
                        labelWidth={calculateLabelWidth(
                          t('login.inputs.password.label'),
                          document,
                        )}
                      />
                      <FormHelperText
                        className={classes.fieldHelperTextStyle}
                        error
                      >
                        {(props.status && props.status['password']) ||
                          (props.touched['password'] &&
                            props.errors['password'] &&
                            t(
                              `login.inputs.password.errors.${props.errors['password']}`,
                            ))}
                      </FormHelperText>
                    </FormControl>
                  </Grid>
                  <Grid item xs={12}>
                    <CustomButton
                      variant="contained"
                      size="large"
                      type="submit"
                      primaryButtonStyle
                      customButtonStyle
                      fullWidth
                    >
                      {t('login.inputs.submit')}
                    </CustomButton>
                  </Grid>
                </Grid>
              </form>
              <Grid container spacing={3}>
                <Grid item xs={12}>
                  <Box className={classes.center}>
                    <Divider className={classes.divider} />
                    <Typography
                      className={classes.dividerText}
                      variant="body2"
                      color="textSecondary"
                      component="p"
                    >
                      {t('login.notAMember')}
                    </Typography>
                    <Divider className={classes.divider} />
                  </Box>
                </Grid>
                <Grid item xs={12}>
                  <Link to="/signup" className={classes.textDecorationNone}>
                    <CustomButton
                      variant="outlined"
                      size="large"
                      secondaryButtonStyle
                      customButtonStyle
                      fullWidth
                    >
                      {t('login.signup')}
                    </CustomButton>
                  </Link>
                </Grid>
                <Grid item xs={12}>
                  <Box className={classes.center}>
                    <Link
                      to="/password-reset"
                      className={classes.secondaryLink}
                    >
                      {t('login.forgotPassword')}
                    </Link>
                  </Box>
                </Grid>
              </Grid>
            </CardContent>
          </CardActionArea>
        </Card>
      </Container>
    </Box>
  );
}
Example #24
Source File: GroupInviteConfirm.jsx    From zubhub with GNU Affero General Public License v3.0 4 votes vote down vote up
/**
 * @function GroupInviteConfirm
 * @author Raymond Ndibe <[email protected]>
 *
 * @todo - describe function's signature
 */
function GroupInviteConfirm(props) {
  const classes = useStyles();

  let { username, key } = getUsernameAndKey(props.location.search);

  const [state, setState] = React.useState({
    username: username ?? null,
    key: key ?? null,
    errors: null,
  });

  const handleSetState = obj => {
    if (obj) {
      Promise.resolve(obj).then(obj => {
        setState({ ...state, ...obj });
      });
    }
  };

  username = state.username;
  const { t } = props;

  return (
    <Box className={classes.root}>
      <Container className={classes.containerStyle}>
        <Card className={classes.cardStyle}>
          <CardActionArea>
            <CardContent>
              <form
                className="auth-form"
                name="email_confirm"
                noValidate="noValidate"
                onSubmit={e =>
                  handleSetState(confirmGroupInvite(e, props, state))
                }
              >
                <Typography
                  gutterBottom
                  variant="h5"
                  component="h2"
                  color="textPrimary"
                  className={classes.titleStyle}
                >
                  {t('groupInviteConfirm.welcomeMsg.primary')}
                </Typography>
                <Typography
                  className={classes.descStyle}
                  variant="body2"
                  color="textSecondary"
                  component="p"
                >
                  {t('groupInviteConfirm.welcomeMsg.secondary').replace(
                    '<>',
                    username,
                  )}
                </Typography>

                <Grid container spacing={3}>
                  <Grid item xs={12}>
                    <Box
                      component="p"
                      className={
                        props.status &&
                        props.status['non_field_errors'] &&
                        classes.errorBox
                      }
                    >
                      {props.status && props.status['non_field_errors'] && (
                        <Box component="span" className={classes.error}>
                          {props.status['non_field_errors']}
                        </Box>
                      )}
                    </Box>
                  </Grid>
                  <Grid item xs={12}>
                    <CustomButton
                      variant="contained"
                      size="large"
                      type="submit"
                      fullWidth
                      primaryButtonStyle
                      customButtonStyle
                    >
                      {t('groupInviteConfirm.inputs.submit')}
                    </CustomButton>
                  </Grid>
                </Grid>
              </form>
            </CardContent>
          </CardActionArea>
        </Card>
      </Container>
    </Box>
  );
}
Example #25
Source File: EmailConfirm.jsx    From zubhub with GNU Affero General Public License v3.0 4 votes vote down vote up
/**
 * @function EmailConfirm View
 * @author Raymond Ndibe <[email protected]>
 *
 * @todo - describe function's signature
 */
function EmailConfirm(props) {
  const classes = useStyles();

  let { username, key } = getUsernameAndKey(props.location.search);

  const [state, setState] = React.useState({
    username: username ?? null,
    key: key ?? null,
    errors: null,
  });

  const handleSetState = obj => {
    if (obj) {
      Promise.resolve(obj).then(obj => {
        setState(state => ({ ...state, ...obj }));
      });
    }
  };

  username = state.username;
  const { t } = props;

  return (
    <Box className={classes.root}>
      <Container className={classes.containerStyle}>
        <Card className={classes.cardStyle}>
          <CardActionArea>
            <CardContent>
              <form
                className="auth-form"
                name="email_confirm"
                noValidate="noValidate"
                onSubmit={e => handleSetState(confirmEmail(e, props, state))}
              >
                <Typography
                  gutterBottom
                  variant="h5"
                  component="h2"
                  color="textPrimary"
                  className={classes.titleStyle}
                >
                  {t('emailConfirm.welcomeMsg.primary')}
                </Typography>
                <Typography
                  className={classes.descStyle}
                  variant="body2"
                  color="textSecondary"
                  component="p"
                >
                  {t('emailConfirm.welcomeMsg.secondary').replace(
                    '<>',
                    username,
                  )}
                </Typography>

                <Grid container spacing={3}>
                  <Grid item xs={12}>
                    <Box
                      component="p"
                      className={
                        props.status &&
                        props.status['non_field_errors'] &&
                        classes.errorBox
                      }
                    >
                      {props.status && props.status['non_field_errors'] && (
                        <Box component="span" className={classes.error}>
                          {props.status['non_field_errors']}
                        </Box>
                      )}
                    </Box>
                  </Grid>
                  <Grid item xs={12}>
                    <CustomButton
                      variant="contained"
                      size="large"
                      type="submit"
                      fullWidth
                      primaryButtonStyle
                      customButtonStyle
                    >
                      {t('emailConfirm.inputs.submit')}
                    </CustomButton>
                  </Grid>
                </Grid>
              </form>
            </CardContent>
          </CardActionArea>
        </Card>
      </Container>
    </Box>
  );
}
Example #26
Source File: EditProfile.jsx    From zubhub with GNU Affero General Public License v3.0 4 votes vote down vote up
/**
 * @function EditProfile View
 * @author Raymond Ndibe <[email protected]>
 *
 * @todo - describe function's signature
 */
function EditProfile(props) {
  const refs = {
    username_el: React.useRef(null),
    location_el: React.useRef(null),
    email_el: React.useRef(null),
    phone_el: React.useRef(null),
    bio_el: React.useRef(null),
  };

  const [state, setState] = React.useState({
    locations: [],
    tool_tip_open: false,
  });

  React.useEffect(() => {
    getProfile(refs, props);
    handleSetState(getLocations(props));
  }, []);

  const classes = useStyles();

  const handleSetState = obj => {
    if (obj) {
      Promise.resolve(obj).then(obj => {
        setState(state => ({ ...state, ...obj }));
      });
    }
  };

  const { locations, tool_tip_open } = state;
  const { t } = props;

  return (
    <Box className={classes.root}>
      <Container className={classes.containerStyle}>
        <Card className={classes.cardStyle}>
          <CardActionArea>
            <CardContent>
              <form
                className="auth-form"
                name="signup"
                noValidate="noValidate"
                onSubmit={e => editProfile(e, props, toast)}
              >
                <Typography
                  gutterBottom
                  variant="h5"
                  component="h2"
                  color="textPrimary"
                  className={classes.titleStyle}
                >
                  {t('editProfile.welcomeMsg.primary')}
                </Typography>
                <Typography
                  className={classes.descStyle}
                  variant="body2"
                  color="textSecondary"
                  component="p"
                >
                  {t('editProfile.welcomeMsg.secondary')}
                </Typography>
                <Grid container spacing={3}>
                  <Grid item xs={12}>
                    <Box
                      component="p"
                      className={
                        props.status &&
                        props.status['non_field_errors'] &&
                        classes.errorBox
                      }
                    >
                      {props.status && props.status['non_field_errors'] && (
                        <Box component="span" className={classes.error}>
                          {props.status['non_field_errors']}
                        </Box>
                      )}
                    </Box>
                  </Grid>
                  <Grid item xs={12} sm={6} md={6}>
                    <FormControl
                      className={clsx(classes.margin, classes.textField)}
                      variant="outlined"
                      size="small"
                      fullWidth
                      margin="normal"
                      error={
                        (props.status && props.status['username']) ||
                        (props.touched['username'] && props.errors['username'])
                      }
                    >
                      <InputLabel
                        className={classes.customLabelStyle}
                        htmlFor="username"
                      >
                        {t('editProfile.inputs.username.label')}
                      </InputLabel>
                      <ClickAwayListener
                        onClickAway={() => handleSetState(handleTooltipClose())}
                      >
                        <Tooltip
                          title={t('editProfile.tooltips.noRealName')}
                          placement="top-start"
                          arrow
                          onClose={() => handleSetState(handleTooltipClose())}
                          PopperProps={{
                            disablePortal: true,
                          }}
                          open={tool_tip_open}
                          disableFocusListener
                          disableHoverListener
                          disableTouchListener
                        >
                          <OutlinedInput
                            ref={refs.username_el}
                            className={clsx(classes.customInputStyle)}
                            id="username"
                            name="username"
                            type="text"
                            value={
                              props.values.username ? props.values.username : ''
                            }
                            onClick={() => handleSetState(handleTooltipOpen())}
                            onChange={props.handleChange}
                            onBlur={props.handleBlur}
                            labelWidth={calculateLabelWidth(
                              t('editProfile.inputs.username.label'),
                              document,
                            )}
                          />
                        </Tooltip>
                      </ClickAwayListener>
                      <FormHelperText
                        className={classes.fieldHelperTextStyle}
                        error
                      >
                        {(props.status && props.status['username']) ||
                          (props.touched['username'] &&
                            props.errors['username'] &&
                            t(
                              `editProfile.inputs.username.errors.${props.errors['username']}`,
                            ))}
                      </FormHelperText>
                    </FormControl>
                  </Grid>

                  <Grid item xs={12} sm={6} md={6}>
                    <FormControl
                      ref={refs.location_el}
                      className={clsx(classes.margin, classes.textField)}
                      variant="outlined"
                      size="small"
                      fullWidth
                      margin="normal"
                      error={
                        (props.status && props.status['user_location']) ||
                        (props.touched['user_location'] &&
                          props.errors['user_location'])
                      }
                    >
                      <InputLabel
                        className={classes.customLabelStyle}
                        id="user_location"
                      >
                        {t('editProfile.inputs.location.label')}
                      </InputLabel>
                      <Select
                        labelId="user_location"
                        id="user_location"
                        name="user_location"
                        className={clsx(classes.customInputStyle)}
                        value={
                          props.values.user_location
                            ? props.values.user_location
                            : ''
                        }
                        onChange={props.handleChange}
                        onBlur={props.handleBlur}
                        label="Location"
                      >
                        <MenuItem value="">
                          <em>None</em>
                        </MenuItem>
                        {Array.isArray(locations) &&
                          locations.map(location => (
                            <MenuItem key={location.name} value={location.name}>
                              {location.name}
                            </MenuItem>
                          ))}
                      </Select>
                      <FormHelperText
                        className={classes.fieldHelperTextStyle}
                        error
                      >
                        {(props.status && props.status['user_location']) ||
                          (props.touched['user_location'] &&
                            props.errors['user_location'] &&
                            t(
                              `editProfile.inputs.location.errors.${props.errors['user_location']}`,
                            ))}
                      </FormHelperText>
                    </FormControl>
                  </Grid>

                  <Grid item xs={12} sm={6} md={6}>
                    <FormControl
                      className={clsx(classes.margin, classes.textField)}
                      variant="outlined"
                      size="small"
                      fullWidth
                      margin="normal"
                      error={
                        (props.status && props.status['email']) ||
                        (props.touched['email'] && props.errors['email'])
                      }
                    >
                      <InputLabel
                        className={classes.customLabelStyle}
                        htmlFor="email"
                      >
                        {t('editProfile.inputs.email.label')}
                      </InputLabel>
                      <OutlinedInput
                        ref={refs.email_el}
                        disabled={
                          props.status && props.status['init_email']
                            ? true
                            : false
                        }
                        className={clsx(classes.customInputStyle)}
                        id="email"
                        name="email"
                        type="text"
                        value={props.values.email ? props.values.email : ''}
                        onChange={props.handleChange}
                        onBlur={props.handleBlur}
                        labelWidth={calculateLabelWidth(
                          t('editProfile.inputs.email.label'),
                          document,
                        )}
                      />
                      <FormHelperText
                        className={classes.fieldHelperTextStyle}
                        error
                      >
                        {props.status && props.status['init_email'] && (
                          <Typography
                            color="textSecondary"
                            variant="caption"
                            component="span"
                            className={classes.fieldHelperTextStyle}
                          >
                            {t('editProfile.inputs.email.disabledHelperText')}
                          </Typography>
                        )}
                        <br />
                        {(props.status && props.status['email']) ||
                          (props.touched['email'] &&
                            props.errors['email'] &&
                            t(
                              `editProfile.inputs.email.errors.${props.errors['email']}`,
                            ))}
                      </FormHelperText>
                    </FormControl>
                  </Grid>

                  <Grid item xs={12} sm={6} md={6}>
                    <FormControl
                      className={clsx(classes.margin, classes.textField)}
                      variant="outlined"
                      size="small"
                      fullWidth
                      margin="normal"
                      error={
                        (props.status && props.status['phone']) ||
                        (props.touched['phone'] && props.errors['phone'])
                      }
                    >
                      <InputLabel
                        className={classes.customLabelStyle}
                        htmlFor="phone"
                      >
                        {t('editProfile.inputs.phone.label')}
                      </InputLabel>
                      <OutlinedInput
                        ref={refs.phone_el}
                        disabled={
                          props.status && props.status['init_phone']
                            ? true
                            : false
                        }
                        className={clsx(classes.customInputStyle)}
                        id="phone"
                        name="phone"
                        type="phone"
                        value={props.values.phone ? props.values.phone : ''}
                        onChange={props.handleChange}
                        onBlur={props.handleBlur}
                        labelWidth={calculateLabelWidth(
                          t('editProfile.inputs.phone.label'),
                          document,
                        )}
                      />
                      <FormHelperText
                        className={classes.fieldHelperTextStyle}
                        error
                      >
                        {props.status && props.status['init_phone'] && (
                          <Typography
                            color="textSecondary"
                            variant="caption"
                            component="span"
                            className={classes.fieldHelperTextStyle}
                          >
                            {t('editProfile.inputs.phone.disabledHelperText')}
                          </Typography>
                        )}
                        <br />
                        {(props.status && props.status['phone']) ||
                          (props.touched['phone'] &&
                            props.errors['phone'] &&
                            t(
                              `editProfile.inputs.phone.errors.${props.errors['phone']}`,
                            ))}
                      </FormHelperText>
                    </FormControl>
                  </Grid>

                  <Grid item xs={12}>
                    <FormControl
                      className={clsx(classes.margin, classes.textField)}
                      variant="outlined"
                      size="small"
                      fullWidth
                      margin="small"
                      error={
                        (props.status && props.status['bio']) ||
                        (props.touched['bio'] && props.errors['bio'])
                      }
                    >
                      <InputLabel
                        className={classes.customLabelStyle}
                        htmlFor="bio"
                      >
                        {t('editProfile.inputs.bio.label')}
                      </InputLabel>
                      <OutlinedInput
                        ref={refs.bio_el}
                        className={clsx(classes.customInputStyle)}
                        id="bio"
                        name="bio"
                        type="text"
                        multiline
                        rows={6}
                        rowsMax={6}
                        value={props.values.bio ? props.values.bio : ''}
                        onChange={props.handleChange}
                        onBlur={props.handleBlur}
                        labelWidth={calculateLabelWidth(
                          t('editProfile.inputs.bio.label'),
                          document,
                        )}
                      />
                      <FormHelperText
                        className={classes.fieldHelperTextStyle}
                        error
                      >
                        <Typography
                          color="textSecondary"
                          variant="caption"
                          component="span"
                          className={classes.fieldHelperTextStyle}
                        >
                          {t('editProfile.inputs.bio.helpText')}
                        </Typography>
                        <br />
                        {(props.status && props.status['bio']) ||
                          (props.touched['bio'] &&
                            props.errors['bio'] &&
                            t(
                              `editProfile.inputs.bio.errors.${props.errors['bio']}`,
                            ))}
                      </FormHelperText>
                    </FormControl>
                  </Grid>

                  <Grid item xs={12}>
                    <CustomButton
                      variant="contained"
                      size="large"
                      primaryButtonStyle
                      type="submit"
                      fullWidth
                      customButtonStyle
                    >
                      {t('editProfile.inputs.submit')}
                    </CustomButton>
                  </Grid>
                </Grid>
              </form>
              <Grid container spacing={3}>
                <Grid item xs={12}>
                  <Box className={classes.center}>
                    <Divider className={classes.divider} />
                    <Typography
                      variant="body2"
                      color="textSecondary"
                      component="p"
                    >
                      {t('editProfile.or')}
                    </Typography>
                    <Divider className={classes.divider} />
                  </Box>
                </Grid>
                <Grid item xs={12}>
                  <Link to="/profile" className={classes.textDecorationNone}>
                    <CustomButton
                      variant="outlined"
                      size="large"
                      secondaryButtonStyle
                      customButtonStyle
                      fullWidth
                    >
                      {t('editProfile.backToProfile')}
                    </CustomButton>
                  </Link>
                </Grid>
              </Grid>
            </CardContent>
          </CardActionArea>
        </Card>
      </Container>
    </Box>
  );
}
Example #27
Source File: CreateProject.jsx    From zubhub with GNU Affero General Public License v3.0 4 votes vote down vote up
/**
 * @function CreateProject View
 * @author Raymond Ndibe <[email protected]>
 *
 * @todo - describe function's signature
 */
function CreateProject(props) {
  const [category, setCategory] = React.useState([]);

  const classes = useStyles();
  const common_classes = useCommonStyles();

  const refs = {
    title_el: React.useRef(null),
    desc_el: React.useRef(null),
    image_el: React.useRef(null),
    image_upload_button_el: React.useRef(null),
    video_upload_button_el: React.useRef(null),
    image_count_el: React.useRef(null),
    video_el: React.useRef(null),
    video_file_el: React.useRef(null),
    video_selection_feedback_el: React.useRef(null),
    add_materials_used_el: React.useRef(null),
    add_tags_el: React.useRef(null),
    publish_type_el: React.useRef(null),
    publish_visible_to_el: React.useRef(null),
  };

  const [state, setState] = React.useState({
    ...JSON.parse(JSON.stringify(vars.default_state)),
  });

  React.useEffect(() => {
    if (props.match.params.id) {
      Promise.all([getProject(refs, props, state), getCategories(props)]).then(
        result => handleSetState({ ...result[0], ...result[1] }),
      );
    } else {
      handleSetState(getCategories(props));
    }
    handleSetState(buildPublishTypes(props));
  }, []);

  React.useEffect(() => {
    checkMediaFilesErrorState(refs, props);
  }, [
    props.errors['project_images'],
    props.touched['project_images'],
    props.errors['video'],
    props.touched['video'],
  ]);

  const handleSetState = obj => {
    if (obj) {
      Promise.resolve(obj).then(obj => {
        setState(state => ({ ...state, ...obj }));
      });
    }
  };

  const {
    desc_input_is_focused,
    video_upload_dialog_open,
    media_upload,
    categories,
    tag_suggestion,
    tag_suggestion_open,
    select_video_file,
    publish_types,
    publish_visible_to_suggestion_open,
    publish_visible_to_suggestion,
  } = state;
  const { t } = props;
  const id = props.match.params.id;
  if (!props.auth.token) {
    return <ErrorPage error={t('createProject.errors.notLoggedIn')} />;
  } else {
    return (
      <Box className={classes.root}>
        <Container className={classes.containerStyle}>
          <Card className={classes.cardStyle}>
            <CardActionArea>
              <CardContent>
                <form
                  className="project-create-form"
                  name="create_project"
                  noValidate="noValidate"
                  onSubmit={e =>
                    !vars.upload_in_progress
                      ? initUpload(e, state, props, handleSetState)
                      : e.preventDefault()
                  }
                >
                  <Typography
                    className={classes.titleStyle}
                    gutterBottom
                    variant="h5"
                    component="h2"
                    color="textPrimary"
                  >
                    {!id
                      ? t('createProject.welcomeMsg.primary')
                      : t('createProject.inputs.edit')}
                  </Typography>
                  <Typography
                    variant="body2"
                    color="textSecondary"
                    component="p"
                    className={classes.descStyle}
                  >
                    {t('createProject.welcomeMsg.secondary')}
                  </Typography>

                  <Grid container spacing={3}>
                    <Grid item xs={12}>
                      <Box
                        component="p"
                        className={
                          props.status &&
                          props.status['non_field_errors'] &&
                          classes.errorBox
                        }
                      >
                        {props.status && props.status['non_field_errors'] && (
                          <Box component="span" className={classes.error}>
                            {props.status['non_field_errors']}
                          </Box>
                        )}
                      </Box>
                    </Grid>

                    <Grid item xs={12} className={common_classes.marginTop1em}>
                      <FormControl
                        className={clsx(classes.margin, classes.textField)}
                        variant="outlined"
                        size="small"
                        fullWidth
                        margin="small"
                        error={
                          (props.status && props.status['title']) ||
                          (props.touched['title'] && props.errors['title'])
                        }
                      >
                        <label htmlFor="title">
                          <Typography
                            color="textSecondary"
                            className={clsx(
                              classes.customLabelStyle,
                              common_classes.marginBottom1em,
                            )}
                          >
                            <Box className={classes.fieldNumberStyle}>1</Box>
                            {t('createProject.inputs.title.label')}
                          </Typography>
                        </label>
                        <OutlinedInput
                          ref={refs.title_el}
                          className={classes.customInputStyle}
                          id="title"
                          name="title"
                          type="text"
                          onChange={e => handleTextFieldChange(e, props)}
                          onBlur={e => handleTextFieldBlur(e, props)}
                        />
                        <FormHelperText
                          error
                          className={classes.fieldHelperTextStyle}
                        >
                          {(props.status && props.status['title']) ||
                            (props.touched['title'] &&
                              props.errors['title'] &&
                              t(
                                `createProject.inputs.title.errors.${props.errors['title']}`,
                              ))}
                        </FormHelperText>
                      </FormControl>
                    </Grid>

                    <Grid item xs={12} className={common_classes.marginTop1em}>
                      <FormControl
                        className={clsx(classes.margin, classes.textField)}
                        variant="outlined"
                        size="small"
                        fullWidth
                        margin="small"
                      >
                        <label htmlFor="description">
                          <Typography
                            color="textSecondary"
                            className={clsx(
                              classes.customLabelStyle,
                              common_classes.marginBottom1em,
                            )}
                          >
                            <Box className={classes.fieldNumberStyle}>2</Box>
                            {t('createProject.inputs.description.label')}
                          </Typography>
                        </label>
                        <Typography
                          color="textSecondary"
                          variant="caption"
                          component="span"
                          className={clsx(
                            classes.fieldHelperTextStyle,
                            common_classes.marginBottom1em,
                          )}
                        >
                          {t('createProject.inputs.description.helperText')}
                        </Typography>
                        <ClickAwayListener
                          onClickAway={() =>
                            handleSetState({ desc_input_is_focused: false })
                          }
                        >
                          <ReactQuill
                            ref={refs.desc_el}
                            className={clsx(
                              classes.descInputStyle,
                              {
                                [classes.descInputFocusStyle]:
                                  desc_input_is_focused,
                              },
                              {
                                [classes.descInputErrorStyle]:
                                  (props.status &&
                                    props.status['description']) ||
                                  (props.touched['description'] &&
                                    props.errors['description']),
                              },
                            )}
                            modules={vars.quill.modules}
                            formats={vars.quill.formats}
                            defaultValue={''}
                            placeholder={t(
                              'createProject.inputs.description.placeholder',
                            )}
                            onChange={value =>
                              handleDescFieldChange(
                                value,
                                props,
                                handleSetState,
                              )
                            }
                            onFocus={() =>
                              handleDescFieldFocusChange(
                                null,
                                props,
                                handleSetState,
                              )
                            }
                          />
                        </ClickAwayListener>
                        <FormHelperText
                          error
                          className={classes.fieldHelperTextStyle}
                        >
                          {(props.status && props.status['description']) ||
                            (props.touched['description'] &&
                              props.errors['description'] &&
                              t(
                                `createProject.inputs.description.errors.${props.errors['description']}`,
                              ))}
                        </FormHelperText>
                      </FormControl>
                    </Grid>

                    <Grid item xs={12} className={common_classes.marginTop1em}>
                      <FormControl
                        fullWidth
                        error={
                          (props.status && props.status['project_images']) ||
                          (props.touched['project_images'] &&
                            props.errors['project_images'])
                        }
                      >
                        <label htmlFor="project_images">
                          <Typography
                            color="textSecondary"
                            className={classes.customLabelStyle}
                          >
                            <Box className={classes.fieldNumberStyle}>3</Box>
                            {t('createProject.inputs.projectImages.label')}
                          </Typography>
                        </label>

                        <Typography
                          color="textSecondary"
                          variant="caption"
                          component="span"
                          className={clsx(
                            classes.fieldHelperTextStyle,
                            common_classes.marginBottom1em,
                          )}
                        >
                          {t(
                            'createProject.inputs.projectImages.topHelperText',
                          )}
                        </Typography>
                        <Grid container spacing={1}>
                          <Grid item xs={12} sm={6} md={6}>
                            <CustomButton
                              ref={refs.image_upload_button_el}
                              variant="outlined"
                              size="large"
                              margin="normal"
                              id="image_upload_button"
                              startIcon={<ImageIcon />}
                              onClick={e =>
                                handleImageButtonClick(e, props, refs)
                              }
                              secondaryButtonStyle
                              mediaUploadButtonStyle
                              customButtonStyle
                              fullWidth
                            >
                              {t('createProject.inputs.projectImages.label2')}
                            </CustomButton>
                            <Typography
                              color="textSecondary"
                              variant="caption"
                              component="span"
                              ref={refs.image_count_el}
                            ></Typography>
                          </Grid>
                        </Grid>
                        <input
                          ref={refs.image_el}
                          className={classes.displayNone}
                          aria-hidden="true"
                          type="file"
                          accept="image/*"
                          id="project_images"
                          name="project_images"
                          multiple
                          onChange={_ =>
                            handleImageFieldChange(
                              refs,
                              props,
                              state,
                              handleSetState,
                            )
                          }
                          onBlur={props.handleBlur}
                        />
                        <FormHelperText
                          error
                          className={classes.fieldHelperTextStyle}
                        >
                          {(props.status && props.status['images']) ||
                            (props.errors['project_images'] &&
                              t(
                                `createProject.inputs.projectImages.errors.${props.errors['project_images']}`,
                              ))}
                        </FormHelperText>
                      </FormControl>
                    </Grid>

                    <Grid item xs={12} className={common_classes.marginTop1em}>
                      <FormControl
                        fullWidth
                        error={
                          (props.status && props.status['video']) ||
                          (props.touched['video'] && props.errors['video'])
                        }
                      >
                        <label htmlFor="video">
                          <Typography
                            color="textSecondary"
                            className={classes.customLabelStyle}
                          >
                            <Box className={classes.fieldNumberStyle}>4</Box>
                            {t('createProject.inputs.video.label')}
                          </Typography>
                        </label>

                        <Typography
                          color="textSecondary"
                          variant="caption"
                          component="span"
                          className={clsx(
                            classes.fieldHelperTextStyle,
                            common_classes.marginBottom1em,
                          )}
                        >
                          {t('createProject.inputs.video.topHelperText')}
                        </Typography>
                        <Grid container spacing={1}>
                          <Grid item xs={12} sm={6} md={6}>
                            <CustomButton
                              ref={refs.video_upload_button_el}
                              variant="outlined"
                              size="large"
                              margin="normal"
                              id="video_upload_button"
                              startIcon={<VideoIcon />}
                              onClick={e =>
                                handleSetState(
                                  handleVideoButtonClick(
                                    e,
                                    props,
                                    video_upload_dialog_open,
                                  ),
                                )
                              }
                              secondaryButtonStyle
                              mediaUploadButtonStyle
                              customButtonStyle
                              fullWidth
                            >
                              {t('createProject.inputs.video.label2')}
                            </CustomButton>
                            <Typography
                              color="textSecondary"
                              variant="caption"
                              component="span"
                              ref={refs.video_selection_feedback_el}
                            ></Typography>
                          </Grid>
                        </Grid>
                        <FormHelperText
                          error
                          className={classes.fieldHelperTextStyle}
                        >
                          {(props.status && props.status['video']) ||
                            (props.errors['video'] &&
                              t(
                                `createProject.inputs.video.errors.${props.errors['video']}`,
                              ))}
                        </FormHelperText>
                        <Typography
                          color="textSecondary"
                          variant="caption"
                          component="span"
                          className={classes.fieldHelperTextStyle}
                        >
                          {t('createProject.inputs.video.bottomHelperText')}
                        </Typography>
                      </FormControl>
                    </Grid>

                    <Grid item xs={12} className={common_classes.marginTop1em}>
                      <FormControl
                        className={clsx(classes.margin, classes.textField)}
                        variant="outlined"
                        size="small"
                        fullWidth
                        margin="small"
                        error={
                          (props.status && props.status['materials_used']) ||
                          (props.touched['materials_used'] &&
                            props.errors['materials_used'])
                        }
                      >
                        <label htmlFor="add_materials_used">
                          <Typography
                            color="textSecondary"
                            className={clsx(
                              classes.customLabelStyle,
                              common_classes.marginBottom1em,
                            )}
                          >
                            <Box className={classes.fieldNumberStyle}>5</Box>
                            {t('createProject.inputs.materialsUsed.label')}
                          </Typography>
                        </label>

                        <Grid container spacing={1} alignItems="flex-end">
                          <Grid item xs={12} sm={8}>
                            <Box ref={refs.add_materials_used_el}>
                              {buildMaterialUsedNodes({
                                props,
                                refs,
                                classes,
                                common_classes,
                              })}
                            </Box>
                          </Grid>
                          <Grid item xs={12} sm={4} md={4}>
                            <CustomButton
                              variant="outlined"
                              size="large"
                              onClick={e => addMaterialsUsedNode(e, props)}
                              secondaryButtonStyle
                              customButtonStyle
                              fullWidth
                            >
                              <AddIcon />{' '}
                              {t('createProject.inputs.materialsUsed.addMore')}
                            </CustomButton>
                          </Grid>
                          <FormHelperText
                            error
                            className={classes.fieldHelperTextStyle}
                          >
                            {(props.status && props.status['materials_used']) ||
                              (props.touched['materials_used'] &&
                                props.errors['materials_used'] &&
                                t(
                                  `createProject.inputs.materialsUsed.errors.${props.errors['materials_used']}`,
                                ))}
                          </FormHelperText>
                        </Grid>
                      </FormControl>
                    </Grid>

                    <Grid item xs={12} className={common_classes.marginTop1em}>
                      <FormControl
                        className={clsx(classes.margin, classes.textField)}
                        variant="outlined"
                        size="small"
                        fullWidth
                        margin="small"
                        error={
                          (props.status && props.status['category']) ||
                          (props.touched['category'] &&
                            props.errors['category'])
                        }
                      >
                        <label htmlFor="category">
                          <Typography
                            color="textSecondary"
                            className={classes.customLabelStyle}
                          >
                            <Box className={classes.fieldNumberStyle}>6</Box>
                            {t('createProject.inputs.category.label')}
                          </Typography>
                        </label>
                        <Typography
                          color="textSecondary"
                          variant="caption"
                          component="span"
                          className={clsx(
                            classes.fieldHelperTextStyle,
                            common_classes.marginBottom1em,
                          )}
                        >
                          {t('createProject.inputs.category.topHelperText')}
                        </Typography>
                        <Select
                          labelId="category"
                          id="category"
                          name="category"
                          className={classes.customInputStyle}
                          value={
                            props.values.category ? props.values.category : ''
                          }
                          onChange={props.handleChange}
                          onBlur={props.handleBlur}
                        >
                          <MenuItem value="">
                            <em>None</em>
                          </MenuItem>
                          {Array.isArray(categories) &&
                            categories.map(category => (
                              <MenuItem key={category.id} value={category.name}>
                                {category.name}
                              </MenuItem>
                            ))}
                        </Select>
                        <FormHelperText
                          error
                          className={classes.fieldHelperTextStyle}
                        >
                          {(props.status && props.status['category']) ||
                            (props.touched['category'] &&
                              props.errors['category'] &&
                              t(
                                `createProject.inputs.category.errors.${props.errors['category']}`,
                              ))}
                        </FormHelperText>
                      </FormControl>
                    </Grid>

                    <Grid item xs={12} className={common_classes.marginTop1em}>
                      <FormControl
                        className={clsx(classes.margin, classes.textField)}
                        variant="outlined"
                        size="small"
                        fullWidth
                        margin="small"
                        error={
                          (props.status && props.status['tags']) ||
                          (props.touched['tags'] && props.errors['tags'])
                        }
                      >
                        <label htmlFor="add_tags">
                          <Typography
                            color="textSecondary"
                            className={classes.customLabelStyle}
                          >
                            <Box className={classes.fieldNumberStyle}>7</Box>
                            {t('createProject.inputs.tags.label')}
                          </Typography>
                        </label>

                        <Typography
                          color="textSecondary"
                          variant="caption"
                          component="span"
                          className={clsx(
                            classes.fieldHelperTextStyle,
                            common_classes.marginBottom1em,
                          )}
                        >
                          {t('createProject.inputs.tags.topHelperText')}
                        </Typography>
                        <Box className={classes.tagsViewStyle}>
                          {props.values['tags'] &&
                            JSON.parse(props.values['tags']).map((tag, num) =>
                              tag && tag.name ? (
                                <Chip
                                  className={classes.customChipStyle}
                                  key={num}
                                  label={tag.name}
                                  onDelete={e => removeTag(e, props, tag.name)}
                                  color="secondary"
                                  variant="outlined"
                                />
                              ) : null,
                            )}
                          <input
                            ref={refs.add_tags_el}
                            className={classes.tagsInputStyle}
                            name="tags"
                            type="text"
                            autocomplete="off"
                            placeholder={
                              props.values['tags'] &&
                              JSON.parse(props.values['tags']).length >= 5
                                ? t(
                                    'createProject.inputs.tags.errors.limitReached',
                                  )
                                : `${t('createProject.inputs.tags.addTag')}...`
                            }
                            onChange={e => {
                              handleSuggestTags(
                                e,
                                props,
                                state,
                                handleSetState,
                              );
                              handleSetState(handleAddTags(e, props));
                            }}
                            onBlur={e => {
                              handleAddTags(e, props);
                            }}
                          />
                          <ClickAwayListener
                            onClickAway={() =>
                              handleSetState({
                                tag_suggestion_open: false,
                                tag_suggestion: [],
                              })
                            }
                          >
                            <Box
                              className={clsx(
                                classes.tagSuggestionStyle,
                                !tag_suggestion_open
                                  ? common_classes.displayNone
                                  : null,
                              )}
                            >
                              {tag_suggestion && tag_suggestion.length > 0 ? (
                                tag_suggestion.map((tag, index) => (
                                  <Typography
                                    key={index}
                                    color="textPrimary"
                                    className={classes.tagSuggestionTextStyle}
                                    onClick={() => {
                                      clearTimeout(vars.timer.id);
                                      handleSetState(
                                        handleAddTags(
                                          {
                                            currentTarget: {
                                              value: `${tag.name},`,
                                            },
                                          },
                                          props,
                                          refs.add_tags_el,
                                        ),
                                      );
                                    }}
                                  >
                                    {tag.name}
                                  </Typography>
                                ))
                              ) : (
                                <CircularProgress size={30} thickness={3} />
                              )}
                            </Box>
                          </ClickAwayListener>
                        </Box>
                        <FormHelperText
                          error
                          className={classes.fieldHelperTextStyle}
                        >
                          {(props.status && props.status['tags']) ||
                            (props.touched['tags'] &&
                              props.errors['tags'] &&
                              t(
                                `createProject.inputs.tags.errors.${props.errors['tags']}`,
                              ))}
                        </FormHelperText>
                      </FormControl>
                    </Grid>

                    <Grid item xs={12} className={common_classes.marginTop1em}>
                      <FormControl
                        className={clsx(classes.margin, classes.textField)}
                        variant="outlined"
                        size="small"
                        fullWidth
                        margin="small"
                        error={
                          (props.status && props.status['publish']) ||
                          (props.touched['publish'] && props.errors['publish'])
                        }
                      >
                        <label htmlFor="publish">
                          <Typography
                            color="textSecondary"
                            className={classes.customLabelStyle}
                          >
                            <Box className={classes.fieldNumberStyle}>8</Box>
                            {t('createProject.inputs.publish.label')}
                          </Typography>
                        </label>

                        <Typography
                          color="textSecondary"
                          variant="caption"
                          component="span"
                          className={clsx(
                            classes.fieldHelperTextStyle,
                            common_classes.marginBottom1em,
                          )}
                        >
                          {t('createProject.inputs.publish.topHelperText')}
                        </Typography>

                        <Select
                          ref={refs.publish_type_el}
                          labelId="publish"
                          id="publish"
                          name="publish"
                          className={classes.customInputStyle}
                          value={
                            props.values.publish
                              ? props.values.publish.type
                              : publish_types[0]
                              ? publish_types[0].value
                              : ''
                          }
                          onChange={e => handlePublishFieldChange(e, props)}
                          onBlur={e => handlePublishFieldBlur(e, props)}
                        >
                          {publish_types.map(type => (
                            <MenuItem key={type.name} value={type.value}>
                              {t(`createProject.inputs.publish.publishTypes.${type.name}`)}
                            </MenuItem>
                          ))}
                        </Select>

                        <Box
                          className={clsx(
                            classes.tagsViewStyle,
                            common_classes.marginTop1em,
                            {
                              [common_classes.displayNone]:
                                props.values.publish?.type !==
                                publish_type['Preview'],
                            },
                          )}
                        >
                          {props.values.publish?.visible_to &&
                            props.values['publish']['visible_to'].map(
                              (username, num) =>
                                username ? (
                                  <Chip
                                    className={classes.customChipStyle}
                                    key={num}
                                    label={username}
                                    onDelete={e =>
                                      handleRemovePublishVisibleTo(
                                        e,
                                        props,
                                        username,
                                      )
                                    }
                                    color="secondary"
                                    variant="outlined"
                                  />
                                ) : null,
                            )}
                          <input
                            ref={refs.publish_visible_to_el}
                            className={classes.tagsInputStyle}
                            name="publish_visible_to"
                            type="text"
                            autocomplete="off"
                            placeholder={`${t(
                              'createProject.inputs.publish.addUsernames',
                            )}...`}
                            onChange={e => {
                              handleSuggestPublishVisibleTo(
                                e,
                                props,
                                state,
                                handleSetState,
                              );
                              handleSetState(
                                handleAddPublishVisibleTo(e, props),
                              );
                            }}
                            onBlur={e => {
                              handleAddPublishVisibleTo(e, props);
                            }}
                          />
                          <ClickAwayListener
                            onClickAway={() =>
                              handleSetState({
                                publish_visible_to_suggestion_open: false,
                                publish_visible_to_suggestion: [],
                              })
                            }
                          >
                            <Box
                              className={clsx(
                                classes.tagSuggestionStyle,
                                !publish_visible_to_suggestion_open
                                  ? common_classes.displayNone
                                  : null,
                              )}
                            >
                              {publish_visible_to_suggestion &&
                              publish_visible_to_suggestion.length > 0 ? (
                                publish_visible_to_suggestion.map(
                                  (username, index) => (
                                    <Typography
                                      key={index}
                                      color="textPrimary"
                                      className={classes.tagSuggestionTextStyle}
                                      onClick={() => {
                                        clearTimeout(vars.timer.id);
                                        handleSetState(
                                          handleAddPublishVisibleTo(
                                            {
                                              currentTarget: {
                                                value: `${username},`,
                                              },
                                            },
                                            props,
                                            refs.publish_visible_to_el,
                                          ),
                                        );
                                      }}
                                    >
                                      {username}
                                    </Typography>
                                  ),
                                )
                              ) : (
                                <CircularProgress size={30} thickness={3} />
                              )}
                            </Box>
                          </ClickAwayListener>
                        </Box>
                        <FormHelperText
                          error
                          className={classes.fieldHelperTextStyle}
                        >
                          {(props.status && props.status['publish']) ||
                            (props.touched['publish'] &&
                              props.errors['publish'] &&
                              t(
                                `createProject.inputs.publish.errors.${props.errors['publish']}`,
                              ))}
                        </FormHelperText>
                      </FormControl>
                    </Grid>

                    <Grid item xs={12}>
                      <CustomButton
                        variant="contained"
                        size="large"
                        type="submit"
                        primaryButtonStyle
                        customButtonStyle
                        fullWidth
                      >
                        {!id
                          ? t('createProject.inputs.submit')
                          : t('createProject.inputs.edit')}
                      </CustomButton>
                    </Grid>
                  </Grid>

                  <Dialog
                    PaperProps={{
                      style: {
                        backgroundColor: 'transparent',
                        boxShadow: 'none',
                      },
                    }}
                    open={video_upload_dialog_open}
                    onClose={async () =>
                      handleSetState({
                        ...(await handleVideoFieldCancel(refs, props, state)),
                        video_upload_dialog_open: false,
                      })
                    }
                    aria-labelledby="video upload dialog"
                  >
                    <Container
                      className={clsx(
                        classes.containerStyle,
                        classes.videoInputDialogContainerStyle,
                      )}
                    >
                      <Card
                        className={clsx(
                          classes.cardStyle,
                          classes.videoInputDialogCardStyle,
                        )}
                      >
                        <CardActionArea>
                          <CardContent>
                            <div
                              className={
                                classes.videoInputDialogControlSectionStyle
                              }
                            >
                              <CustomButton
                                className={
                                  classes.videoInputDialogControlButtonStyle
                                }
                                primaryButtonStyle={!select_video_file}
                                secondaryButtonStyle={select_video_file}
                                size="medium"
                                onClick={_ =>
                                  handleSetState({ select_video_file: false })
                                }
                              >
                                <div
                                  className={
                                    classes.videoInputDialogControlButtonUseTextDescStyle
                                  }
                                >
                                  {t(
                                    'createProject.inputs.video.dialogURLToggle',
                                  )}
                                </div>
                                <InsertLinkIcon
                                  className={
                                    classes.videoInputDialogControlButtonUseIconDescStyle
                                  }
                                />
                              </CustomButton>
                              <CustomButton
                                className={
                                  classes.videoInputDialogControlButtonStyle
                                }
                                primaryButtonStyle={select_video_file}
                                secondaryButtonStyle={!select_video_file}
                                size="medium"
                                onClick={_ =>
                                  handleSetState(
                                    handleSelectVideoFileChecked(
                                      refs.video_file_el.current,
                                    ),
                                  )
                                }
                              >
                                <div
                                  className={
                                    classes.videoInputDialogControlButtonUseTextDescStyle
                                  }
                                >
                                  {t(
                                    'createProject.inputs.video.dialogFileToggle',
                                  )}
                                </div>
                                <MovieIcon
                                  className={
                                    classes.videoInputDialogControlButtonUseIconDescStyle
                                  }
                                />
                              </CustomButton>
                            </div>
                            <Grid container spacing={1} alignItems="flex-end">
                              <Grid
                                item
                                xs={12}
                                sm={12}
                                className={clsx(
                                  common_classes.marginTop1em,
                                  classes.videoInputDialogBodyGridStyle,
                                )}
                              >
                                {!select_video_file ? (
                                  <FormControl
                                    className={clsx(
                                      classes.margin,
                                      classes.textField,
                                      classes.videoInputDialogURLFormControlStyle,
                                    )}
                                    variant="outlined"
                                    size="small"
                                  >
                                    <InputLabel
                                      className={classes.customLabelStyle}
                                      htmlFor="url-input"
                                    >
                                      {t(
                                        'createProject.inputs.video.dialogURLFieldLabel',
                                      )}
                                    </InputLabel>
                                    <OutlinedInput
                                      ref={refs.video_el}
                                      className={classes.customInputStyle}
                                      type="text"
                                      name="url-input"
                                      labelWidth={calculateLabelWidth(
                                        t(
                                          'createProject.inputs.video.dialogURLFieldLabel',
                                        ),
                                        document,
                                      )}
                                      placeholder="https://youtube.com/..."
                                      onChange={async e =>
                                        handleSetState(
                                          await handleVideoFieldChange(
                                            e,
                                            refs,
                                            props,
                                            state,
                                            handleSetState,
                                          ),
                                        )
                                      }
                                    />
                                  </FormControl>
                                ) : null}
                                {select_video_file ? (
                                  <p className={classes.videoFileName}>
                                    {refs.video_file_el.current?.files?.[0]
                                      ? refs.video_file_el.current?.files?.[0]
                                          ?.name
                                      : t(
                                          'createProject.inputs.video.dialogFileToggle',
                                        )}
                                  </p>
                                ) : null}
                                <CustomButton
                                  className={
                                    classes.videoInputDialogActionButtonStyle
                                  }
                                  secondaryButtonStyle
                                  variant="outlined"
                                  size="medium"
                                  onClick={async () =>
                                    handleSetState({
                                      ...(await handleVideoFieldCancel(
                                        refs,
                                        props,
                                        state,
                                      )),
                                      video_upload_dialog_open: false,
                                    })
                                  }
                                >
                                  <CloseIcon />
                                </CustomButton>

                                <CustomButton
                                  className={
                                    classes.videoInputDialogActionButtonStyle
                                  }
                                  primaryButtonStyle
                                  size="medium"
                                  onClick={async () =>
                                    handleSetState({
                                      ...(await handleVideoSelectDone(
                                        refs,
                                        props,
                                        state,
                                      )),
                                      video_upload_dialog_open: false,
                                    })
                                  }
                                >
                                  <CheckIcon />
                                </CustomButton>

                                <input
                                  className={common_classes.displayNone}
                                  ref={refs.video_file_el}
                                  type="file"
                                  accept="video/*"
                                  id="video"
                                  name="video"
                                  onChange={async e => {
                                    handleSetState(
                                      await handleVideoFieldChange(
                                        e,
                                        refs,
                                        props,
                                        state,
                                        handleSetState,
                                      ),
                                    );
                                  }}
                                  onBlur={props.handleBlur}
                                />
                              </Grid>
                            </Grid>
                          </CardContent>
                        </CardActionArea>
                      </Card>
                    </Container>
                  </Dialog>
                </form>
                <Dialog
                  PaperProps={{
                    style: {
                      backgroundColor: 'transparent',
                      boxShadow: 'none',
                    },
                  }}
                  className={classes.uploadProgressDialogStyle}
                  open={media_upload.upload_dialog}
                  aria-labelledby="upload progress dialog"
                >
                  <Box
                    className={classes.uploadProgressIndicatorContainerStyle}
                  >
                    <CircularProgress
                      className={classes.uploadProgressStyle}
                      variant="determinate"
                      size={70}
                      thickness={6}
                      value={media_upload.upload_percent}
                    />
                    <Box
                      top={0}
                      left={0}
                      bottom={0}
                      right={0}
                      position="absolute"
                      display="flex"
                      alignItems="center"
                      justifyContent="center"
                    >
                      <Typography
                        className={classes.uploadProgressLabelStyle}
                        variant="caption"
                        component="div"
                      >{`${Math.round(
                        media_upload.upload_percent,
                      )}%`}</Typography>
                    </Box>
                  </Box>
                </Dialog>
              </CardContent>
            </CardActionArea>
          </Card>
        </Container>
      </Box>
    );
  }
}
Example #28
Source File: AddGroupMembers.jsx    From zubhub with GNU Affero General Public License v3.0 4 votes vote down vote up
/**
 * @function AddGroupMembers
 * @author Raymond Ndibe <[email protected]>
 *
 * @todo - describe function's signature
 */
function AddGroupMembers(props) {
  const refs = {
    add_group_members_el: React.useRef(null),
    drag_drop_el: React.useRef(null),
  };
  const classes = useStyles();
  const common_classes = useCommonStyles();

  const [state, setState] = React.useState({
    loading: true,
    error: null,
    csv: null,
    upload_dialog: false,
    bulk_add_checked: false,
  });

  const handleSetState = obj => {
    if (obj) {
      Promise.resolve(obj).then(obj => {
        setState({ ...state, ...obj });
      });
    }
  };

  const { upload_dialog, bulk_add_checked, csv } = state;
  const { t } = props;
  vars.csv_not_added = !csv;
  if (!props.auth.token) {
    return <ErrorPage error={t('addGroupMembers.errors.notLoggedIn')} />;
  } else if (props.auth.members_count === null) {
    return <ErrorPage error={t('addGroupMembers.errors.unauthorized')} />;
  } else {
    return (
      <Box className={classes.root}>
        <Container className={classes.containerStyle}>
          <Card className={classes.cardStyle}>
            <CardActionArea>
              <CardContent>
                <form
                  className="project-create-form"
                  name="create_project"
                  noValidate="noValidate"
                  onSubmit={e => handleSubmit(e, state, handleSetState, props)}
                >
                  <Typography
                    className={classes.titleStyle}
                    gutterBottom
                    variant="h5"
                    component="h2"
                    color="textPrimary"
                  >
                    {t('addGroupMembers.welcomeMsg.primary')}
                  </Typography>
                  <Typography
                    variant="body2"
                    color="textSecondary"
                    component="p"
                    className={classes.descStyle}
                  >
                    {t('addGroupMembers.welcomeMsg.secondary')}
                  </Typography>

                  <Grid container spacing={3}>
                    <Grid item xs={12}>
                      <Box
                        component="p"
                        className={
                          props.status &&
                          props.status['non_field_errors'] &&
                          classes.errorBox
                        }
                      >
                        {props.status && props.status['non_field_errors'] && (
                          <Box component="span" className={classes.error}>
                            {props.status['non_field_errors']}
                          </Box>
                        )}
                      </Box>
                    </Grid>

                    <Grid item xs={12} className={common_classes.marginTop1em}>
                      <FormControl
                        variant="outlined"
                        size="small"
                        fullWidth
                        margin="small"
                        error={
                          (props.status && props.status['group_members']) ||
                          (props.touched['group_members'] &&
                            props.errors['group_members'])
                        }
                      >
                        <label htmlFor="add_group_members">
                          <Typography
                            color="textSecondary"
                            className={clsx(
                              classes.customLabelStyle,
                              common_classes.marginBottom1em,
                            )}
                          >
                            {t('addGroupMembers.inputs.groupMembers.label')}
                          </Typography>
                        </label>

                        <Grid container spacing={1} alignItems="flex-end">
                          {!bulk_add_checked ? (
                            <>
                              <Grid item xs={12} sm={8}>
                                <Box ref={refs.add_group_members_el}>
                                  {buildGroupMembersNodes({
                                    props,
                                    refs,
                                    classes,
                                    common_classes,
                                  })}
                                </Box>
                              </Grid>
                              <Grid item xs={12} sm={4}>
                                <CustomButton
                                  variant="outlined"
                                  size="large"
                                  onClick={e => addGroupMembersNode(e, props)}
                                  secondaryButtonStyle
                                  customButtonStyle
                                  fullWidth
                                >
                                  <AddIcon />{' '}
                                  {t(
                                    'addGroupMembers.inputs.groupMembers.addMore',
                                  )}
                                </CustomButton>
                              </Grid>
                              <FormHelperText
                                error
                                className={classes.fieldHelperTextStyle}
                              >
                                {(props.status &&
                                  props.status['group_members']) ||
                                  (props.touched['group_members'] &&
                                    props.errors['group_members'] &&
                                    t(
                                      `addGroupMembers.inputs.groupMembers.errors.${props.errors['group_members']}`,
                                    ))}
                              </FormHelperText>
                            </>
                          ) : (
                            <label
                              htmlFor="addcsv"
                              className={classes.addCSVStyles}
                            >
                              <Box
                                className={classes.CSVBoxStyles}
                                ref={refs.drag_drop_el}
                                onDragLeave={e => {
                                  refs.drag_drop_el.current.style.border =
                                    '1px dashed rgb(196, 194, 194)';
                                }}
                                onDragOver={e => {
                                  e.preventDefault();
                                  refs.drag_drop_el.current.style.border =
                                    '1px solid #878dcd';
                                }}
                                onDrop={e =>
                                  handleSetState(handleAddCSV(e, refs))
                                }
                              >
                                <img
                                  src={csvLogo}
                                  alt={
                                    csv
                                      ? csv.name
                                      : t(
                                          'addGroupMembers.inputs.groupMembers.addCSV',
                                        )
                                  }
                                />
                                <br />
                                {csv
                                  ? csv.name
                                  : t(
                                      'addGroupMembers.inputs.groupMembers.addCSV',
                                    )}
                                <FormHelperText
                                  error
                                  className={classes.fieldHelperTextStyle}
                                >
                                  {(props.status &&
                                    props.status['group_members']) ||
                                    (props.touched['group_members'] &&
                                      props.errors['group_members'] &&
                                      t(
                                        `addGroupMembers.inputs.groupMembers.errors.${props.errors['group_members']}`,
                                      ))}
                                </FormHelperText>
                                <input
                                  type="file"
                                  accept=".csv"
                                  style={{ display: 'none' }}
                                  id="addcsv"
                                  onChange={e =>
                                    handleSetState({
                                      csv: e.target.files[0],
                                    })
                                  }
                                />
                              </Box>
                            </label>
                          )}
                        </Grid>
                      </FormControl>
                    </Grid>
                    <Grid item xs={12} sm={8}>
                      <FormControlLabel
                        className={common_classes.floatLeft}
                        control={
                          <Switch
                            className={classes.bulkAddStyles}
                            checked={bulk_add_checked}
                            onChange={e =>
                              handleSetState(
                                handleBulkAddCheck(bulk_add_checked),
                              )
                            }
                          />
                        }
                        label={
                          <Typography
                            color="textSecondary"
                            className={classes.customLabelStyle}
                          >
                            {t('addGroupMembers.inputs.groupMembers.bulkAdd')}
                          </Typography>
                        }
                      />
                    </Grid>
                    <Grid item xs={12} sm={4}>
                      <CustomButton
                        variant="contained"
                        size="large"
                        type="submit"
                        primaryButtonStyle
                        customButtonStyle
                        fullWidth
                        className={common_classes.floatRight}
                      >
                        {t('addGroupMembers.inputs.submit')}
                      </CustomButton>
                    </Grid>
                  </Grid>
                </form>
                <Dialog
                  PaperProps={{
                    style: {
                      backgroundColor: 'transparent',
                      boxShadow: 'none',
                      overflow: 'hidden',
                    },
                  }}
                  open={upload_dialog}
                  aria-label={t('addGroupMembers.ariaLabels.submitting')}
                >
                  <Box position="relative" display="inline-flex">
                    <CircularProgress
                      className={classes.uploadProgressStyle}
                      size={70}
                      thickness={6}
                    />
                  </Box>
                </Dialog>
              </CardContent>
            </CardActionArea>
          </Card>
        </Container>
      </Box>
    );
  }
}
Example #29
Source File: GrowerTooltip.js    From treetracker-admin-client with GNU Affero General Public License v3.0 4 votes vote down vote up
GrowerTooltip = ({ grower, growerClick }) => {
  const classes = useStyle();
  const matches = grower.imageUrl?.match(/\/\/(.*?)\/(.*)/);
  const useStyles = makeStyles(() => ({
    box: {
      display: 'flex',
      marginTop: '2px',
    },
    label: {
      marginLeft: '12px',
    },
  }));

  const growerToolTipStyles = useStyles();

  return (
    <Box>
      <Box style={{ width: '160px', display: 'block' }}>
        <Card
          style={{
            display: 'flex',
            justifyContent: 'space-around',
            flexDirection: 'column',
            alignItems: 'center',
          }}
          onClick={() => growerClick(grower)}
        >
          <CardActionArea>
            <Box style={{ display: 'flex', margin: '4px' }}>
              <Box
                style={{
                  display: 'flex',
                  justifyContent: 'space-between',
                  alignItems: 'center',
                  margin: '2px',
                }}
              >
                {matches?.length > 1 ? (
                  <OptimizedImage
                    rotation={grower.imageRotation}
                    src={grower.imageUrl}
                    style={{
                      height: '24px',
                      width: '24px',
                    }}
                  />
                ) : (
                  <Person
                    className={classes.person}
                    style={{
                      height: '24px',
                      width: '24px',
                    }}
                  />
                )}
              </Box>
              <Box>
                <Typography className={growerToolTipStyles.label}>
                  {grower.firstName} {grower.lastName}
                </Typography>
              </Box>
            </Box>
            <Divider
              variant="middle"
              sx={{
                marginBottom: '2px',
                marginTop: '4px',
              }}
            />
            <Box
              style={{
                display: 'flex',
                flexDirection: 'column',
                justifyContent: 'flex-start',
                margin: '0 4px 0 4px',
              }}
            >
              {grower.email && (
                <Box className={growerToolTipStyles.box}>
                  <EmailIcon color="primary" />
                  <Typography className={growerToolTipStyles.label}>
                    {grower.email}
                  </Typography>
                </Box>
              )}
              {(grower.organizaton || grower.organizationId) && (
                <Box className={growerToolTipStyles.box}>
                  <OrgIcon color="primary" />
                  <Box className={growerToolTipStyles.label}>
                    <GrowerOrganization
                      organizationName={grower.organization}
                      assignedOrganizationId={grower.organizationId}
                      compact={true}
                    />
                  </Box>
                </Box>
              )}
              {grower.phone && (
                <Box className={growerToolTipStyles.box}>
                  <PhoneIcon color="primary" />
                  <Typography className={growerToolTipStyles.label}>
                    {grower.phone}
                  </Typography>
                </Box>
              )}
            </Box>
          </CardActionArea>
        </Card>
      </Box>
    </Box>
  );
}